Implement Keyring system base
This commit is contained in:
parent
ce867d9169
commit
f01bf10dc5
@ -48,6 +48,7 @@ find_package(ZLIB REQUIRED)
|
|||||||
|
|
||||||
# Add quazip
|
# Add quazip
|
||||||
add_subdirectory(quazip)
|
add_subdirectory(quazip)
|
||||||
|
include_directories(quazip)
|
||||||
|
|
||||||
# Add bspatch
|
# Add bspatch
|
||||||
add_subdirectory(patchlib)
|
add_subdirectory(patchlib)
|
||||||
@ -260,6 +261,12 @@ libUtil libSettings libMultiMC libGroupView
|
|||||||
${MultiMC_LINK_ADDITIONAL_LIBS})
|
${MultiMC_LINK_ADDITIONAL_LIBS})
|
||||||
ADD_DEPENDENCIES(MultiMC MultiMCLauncher libUtil libSettings libMultiMC libGroupView)
|
ADD_DEPENDENCIES(MultiMC MultiMCLauncher libUtil libSettings libMultiMC libGroupView)
|
||||||
|
|
||||||
|
IF(DEFINED MMC_KEYRING_TEST)
|
||||||
|
# test.cpp
|
||||||
|
ADD_EXECUTABLE(Test test.cpp)
|
||||||
|
QT5_USE_MODULES(Test Core)
|
||||||
|
TARGET_LINK_LIBRARIES(Test libmmcutil libmmcsettings)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
################################ INSTALLATION AND PACKAGING ################################
|
################################ INSTALLATION AND PACKAGING ################################
|
||||||
# use QtCreator's QTDIR var
|
# use QtCreator's QTDIR var
|
||||||
|
85
libsettings/include/keyring.h
Normal file
85
libsettings/include/keyring.h
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/* Copyright 2013 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KEYRING_H
|
||||||
|
#define KEYRING_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "libsettings_config.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file libsettings/include/keyring.h
|
||||||
|
* Access to System Keyrings
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The Keyring class
|
||||||
|
* the System Keyring/Keychain/Wallet/Vault/etc
|
||||||
|
*/
|
||||||
|
class LIBMMCSETTINGS_EXPORT Keyring : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief the System Keyring instance
|
||||||
|
* @return the Keyring instance
|
||||||
|
*/
|
||||||
|
static Keyring *instance();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief store a password in the Keyring
|
||||||
|
* @param service the service name
|
||||||
|
* @param username the account name
|
||||||
|
* @param password the password to store
|
||||||
|
* @return success
|
||||||
|
*/
|
||||||
|
virtual bool storePassword(QString service, QString username, QString password) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief get a password from the Keyring
|
||||||
|
* @param service the service name
|
||||||
|
* @param username the account name
|
||||||
|
* @return the password (success=!isNull())
|
||||||
|
*/
|
||||||
|
virtual QString getPassword(QString service, QString username) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief lookup a password
|
||||||
|
* @param service the service name
|
||||||
|
* @param username the account name
|
||||||
|
* @return wether the password is available
|
||||||
|
*/
|
||||||
|
virtual bool hasPassword(QString service, QString username) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief get a list of all stored accounts.
|
||||||
|
* @param service the service name
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual QStringList getStoredAccounts(QString service) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// fall back to StubKeyring if false
|
||||||
|
virtual bool isValid() { return false; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static Keyring *m_instance;
|
||||||
|
static void destroy();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KEYRING_H
|
63
libsettings/src/keyring.cpp
Normal file
63
libsettings/src/keyring.cpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/* Copyright 2013 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "include/keyring.h"
|
||||||
|
|
||||||
|
#include "osutils.h"
|
||||||
|
|
||||||
|
#include "stubkeyring.h"
|
||||||
|
|
||||||
|
// system specific keyrings
|
||||||
|
/*#if defined(OSX)
|
||||||
|
class OSXKeychain;
|
||||||
|
#define KEYRING OSXKeychain
|
||||||
|
#elif defined(LINUX)
|
||||||
|
class XDGKeyring;
|
||||||
|
#define KEYRING XDGKeyring
|
||||||
|
#elif defined(WINDOWS)
|
||||||
|
class Win32Keystore;
|
||||||
|
#define KEYRING Win32Keystore
|
||||||
|
#else
|
||||||
|
#pragma message Keyrings are not supported on your os. Falling back to the insecure StubKeyring
|
||||||
|
#endif*/
|
||||||
|
|
||||||
|
Keyring *Keyring::instance()
|
||||||
|
{
|
||||||
|
if (m_instance == nullptr)
|
||||||
|
{
|
||||||
|
#ifdef KEYRING
|
||||||
|
m_instance = new KEYRING();
|
||||||
|
if (!m_instance->isValid())
|
||||||
|
{
|
||||||
|
qWarning("Could not create SystemKeyring! falling back to StubKeyring.");
|
||||||
|
m_instance = new StubKeyring();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
qWarning("Keyrings are not supported on your OS. Fallback StubKeyring is insecure!");
|
||||||
|
m_instance = new StubKeyring();
|
||||||
|
#endif
|
||||||
|
atexit(Keyring::destroy);
|
||||||
|
}
|
||||||
|
return m_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Keyring::destroy()
|
||||||
|
{
|
||||||
|
delete m_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
Keyring *Keyring::m_instance;
|
96
libsettings/src/stubkeyring.cpp
Normal file
96
libsettings/src/stubkeyring.cpp
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/* Copyright 2013 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stubkeyring.h"
|
||||||
|
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
// Scrambling
|
||||||
|
// this is NOT SAFE, but it's not plain either.
|
||||||
|
int scrambler = 0x9586309;
|
||||||
|
|
||||||
|
QString scramble(QString in_)
|
||||||
|
{
|
||||||
|
QByteArray in = in_.toUtf8();
|
||||||
|
QByteArray out;
|
||||||
|
for (int i = 0; i<in.length(); i++)
|
||||||
|
out.append(in.at(i) ^ scrambler);
|
||||||
|
return QString::fromUtf8(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QString base64(QString in)
|
||||||
|
{
|
||||||
|
return QString(in.toUtf8().toBase64());
|
||||||
|
}
|
||||||
|
inline QString unbase64(QString in)
|
||||||
|
{
|
||||||
|
return QString::fromUtf8(QByteArray::fromBase64(in.toLatin1()));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QString scramble64(QString in)
|
||||||
|
{
|
||||||
|
return base64(scramble(in));
|
||||||
|
}
|
||||||
|
inline QString unscramble64(QString in)
|
||||||
|
{
|
||||||
|
return scramble(unbase64(in));
|
||||||
|
}
|
||||||
|
|
||||||
|
// StubKeyring implementation
|
||||||
|
inline QString generateKey(QString service, QString username)
|
||||||
|
{
|
||||||
|
return QString("%1/%2").arg(base64(service)).arg(scramble64(username));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StubKeyring::storePassword(QString service, QString username, QString password)
|
||||||
|
{
|
||||||
|
m_settings.setValue(generateKey(service, username), scramble64(password));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString StubKeyring::getPassword(QString service, QString username)
|
||||||
|
{
|
||||||
|
QString key = generateKey(service, username);
|
||||||
|
if (!m_settings.contains(key))
|
||||||
|
return QString();
|
||||||
|
return unscramble64(m_settings.value(key).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool StubKeyring::hasPassword(QString service, QString username)
|
||||||
|
{
|
||||||
|
return m_settings.contains(generateKey(service, username));
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList StubKeyring::getStoredAccounts(QString service)
|
||||||
|
{
|
||||||
|
service = base64(service).append('/');
|
||||||
|
QStringList out;
|
||||||
|
QStringList in(m_settings.allKeys());
|
||||||
|
QStringListIterator it(in);
|
||||||
|
while(it.hasNext())
|
||||||
|
{
|
||||||
|
QString c = it.next();
|
||||||
|
if (c.startsWith(service))
|
||||||
|
out << unscramble64(c.mid(service.length()));
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
StubKeyring::StubKeyring() :
|
||||||
|
m_settings(QSettings::UserScope, "Orochimarufan", "Keyring")
|
||||||
|
{
|
||||||
|
}
|
42
libsettings/src/stubkeyring.h
Normal file
42
libsettings/src/stubkeyring.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/* Copyright 2013 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef STUBKEYRING_H
|
||||||
|
#define STUBKEYRING_H
|
||||||
|
|
||||||
|
#include "include/keyring.h"
|
||||||
|
|
||||||
|
#include <QSettings>
|
||||||
|
|
||||||
|
class StubKeyring : public Keyring
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
virtual bool storePassword(QString service, QString username, QString password);
|
||||||
|
virtual QString getPassword(QString service, QString username);
|
||||||
|
virtual bool hasPassword(QString service, QString username);
|
||||||
|
virtual QStringList getStoredAccounts(QString service);
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class Keyring;
|
||||||
|
explicit StubKeyring();
|
||||||
|
virtual bool isValid() { return true; }
|
||||||
|
|
||||||
|
QSettings m_settings;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // STUBKEYRING_H
|
60
test.cpp
Normal file
60
test.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "keyring.h"
|
||||||
|
#include "cmdutils.h"
|
||||||
|
|
||||||
|
using namespace Util::Commandline;
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
QCoreApplication app(argc, argv);
|
||||||
|
app.setApplicationName("MMC Keyring test");
|
||||||
|
app.setOrganizationName("Orochimarufan");
|
||||||
|
|
||||||
|
Parser p;
|
||||||
|
p.addArgument("user", false);
|
||||||
|
p.addArgument("password", false);
|
||||||
|
p.addSwitch("set");
|
||||||
|
p.addSwitch("get");
|
||||||
|
p.addSwitch("list");
|
||||||
|
p.addOption("service", "Test");
|
||||||
|
p.addShortOpt("service", 's');
|
||||||
|
|
||||||
|
QHash<QString, QVariant> args;
|
||||||
|
try {
|
||||||
|
args = p.parse(app.arguments());
|
||||||
|
} catch (ParsingError) {
|
||||||
|
std::cout << "Syntax error." << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args["set"].toBool()) {
|
||||||
|
if (args["user"].isNull() || args["password"].isNull()) {
|
||||||
|
std::cout << "set operation needs bot user and password set" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Keyring::instance()->storePassword(args["service"].toString(),
|
||||||
|
args["user"].toString(), args["password"].toString());
|
||||||
|
} else if (args["get"].toBool()) {
|
||||||
|
if (args["user"].isNull()) {
|
||||||
|
std::cout << "get operation needs user set" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Password: " << qPrintable(Keyring::instance()->getPassword(args["service"].toString(),
|
||||||
|
args["user"].toString())) << std::endl;
|
||||||
|
return 0;
|
||||||
|
} else if (args["list"].toBool()) {
|
||||||
|
QStringList accounts = Keyring::instance()->getStoredAccounts(args["service"].toString());
|
||||||
|
std::cout << "stored accounts:" << std::endl << '\t' << qPrintable(accounts.join("\n\t")) << std::endl;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
std::cout << "No operation given!" << std::endl;
|
||||||
|
std::cout << qPrintable(p.compileHelp(argv[0])) << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user