comparison sqlickrypt.c @ 117:c08717cb7793

sqlickrypt: add getmail and setmail commands. Add the ability to retrieve and alter users' e-mail addresses, and clean up some of the code too.
author John "Elwin" Edwards <elwin@sdf.org>
date Wed, 18 Jul 2012 17:00:05 -0700
parents f275d816e857
children b1480488ce9d
comparison
equal deleted inserted replaced
116:d7d7cdcba3b4 117:c08717cb7793
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 11
12 /* General idea for return status:
13 * 0: success
14 * 1: password check failed
15 * 2: username not found
16 * 3: database error
17 * 4: invalid input
18 */
19
20 /* Opens the database and, less obviously, initializes a statement. */
21 int opendb(sqlite3 **dbp, sqlite3_stmt **stmtp, char *query) {
22 int status;
23 status = sqlite3_open(DATABASE, dbp);
24 if (status) {
25 sqlite3_close(*dbp);
26 exit(3);
27 }
28 sqlite3_prepare_v2(*dbp, query, -1, stmtp, NULL);
29 if (*stmtp == NULL) {
30 sqlite3_close(*dbp);
31 exit(3);
32 }
33 return 0;
34 }
35
36 void cleanup(sqlite3 *db, sqlite3_stmt *stmt, int status) {
37 if (stmt)
38 sqlite3_finalize(stmt);
39 sqlite3_close(db);
40 if (status)
41 exit(status);
42 return;
43 }
44
12 int check(char *uname, char *pw) { 45 int check(char *uname, char *pw) {
13 char *pwhash, *comphash; 46 char *pwhash, *comphash;
14 char *query = "SELECT password FROM dglusers WHERE username=?;"; 47 char *query = "SELECT password FROM dglusers WHERE username=?;";
15 int status; 48 int status;
16 sqlite3 *db; 49 sqlite3 *db;
17 sqlite3_stmt *qstmt; 50 sqlite3_stmt *qstmt;
18 51
19 status = sqlite3_open(DATABASE, &db); 52 opendb(&db, &qstmt, query);
20 if (status) {
21 sqlite3_close(db);
22 return 3;
23 }
24 sqlite3_prepare_v2(db, query, -1, &qstmt, NULL);
25 if (qstmt == NULL) {
26 sqlite3_close(db);
27 return 3;
28 }
29 status = sqlite3_bind_text(qstmt, 1, uname, -1, SQLITE_TRANSIENT); 53 status = sqlite3_bind_text(qstmt, 1, uname, -1, SQLITE_TRANSIENT);
30 if (status) { 54 if (status)
31 sqlite3_finalize(qstmt); 55 cleanup(db, qstmt, 3);
32 sqlite3_close(db);
33 return 3;
34 }
35 status = sqlite3_step(qstmt); 56 status = sqlite3_step(qstmt);
36 if (status != SQLITE_ROW) { 57 if (status != SQLITE_ROW) {
37 sqlite3_finalize(qstmt); 58 sqlite3_finalize(qstmt);
38 sqlite3_close(db); 59 sqlite3_close(db);
39 if (status == SQLITE_DONE) 60 if (status == SQLITE_DONE)
40 return 2; /* User not found */ 61 return 2; /* User not found */
41 return 3; 62 return 3;
42 } 63 }
43 pwhash = strdup((char *) sqlite3_column_text(qstmt, 0)); 64 pwhash = strdup((char *) sqlite3_column_text(qstmt, 0));
44 /* Clean up */ 65 cleanup(db, qstmt, 0);
45 sqlite3_finalize(qstmt);
46 sqlite3_close(db);
47 66
48 /* Check the password */ 67 /* Check the password */
49 comphash = crypt(pw, pwhash); 68 comphash = crypt(pw, pwhash);
50 if (!strcmp(pwhash, comphash)) 69 if (!strcmp(pwhash, comphash))
51 status = 0; 70 status = 0;
60 char *addquery = "INSERT INTO dglusers (username, password, email) VALUES (?, ?, ?);"; 79 char *addquery = "INSERT INTO dglusers (username, password, email) VALUES (?, ?, ?);";
61 int status; 80 int status;
62 sqlite3 *db; 81 sqlite3 *db;
63 sqlite3_stmt *qstmt; 82 sqlite3_stmt *qstmt;
64 83
65 status = sqlite3_open(DATABASE, &db); 84 opendb(&db, &qstmt, checkquery);
66 if (status) {
67 sqlite3_close(db);
68 return 3;
69 }
70 /* Check for existing account in the same transaction with creating it. */ 85 /* Check for existing account in the same transaction with creating it. */
71 status = sqlite3_exec(db, "BEGIN;", NULL, NULL, NULL); 86 status = sqlite3_exec(db, "BEGIN;", NULL, NULL, NULL);
72 if (status) { 87 if (status)
73 sqlite3_close(db); 88 cleanup(db, qstmt, 3);
74 return 3;
75 }
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); 89 sqlite3_bind_text(qstmt, 1, uname, -1, SQLITE_TRANSIENT);
82 status = sqlite3_step(qstmt); 90 status = sqlite3_step(qstmt);
83 if (status != SQLITE_DONE) { 91 if (status != SQLITE_DONE) {
84 sqlite3_finalize(qstmt); 92 sqlite3_finalize(qstmt);
85 sqlite3_close(db); 93 sqlite3_close(db);
88 return 3; 96 return 3;
89 } 97 }
90 /* The username doesn't exist yet, so create a new account. */ 98 /* The username doesn't exist yet, so create a new account. */
91 sqlite3_finalize(qstmt); 99 sqlite3_finalize(qstmt);
92 sqlite3_prepare_v2(db, addquery, -1, &qstmt, NULL); 100 sqlite3_prepare_v2(db, addquery, -1, &qstmt, NULL);
93 if (qstmt == NULL) { 101 if (qstmt == NULL)
94 sqlite3_close(db); 102 cleanup(db, NULL, 3);
95 return 3;
96 }
97 sqlite3_bind_text(qstmt, 1, uname, -1, SQLITE_TRANSIENT); 103 sqlite3_bind_text(qstmt, 1, uname, -1, SQLITE_TRANSIENT);
98 sqlite3_bind_text(qstmt, 2, strdup(crypt(pw, pw)), -1, free); 104 sqlite3_bind_text(qstmt, 2, strdup(crypt(pw, pw)), -1, free);
99 sqlite3_bind_text(qstmt, 3, email, -1, SQLITE_TRANSIENT); 105 sqlite3_bind_text(qstmt, 3, email, -1, SQLITE_TRANSIENT);
100 status = sqlite3_step(qstmt); 106 status = sqlite3_step(qstmt);
101 if (status != SQLITE_DONE) { 107 if (status != SQLITE_DONE)
108 cleanup(db, qstmt, 3);
109 status = sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL);
110 cleanup(db, qstmt, 0);
111 return status;
112 }
113
114 int getmail(char *uname) {
115 char *mailquery = "SELECT email FROM dglusers WHERE username = ?;";
116 int status;
117 sqlite3 *db;
118 sqlite3_stmt *qstmt;
119
120 opendb(&db, &qstmt, mailquery);
121 status = sqlite3_bind_text(qstmt, 1, uname, -1, SQLITE_TRANSIENT);
122 if (status)
123 cleanup(db, qstmt, 3);
124 status = sqlite3_step(qstmt);
125 if (status != SQLITE_ROW) {
102 sqlite3_finalize(qstmt); 126 sqlite3_finalize(qstmt);
103 sqlite3_close(db); 127 sqlite3_close(db);
128 if (status == SQLITE_DONE)
129 return 2; /* User not found */
104 return 3; 130 return 3;
105 } 131 }
106 status = sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL); 132 printf("%s\n", sqlite3_column_text(qstmt, 0));
107 sqlite3_finalize(qstmt); 133 cleanup(db, qstmt, 0);
108 sqlite3_close(db); 134 return 0;
109 return status; 135 }
136
137 int setmail(char *uname, char *newmail) {
138 char *setquery = "UPDATE dglusers SET email = ? WHERE username = ?;";
139 sqlite3 *db;
140 sqlite3_stmt *qstmt;
141 int status;
142
143 opendb(&db, &qstmt, setquery);
144 status = sqlite3_bind_text(qstmt, 2, uname, -1, SQLITE_TRANSIENT);
145 if (status)
146 cleanup(db, qstmt, 3);
147 status = sqlite3_bind_text(qstmt, 1, newmail, -1, SQLITE_TRANSIENT);
148 if (status)
149 cleanup(db, qstmt, 3);
150 status = sqlite3_step(qstmt);
151 if (status != SQLITE_DONE)
152 cleanup(db, qstmt, 3);
153 cleanup(db, qstmt, 0);
154 return 0;
110 } 155 }
111 156
112 int main(int argc, char *argv[]) { 157 int main(int argc, char *argv[]) {
113 char ibuf[IBUFSIZE], *uname, *pw, *email; 158 char ibuf[IBUFSIZE], *uname, *line1, *line2;
114 char *cptr; // Utility pointer 159 char *cptr; // Utility pointer
115 int status; 160 int status;
116 161
117 /* Read in the username and password */ 162 /* Read in the username and password */
118 fgets(ibuf, IBUFSIZE, stdin); 163 fgets(ibuf, IBUFSIZE, stdin);
119 uname = ibuf; 164 uname = ibuf;
120 pw = strchr(uname, '\n'); 165 line1 = strchr(uname, '\n');
121 if (pw == NULL) 166 if (line1 == NULL)
122 exit(4); /* Truncated */ 167 exit(4); /* Truncated */
123 *pw = '\0'; 168 *line1 = '\0';
124 pw++; 169 if (argc == 1 || strcmp(argv[1], "getmail")) {
125 fgets(pw, IBUFSIZE - (pw - ibuf), stdin); 170 line1++;
126 if (pw[strlen(pw) - 1] == '\n') 171 fgets(line1, IBUFSIZE - (line1 - ibuf), stdin);
127 pw[strlen(pw) - 1] = '\0'; 172 if (line1[strlen(line1) - 1] == '\n')
128 else 173 line1[strlen(line1) - 1] = '\0';
129 exit(4); /* Truncated */ 174 else
175 exit(4); /* Truncated */
176 }
177 if (argc > 1 && !strcmp(argv[1], "setmail")) {
178 /* E-mail, sanitize */
179 for (cptr = line1; *cptr != '\0'; cptr++) {
180 if (!isalnum(*cptr) && !strchr("@._-", *cptr)) {
181 exit(4);
182 }
183 }
184 }
130 if (argc > 1 && !strcmp(argv[1], "register")) { 185 if (argc > 1 && !strcmp(argv[1], "register")) {
131 email = pw + strlen(pw) + 1; 186 line2 = line1 + strlen(line1) + 1;
132 fgets(email, IBUFSIZE - (email - ibuf), stdin); 187 fgets(line2, IBUFSIZE - (line2 - ibuf), stdin);
133 if (email[strlen(email) - 1] == '\n') 188 if (line2[strlen(line2) - 1] == '\n')
134 email[strlen(email) - 1] = '\0'; 189 line2[strlen(line2) - 1] = '\0';
135 else 190 else
136 exit(4); 191 exit(4);
137 for (cptr = email; *cptr != '\0'; cptr++) { 192 for (cptr = line2; *cptr != '\0'; cptr++) {
138 if (!isalnum(*cptr) && !strchr("@._-", *cptr)) { 193 if (!isalnum(*cptr) && !strchr("@._-", *cptr)) {
139 exit(4); 194 exit(4);
140 } 195 }
141 } 196 }
142 } 197 }
145 if (!isalnum(*cptr)) { 200 if (!isalnum(*cptr)) {
146 exit(4); 201 exit(4);
147 } 202 }
148 } 203 }
149 if (argc == 1 || !strcmp(argv[1], "check")) 204 if (argc == 1 || !strcmp(argv[1], "check"))
150 status = check(uname, pw); 205 status = check(uname, line1);
151 else if (!strcmp(argv[1], "register")) { 206 else if (!strcmp(argv[1], "register")) {
152 status = insertuser(uname, pw, email); 207 status = insertuser(uname, line1, line2);
208 }
209 else if (!strcmp(argv[1], "getmail")) {
210 status = getmail(uname);
211 }
212 else if (!strcmp(argv[1], "setmail")) {
213 status = setmail(uname, line1);
153 } 214 }
154 else 215 else
155 status = 127; 216 status = 127;
156 return status; 217 return status;
157 } 218 }