summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOrochimarufan <orochimarufan.x3@gmail.com>2013-02-24 18:22:35 +0100
committerOrochimarufan <orochimarufan.x3@gmail.com>2013-03-22 13:51:21 +0100
commitf01bf10dc511268ead551a191a6a3211c006ba44 (patch)
tree29cad9dc812def321053bf3436f38b535e644f86
parentce867d91698a9414ff7238e902215e9b76d10459 (diff)
downloadMultiMC-f01bf10dc511268ead551a191a6a3211c006ba44.tar
MultiMC-f01bf10dc511268ead551a191a6a3211c006ba44.tar.gz
MultiMC-f01bf10dc511268ead551a191a6a3211c006ba44.tar.lz
MultiMC-f01bf10dc511268ead551a191a6a3211c006ba44.tar.xz
MultiMC-f01bf10dc511268ead551a191a6a3211c006ba44.zip
Implement Keyring system base
-rw-r--r--CMakeLists.txt7
-rw-r--r--libsettings/include/keyring.h85
-rw-r--r--libsettings/src/keyring.cpp63
-rw-r--r--libsettings/src/stubkeyring.cpp96
-rw-r--r--libsettings/src/stubkeyring.h42
-rw-r--r--test.cpp60
6 files changed, 353 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9ae3e784..6f0204c3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -48,6 +48,7 @@ find_package(ZLIB REQUIRED)
# Add quazip
add_subdirectory(quazip)
+include_directories(quazip)
# Add bspatch
add_subdirectory(patchlib)
@@ -260,6 +261,12 @@ libUtil libSettings libMultiMC libGroupView
${MultiMC_LINK_ADDITIONAL_LIBS})
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 ################################
# use QtCreator's QTDIR var
diff --git a/libsettings/include/keyring.h b/libsettings/include/keyring.h
new file mode 100644
index 00000000..4563a268
--- /dev/null
+++ b/libsettings/include/keyring.h
@@ -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
diff --git a/libsettings/src/keyring.cpp b/libsettings/src/keyring.cpp
new file mode 100644
index 00000000..1b13e35c
--- /dev/null
+++ b/libsettings/src/keyring.cpp
@@ -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;
diff --git a/libsettings/src/stubkeyring.cpp b/libsettings/src/stubkeyring.cpp
new file mode 100644
index 00000000..0e29d2f2
--- /dev/null
+++ b/libsettings/src/stubkeyring.cpp
@@ -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")
+{
+}
diff --git a/libsettings/src/stubkeyring.h b/libsettings/src/stubkeyring.h
new file mode 100644
index 00000000..f8e0eaaa
--- /dev/null
+++ b/libsettings/src/stubkeyring.h
@@ -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
diff --git a/test.cpp b/test.cpp
new file mode 100644
index 00000000..26600220
--- /dev/null
+++ b/test.cpp
@@ -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;
+ }
+}