~ci-train-bot/indicator-network/indicator-network-ubuntu-xenial-landing-067

« back to all changes in this revision

Viewing changes to src/agent/KeyringCredentialStore.cpp

  • Committer: CI Train Bot
  • Author(s): Pete Woods
  • Date: 2016-02-23 09:15:50 UTC
  • mfrom: (564.1.7 trunk)
  • Revision ID: ci-train-bot@canonical.com-20160223091550-ldfalmmskjojc4t7
Add keyring support to secret agent (requires libsecret) Fixes: #1546560

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2016 Canonical, Ltd.
 
3
 *
 
4
 * This program is free software: you can redistribute it and/or modify it
 
5
 * under the terms of the GNU General Public License version 3, as published
 
6
 * by the Free Software Foundation.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful, but
 
9
 * WITHOUT ANY WARRANTY; without even the implied warranties of
 
10
 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
 
11
 * PURPOSE.  See the GNU General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License along
 
14
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 
15
 *
 
16
 * Author: Pete Woods <pete.woods@canonical.com>
 
17
 */
 
18
 
 
19
#include <agent/KeyringCredentialStore.h>
 
20
 
 
21
#include <libsecret/secret.h>
 
22
#include <QDebug>
 
23
 
 
24
#define KEYRING_UUID_TAG "connection-uuid"
 
25
#define KEYRING_SN_TAG "setting-name"
 
26
#define KEYRING_SK_TAG "setting-key"
 
27
 
 
28
static const SecretSchema network_manager_secret_schema = {
 
29
        "org.freedesktop.NetworkManager.Connection",
 
30
        SECRET_SCHEMA_DONT_MATCH_NAME,
 
31
        {
 
32
                {KEYRING_UUID_TAG, SECRET_SCHEMA_ATTRIBUTE_STRING},
 
33
                {KEYRING_SN_TAG, SECRET_SCHEMA_ATTRIBUTE_STRING},
 
34
                {KEYRING_SK_TAG, SECRET_SCHEMA_ATTRIBUTE_STRING},
 
35
                {NULL, (SecretSchemaAttributeType) 0},
 
36
        },
 
37
        // The below junk prevents compilation warnings for
 
38
        // the uninitialised reserved values
 
39
        0,
 
40
        (gpointer) 0,
 
41
        (gpointer) 0,
 
42
        (gpointer) 0,
 
43
        (gpointer) 0,
 
44
        (gpointer) 0,
 
45
        (gpointer) 0,
 
46
        (gpointer) 0
 
47
};
 
48
 
 
49
using namespace std;
 
50
 
 
51
namespace agent {
 
52
 
 
53
KeyringCredentialStore::KeyringCredentialStore() {
 
54
}
 
55
 
 
56
KeyringCredentialStore::~KeyringCredentialStore() {
 
57
}
 
58
 
 
59
void KeyringCredentialStore::save(const QString& uuid,
 
60
                const QString& settingName, const QString& settingKey,
 
61
                const QString& displayName, const QString& secret) {
 
62
        shared_ptr<GHashTable> attrs(
 
63
                        secret_attributes_build(&network_manager_secret_schema,
 
64
                        KEYRING_UUID_TAG, uuid.toUtf8().constData(),
 
65
                        KEYRING_SN_TAG, settingName.toUtf8().constData(),
 
66
                        KEYRING_SK_TAG, settingKey.toUtf8().constData(),
 
67
                        NULL), &g_hash_table_unref);
 
68
 
 
69
        GError* error = NULL;
 
70
        if (!secret_password_storev_sync(&network_manager_secret_schema,
 
71
                        attrs.get(),
 
72
                        NULL,
 
73
                        displayName.toUtf8().constData(),
 
74
                        secret.toUtf8().constData(),
 
75
                        NULL, &error)) {
 
76
                QString message;
 
77
                if (error != NULL) {
 
78
                        if (error->message) {
 
79
                                message = QString::fromUtf8(error->message);
 
80
                        }
 
81
                        g_error_free(error);
 
82
                }
 
83
                qCritical() << __PRETTY_FUNCTION__ << message;
 
84
        }
 
85
}
 
86
 
 
87
QMap<QString, QString> KeyringCredentialStore::get(const QString& uuid, const QString& settingName) {
 
88
        QMap<QString, QString> result;
 
89
 
 
90
        shared_ptr<GHashTable> attrs(secret_attributes_build(
 
91
                                        &network_manager_secret_schema,
 
92
                                        KEYRING_UUID_TAG, uuid.toUtf8().constData(),
 
93
                                        KEYRING_SN_TAG, settingName.toUtf8().constData(),
 
94
                                        NULL), &g_hash_table_unref);
 
95
 
 
96
        GError* error = NULL;
 
97
        shared_ptr<GList> list(secret_service_search_sync(NULL,
 
98
                        &network_manager_secret_schema, attrs.get(),
 
99
                        (SecretSearchFlags) (SECRET_SEARCH_ALL | SECRET_SEARCH_UNLOCK
 
100
                                        | SECRET_SEARCH_LOAD_SECRETS), NULL, &error), [](GList* list) {
 
101
                g_list_free_full (list, g_object_unref);
 
102
        });
 
103
 
 
104
        if (list == NULL) {
 
105
                if (error != NULL) {
 
106
                        string errorMessage;
 
107
                        if (error->message) {
 
108
                                errorMessage = error->message;
 
109
                        }
 
110
                        g_error_free(error);
 
111
                        throw domain_error(errorMessage);
 
112
                }
 
113
 
 
114
                return result;
 
115
        }
 
116
 
 
117
        for (GList* iter = list.get(); iter != NULL; iter = g_list_next(iter)) {
 
118
                SecretItem *item = (SecretItem *) iter->data;
 
119
                shared_ptr<SecretValue> secret(secret_item_get_secret(item), &secret_value_unref);
 
120
                if (secret) {
 
121
                        shared_ptr<GHashTable> attributes(secret_item_get_attributes(item), &g_hash_table_unref);
 
122
                        const char *keyName = (const char *) g_hash_table_lookup(attributes.get(),
 
123
                                        KEYRING_SK_TAG);
 
124
                        if (!keyName) {
 
125
                                continue;
 
126
                        }
 
127
 
 
128
                        QString keyString = QString::fromUtf8(keyName);
 
129
                        QString secretString = QString::fromUtf8(secret_value_get(secret.get(), NULL));
 
130
 
 
131
                        result[keyString] = secretString;
 
132
                }
 
133
        }
 
134
 
 
135
        return result;
 
136
}
 
137
 
 
138
void KeyringCredentialStore::clear(const QString& uuid) {
 
139
        GError *error = NULL;
 
140
        if (!secret_password_clear_sync(&network_manager_secret_schema, NULL, &error,
 
141
                                                   KEYRING_UUID_TAG, uuid.toUtf8().constData(),
 
142
                                                   NULL)) {
 
143
                if (error != NULL) {
 
144
                        QString message;
 
145
                        if (error->message) {
 
146
                                message = QString::fromUtf8(error->message);
 
147
                        }
 
148
                        g_error_free(error);
 
149
                        qCritical() << __PRETTY_FUNCTION__ << message;
 
150
                }
 
151
        }
 
152
}
 
153
 
 
154
}