|
signon
8.40
|
00001 /* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 00002 /* 00003 * This file is part of signon 00004 * 00005 * Copyright (C) 2011 Canonical Ltd. 00006 * 00007 * Contact: Alberto Mardegan <alberto.mardegan@canonical.com> 00008 * 00009 * This library is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public License 00011 * version 2.1 as published by the Free Software Foundation. 00012 * 00013 * This library is distributed in the hope that it will be useful, but 00014 * WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 00021 * 02110-1301 USA 00022 */ 00023 00024 #include "default-secrets-storage.h" 00025 #include "signond-common.h" 00026 00027 #define RETURN_IF_NOT_OPEN(retval) \ 00028 if (!isOpen()) { \ 00029 TRACE() << "Secrets DB is not available"; \ 00030 SignOn::CredentialsDBError error(QLatin1String("Not open"), \ 00031 SignOn::CredentialsDBError::NotOpen); \ 00032 setLastError(error); return retval; \ 00033 } 00034 00035 #define S(s) QLatin1String(s) 00036 00037 using namespace SignonDaemonNS; 00038 00039 bool SecretsDB::createTables() 00040 { 00041 QStringList createTableQuery = QStringList() 00042 << QString::fromLatin1( 00043 "CREATE TABLE CREDENTIALS" 00044 "(id INTEGER NOT NULL UNIQUE," 00045 "username TEXT," 00046 "password TEXT," 00047 "PRIMARY KEY (id))") 00048 << QString::fromLatin1( 00049 "CREATE TABLE STORE" 00050 "(identity_id INTEGER," 00051 "method_id INTEGER," 00052 "key TEXT," 00053 "value BLOB," 00054 "PRIMARY KEY (identity_id, method_id, key))") 00055 00056 << QString::fromLatin1( 00057 // Cascading Delete 00058 "CREATE TRIGGER tg_delete_credentials " 00059 "BEFORE DELETE ON CREDENTIALS " 00060 "FOR EACH ROW BEGIN " 00061 " DELETE FROM STORE WHERE STORE.identity_id = OLD.id; " 00062 "END; " 00063 ); 00064 00065 foreach (QString createTable, createTableQuery) { 00066 QSqlQuery query = exec(createTable); 00067 if (lastError().isValid()) { 00068 TRACE() << "Error occurred while creating the database."; 00069 return false; 00070 } 00071 query.clear(); 00072 commit(); 00073 } 00074 return true; 00075 } 00076 00077 bool SecretsDB::clear() 00078 { 00079 TRACE(); 00080 00081 QStringList clearCommands = QStringList() 00082 << QLatin1String("DELETE FROM CREDENTIALS") 00083 << QLatin1String("DELETE FROM STORE"); 00084 00085 return transactionalExec(clearCommands); 00086 } 00087 00088 bool SecretsDB::updateCredentials(const quint32 id, 00089 const QString &username, 00090 const QString &password) 00091 { 00092 if (!startTransaction()) { 00093 TRACE() << "Could not start transaction. Error inserting credentials."; 00094 return false; 00095 } 00096 QSqlQuery query = newQuery(); 00097 00098 TRACE() << "INSERT:" << id; 00099 query.prepare(S("INSERT OR REPLACE INTO CREDENTIALS " 00100 "(id, username, password) " 00101 "VALUES(:id, :username, :password)")); 00102 00103 query.bindValue(S(":id"), id); 00104 query.bindValue(S(":username"), username); 00105 query.bindValue(S(":password"), password); 00106 00107 exec(query); 00108 00109 if (errorOccurred()) { 00110 rollback(); 00111 TRACE() << "Error occurred while storing crendentials"; 00112 return false; 00113 } 00114 return commit(); 00115 } 00116 00117 bool SecretsDB::removeCredentials(const quint32 id) 00118 { 00119 TRACE(); 00120 00121 QStringList queries = QStringList() 00122 << QString::fromLatin1( 00123 "DELETE FROM CREDENTIALS WHERE id = %1").arg(id) 00124 << QString::fromLatin1( 00125 "DELETE FROM STORE WHERE identity_id = %1").arg(id); 00126 00127 return transactionalExec(queries); 00128 } 00129 00130 bool SecretsDB::loadCredentials(const quint32 id, 00131 QString &username, 00132 QString &password) 00133 { 00134 TRACE(); 00135 00136 QString queryStr = 00137 QString::fromLatin1("SELECT username, password FROM credentials " 00138 "WHERE id = %1").arg(id); 00139 QSqlQuery query = exec(queryStr); 00140 if (!query.first()) { 00141 TRACE() << "No result or invalid credentials query."; 00142 return false; 00143 } 00144 00145 username = query.value(0).toString(); 00146 password = query.value(1).toString(); 00147 return true; 00148 } 00149 00150 QVariantMap SecretsDB::loadData(quint32 id, quint32 method) 00151 { 00152 TRACE(); 00153 00154 QSqlQuery q = newQuery(); 00155 q.prepare(S("SELECT key, value " 00156 "FROM STORE WHERE identity_id = :id AND method_id = :method")); 00157 q.bindValue(S(":id"), id); 00158 q.bindValue(S(":method"), method); 00159 exec(q); 00160 if (errorOccurred()) 00161 return QVariantMap(); 00162 00163 QVariantMap result; 00164 while (q.next()) { 00165 QByteArray array; 00166 array = q.value(1).toByteArray(); 00167 QDataStream stream(array); 00168 QVariant data; 00169 stream >> data; 00170 result.insert(q.value(0).toString(), data); 00171 } 00172 return result; 00173 } 00174 00175 bool SecretsDB::storeData(quint32 id, quint32 method, const QVariantMap &data) 00176 { 00177 TRACE(); 00178 00179 if (!startTransaction()) { 00180 TRACE() << "Could not start transaction. Error inserting data."; 00181 return false; 00182 } 00183 00184 bool allOk = true; 00185 qint32 dataCounter = 0; 00186 if (!(data.keys().empty())) { 00187 QMapIterator<QString, QVariant> it(data); 00188 while (it.hasNext()) { 00189 it.next(); 00190 00191 QByteArray array; 00192 QDataStream stream(&array, QIODevice::WriteOnly); 00193 stream << it.value(); 00194 00195 dataCounter += it.key().size() +array.size(); 00196 if (dataCounter >= SSO_MAX_TOKEN_STORAGE) { 00197 BLAME() << "storing data max size exceeded"; 00198 allOk = false; 00199 break; 00200 } 00201 /* Key/value insert/replace/delete */ 00202 QSqlQuery query = newQuery(); 00203 if (it.value().isValid() && !it.value().isNull()) { 00204 TRACE() << "insert"; 00205 query.prepare(S( 00206 "INSERT OR REPLACE INTO STORE " 00207 "(identity_id, method_id, key, value) " 00208 "VALUES(:id, :method, :key, :value)")); 00209 query.bindValue(S(":value"), array); 00210 } else { 00211 TRACE() << "remove"; 00212 query.prepare(S( 00213 "DELETE FROM STORE WHERE identity_id = :id " 00214 "AND method_id = :method " 00215 "AND key = :key")); 00216 00217 } 00218 query.bindValue(S(":id"), id); 00219 query.bindValue(S(":method"), method); 00220 query.bindValue(S(":key"), it.key()); 00221 exec(query); 00222 if (errorOccurred()) { 00223 allOk = false; 00224 break; 00225 } 00226 } 00227 } 00228 00229 if (allOk && commit()) { 00230 TRACE() << "Data insertion ok."; 00231 return true; 00232 } 00233 rollback(); 00234 TRACE() << "Data insertion failed."; 00235 return false; 00236 } 00237 00238 bool SecretsDB::removeData(quint32 id, quint32 method) 00239 { 00240 TRACE(); 00241 00242 if (!startTransaction()) { 00243 TRACE() << "Could not start transaction. Error removing data."; 00244 return false; 00245 } 00246 00247 QSqlQuery q = newQuery(); 00248 if (method == 0) { 00249 q.prepare(S("DELETE FROM STORE WHERE identity_id = :id")); 00250 } else { 00251 q.prepare(S("DELETE FROM STORE WHERE identity_id = :id " 00252 "AND method_id = :method")); 00253 q.bindValue(S(":method"), method); 00254 } 00255 q.bindValue(S(":id"), id); 00256 exec(q); 00257 if (!errorOccurred() && commit()) { 00258 TRACE() << "Data removal ok."; 00259 return true; 00260 } else { 00261 rollback(); 00262 TRACE() << "Data removal failed."; 00263 return false; 00264 } 00265 } 00266 00267 DefaultSecretsStorage::DefaultSecretsStorage(QObject *parent): 00268 AbstractSecretsStorage(parent) 00269 { 00270 } 00271 00272 DefaultSecretsStorage::~DefaultSecretsStorage() 00273 { 00274 close(); 00275 } 00276 00277 bool DefaultSecretsStorage::initialize(const QVariantMap &configuration) 00278 { 00279 if (isOpen()) { 00280 TRACE() << "Initializing open DB; closing first..."; 00281 close(); 00282 } 00283 00284 QString name = configuration.value(QLatin1String("name")).toString(); 00285 00286 m_secretsDB = new SecretsDB(name); 00287 if (!m_secretsDB->init()) { 00288 setLastError(m_secretsDB->lastError()); 00289 delete m_secretsDB; 00290 m_secretsDB = 0; 00291 return false; 00292 } 00293 00294 setIsOpen(true); 00295 return true; 00296 } 00297 00298 bool DefaultSecretsStorage::close() 00299 { 00300 if (m_secretsDB != 0) { 00301 QString connectionName = m_secretsDB->connectionName(); 00302 delete m_secretsDB; 00303 QSqlDatabase::removeDatabase(connectionName); 00304 m_secretsDB = 0; 00305 } 00306 return AbstractSecretsStorage::close(); 00307 } 00308 00309 bool DefaultSecretsStorage::clear() 00310 { 00311 RETURN_IF_NOT_OPEN(false); 00312 00313 return m_secretsDB->clear(); 00314 } 00315 00316 bool DefaultSecretsStorage::updateCredentials(const quint32 id, 00317 const QString &username, 00318 const QString &password) 00319 { 00320 RETURN_IF_NOT_OPEN(false); 00321 00322 return m_secretsDB->updateCredentials(id, username, password); 00323 } 00324 00325 bool DefaultSecretsStorage::removeCredentials(const quint32 id) 00326 { 00327 RETURN_IF_NOT_OPEN(false); 00328 00329 return m_secretsDB->removeCredentials(id); 00330 } 00331 00332 bool DefaultSecretsStorage::loadCredentials(const quint32 id, 00333 QString &username, 00334 QString &password) 00335 { 00336 RETURN_IF_NOT_OPEN(false); 00337 00338 return m_secretsDB->loadCredentials(id, username, password); 00339 } 00340 00341 QVariantMap DefaultSecretsStorage::loadData(quint32 id, quint32 method) 00342 { 00343 RETURN_IF_NOT_OPEN(QVariantMap()); 00344 00345 return m_secretsDB->loadData(id, method); 00346 } 00347 00348 bool DefaultSecretsStorage::storeData(quint32 id, quint32 method, 00349 const QVariantMap &data) 00350 { 00351 RETURN_IF_NOT_OPEN(false); 00352 00353 return m_secretsDB->storeData(id, method, data); 00354 } 00355 00356 bool DefaultSecretsStorage::removeData(quint32 id, quint32 method) 00357 { 00358 RETURN_IF_NOT_OPEN(false); 00359 00360 return m_secretsDB->removeData(id, method); 00361 }