changeset 25:f275d816e857

sqlickrypt.c: finish switching to parametrized queries. sqlickrypt should now be injection-resistant.
author John "Elwin" Edwards <elwin@sdf.org>
date Sun, 03 Jun 2012 18:26:11 -0700
parents 9d5da43c0e83
children 9b58f8d3ea70
files sqlickrypt.c
diffstat 1 files changed, 41 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/sqlickrypt.c	Sun Jun 03 17:08:40 2012 -0700
+++ b/sqlickrypt.c	Sun Jun 03 18:26:11 2012 -0700
@@ -9,26 +9,6 @@
 #define DATABASE "/dgldir/dgamelaunch.db"
 #define IBUFSIZE 200
 
-int xcallback(void *targ, int ncols, char **vals, char **colnames) {
-  char *pws;
-  int j;
-  pws = *((char **) targ);
-  if (pws == NULL) {
-    for (j = 0; j < ncols; j++) {
-      if (!strcmp(colnames[j], "password"))
-        *((char **) targ) = strdup(vals[j]);
-    }
-  }
-  /* Otherwise, this isn't the first row. */
-  return 0;
-}
-
-/* Simple callback, for checking if there are any matches. */
-int searchcallback(void *targ, int ncols, char **vals, char **colnames) {
-  *((int *) targ) = 1;
-  return 0;
-}
-
 int check(char *uname, char *pw) {
   char *pwhash, *comphash;
   char *query = "SELECT password FROM dglusers WHERE username=?;";
@@ -76,33 +56,55 @@
 }
 
 int insertuser(char *uname, char *pw, char *email) {
-  char finduser_sql[160];
+  char *checkquery = "SELECT * FROM dglusers WHERE username = ?;";
+  char *addquery =  "INSERT INTO dglusers (username, password, email) VALUES (?, ?, ?);";
   int status;
   sqlite3 *db;
-
-  strcpy(finduser_sql, "BEGIN; SELECT * FROM dglusers WHERE username='");
-  strncat(finduser_sql, uname, 40);
-  strcat(finduser_sql, "';");
+  sqlite3_stmt *qstmt;
 
   status = sqlite3_open(DATABASE, &db);
   if (status) {
     sqlite3_close(db);
-    return 1;
+    return 3;
+  }
+  /* Check for existing account in the same transaction with creating it. */
+  status = sqlite3_exec(db, "BEGIN;", NULL, NULL, NULL);
+  if (status) {
+    sqlite3_close(db);
+    return 3;
+  }
+  sqlite3_prepare_v2(db, checkquery, -1, &qstmt, NULL);
+  if (qstmt == NULL) {
+    sqlite3_close(db);
+    return 3;
   }
-  status = 0;
-  sqlite3_exec(db, finduser_sql, searchcallback, (void *) &status, NULL);
-  if (!status) {
-    /* FIXME This is ugly, and email is unsanitzed. */
-    strcpy(finduser_sql, "INSERT INTO dglusers (username, password, email) VALUES ('");
-    strncat(finduser_sql, uname, 20);
-    strcat(finduser_sql, "', '");
-    strcat(finduser_sql, crypt(pw, pw));
-    strcat(finduser_sql, "', '");
-    strncat(finduser_sql, email, 40);
-    strcat(finduser_sql, "');");
-    sqlite3_exec(db, finduser_sql, NULL, NULL, NULL);
+  sqlite3_bind_text(qstmt, 1, uname, -1, SQLITE_TRANSIENT);
+  status = sqlite3_step(qstmt);
+  if (status != SQLITE_DONE) {
+    sqlite3_finalize(qstmt);
+    sqlite3_close(db);
+    if (status == SQLITE_ROW)
+      return 1; /* User already exists */
+    return 3;
   }
-  sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL);
+  /* The username doesn't exist yet, so create a new account. */
+  sqlite3_finalize(qstmt);
+  sqlite3_prepare_v2(db, addquery, -1, &qstmt, NULL);
+  if (qstmt == NULL) {
+    sqlite3_close(db);
+    return 3;
+  }
+  sqlite3_bind_text(qstmt, 1, uname, -1, SQLITE_TRANSIENT);
+  sqlite3_bind_text(qstmt, 2, strdup(crypt(pw, pw)), -1, free);
+  sqlite3_bind_text(qstmt, 3, email, -1, SQLITE_TRANSIENT);
+  status = sqlite3_step(qstmt);
+  if (status != SQLITE_DONE) {
+    sqlite3_finalize(qstmt);
+    sqlite3_close(db);
+    return 3;
+  }
+  status = sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL);
+  sqlite3_finalize(qstmt);
   sqlite3_close(db);
   return status;
 }