X-Git-Url: https://git.quassel-irc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fcore%2Fcore.cpp;h=80646c0335e52ee5261c3ce77e369203b5ebc5c9;hb=27df512ce272d88cf85b854f6bfb3f1c7ba4a65c;hp=1a418f1d08ddce65ece600e5393c608bacd3cf7d;hpb=cfbd4daee17dbb3c4052d938bf33edd08711d728;p=quassel.git diff --git a/src/core/core.cpp b/src/core/core.cpp index 1a418f1d..80646c03 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-2016 by the Quassel Project * + * Copyright (C) 2005-2018 by the Quassel Project * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * @@ -49,11 +49,6 @@ # include #endif /* Q_OS_WIN */ -#ifdef HAVE_UMASK -# include -# include -#endif /* HAVE_UMASK */ - // ============================== // Custom Events // ============================== @@ -91,80 +86,10 @@ void Core::destroy() Core::Core() { -#ifdef HAVE_UMASK - umask(S_IRWXG | S_IRWXO); -#endif _startTime = QDateTime::currentDateTime().toUTC(); // for uptime :) Quassel::loadTranslation(QLocale::system()); - // FIXME: MIGRATION 0.3 -> 0.4: Move database and core config to new location - // Move settings, note this does not delete the old files -#ifdef Q_OS_MAC - QSettings newSettings("quassel-irc.org", "quasselcore"); -#else - -# ifdef Q_OS_WIN - QSettings::Format format = QSettings::IniFormat; -# else - QSettings::Format format = QSettings::NativeFormat; -# endif - QString newFilePath = Quassel::configDirPath() + "quasselcore" - + ((format == QSettings::NativeFormat) ? QLatin1String(".conf") : QLatin1String(".ini")); - QSettings newSettings(newFilePath, format); -#endif /* Q_OS_MAC */ - - if (newSettings.value("Config/Version").toUInt() == 0) { -# ifdef Q_OS_MAC - QString org = "quassel-irc.org"; -# else - QString org = "Quassel Project"; -# endif - QSettings oldSettings(org, "Quassel Core"); - if (oldSettings.allKeys().count()) { - quWarning() << "\n\n*** IMPORTANT: Config and data file locations have changed. Attempting to auto-migrate your core settings..."; - foreach(QString key, oldSettings.allKeys()) - newSettings.setValue(key, oldSettings.value(key)); - newSettings.setValue("Config/Version", 1); - quWarning() << "* Your core settings have been migrated to" << newSettings.fileName(); - -#ifndef Q_OS_MAC /* we don't need to move the db and cert for mac */ -#ifdef Q_OS_WIN - QString quasselDir = qgetenv("APPDATA") + "/quassel/"; -#elif defined Q_OS_MAC - QString quasselDir = QDir::homePath() + "/Library/Application Support/Quassel/"; -#else - QString quasselDir = QDir::homePath() + "/.quassel/"; -#endif - - QFileInfo info(Quassel::configDirPath() + "quassel-storage.sqlite"); - if (!info.exists()) { - // move database, if we found it - QFile oldDb(quasselDir + "quassel-storage.sqlite"); - if (oldDb.exists()) { - bool success = oldDb.rename(Quassel::configDirPath() + "quassel-storage.sqlite"); - if (success) - quWarning() << "* Your database has been moved to" << Quassel::configDirPath() + "quassel-storage.sqlite"; - else - quWarning() << "!!! Moving your database has failed. Please move it manually into" << Quassel::configDirPath(); - } - } - // move certificate - QFileInfo certInfo(quasselDir + "quasselCert.pem"); - if (certInfo.exists()) { - QFile cert(quasselDir + "quasselCert.pem"); - bool success = cert.rename(Quassel::configDirPath() + "quasselCert.pem"); - if (success) - quWarning() << "* Your certificate has been moved to" << Quassel::configDirPath() + "quasselCert.pem"; - else - quWarning() << "!!! Moving your certificate has failed. Please move it manually into" << Quassel::configDirPath(); - } -#endif /* !Q_OS_MAC */ - quWarning() << "*** Migration completed.\n\n"; - } - } - // MIGRATION end - // check settings version // so far, we only have 1 CoreSettings s; @@ -184,15 +109,40 @@ Core::Core() void Core::init() { - CoreSettings cs; + QProcessEnvironment environment = QProcessEnvironment::systemEnvironment(); + bool config_from_environment = Quassel::isOptionSet("config-from-environment"); + + QString db_backend; + QVariantMap db_connectionProperties; + + QString auth_authenticator; + QVariantMap auth_properties; + + bool writeError = false; + + if (config_from_environment) { + db_backend = environment.value("DB_BACKEND"); + auth_authenticator = environment.value("AUTH_AUTHENTICATOR"); + } else { + CoreSettings cs; + + QVariantMap dbsettings = cs.storageSettings().toMap(); + db_backend = dbsettings.value("Backend").toString(); + db_connectionProperties = dbsettings.value("ConnectionProperties").toMap(); + + QVariantMap authSettings = cs.authSettings().toMap(); + auth_authenticator = authSettings.value("Authenticator", "Database").toString(); + auth_properties = authSettings.value("AuthProperties").toMap(); + + writeError = !cs.isWritable(); + } + // legacy - QVariantMap dbsettings = cs.storageSettings().toMap(); - _configured = initStorage(dbsettings.value("Backend").toString(), dbsettings.value("ConnectionProperties").toMap()); + _configured = initStorage(db_backend, db_connectionProperties, environment, config_from_environment); // Not entirely sure what is 'legacy' about the above, but it seems to be the way things work! if (_configured) { - QVariantMap authSettings = cs.authSettings().toMap(); - initAuthenticator(authSettings.value("Authenticator", "Database").toString(), authSettings.value("AuthProperties").toMap()); + initAuthenticator(auth_authenticator, auth_properties, environment, config_from_environment); } if (Quassel::isOptionSet("select-backend") || Quassel::isOptionSet("select-authenticator")) { @@ -206,20 +156,30 @@ void Core::init() } if (!_configured) { - if (_registeredStorageBackends.size() == 0) { - quWarning() << qPrintable(tr("Could not initialize any storage backend! Exiting...")); - quWarning() << qPrintable(tr("Currently, Quassel supports SQLite3 and PostgreSQL. You need to build your\n" - "Qt library with the sqlite or postgres plugin enabled in order for quasselcore\n" - "to work.")); - exit(EXIT_FAILURE); // TODO make this less brutal (especially for mono client -> popup) - } - quWarning() << "Core is currently not configured! Please connect with a Quassel Client for basic setup."; + if (config_from_environment) { + _configured = initStorage(db_backend, db_connectionProperties, environment, config_from_environment, true); + initAuthenticator(auth_authenticator, auth_properties, environment, config_from_environment, true); - if (!cs.isWritable()) { - qWarning() << "Cannot write quasselcore configuration; probably a permission problem."; - exit(EXIT_FAILURE); - } + if (!_configured) { + qWarning() << "Cannot configure from environment"; + exit(EXIT_FAILURE); + } + } else { + if (_registeredStorageBackends.empty()) { + quWarning() << qPrintable(tr("Could not initialize any storage backend! Exiting...")); + quWarning() + << qPrintable(tr("Currently, Quassel supports SQLite3 and PostgreSQL. You need to build your\n" + "Qt library with the sqlite or postgres plugin enabled in order for quasselcore\n" + "to work.")); + exit(EXIT_FAILURE); // TODO make this less brutal (especially for mono client -> popup) + } + quWarning() << "Core is currently not configured! Please connect with a Quassel Client for basic setup."; + if (writeError) { + qWarning() << "Cannot write quasselcore configuration; probably a permission problem."; + exit(EXIT_FAILURE); + } + } } if (Quassel::isOptionSet("add-user")) { @@ -236,8 +196,14 @@ void Core::init() connect(&_v6server, SIGNAL(newConnection()), this, SLOT(incomingConnection())); if (!startListening()) exit(1); // TODO make this less brutal - if (Quassel::isOptionSet("oidentd")) + _strictIdentEnabled = Quassel::isOptionSet("strict-ident"); + if (_strictIdentEnabled) { + cacheSysIdent(); + } + + if (Quassel::isOptionSet("oidentd")) { _oidentdConfigGenerator = new OidentdConfigGenerator(this); + } } @@ -255,14 +221,10 @@ Core::~Core() void Core::saveState() { - CoreSettings s; - QVariantMap state; QVariantList activeSessions; foreach(UserId user, instance()->_sessions.keys()) activeSessions << QVariant::fromValue(user); - state["CoreStateVersion"] = 1; - state["ActiveSessions"] = activeSessions; - s.setCoreState(state); + instance()->_storage->setCoreState(activeSessions); } @@ -285,7 +247,9 @@ void Core::restoreState() } */ - QVariantList activeSessions = s.coreState().toMap()["ActiveSessions"].toList(); + const QList &activeSessionsFallback = s.coreState().toMap()["ActiveSessions"].toList(); + QVariantList activeSessions = instance()->_storage->getCoreState(activeSessionsFallback); + if (activeSessions.count() > 0) { quInfo() << "Restoring previous core state..."; foreach(QVariant v, activeSessions) { @@ -312,12 +276,12 @@ QString Core::setupCore(const QString &adminUser, const QString &adminPassword, if (adminUser.isEmpty() || adminPassword.isEmpty()) { return tr("Admin user or password not set."); } - if (!(_configured = initStorage(backend, setupData, true))) { + if (!(_configured = initStorage(backend, setupData, {}, false, true))) { return tr("Could not setup storage!"); } quInfo() << "Selected authenticator:" << authenticator; - if (!(_configured = initAuthenticator(authenticator, authSetupData, true))) + if (!(_configured = initAuthenticator(authenticator, authSetupData, {}, false, true))) { return tr("Could not setup authenticator!"); } @@ -329,6 +293,7 @@ QString Core::setupCore(const QString &adminUser, const QString &adminPassword, quInfo() << qPrintable(tr("Creating admin user...")); _storage->addUser(adminUser, adminPassword); + cacheSysIdent(); startListening(); // TODO check when we need this return QString(); } @@ -338,7 +303,7 @@ QString Core::setupCoreForInternalUsage() { Q_ASSERT(!_registeredStorageBackends.empty()); - qsrand(QDateTime::currentDateTime().toTime_t()); + qsrand(QDateTime::currentDateTime().toMSecsSinceEpoch()); int pass = 0; for (int i = 0; i < 10; i++) { pass *= 10; @@ -383,7 +348,8 @@ DeferredSharedPtr Core::storageBackend(const QString &backendId) const // old db settings: // "Type" => "sqlite" -bool Core::initStorage(const QString &backend, const QVariantMap &settings, bool setup) +bool Core::initStorage(const QString &backend, const QVariantMap &settings, + const QProcessEnvironment &environment, bool loadFromEnvironment, bool setup) { if (backend.isEmpty()) { quWarning() << "No storage backend selected!"; @@ -396,17 +362,22 @@ bool Core::initStorage(const QString &backend, const QVariantMap &settings, bool return false; } - Storage::State storageState = storage->init(settings); + Storage::State storageState = storage->init(settings, environment, loadFromEnvironment); switch (storageState) { case Storage::NeedsSetup: if (!setup) return false; // trigger setup process - if (storage->setup(settings)) - return initStorage(backend, settings, false); + if (storage->setup(settings, environment, loadFromEnvironment)) + return initStorage(backend, settings, environment, loadFromEnvironment, false); + return false; + // if initialization wasn't successful, we quit to keep from coming up unconfigured case Storage::NotAvailable: qCritical() << "FATAL: Selected storage backend is not available:" << backend; - exit(EXIT_FAILURE); + if (!setup) + exit(EXIT_FAILURE); + return false; + case Storage::IsReady: // delete all other backends _registeredStorageBackends.clear(); @@ -475,7 +446,9 @@ DeferredSharedPtr Core::authenticator(const QString &backendId) c // FIXME: Apparently, this is the legacy way of initting storage backends? // If there's a not-legacy way, it should be used here -bool Core::initAuthenticator(const QString &backend, const QVariantMap &settings, bool setup) +bool Core::initAuthenticator(const QString &backend, const QVariantMap &settings, + const QProcessEnvironment &environment, bool loadFromEnvironment, + bool setup) { if (backend.isEmpty()) { quWarning() << "No authenticator selected!"; @@ -488,17 +461,22 @@ bool Core::initAuthenticator(const QString &backend, const QVariantMap &settings return false; } - Authenticator::State authState = auth->init(settings); + Authenticator::State authState = auth->init(settings, environment, loadFromEnvironment); switch (authState) { case Authenticator::NeedsSetup: if (!setup) return false; // trigger setup process - if (auth->setup(settings)) - return initAuthenticator(backend, settings, false); + if (auth->setup(settings, environment, loadFromEnvironment)) + return initAuthenticator(backend, settings, environment, loadFromEnvironment, false); + return false; + // if initialization wasn't successful, we quit to keep from coming up unconfigured case Authenticator::NotAvailable: qCritical() << "FATAL: Selected auth backend is not available:" << backend; - exit(EXIT_FAILURE); + if (!setup) + exit(EXIT_FAILURE); + return false; + case Authenticator::IsReady: // delete all other backends _registeredAuthenticators.clear(); @@ -539,6 +517,34 @@ bool Core::reloadCerts() } +void Core::cacheSysIdent() +{ + if (isConfigured()) { + instance()->_authUserNames = instance()->_storage->getAllAuthUserNames(); + } +} + + +QString Core::strictSysIdent(UserId user) const +{ + if (_authUserNames.contains(user)) { + return _authUserNames[user]; + } + + // A new user got added since we last pulled our cache from the database. + // There's no way to avoid a database hit - we don't even know the authname! + cacheSysIdent(); + + if (_authUserNames.contains(user)) { + return _authUserNames[user]; + } + + // ...something very weird is going on if we ended up here (an active CoreSession without a corresponding database entry?) + qWarning().nospace() << "Unable to find authusername for UserId " << user << ", this should never happen!"; + return "unknown"; // Should we just terminate the program instead? +} + + bool Core::startListening() { // in mono mode we only start a local port if a port is specified in the cli call @@ -746,7 +752,7 @@ SessionThread *Core::sessionForUser(UserId uid, bool restore) if (_sessions.contains(uid)) return _sessions[uid]; - SessionThread *session = new SessionThread(uid, restore, this); + SessionThread *session = new SessionThread(uid, restore, strictIdentEnabled(), this); _sessions[uid] = session; session->start(); return session; @@ -862,7 +868,7 @@ bool Core::selectBackend(const QString &backend) qDebug() << qPrintable(tr("Migrating storage backend %1 to %2...").arg(_storage->displayName(), storage->displayName())); _storage.reset(); storage.reset(); - if (reader->migrateTo(writer)) { + if (reader->migrateTo(writer.get())) { qDebug() << "Migration finished!"; qDebug() << qPrintable(tr("Migration finished!")); if (!saveBackendSettings(backend, settings)) {