/*!
    Finds a user by \a userName.
    Sync blocking API.

    \param userName The user name to look up.
    \return the corresponding UserAccount object.
*/
UserAccount *AccountsManager::findUserByName(const QString &userName)
{
    Q_D(AccountsManager);

    QDBusPendingReply<QDBusObjectPath> reply = d->interface->FindUserByName(userName);
    reply.waitForFinished();

    if (reply.isError()) {
        QDBusError error = reply.error();
        qWarning("Couldn't find user by user name %s: %s",
                 userName.toUtf8().constData(),
                 error.errorString(error.type()).toUtf8().constData());
        return 0;
    }

    QDBusObjectPath path = reply.argumentAt<0>();
    if (path.path().isEmpty())
        return Q_NULLPTR;

    UserAccount *account = d->usersCache.value(path.path(), Q_NULLPTR);
    if (!account) {
        account = new UserAccount(path.path(), d->interface->connection());
        d->usersCache[path.path()] = account;
    }
    return account;
}
/*!
    Cached a list of user accounts.
    Async unblocking API.
*/
void AccountsManager::listCachedUsersAsync()
{
    Q_D(AccountsManager);

    QDBusPendingCall call = d->interface->ListCachedUsers();
    QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
    connect(watcher, &QDBusPendingCallWatcher::finished, this, [=](QDBusPendingCallWatcher *w) {
        QDBusPendingReply< QList<QDBusObjectPath> > reply = *w;
        w->deleteLater();
        if (reply.isError()) {
            QDBusError error = reply.error();
            qWarning("Couldn't list cached users: %s",
                     error.errorString(error.type()).toUtf8().constData());
        } else {
            UserAccountList userList;
            QList<QDBusObjectPath> value = reply.argumentAt<0>();
            userList.reserve(value.size());
            for (int i = 0; i < value.size(); i++) {
                const QString path = value.at(i).path();
                UserAccount *account = d->usersCache.value(path, Q_NULLPTR);
                if (!account) {
                    account = new UserAccount(path, d->interface->connection());
                    d->usersCache[path] = account;
                }
                userList.append(account);
            }
            Q_EMIT listCachedUsersFinished(userList);
        }
    });
}
/*!
    Returns a list of user accounts.

    \param systemUsers If true, returns also system users.
*/
UserAccountList AccountsManager::listCachedUsers()
{
    Q_D(AccountsManager);

    UserAccountList list;

    QDBusPendingReply< QList<QDBusObjectPath> > reply = d->interface->ListCachedUsers();
    reply.waitForFinished();

    if (reply.isError()) {
        QDBusError error = reply.error();
        qWarning("Couldn't list cached users: %s",
                 error.errorString(error.type()).toUtf8().constData());
        return list;
    }

    QList<QDBusObjectPath> value = reply.argumentAt<0>();
    list.reserve(value.size());

    for (int i = 0; i < value.size(); i++) {
        const QString path = value.at(i).path();
        UserAccount *account = d->usersCache.value(path, Q_NULLPTR);
        if (!account) {
            account = new UserAccount(path, d->interface->connection());
            d->usersCache[path] = account;
        }
        list.append(account);
    }

    return list;
}
/*!
    Caches a user account, so that it shows up in listCachedUsers() output.
    The user name may be a remote user, but the system must be able to lookup
    the user name and resolve the user information.

    A userCached() signal with a UserAccount pointer will be emitted as soon
    as the user account has been cached by AccountsService.

    \param userName The user name for the user.
*/
void AccountsManager::cacheUser(const QString &userName)
{
    Q_D(AccountsManager);

    QDBusPendingCall call = d->interface->CacheUser(userName);
    QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
    connect(watcher, &QDBusPendingCallWatcher::finished, this, [=](QDBusPendingCallWatcher *w) {
        QDBusPendingReply<QDBusObjectPath> reply = *w;
        w->deleteLater();
        if (reply.isError()) {
            QDBusError error = reply.error();
            qWarning("Couldn't cache user %s: %s",
                     userName.toUtf8().constData(),
                     error.errorString(error.type()).toUtf8().constData());
        } else {
            QDBusObjectPath path = reply.argumentAt<0>();
            if (path.path().isEmpty())
                return;

            UserAccount *account = d->usersCache.value(path.path(), Q_NULLPTR);
            if (!account) {
                account = new UserAccount(path.path(), d->interface->connection());
                d->usersCache[path.path()] = account;
            }
            Q_EMIT userCached(account);
        }
    });
}
Esempio n. 5
0
QScriptValue qDBusErrorToScriptValue(QScriptEngine *engine, const QDBusError &error)
{
    QScriptValue v = engine->newObject();
    v.setProperty(QLatin1String("type"), QScriptValue(engine, error.type()), QScriptValue::ReadOnly);
    v.setProperty(QLatin1String("name"), QScriptValue(engine, error.name()), QScriptValue::ReadOnly);
    v.setProperty(QLatin1String("message"), QScriptValue(engine, error.message()), QScriptValue::ReadOnly);
    v.setProperty(QLatin1String("isValid"), QScriptValue(engine, error.isValid()), QScriptValue::ReadOnly);
    return v;
}
/*!
    Deletes the user designated by \a uid.

    \param uid The user identifier.
    \param removeFiles If true all files owned by the user will be removed.
    \return whether the user was deleted successfully.
*/
bool AccountsManager::deleteUser(uid_t uid, bool removeFiles)
{
    Q_D(AccountsManager);

    QDBusPendingReply<> reply = d->interface->DeleteUser(uid, removeFiles);
    if (reply.isError()) {
        QDBusError error = reply.error();
        qWarning("Couldn't delete user %d: %s", uid,
                 error.errorString(error.type()).toUtf8().constData());
        return false;
    }

    return true;
}
/*!
    Creates a new \a accountType type user account whose name is \a userName,
    real name is \a fullName.

    \param userName The name of the new user to be created.
    \param fullName First name and last name.
    \param accountType The account type.
    \return whether the user was created successfully.
*/
bool AccountsManager::createUser(const QString &userName,
                                 const QString &fullName,
                                 UserAccount::AccountType accountType)
{
    Q_D(AccountsManager);

    QDBusPendingReply<QDBusObjectPath> reply = d->interface->CreateUser(userName, fullName, accountType);
    if (reply.isError()) {
        QDBusError error = reply.error();
        qWarning("Couldn't create user %s: %s", userName.toUtf8().constData(),
                 error.errorString(error.type()).toUtf8().constData());
        return false;
    }

    return true;
}
Esempio n. 8
0
ConnectionManager::SocketConnectionStatus
ConnectionManager::setupSocketConnection()
{
    QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
    QLatin1String one("1");
    if (environment.value(QLatin1String("SSO_USE_PEER_BUS"), one) != one) {
        return SocketConnectionUnavailable;
    }

#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
    QString runtimeDir =
        QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
#else
    QString runtimeDir = environment.value(QLatin1String("XDG_RUNTIME_DIR"));
#endif
    if (runtimeDir.isEmpty()) return SocketConnectionUnavailable;

    QString socketFileName =
        QString::fromLatin1("unix:path=%1/" SIGNOND_SOCKET_FILENAME).arg(runtimeDir);
    static int count = 0;

    QDBusConnection connection =
        QDBusConnection::connectToPeer(socketFileName,
                                       QString(QLatin1String("libsignon-qt%1")).arg(count++));
    if (!connection.isConnected()) {
        QDBusError error = connection.lastError();
        QString name = error.name();
        BLAME() << "p2p error:" << error << error.type();
        if (name == QLatin1String("org.freedesktop.DBus.Error.FileNotFound") &&
            m_serviceStatus != ServiceActivated) {
            return SocketConnectionNoService;
        } else {
            return SocketConnectionUnavailable;
        }
    }

    m_connection = connection;
    m_connection.connect(QString(),
                         QLatin1String("/org/freedesktop/DBus/Local"),
                         QLatin1String("org.freedesktop.DBus.Local"),
                         QLatin1String("Disconnected"),
                         this, SLOT(onDisconnected()));

    return SocketConnectionOk;
}
/*!
    Finds a user by user \a userName
    Async unblocking API

    \param userName The user name to look up.
*/
void AccountsManager::findUserByNameAsync(const QString &userName)
{
    Q_D(AccountsManager);

    QDBusPendingCall call = d->interface->FindUserByName(userName);
    QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
    connect(watcher, &QDBusPendingCallWatcher::finished, this, [=](QDBusPendingCallWatcher *w) {
        QDBusPendingReply<QDBusObjectPath> reply = *w;
        w->deleteLater();
        if (reply.isError()) {
            QDBusError error = reply.error();
            qWarning("Couldn't find user by name %s: %s",
                     userName.toUtf8().constData(),
                     error.errorString(error.type()).toUtf8().constData());
        } else {
            QDBusObjectPath path = reply.argumentAt<0>();
            if (!path.path().isEmpty())
                Q_EMIT userFound(new UserAccount(path.path(), d->interface->connection()));
        }
    });
}
Esempio n. 10
0
void ReadPasswordJobPrivate::kwalletOpenFinished( QDBusPendingCallWatcher* watcher ) {
    watcher->deleteLater();
    const QDBusPendingReply<int> reply = *watcher;

    std::auto_ptr<QSettings> local( !q->settings() ? new QSettings( q->service() ) : 0 );
    QSettings* actual = q->settings() ? q->settings() : local.get();
    WritePasswordJobPrivate::Mode mode;

    const QString typeKey = QString( "%1/type" ).arg( key );
    const QString dataKey = QString( "%1/data" ).arg( key );
    if ( reply.isError() ) {
        const QDBusError err = reply.error();

        if ( q->insecureFallback() && actual->contains( dataKey ) ) {

            mode = (WritePasswordJobPrivate::Mode)actual->value( typeKey ).toInt();
            data = actual->value( dataKey ).toByteArray();

            q->emitFinished();

            return;
        } else {
            if ( err.type() == QDBusError::ServiceUnknown ) //KWalletd not running
                q->emitFinishedWithError( NoBackendAvailable, tr("No keychain service available") );
            else
                q->emitFinishedWithError( OtherError, tr("Could not open wallet: %1; %2").arg( QDBusError::errorString( err.type() ), err.message() ) );

            return;
        }
    }

    if ( actual->contains( dataKey ) ) {
        // We previously stored data in the insecure QSettings, but now have KWallet available.
        // Do the migration

        data = actual->value( dataKey ).toByteArray();
        mode = (WritePasswordJobPrivate::Mode)actual->value( typeKey ).toInt();
        actual->remove( key );

        q->emitFinished();


        WritePasswordJob* j = new WritePasswordJob( q->service(), 0 );
        j->setSettings( q->settings() );
        j->setKey( key );
        j->setAutoDelete( true );
        if ( mode == WritePasswordJobPrivate::Binary )
            j->setBinaryData( data );
        else if ( mode == WritePasswordJobPrivate::Text )
            j->setTextData( QString::fromUtf8( data ) );
        else
            Q_ASSERT( false );

        j->start();

        return;
    }

    walletHandle = reply.value();

    if ( walletHandle < 0 ) {
        q->emitFinishedWithError( AccessDenied, tr("Access to keychain denied") );
        return;
    }

    const QDBusPendingReply<int> nextReply = iface->entryType( walletHandle, q->service(), key, q->service() );
    QDBusPendingCallWatcher* nextWatcher = new QDBusPendingCallWatcher( nextReply, this );
    connect( nextWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletEntryTypeFinished(QDBusPendingCallWatcher*)) );
}
Esempio n. 11
0
void WritePasswordJobPrivate::kwalletWriteFinished( QDBusPendingCallWatcher* watcher ) {
    watcher->deleteLater();
    QDBusPendingReply<int> reply = *watcher;
    if ( reply.isError() ) {
        const QDBusError err = reply.error();
        q->emitFinishedWithError( OtherError, tr("Could not open wallet: %1; %2").arg( QDBusError::errorString( err.type() ), err.message() ) );
        return;
    }

    q->emitFinished();
}
Esempio n. 12
0
void WritePasswordJobPrivate::kwalletOpenFinished( QDBusPendingCallWatcher* watcher ) {
    watcher->deleteLater();
    QDBusPendingReply<int> reply = *watcher;

    std::auto_ptr<QSettings> local( !q->settings() ? new QSettings(  q->service() ) : 0 );
    QSettings* actual = q->settings() ? q->settings() : local.get();

    if ( reply.isError() ) {
        if ( q->insecureFallback() ) {
            if ( mode == Delete ) {
                actual->remove( key );
                actual->sync();

                q->emitFinished();
                return;
            }

            actual->setValue( QString( "%1/type" ).arg( key ), (int)mode );
            if ( mode == Text )
                actual->setValue( QString( "%1/data" ).arg( key ), textData.toUtf8() );
            else if ( mode == Binary )
                actual->setValue( QString( "%1/data" ).arg( key ), binaryData );
            actual->sync();

            q->emitFinished();
        } else {
            const QDBusError err = reply.error();
            q->emitFinishedWithError( OtherError, tr("Could not open wallet: %1; %2").arg( QDBusError::errorString( err.type() ), err.message() ) );
        }
        return;
    }

    if ( actual->contains( key ) )
    {
        // If we had previously written to QSettings, but we now have a kwallet available, migrate and delete old insecure data
        actual->remove( key );
        actual->sync();
    }

    const int handle = reply.value();

    if ( handle < 0 ) {
        q->emitFinishedWithError( AccessDenied, tr("Access to keychain denied") );
        return;
    }

    QDBusPendingReply<int> nextReply;

    if ( !textData.isEmpty() )
        nextReply = iface->writePassword( handle, q->service(), key, textData, q->service() );
    else if ( !binaryData.isEmpty() )
        nextReply = iface->writeEntry( handle, q->service(), key, binaryData, q->service() );
    else
        nextReply = iface->removeEntry( handle, q->service(), key, q->service() );

    QDBusPendingCallWatcher* nextWatcher = new QDBusPendingCallWatcher( nextReply, this );
    connect( nextWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletWriteFinished(QDBusPendingCallWatcher*)) );
}
Esempio n. 13
0
void ReadPasswordJobPrivate::kwalletReadFinished( QDBusPendingCallWatcher* watcher ) {
    watcher->deleteLater();
    if ( watcher->isError() ) {
        const QDBusError err = watcher->error();
        q->emitFinishedWithError( OtherError, tr("Could not read password: %1; %2").arg( QDBusError::errorString( err.type() ), err.message() ) );
        return;
    }

    if ( dataType == Binary ) {
        QDBusPendingReply<QByteArray> reply = *watcher;
        data = reply.value();
    } else {
        QDBusPendingReply<QString> reply = *watcher;
        data = reply.value().toUtf8();
    }
    q->emitFinished();
}
Esempio n. 14
0
void ReadPasswordJobPrivate::kwalletEntryTypeFinished( QDBusPendingCallWatcher* watcher ) {
    watcher->deleteLater();
    if ( watcher->isError() ) {
        const QDBusError err = watcher->error();
        q->emitFinishedWithError( OtherError, tr("Could not determine data type: %1; %2").arg( QDBusError::errorString( err.type() ), err.message() ) );
        return;
    }

    const QDBusPendingReply<int> reply = *watcher;

    dataType = reply.value() == 1/*Password*/ ? Text : Binary;

    const QDBusPendingCall nextReply = dataType == Text
                                       ? QDBusPendingCall( iface->readPassword( walletHandle, q->service(), key, q->service() ) )
                                       : QDBusPendingCall( iface->readEntry( walletHandle, q->service(), key, q->service() ) );
    QDBusPendingCallWatcher* nextWatcher = new QDBusPendingCallWatcher( nextReply, this );
    connect( nextWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletReadFinished(QDBusPendingCallWatcher*)) );
}