sqlickrypt: add support for salted SHA-512 passwords, and fix NULL bug.
Passwords will now be securely encrypted with random salt. Also avoid storing NULL in the database, because that makes dgamelaunch segfault.
This commit is contained in:
parent
b760c1d444
commit
29edae364e
1 changed files with 45 additions and 5 deletions
50
sqlickrypt.c
50
sqlickrypt.c
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#define DATABASE "/dgldir/dgamelaunch.db"
|
||||
#define IBUFSIZE 200
|
||||
#define RANDOMSRC "/dev/urandom"
|
||||
|
||||
/* General idea for return status:
|
||||
* 0: success
|
||||
|
|
@ -42,6 +43,41 @@ void cleanup(sqlite3 *db, sqlite3_stmt *stmt, int status) {
|
|||
return;
|
||||
}
|
||||
|
||||
char encode64(unsigned char c) {
|
||||
if (c < 26)
|
||||
return 'a' + c;
|
||||
else if (c < 52)
|
||||
return 'A' + c - 26;
|
||||
else if (c < 62)
|
||||
return '0' + c - 52;
|
||||
else if (c == 62)
|
||||
return '.';
|
||||
else
|
||||
return '/';
|
||||
}
|
||||
|
||||
/* Initializes a SHA-512 salt. salt must contain at least 20 bytes. */
|
||||
void setsalt(char *salt) {
|
||||
unsigned char rnbytes[3], rnvals[4];
|
||||
FILE *urandom;
|
||||
int loop;
|
||||
salt[0] = salt[2] = salt[19] = '$'; /* Delimiters */
|
||||
salt[1] = '6'; /* SHA-512 */
|
||||
urandom = fopen(RANDOMSRC, "r");
|
||||
for (loop = 0; loop < 4; loop++) {
|
||||
fread(rnbytes, 1, 3, urandom);
|
||||
rnvals[0] = rnbytes[0] >> 2;
|
||||
rnvals[1] = ((rnbytes[0] & 0x03) << 4) | ((rnbytes[1] & 0xf0) >> 4);
|
||||
rnvals[2] = ((rnbytes[1] & 0x0f) << 2) | ((rnbytes[2] & 0xc0) >> 6);
|
||||
rnvals[3] = rnbytes[2] & 0x3f;
|
||||
salt[loop * 4 + 3] = encode64(rnvals[0]);
|
||||
salt[loop * 4 + 4] = encode64(rnvals[1]);
|
||||
salt[loop * 4 + 5] = encode64(rnvals[2]);
|
||||
salt[loop * 4 + 6] = encode64(rnvals[3]);
|
||||
}
|
||||
fclose(urandom);
|
||||
}
|
||||
|
||||
int check(char *uname, char *pw) {
|
||||
char *pwhash, *comphash;
|
||||
char *query = "SELECT password FROM dglusers WHERE username=?;";
|
||||
|
|
@ -76,10 +112,11 @@ int check(char *uname, char *pw) {
|
|||
|
||||
int insertuser(char *uname, char *pw, char *email) {
|
||||
char *checkquery = "SELECT * FROM dglusers WHERE username = ?;";
|
||||
char *addquery = "INSERT INTO dglusers (username, password, email) VALUES (?, ?, ?);";
|
||||
char *addquery = "INSERT INTO dglusers (username, password, email, flags, env) VALUES (?, ?, ?, ?, ?);";
|
||||
int status;
|
||||
sqlite3 *db;
|
||||
sqlite3_stmt *qstmt;
|
||||
char salt[20];
|
||||
|
||||
opendb(&db, &qstmt, checkquery);
|
||||
/* Check for existing account in the same transaction with creating it. */
|
||||
|
|
@ -96,13 +133,16 @@ int insertuser(char *uname, char *pw, char *email) {
|
|||
return 3;
|
||||
}
|
||||
/* The username doesn't exist yet, so create a new account. */
|
||||
setsalt(salt);
|
||||
sqlite3_finalize(qstmt);
|
||||
sqlite3_prepare_v2(db, addquery, -1, &qstmt, NULL);
|
||||
if (qstmt == NULL)
|
||||
cleanup(db, NULL, 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, 2, strdup(crypt(pw, salt)), -1, free);
|
||||
sqlite3_bind_text(qstmt, 3, email, -1, SQLITE_TRANSIENT);
|
||||
sqlite3_bind_int(qstmt, 4, 0);
|
||||
sqlite3_bind_text(qstmt, 5, "", -1, SQLITE_STATIC);
|
||||
status = sqlite3_step(qstmt);
|
||||
if (status != SQLITE_DONE)
|
||||
cleanup(db, qstmt, 3);
|
||||
|
|
@ -160,10 +200,10 @@ int setpw(char *uname, char *newpw) {
|
|||
sqlite3_stmt *qstmt;
|
||||
int status;
|
||||
char *hash;
|
||||
char salt[20];
|
||||
|
||||
/* This is not a smart use of crypt, but it needs to be compatible with
|
||||
* dgamelaunch. */
|
||||
hash = crypt(newpw, newpw);
|
||||
setsalt(salt);
|
||||
hash = crypt(newpw, salt);
|
||||
opendb(&db, &qstmt, setquery);
|
||||
status = sqlite3_bind_text(qstmt, 2, uname, -1, SQLITE_TRANSIENT);
|
||||
if (status)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue