migrated passwords from blob to strings (still hashed), for easier migration between...
authorMarcus Eggenberger <egs@quassel-irc.org>
Thu, 21 Feb 2008 20:46:03 +0000 (20:46 +0000)
committerMarcus Eggenberger <egs@quassel-irc.org>
Thu, 21 Feb 2008 20:46:03 +0000 (20:46 +0000)
src/core/abstractsqlstorage.h
src/core/sqlitestorage.cpp
src/core/sqlitestorage.h
src/core/storage.cpp
src/core/storage.h
version.inc

index a85fdbb..c94bc4a 100644 (file)
@@ -35,7 +35,7 @@ public:
   virtual ~AbstractSqlStorage();
 
 protected:
-  bool init(const QVariantMap &settings = QVariantMap());
+  virtual bool init(const QVariantMap &settings = QVariantMap());
   virtual void sync();
   
   QSqlDatabase logDb();
index 7ae4f0e..81f2fa9 100644 (file)
@@ -20,7 +20,6 @@
 
 #include "sqlitestorage.h"
 
-#include <QCryptographicHash>
 #include <QtSql>
 
 #include "network.h"
@@ -62,13 +61,10 @@ int SqliteStorage::installedSchemaVersion() {
 }
 
 UserId SqliteStorage::addUser(const QString &user, const QString &password) {
-  QByteArray cryptopass = QCryptographicHash::hash(password.toUtf8(), QCryptographicHash::Sha1);
-  cryptopass = cryptopass.toHex();
-
   QSqlQuery query(logDb());
   query.prepare(queryString("insert_quasseluser"));
   query.bindValue(":username", user);
-  query.bindValue(":password", cryptopass);
+  query.bindValue(":password", cryptedPassword(password));
   query.exec();
   if(query.lastError().isValid() && query.lastError().number() == 19) { // user already exists - sadly 19 seems to be the general constraint violation error...
     return 0;
@@ -84,13 +80,10 @@ UserId SqliteStorage::addUser(const QString &user, const QString &password) {
 }
 
 void SqliteStorage::updateUser(UserId user, const QString &password) {
-  QByteArray cryptopass = QCryptographicHash::hash(password.toUtf8(), QCryptographicHash::Sha1);
-  cryptopass = cryptopass.toHex();
-
   QSqlQuery query(logDb());
   query.prepare(queryString("update_userpassword"));
   query.bindValue(":userid", user.toInt());
-  query.bindValue(":password", cryptopass);
+  query.bindValue(":password", cryptedPassword(password));
   query.exec();
 }
 
@@ -104,13 +97,10 @@ void SqliteStorage::renameUser(UserId user, const QString &newName) {
 }
 
 UserId SqliteStorage::validateUser(const QString &user, const QString &password) {
-  QByteArray cryptopass = QCryptographicHash::hash(password.toUtf8(), QCryptographicHash::Sha1);
-  cryptopass = cryptopass.toHex();
-
   QSqlQuery query(logDb());
   query.prepare(queryString("select_authuser"));
   query.bindValue(":username", user);
-  query.bindValue(":password", cryptopass);
+  query.bindValue(":password", cryptedPassword(password));
   query.exec();
 
   if(query.first()) {
@@ -664,3 +654,50 @@ QString SqliteStorage::backlogFile() {
   return quasselDir + "quassel-storage.sqlite";  
 }
 
+
+// ONLY NEEDED FOR MIGRATION
+bool SqliteStorage::init(const QVariantMap &settings) {
+  if(!AbstractSqlStorage::init(settings))
+    return false;
+
+  QSqlQuery checkMigratedQuery(logDb());
+  checkMigratedQuery.prepare("SELECT DISTINCT typeOf(password) FROM quasseluser");
+  checkMigratedQuery.exec();
+  if(!watchQuery(&checkMigratedQuery))
+    return false;
+
+  if(!checkMigratedQuery.first())
+    return false;
+
+  QString passType = checkMigratedQuery.value(0).toString().toLower();
+  if(passType == "text")
+    return true; // allready migrated
+
+  Q_ASSERT(passType == "blob");
+  
+  QSqlQuery getPasswordsQuery(logDb());
+  getPasswordsQuery.prepare("SELECT userid, password FROM quasseluser");
+  getPasswordsQuery.exec();
+
+  if(!watchQuery(&getPasswordsQuery)) {
+    qWarning() << "unable to migrate to new password format!";
+    return false;
+  }
+
+  QHash<int, QByteArray> passHash;
+  while(getPasswordsQuery.next()) {
+    passHash[getPasswordsQuery.value(0).toInt()] = getPasswordsQuery.value(1).toByteArray();
+  }
+
+  QSqlQuery setPasswordsQuery(logDb());
+  setPasswordsQuery.prepare("UPDATE quasseluser SET password = :password WHERE userid = :userid");
+  foreach(int userId, passHash.keys()) {
+    setPasswordsQuery.bindValue(":password", QString(passHash[userId]));
+    setPasswordsQuery.bindValue(":userid", userId);
+    setPasswordsQuery.exec();
+    watchQuery(&setPasswordsQuery);
+  }
+
+  qDebug() << "successfully migrated passwords!";
+  return true;
+}
index 4c133e6..944c46b 100644 (file)
@@ -77,6 +77,8 @@ protected:
   inline virtual QString driverName() { return "QSQLITE"; }
   inline virtual QString databaseName() { return backlogFile(); }
   virtual int installedSchemaVersion();
+
+  virtual bool init(const QVariantMap &settings = QVariantMap()); // only needed for migration
   
 private:
   static QString backlogFile();
index 26172c8..4bf6b30 100644 (file)
 
 #include "storage.h"
 
+#include <QCryptographicHash>
+
 Storage::Storage(QObject *parent)
   : QObject(parent)
 {
 }
+
+QString Storage::cryptedPassword(const QString &password) {
+  return QString(QCryptographicHash::hash(password.toUtf8(), QCryptographicHash::Sha1).toHex());
+}
index 2c975ca..3e8cbb1 100644 (file)
@@ -252,8 +252,11 @@ class Storage : public QObject {
     //! Sent when a user has been removed
     void userRemoved(UserId);
 
-  public:
-
+  protected:
+    //! when implementing a storage handler, use this method to crypt user passwords.
+    /**  This guarantees compatibility with other storage handlers and allows easy migration
+     */
+    QString cryptedPassword(const QString &password);
 };
 
 
index 113c435..ccd8341 100644 (file)
@@ -4,8 +4,8 @@
 { using namespace Global;
 
   quasselVersion = "0.2.0-pre";
-  quasselDate = "2008-02-20";
-  quasselBuild = 572;
+  quasselDate = "2008-02-21";
+  quasselBuild = 573;
 
   //! Minimum client build number the core needs
   clientBuildNeeded = 563;