EXPERIMENTAL Password Hashing

This commit is contained in:
Andrew Pamment 2016-08-04 21:41:37 +10:00
parent 3954817248
commit 73aa146b84
8 changed files with 290 additions and 87 deletions

View File

@ -10,7 +10,7 @@ OBJ = inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o
$(CC) -c -o $@ $< $(CFLAGS) $(CC) -c -o $@ $< $(CFLAGS)
magicka: $(OBJ) magicka: $(OBJ)
$(CC) -o magicka -o $@ $^ $(CFLAGS) -L/usr/local/lib -lsqlite3 $(JAMLIB) $(ZMODEM) $(LUA) -lutil -lm $(CC) -o magicka -o $@ $^ $(CFLAGS) -L/usr/local/lib -lsqlite3 $(JAMLIB) $(ZMODEM) $(LUA) -lutil -lm -lssl -lcrypto
.PHONY: clean .PHONY: clean

View File

@ -10,7 +10,7 @@ OBJ = inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o
$(CC) -c -o $@ $< $(CFLAGS) $(CC) -c -o $@ $< $(CFLAGS)
magicka: $(OBJ) magicka: $(OBJ)
$(CC) -o magicka -o $@ $^ $(CFLAGS) -L/usr/local/lib -lsqlite3 $(JAMLIB) $(ZMODEM) $(LUA) -lutil -lm -ldl $(CC) -o magicka -o $@ $^ $(CFLAGS) -L/usr/local/lib -lsqlite3 $(JAMLIB) $(ZMODEM) $(LUA) -lutil -lm -ldl -lssl -lcrypto
.PHONY: clean .PHONY: clean

View File

@ -10,7 +10,7 @@ OBJ = inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o
$(CC) -c -o $@ $< $(CFLAGS) $(CC) -c -o $@ $< $(CFLAGS)
magicka: $(OBJ) magicka: $(OBJ)
$(CC) -o magicka -o $@ $^ $(CFLAGS) -L/usr/pkg/lib -lsqlite3 $(JAMLIB) $(ZMODEM) $(LUA) -lutil -lm $(CC) -o magicka -o $@ $^ $(CFLAGS) -L/usr/pkg/lib -lsqlite3 $(JAMLIB) $(ZMODEM) $(LUA) -lutil -lm -lssl -lcrypto
.PHONY: clean .PHONY: clean

1
bbs.h
View File

@ -120,6 +120,7 @@ struct user_record {
int id; int id;
char *loginname; char *loginname;
char *password; char *password;
char *salt;
char *firstname; char *firstname;
char *lastname; char *lastname;
char *email; char *email;

151
users.c
View File

@ -3,11 +3,64 @@
#include <stdlib.h> #include <stdlib.h>
#include <sqlite3.h> #include <sqlite3.h>
#include <ctype.h> #include <ctype.h>
#include <openssl/sha.h>
#include "bbs.h" #include "bbs.h"
#include "inih/ini.h" #include "inih/ini.h"
extern struct bbs_config conf; extern struct bbs_config conf;
char *hash_sha256(char *pass, char *salt) {
char *buffer = (char *)malloc(strlen(pass) + strlen(salt) + 1);
char *shash = (char *)malloc(66);
unsigned char hash[SHA256_DIGEST_LENGTH];
if (!buffer) {
dolog("Out of memory!");
exit(-1);
}
sprintf(buffer, "%s%s", pass, salt);
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, buffer, strlen(buffer));
SHA256_Final(hash, &sha256);
int i = 0;
for(i = 0; i < SHA256_DIGEST_LENGTH; i++) {
sprintf(shash + (i * 2), "%02x", hash[i]);
}
shash[64] = 0;
free(buffer);
return shash;
}
void gen_salt(char **s) {
FILE *fptr;
int i;
char c;
*s = (char *)malloc(11);
char *salt = *s;
if (!salt) {
dolog("Out of memory..");
exit(-1);
}
fptr = fopen("/dev/urandom", "rb");
if (!fptr) {
dolog("Unable to open /dev/urandom!");
exit(-1);
}
for (i=0;i<10;i++) {
fread(&c, 1, 1, fptr);
salt[i] = (char)((abs(c) % 93) + 33);
}
fclose(fptr);
salt[10] = '\0';
}
static int secLevel(void* user, const char* section, const char* name, static int secLevel(void* user, const char* section, const char* name,
const char* value) const char* value)
{ {
@ -27,7 +80,7 @@ int save_user(struct user_record *user) {
sqlite3_stmt *res; sqlite3_stmt *res;
int rc; int rc;
char *update_sql = "UPDATE users SET password=?, firstname=?," char *update_sql = "UPDATE users SET password=?, salt=?, firstname=?,"
"lastname=?, email=?, location=?, sec_level=?, last_on=?, time_left=?, cur_mail_conf=?, cur_mail_area=?, cur_file_dir=?, cur_file_sub=?, times_on=? where loginname LIKE ?"; "lastname=?, email=?, location=?, sec_level=?, last_on=?, time_left=?, cur_mail_conf=?, cur_mail_area=?, cur_file_dir=?, cur_file_sub=?, times_on=? where loginname LIKE ?";
char *err_msg = 0; char *err_msg = 0;
@ -46,19 +99,20 @@ int save_user(struct user_record *user) {
if (rc == SQLITE_OK) { if (rc == SQLITE_OK) {
sqlite3_bind_text(res, 1, user->password, -1, 0); sqlite3_bind_text(res, 1, user->password, -1, 0);
sqlite3_bind_text(res, 2, user->firstname, -1, 0); sqlite3_bind_text(res, 2, user->salt, -1, 0);
sqlite3_bind_text(res, 3, user->lastname, -1, 0); sqlite3_bind_text(res, 3, user->firstname, -1, 0);
sqlite3_bind_text(res, 4, user->email, -1, 0); sqlite3_bind_text(res, 4, user->lastname, -1, 0);
sqlite3_bind_text(res, 5, user->location, -1, 0); sqlite3_bind_text(res, 5, user->email, -1, 0);
sqlite3_bind_int(res, 6, user->sec_level); sqlite3_bind_text(res, 6, user->location, -1, 0);
sqlite3_bind_int(res, 7, user->laston); sqlite3_bind_int(res, 7, user->sec_level);
sqlite3_bind_int(res, 8, user->timeleft); sqlite3_bind_int(res, 8, user->laston);
sqlite3_bind_int(res, 9, user->cur_mail_conf); sqlite3_bind_int(res, 9, user->timeleft);
sqlite3_bind_int(res, 10, user->cur_mail_area); sqlite3_bind_int(res, 10, user->cur_mail_conf);
sqlite3_bind_int(res, 11, user->cur_file_dir); sqlite3_bind_int(res, 11, user->cur_mail_area);
sqlite3_bind_int(res, 12, user->cur_file_sub); sqlite3_bind_int(res, 12, user->cur_file_dir);
sqlite3_bind_int(res, 13, user->timeson); sqlite3_bind_int(res, 13, user->cur_file_sub);
sqlite3_bind_text(res, 14, user->loginname, -1, 0); sqlite3_bind_int(res, 14, user->timeson);
sqlite3_bind_text(res, 15, user->loginname, -1, 0);
} else { } else {
dolog("Failed to execute statement: %s", sqlite3_errmsg(db)); dolog("Failed to execute statement: %s", sqlite3_errmsg(db));
} }
@ -86,6 +140,7 @@ int inst_user(struct user_record *user) {
"Id INTEGER PRIMARY KEY," "Id INTEGER PRIMARY KEY,"
"loginname TEXT COLLATE NOCASE," "loginname TEXT COLLATE NOCASE,"
"password TEXT," "password TEXT,"
"salt TEXT,"
"firstname TEXT," "firstname TEXT,"
"lastname TEXT," "lastname TEXT,"
"email TEXT," "email TEXT,"
@ -99,8 +154,8 @@ int inst_user(struct user_record *user) {
"cur_file_dir INTEGER," "cur_file_dir INTEGER,"
"times_on INTEGER);"; "times_on INTEGER);";
char *insert_sql = "INSERT INTO users (loginname, password, firstname," char *insert_sql = "INSERT INTO users (loginname, password, salt, firstname,"
"lastname, email, location, sec_level, last_on, time_left, cur_mail_conf, cur_mail_area, cur_file_dir, cur_file_sub, times_on) VALUES(?,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; "lastname, email, location, sec_level, last_on, time_left, cur_mail_conf, cur_mail_area, cur_file_dir, cur_file_sub, times_on) VALUES(?,?, ?,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
char *err_msg = 0; char *err_msg = 0;
sprintf(buffer, "%s/users.sq3", conf.bbs_path); sprintf(buffer, "%s/users.sq3", conf.bbs_path);
@ -130,18 +185,19 @@ int inst_user(struct user_record *user) {
if (rc == SQLITE_OK) { if (rc == SQLITE_OK) {
sqlite3_bind_text(res, 1, user->loginname, -1, 0); sqlite3_bind_text(res, 1, user->loginname, -1, 0);
sqlite3_bind_text(res, 2, user->password, -1, 0); sqlite3_bind_text(res, 2, user->password, -1, 0);
sqlite3_bind_text(res, 3, user->firstname, -1, 0); sqlite3_bind_text(res, 3, user->salt, -1, 0);
sqlite3_bind_text(res, 4, user->lastname, -1, 0); sqlite3_bind_text(res, 4, user->firstname, -1, 0);
sqlite3_bind_text(res, 5, user->email, -1, 0); sqlite3_bind_text(res, 5, user->lastname, -1, 0);
sqlite3_bind_text(res, 6, user->location, -1, 0); sqlite3_bind_text(res, 6, user->email, -1, 0);
sqlite3_bind_int(res, 7, user->sec_level); sqlite3_bind_text(res, 7, user->location, -1, 0);
sqlite3_bind_int(res, 8, user->laston); sqlite3_bind_int(res, 8, user->sec_level);
sqlite3_bind_int(res, 9, user->timeleft); sqlite3_bind_int(res, 9, user->laston);
sqlite3_bind_int(res, 10, user->cur_mail_conf); sqlite3_bind_int(res, 10, user->timeleft);
sqlite3_bind_int(res, 11, user->cur_mail_area); sqlite3_bind_int(res, 11, user->cur_mail_conf);
sqlite3_bind_int(res, 12, user->cur_file_dir); sqlite3_bind_int(res, 12, user->cur_mail_area);
sqlite3_bind_int(res, 13, user->cur_file_sub); sqlite3_bind_int(res, 13, user->cur_file_dir);
sqlite3_bind_int(res, 14, user->timeson); sqlite3_bind_int(res, 14, user->cur_file_sub);
sqlite3_bind_int(res, 15, user->timeson);
} else { } else {
dolog("Failed to execute statement: %s", sqlite3_errmsg(db)); dolog("Failed to execute statement: %s", sqlite3_errmsg(db));
@ -151,7 +207,6 @@ int inst_user(struct user_record *user) {
rc = sqlite3_step(res); rc = sqlite3_step(res);
if (rc != SQLITE_DONE) { if (rc != SQLITE_DONE) {
dolog("execution failed: %s", sqlite3_errmsg(db)); dolog("execution failed: %s", sqlite3_errmsg(db));
sqlite3_close(db); sqlite3_close(db);
exit(1); exit(1);
@ -171,6 +226,7 @@ struct user_record *check_user_pass(int socket, char *loginname, char *password)
sqlite3_stmt *res; sqlite3_stmt *res;
int rc; int rc;
char *sql = "SELECT * FROM users WHERE loginname LIKE ?"; char *sql = "SELECT * FROM users WHERE loginname LIKE ?";
char *pass_hash;
sprintf(buffer, "%s/users.sq3", conf.bbs_path); sprintf(buffer, "%s/users.sq3", conf.bbs_path);
@ -199,30 +255,36 @@ struct user_record *check_user_pass(int socket, char *loginname, char *password)
user->id = sqlite3_column_int(res, 0); user->id = sqlite3_column_int(res, 0);
user->loginname = strdup((char *)sqlite3_column_text(res, 1)); user->loginname = strdup((char *)sqlite3_column_text(res, 1));
user->password = strdup((char *)sqlite3_column_text(res, 2)); user->password = strdup((char *)sqlite3_column_text(res, 2));
user->firstname = strdup((char *)sqlite3_column_text(res, 3)); user->salt = strdup((char *)sqlite3_column_text(res, 3));
user->lastname = strdup((char *)sqlite3_column_text(res, 4)); user->firstname = strdup((char *)sqlite3_column_text(res, 4));
user->email = strdup((char *)sqlite3_column_text(res, 5)); user->lastname = strdup((char *)sqlite3_column_text(res, 5));
user->location = strdup((char *)sqlite3_column_text(res, 6)); user->email = strdup((char *)sqlite3_column_text(res, 6));
user->sec_level = sqlite3_column_int(res, 7); user->location = strdup((char *)sqlite3_column_text(res, 7));
user->laston = (time_t)sqlite3_column_int(res, 8); user->sec_level = sqlite3_column_int(res, 8);
user->timeleft = sqlite3_column_int(res, 9); user->laston = (time_t)sqlite3_column_int(res, 9);
user->cur_mail_conf = sqlite3_column_int(res, 10); user->timeleft = sqlite3_column_int(res, 10);
user->cur_mail_area = sqlite3_column_int(res, 11); user->cur_mail_conf = sqlite3_column_int(res, 11);
user->cur_file_dir = sqlite3_column_int(res, 13); user->cur_mail_area = sqlite3_column_int(res, 12);
user->cur_file_sub = sqlite3_column_int(res, 12); user->cur_file_dir = sqlite3_column_int(res, 14);
user->timeson = sqlite3_column_int(res, 14); user->cur_file_sub = sqlite3_column_int(res, 13);
user->timeson = sqlite3_column_int(res, 15);
if (strcmp(password, user->password) != 0) { pass_hash = hash_sha256(password, user->salt);
if (strcmp(pass_hash, user->password) != 0) {
free(user->loginname); free(user->loginname);
free(user->firstname); free(user->firstname);
free(user->lastname); free(user->lastname);
free(user->email); free(user->email);
free(user->location); free(user->location);
free(user->salt);
free(user); free(user);
free(pass_hash);
sqlite3_finalize(res); sqlite3_finalize(res);
sqlite3_close(db); sqlite3_close(db);
return NULL; return NULL;
} }
free(pass_hash);
} else { } else {
sqlite3_finalize(res); sqlite3_finalize(res);
sqlite3_close(db); sqlite3_close(db);
@ -437,7 +499,8 @@ struct user_record *new_user(int socket) {
s_putstring(socket, "Password too short!\r\n"); s_putstring(socket, "Password too short!\r\n");
} }
} while (!passok); } while (!passok);
user->password = strdup(buffer); gen_salt(&user->salt);
user->password = hash_sha256(buffer, salt);
s_putstring(socket, "You Entered:\r\n"); s_putstring(socket, "You Entered:\r\n");
s_putstring(socket, "-------------------------------------\r\n"); s_putstring(socket, "-------------------------------------\r\n");
@ -451,8 +514,6 @@ struct user_record *new_user(int socket) {
s_putstring(socket, user->email); s_putstring(socket, user->email);
s_putstring(socket, "\r\nLocation: "); s_putstring(socket, "\r\nLocation: ");
s_putstring(socket, user->location); s_putstring(socket, user->location);
s_putstring(socket, "\r\nPassword: ");
s_putstring(socket, user->password);
s_putstring(socket, "\r\n-------------------------------------\r\n"); s_putstring(socket, "\r\n-------------------------------------\r\n");
s_putstring(socket, "Is this Correct? (Y/N)"); s_putstring(socket, "Is this Correct? (Y/N)");
c = s_getchar(socket); c = s_getchar(socket);

View File

@ -50,7 +50,7 @@ int main(int argc, char **argv) {
} }
if (tolower(argv[1][0]) != 'l' && tolower(argv[1][0]) != 'e') { if (tolower(argv[1][0]) != 'l' && tolower(argv[1][0]) != 'e') {
printf("Usage:\n"); printf("Usage:\n");
printf("%s [l|e] filename jambase from subject\n", argv[0]); printf("%s [l|e] filename jambase from subject laddress\n", argv[0]);
printf(" l = Local Message, e = Echomail Message\n"); printf(" l = Local Message, e = Echomail Message\n");
printf(" laddress is your network address, and only required on echomail.\n"); printf(" laddress is your network address, and only required on echomail.\n");
exit(1); exit(1);
@ -58,7 +58,7 @@ int main(int argc, char **argv) {
if (tolower(argv[1][0]) == 'e' && argc < 7) { if (tolower(argv[1][0]) == 'e' && argc < 7) {
printf("Usage:\n"); printf("Usage:\n");
printf("%s [l|e] filename jambase from subject\n", argv[0]); printf("%s [l|e] filename jambase from subject laddress\n", argv[0]);
printf(" l = Local Message, e = Echomail Message\n"); printf(" l = Local Message, e = Echomail Message\n");
printf(" laddress is your network address, and only required on echomail.\n"); printf(" laddress is your network address, and only required on echomail.\n");
exit(1); exit(1);

View File

@ -0,0 +1,15 @@
CC=cc
CFLAGS=-I/usr/local/include
DEPS = update_pass.c
OBJ = update_pass.o
%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
update_pass: $(OBJ)
$(CC) -o update_pass -o $@ $^ $(CFLAGS) -L/usr/local/lib -lsqlite3 -lssl -lcrypto
.PHONY: clean
clean:
rm -f $(OBJ) update_pass

View File

@ -0,0 +1,126 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sqlite3.h>
#include <ctype.h>
#include <openssl/sha.h>
char *hash_sha256(char *pass, char *salt) {
char *buffer = (char *)malloc(strlen(pass) + strlen(salt) + 1);
char *shash = (char *)malloc(66);
unsigned char hash[SHA256_DIGEST_LENGTH];
if (!buffer) {
printf("Out of memory!");
exit(-1);
}
sprintf(buffer, "%s%s", pass, salt);
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, buffer, strlen(buffer));
SHA256_Final(hash, &sha256);
int i = 0;
for(i = 0; i < SHA256_DIGEST_LENGTH; i++) {
sprintf(shash + (i * 2), "%02x", hash[i]);
}
shash[64] = 0;
free(buffer);
return shash;
}
void gen_salt(char **s) {
FILE *fptr;
int i;
char c;
*s = (char *)malloc(11);
char *salt = *s;
if (!salt) {
printf("Out of memory..");
exit(-1);
}
fptr = fopen("/dev/urandom", "rb");
if (!fptr) {
printf("Unable to open /dev/urandom!");
exit(-1);
}
for (i=0;i<10;i++) {
fread(&c, 1, 1, fptr);
salt[i] = (char)((abs(c) % 93) + 33);
}
fclose(fptr);
salt[10] = '\0';
}
int main(int argc, char **argv) {
sqlite3 *db;
sqlite3_stmt *res;
sqlite3_stmt *res2;
char *alter_table_sql = "ALTER TABLE users ADD COLUMN salt TEXT";
char *select_sql = "SELECT Id,password FROM users";
char *update_sql = "UPDATE users SET password=?, salt=? WHERE Id=?";
char *err_msg = 0;
int id;
int rc;
char *password;
char *hash;
char *salt;
rc = sqlite3_open(argv[1], &db);
if (rc != SQLITE_OK) {
printf("Error opening database\n");
return -1;
}
rc = sqlite3_exec(db, alter_table_sql, 0, 0, &err_msg);
if (rc != SQLITE_OK ) {
printf("SQL error: %s\n", err_msg);
sqlite3_free(err_msg);
sqlite3_close(db);
return 1;
}
rc = sqlite3_prepare_v2(db, select_sql, -1, &res, 0);
if (rc != SQLITE_OK) {
printf("Cannot prepare statement: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
exit(1);
}
while (sqlite3_step(res) == SQLITE_ROW) {
id = sqlite3_column_int(res, 0);
password = strdup(sqlite3_column_text(res, 1));
gen_salt(&salt);
hash = hash_sha256(password, salt);
rc = sqlite3_prepare_v2(db, update_sql, -1, &res2, 0);
if (rc != SQLITE_OK) {
printf("Cannot prepare statement: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
exit(1);
}
sqlite3_bind_text(res2, 1, hash, -1, 0);
sqlite3_bind_text(res2, 2, salt, -1, 0);
sqlite3_bind_int(res2, 3, id);
rc = sqlite3_step(res2);
if (rc != SQLITE_DONE) {
printf("Error: %s\n", sqlite3_errmsg(db));
exit(1);
}
sqlite3_finalize(res2);
}
printf("Converted!\n");
sqlite3_finalize(res);
sqlite3_close(db);
}