Mercurial > hg > rlgwebd
comparison sqlickrypt.c @ 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 | c08717cb7793 |
comparison
equal
deleted
inserted
replaced
| 24:9d5da43c0e83 | 25:f275d816e857 |
|---|---|
| 6 #include <unistd.h> | 6 #include <unistd.h> |
| 7 #include <crypt.h> | 7 #include <crypt.h> |
| 8 | 8 |
| 9 #define DATABASE "/dgldir/dgamelaunch.db" | 9 #define DATABASE "/dgldir/dgamelaunch.db" |
| 10 #define IBUFSIZE 200 | 10 #define IBUFSIZE 200 |
| 11 | |
| 12 int xcallback(void *targ, int ncols, char **vals, char **colnames) { | |
| 13 char *pws; | |
| 14 int j; | |
| 15 pws = *((char **) targ); | |
| 16 if (pws == NULL) { | |
| 17 for (j = 0; j < ncols; j++) { | |
| 18 if (!strcmp(colnames[j], "password")) | |
| 19 *((char **) targ) = strdup(vals[j]); | |
| 20 } | |
| 21 } | |
| 22 /* Otherwise, this isn't the first row. */ | |
| 23 return 0; | |
| 24 } | |
| 25 | |
| 26 /* Simple callback, for checking if there are any matches. */ | |
| 27 int searchcallback(void *targ, int ncols, char **vals, char **colnames) { | |
| 28 *((int *) targ) = 1; | |
| 29 return 0; | |
| 30 } | |
| 31 | 11 |
| 32 int check(char *uname, char *pw) { | 12 int check(char *uname, char *pw) { |
| 33 char *pwhash, *comphash; | 13 char *pwhash, *comphash; |
| 34 char *query = "SELECT password FROM dglusers WHERE username=?;"; | 14 char *query = "SELECT password FROM dglusers WHERE username=?;"; |
| 35 int status; | 15 int status; |
| 74 free(pwhash); | 54 free(pwhash); |
| 75 return status; | 55 return status; |
| 76 } | 56 } |
| 77 | 57 |
| 78 int insertuser(char *uname, char *pw, char *email) { | 58 int insertuser(char *uname, char *pw, char *email) { |
| 79 char finduser_sql[160]; | 59 char *checkquery = "SELECT * FROM dglusers WHERE username = ?;"; |
| 60 char *addquery = "INSERT INTO dglusers (username, password, email) VALUES (?, ?, ?);"; | |
| 80 int status; | 61 int status; |
| 81 sqlite3 *db; | 62 sqlite3 *db; |
| 82 | 63 sqlite3_stmt *qstmt; |
| 83 strcpy(finduser_sql, "BEGIN; SELECT * FROM dglusers WHERE username='"); | |
| 84 strncat(finduser_sql, uname, 40); | |
| 85 strcat(finduser_sql, "';"); | |
| 86 | 64 |
| 87 status = sqlite3_open(DATABASE, &db); | 65 status = sqlite3_open(DATABASE, &db); |
| 88 if (status) { | 66 if (status) { |
| 89 sqlite3_close(db); | 67 sqlite3_close(db); |
| 90 return 1; | 68 return 3; |
| 91 } | 69 } |
| 92 status = 0; | 70 /* Check for existing account in the same transaction with creating it. */ |
| 93 sqlite3_exec(db, finduser_sql, searchcallback, (void *) &status, NULL); | 71 status = sqlite3_exec(db, "BEGIN;", NULL, NULL, NULL); |
| 94 if (!status) { | 72 if (status) { |
| 95 /* FIXME This is ugly, and email is unsanitzed. */ | 73 sqlite3_close(db); |
| 96 strcpy(finduser_sql, "INSERT INTO dglusers (username, password, email) VALUES ('"); | 74 return 3; |
| 97 strncat(finduser_sql, uname, 20); | |
| 98 strcat(finduser_sql, "', '"); | |
| 99 strcat(finduser_sql, crypt(pw, pw)); | |
| 100 strcat(finduser_sql, "', '"); | |
| 101 strncat(finduser_sql, email, 40); | |
| 102 strcat(finduser_sql, "');"); | |
| 103 sqlite3_exec(db, finduser_sql, NULL, NULL, NULL); | |
| 104 } | 75 } |
| 105 sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL); | 76 sqlite3_prepare_v2(db, checkquery, -1, &qstmt, NULL); |
| 77 if (qstmt == NULL) { | |
| 78 sqlite3_close(db); | |
| 79 return 3; | |
| 80 } | |
| 81 sqlite3_bind_text(qstmt, 1, uname, -1, SQLITE_TRANSIENT); | |
| 82 status = sqlite3_step(qstmt); | |
| 83 if (status != SQLITE_DONE) { | |
| 84 sqlite3_finalize(qstmt); | |
| 85 sqlite3_close(db); | |
| 86 if (status == SQLITE_ROW) | |
| 87 return 1; /* User already exists */ | |
| 88 return 3; | |
| 89 } | |
| 90 /* The username doesn't exist yet, so create a new account. */ | |
| 91 sqlite3_finalize(qstmt); | |
| 92 sqlite3_prepare_v2(db, addquery, -1, &qstmt, NULL); | |
| 93 if (qstmt == NULL) { | |
| 94 sqlite3_close(db); | |
| 95 return 3; | |
| 96 } | |
| 97 sqlite3_bind_text(qstmt, 1, uname, -1, SQLITE_TRANSIENT); | |
| 98 sqlite3_bind_text(qstmt, 2, strdup(crypt(pw, pw)), -1, free); | |
| 99 sqlite3_bind_text(qstmt, 3, email, -1, SQLITE_TRANSIENT); | |
| 100 status = sqlite3_step(qstmt); | |
| 101 if (status != SQLITE_DONE) { | |
| 102 sqlite3_finalize(qstmt); | |
| 103 sqlite3_close(db); | |
| 104 return 3; | |
| 105 } | |
| 106 status = sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL); | |
| 107 sqlite3_finalize(qstmt); | |
| 106 sqlite3_close(db); | 108 sqlite3_close(db); |
| 107 return status; | 109 return status; |
| 108 } | 110 } |
| 109 | 111 |
| 110 int main(int argc, char *argv[]) { | 112 int main(int argc, char *argv[]) { |
