Add password hashing
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <crypt_blowfish.h>
|
||||
#include "bcrypt.h"
|
||||
|
||||
int hash_password(char *pass, int passlen, int cost, PasswordHash *hash)
|
||||
{
|
||||
char passzt[128];
|
||||
if (passlen >= (int) sizeof(passzt))
|
||||
return -1;
|
||||
memcpy(passzt, pass, passlen);
|
||||
passzt[passlen] = '\0';
|
||||
|
||||
unsigned char random[16] = {
|
||||
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, // TODO
|
||||
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
|
||||
};
|
||||
|
||||
char salt[30];
|
||||
if (_crypt_gensalt_blowfish_rn("$2b$", cost, (char*) random, sizeof(random), salt, sizeof(salt)) == NULL)
|
||||
return -1;
|
||||
|
||||
if (_crypt_blowfish_rn(passzt, salt, hash->data, (int) sizeof(hash->data)) == NULL)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int check_password(char *pass, int passlen, PasswordHash hash)
|
||||
{
|
||||
char passzt[128];
|
||||
if (passlen >= (int) sizeof(passzt))
|
||||
return -1;
|
||||
memcpy(passzt, pass, passlen);
|
||||
passzt[passlen] = '\0';
|
||||
|
||||
PasswordHash new_hash;
|
||||
if (_crypt_blowfish_rn(passzt, hash.data, new_hash.data, sizeof(new_hash.data)) == NULL)
|
||||
return -1;
|
||||
|
||||
if (strcmp(hash.data, new_hash.data)) // TODO: should be constant-time
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef BCRYPT_INCLUDED
|
||||
#define BCRYPT_INCLUDED
|
||||
|
||||
typedef struct {
|
||||
char data[61];
|
||||
} PasswordHash;
|
||||
|
||||
int hash_password(char *pass, int passlen, int cost, PasswordHash *hash);
|
||||
int check_password(char *pass, int passlen, PasswordHash hash);
|
||||
|
||||
#endif // BCRYPT_INCLUDED
|
||||
+34
-5
@@ -4,8 +4,9 @@
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include "sqlite3.h"
|
||||
#include "chttp.h"
|
||||
#include "bcrypt.h"
|
||||
#include "sqlite3.h"
|
||||
#include "sqlite3utils.h"
|
||||
#include "template.h"
|
||||
|
||||
@@ -45,9 +46,13 @@ int load_file(char *file, char **data, long *size)
|
||||
|
||||
int create_user(SQLiteCache *dbcache, HTTP_String name, HTTP_String email, HTTP_String pass)
|
||||
{
|
||||
PasswordHash hash;
|
||||
int ret = hash_password(pass.ptr, pass.len, 12, &hash);
|
||||
if (ret) return -500;
|
||||
|
||||
sqlite3_stmt *stmt;
|
||||
int ret = sqlite3utils_prepare_and_bind(dbcache, &stmt,
|
||||
"INSERT INTO Users(username, email, password) VALUES (?, ?, ?)", name, email, pass);
|
||||
ret = sqlite3utils_prepare_and_bind(dbcache, &stmt,
|
||||
"INSERT INTO Users(username, email, hash) VALUES (?, ?, ?)", name, email, ((HTTP_String) { hash.data, strlen(hash.data) }));
|
||||
if (ret != SQLITE_OK)
|
||||
return -500;
|
||||
|
||||
@@ -80,7 +85,7 @@ int user_exists(SQLiteCache *dbcache, HTTP_String name, HTTP_String pass)
|
||||
{
|
||||
sqlite3_stmt *stmt;
|
||||
int ret = sqlite3utils_prepare_and_bind(dbcache, &stmt,
|
||||
"SELECT id FROM Users WHERE username=? AND password=?", name, pass);
|
||||
"SELECT id, hash FROM Users WHERE username=?", name);
|
||||
if (ret != SQLITE_OK)
|
||||
return -500;
|
||||
|
||||
@@ -100,6 +105,30 @@ int user_exists(SQLiteCache *dbcache, HTTP_String name, HTTP_String pass)
|
||||
return -500;
|
||||
}
|
||||
|
||||
const char *rawhash = (const char*) sqlite3_column_text(stmt, 1);
|
||||
if (rawhash == NULL) {
|
||||
sqlite3_reset(stmt);
|
||||
return -500;
|
||||
}
|
||||
int rawhashlen = sqlite3_column_bytes(stmt, 1);
|
||||
|
||||
PasswordHash hash;
|
||||
if (rawhashlen >= sizeof(hash.data)) {
|
||||
sqlite3_reset(stmt);
|
||||
return -500;
|
||||
}
|
||||
strcpy(hash.data, rawhash);
|
||||
|
||||
ret = check_password(pass.ptr, pass.len, hash);
|
||||
if (ret < 0) {
|
||||
sqlite3_reset(stmt);
|
||||
return -500;
|
||||
}
|
||||
if (ret > 0) {
|
||||
sqlite3_reset(stmt);
|
||||
return -400;
|
||||
}
|
||||
|
||||
ret = sqlite3_reset(stmt);
|
||||
if (ret != SQLITE_OK)
|
||||
return -500;
|
||||
@@ -382,7 +411,7 @@ int main(void)
|
||||
{
|
||||
http_global_init();
|
||||
|
||||
printf("%s\n", sqlite3_libversion());
|
||||
printf("%s\n", sqlite3_libversion());
|
||||
|
||||
sqlite3 *db;
|
||||
int ret = sqlite3_open(":memory:", &db);
|
||||
|
||||
+2
-2
@@ -83,7 +83,7 @@ static int lookup(SQLiteCache *cache, char *fmt, int fmtlen)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int sqlite3utils_prepare(SQLiteCache *cache, sqlite3_stmt **pstmt, const char *fmt, int fmtlen)
|
||||
int sqlite3utils_prepare(SQLiteCache *cache, sqlite3_stmt **pstmt, char *fmt, int fmtlen)
|
||||
{
|
||||
if (fmtlen < 0)
|
||||
fmtlen = strlen(fmt);
|
||||
@@ -118,7 +118,7 @@ int sqlite3utils_prepare(SQLiteCache *cache, sqlite3_stmt **pstmt, const char *f
|
||||
}
|
||||
|
||||
int sqlite3utils_prepare_and_bind_impl(SQLiteCache *cache,
|
||||
sqlite3_stmt **pstmt, const char *fmt, VArgs args)
|
||||
sqlite3_stmt **pstmt, char *fmt, VArgs args)
|
||||
{
|
||||
sqlite3_stmt *stmt;
|
||||
int ret = sqlite3utils_prepare(cache, &stmt, fmt, strlen(fmt));
|
||||
|
||||
+2
-2
@@ -13,9 +13,9 @@ void sqlite_cache_free(SQLiteCache *cache);
|
||||
sqlite3* sqlite_cache_getdb(SQLiteCache *cache);
|
||||
|
||||
int sqlite3utils_prepare(SQLiteCache *cache,
|
||||
sqlite3_stmt **pstmt, const char *fmt, int fmtlen);
|
||||
sqlite3_stmt **pstmt, char *fmt, int fmtlen);
|
||||
|
||||
int sqlite3utils_prepare_and_bind_impl(SQLiteCache *cache,
|
||||
sqlite3_stmt **pstmt, const char *fmt, VArgs args);
|
||||
sqlite3_stmt **pstmt, char *fmt, VArgs args);
|
||||
|
||||
#endif // SQLITE3UTILS_INCLUDED
|
||||
Reference in New Issue
Block a user