diff --git a/Makefile b/Makefile index 3ed2247..d2e19ca 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ all: $(SERVER) $(CLIENT) $(SERVER): $(SERVERSRC) $(LIBSRC) mkdir -p bin - $(CC) $(SERVERSRC) $(LIBSRC) $(INCLUDE) -o bin/$@ $(CFLAGS) $(LDFLAGS) + $(CC) $(SERVERSRC) $(LIBSRC) $(INCLUDE) -DUSERNAME=\"$(username)\" -o bin/$@ $(CFLAGS) $(LDFLAGS) $(CLIENT): $(CLIENTSRC) $(LIBSRC) mkdir -p bin diff --git a/include/client/db.h b/include/client/db.h index 3d201ad..059b76e 100644 --- a/include/client/db.h +++ b/include/client/db.h @@ -3,6 +3,9 @@ #include -int sqlite_init(); +void get_users(); +uint8_t *get_sharedkey(uint8_t *username); +void save_sharedkey(uint8_t *username, uint8_t *shared_key); +void sqlite_init(); #endif diff --git a/include/key.h b/include/key.h index f9876ae..17f42eb 100644 --- a/include/key.h +++ b/include/key.h @@ -29,5 +29,6 @@ typedef struct keypair_t { keypair_t *create_keypair(char *username); keypair_t *get_keypair(char *username); +uint8_t *get_pk_from_ks(char *username); #endif diff --git a/include/util.h b/include/util.h index 54e28e9..2515acf 100644 --- a/include/util.h +++ b/include/util.h @@ -10,7 +10,7 @@ void error(int fatal, const char *fmt, ...); void *memalloc(size_t size); void *estrdup(void *str); char *replace_home(char *str); -void mkdir_p(const char *destdir); +void mkdir_p(const char *file); void write_log(int type, const char *fmt, ...); void print_bin(const unsigned char *ptr, size_t length); diff --git a/src/lib/key.c b/src/lib/key.c index 5630c8e..fff4a74 100644 --- a/src/lib/key.c +++ b/src/lib/key.c @@ -32,16 +32,25 @@ keypair_t *create_keypair(char *username) memcpy(pk, pk_data, PK_DATA_SIZE); memcpy(pk + PK_DATA_SIZE, pk_sign, SIGN_SIZE); - /* USE DB INSTEAD OF FILES */ - char pk_path[PATH_MAX], sk_path[PATH_MAX]; - sprintf(pk_path, "/home/night/%s_pk", username); - sprintf(sk_path, "/home/night/%s_sk", username); - FILE *pkf = fopen(pk_path, "w+"); - FILE *skf = fopen(sk_path, "w+"); - fwrite(pk, 1, PK_SIZE, pkf); - fwrite(sk, 1, SK_SIZE, skf); - fclose(pkf); - fclose(skf); + char keyf_path[PATH_MAX]; + char *data_dir = replace_home(CLIENT_DATA_DIR); + snprintf(keyf_path, PATH_MAX, "%s/%s/keys", data_dir, USERNAME); + free(data_dir); + + if (access(keyf_path, W_OK) != 0) { + /* If data file doesn't exist, most likely data dir won't exist too */ + mkdir_p(keyf_path); + } + + FILE *keyf = fopen(keyf_path, "w+"); + if (!keyf) { + error(1, "Error opening key file to write"); + return NULL; + } + /* Write key to file */ + fwrite(pk, 1, PK_SIZE, keyf); + fwrite(sk, 1, SK_SIZE, keyf); + fclose(keyf); keypair_t *kp = memalloc(sizeof(keypair_t)); memcpy(kp->pk.raw, pk_raw, PK_RAW_SIZE); @@ -51,29 +60,35 @@ keypair_t *create_keypair(char *username) memcpy(kp->pk.full, pk, PK_SIZE); memcpy(kp->sk, sk, SK_SIZE); + write_log(LOG_INFO, "Created key pair"); return kp; } keypair_t *get_keypair(char *username) { - /* REPLACE WITH DB */ - char pk_path[PATH_MAX], sk_path[PATH_MAX]; - sprintf(pk_path, "/home/night/%s_pk", username); - sprintf(sk_path, "/home/night/%s_sk", username); - FILE *pkf = fopen(pk_path, "r"); - FILE *skf = fopen(sk_path, "r"); - if (!pkf || !skf) { + char keyf_path[PATH_MAX]; + char *data_dir = replace_home(CLIENT_DATA_DIR); + snprintf(keyf_path, PATH_MAX, "%s/%s/keys", data_dir, USERNAME); + free(data_dir); + + if (access(keyf_path, W_OK) != 0) { + /* If data file doesn't exist, most likely data dir won't exist too */ + mkdir_p(keyf_path); + /* Create key pair as file doesn't exist */ create_keypair(username); - printf("Error opening key files.\n"); + } + + FILE *keyf = fopen(keyf_path, "r"); + if (!keyf) { + error(1, "Error opening key file to read"); return NULL; } uint8_t pk[PK_SIZE], sk[SK_SIZE]; - fread(pk, 1, PK_SIZE, pkf); - fread(sk, 1, SK_SIZE, skf); - fclose(pkf); - fclose(skf); + fread(pk, 1, PK_SIZE, keyf); + fread(sk, 1, SK_SIZE, keyf); + fclose(keyf); keypair_t *kp = memalloc(sizeof(keypair_t)); @@ -87,3 +102,21 @@ keypair_t *get_keypair(char *username) return kp; } + +/* + * Get public key from key server + */ +uint8_t *get_pk_from_ks(char *username) +{ + size_t bin_len = PK_RAW_SIZE; + unsigned char *bin = memalloc(bin_len); + /* TEMPORARY */ + if (strcmp(username, "night") == 0) { + sodium_hex2bin(bin, bin_len, "e2f0287d9c23aed8404dd8ba407e7dff8abe40fa98f0b9adf74904978a5fcd50", PK_RAW_SIZE * 2, NULL, NULL, NULL); + return bin; + } else if (strcmp(username, "palanix") == 0) { + sodium_hex2bin(bin, bin_len, "932aee08aa338108e49f65a5c4f0eb0a08a15bf717fdf8c0ff60eefd0ea014ae", PK_RAW_SIZE * 2, NULL, NULL, NULL); + return bin; + } + return NULL; +} diff --git a/src/lib/packet.c b/src/lib/packet.c index e1fddeb..2ed2def 100644 --- a/src/lib/packet.c +++ b/src/lib/packet.c @@ -204,14 +204,14 @@ int verify_packet(packet_t *pkt, int fd) memcpy(from, pkt->data, MAX_NAME); /* TODO: replace with db operations */ - keypair_t *kp_from = get_keypair(from); + uint8_t *pk = get_pk_from_ks(from); /* Verify data confidentiality by signature */ /* Verify data integrity by hash */ uint8_t hash[HASH_SIZE]; crypto_generichash(hash, HASH_SIZE, pkt->data, pkt->length, NULL, 0); - if (crypto_sign_verify_detached(pkt->signature, hash, HASH_SIZE, kp_from->pk.raw) != 0) { + if (crypto_sign_verify_detached(pkt->signature, hash, HASH_SIZE, pk) != 0) { /* Not match */ error(0, "Cannot verify data integrity"); packet_t *error_pkt = create_packet(ZSM_STA_ERROR_INTEGRITY, diff --git a/src/lib/util.c b/src/lib/util.c index bc4c90b..4f4479a 100644 --- a/src/lib/util.c +++ b/src/lib/util.c @@ -76,29 +76,39 @@ char *replace_home(char *str) /* * Recursively create directory by creating each subdirectory * like mkdir -p + * Create the parent folder(s) of given file */ -void mkdir_p(const char *destdir) +void mkdir_p(const char *file) { char *path = memalloc(PATH_MAX); char dir_path[PATH_MAX]; + dir_path[0] = '\0'; - if (destdir[0] == '~') { + if (file[0] == '~') { char *home = getenv("HOME"); if (home == NULL) { write_log(LOG_ERROR, "$HOME not defined"); return; } /* replace ~ with home */ - snprintf(path, PATH_MAX, "%s%s", home, destdir + 1); + snprintf(path, PATH_MAX, "%s%s", home, file + 1); } else { - strcpy(path, destdir); + strcpy(path, file); } /* fix first / not appearing in the string */ if (path[0] == '/') strcat(dir_path, "/"); - char *token = strtok(path, "/"); + /* Find last occurrence of '/' */ + char *last_slash = strrchr(path, '/'); + + /* Remove last slash */ + if (last_slash != NULL) { + path[last_slash - path] = '\0'; + } + + char *token = strtok(path, "/"); while (token != NULL) { strcat(dir_path, token); strcat(dir_path, "/"); @@ -127,13 +137,13 @@ void write_log(int type, const char *fmt, ...) va_list args; va_start(args, fmt); - char *client_log = memalloc(PATH_MAX); + char client_log[PATH_MAX]; char *data_dir = replace_home(CLIENT_DATA_DIR); - snprintf(client_log, PATH_MAX, "%s/%s", data_dir, "zen.log"); + snprintf(client_log, PATH_MAX, "%s/%s/zen.log", data_dir, USERNAME); free(data_dir); if (access(client_log, W_OK) != 0) { /* If log file doesn't exist, most likely data dir won't exist too */ - mkdir_p(CLIENT_DATA_DIR); + mkdir_p(client_log); } FILE *log = fopen(client_log, "a"); @@ -148,8 +158,9 @@ void write_log(int type, const char *fmt, ...) strftime(time, 22, "%Y-%m-%d %H:%M:%S ", t); char details[2 + type_len + 22]; snprintf(details, 2 + type_len + 22, "%s%s", logtype, time); - fprintf(log, "%s\n", details); + fprintf(log, "%s", details); vfprintf(log, fmt, args); + fprintf(log, "\n"); fclose(log); } va_end(args); diff --git a/src/zen/db.c b/src/zen/db.c index c78dd0d..3b6e297 100644 --- a/src/zen/db.c +++ b/src/zen/db.c @@ -5,68 +5,141 @@ #include "client/db.h" #include "client/user.h" -static int callback(void *ignore, int argc, char **argv, char **azColName) +sqlite3 *db; +char zen_db_path[PATH_MAX]; + +static int get_users_callback(void *_, int argc, char **argv, char **col_name) { + /* + for(int i = 0; i < argc; i++) { + printf("%s = %s\n", column[i], argv[i] ? argv[i] : "NULL"); + } +*/ add_username(argv[0]); return 0; } -static int get_shared_key(void *ignore, int argc, char **argv, char **column) +void get_users() { - for(int i = 0; i < argc; i++) { - printf("%s = %s\n", column[i], argv[i] ? argv[i] : "NULL"); - } - printf("\n"); - return 0; -} + char *err_msg; + sqlite3_stmt *statement; + if (sqlite3_open(zen_db_path, &db) != SQLITE_OK) { + error(0, "Cannot open database: %s", sqlite3_errmsg(db)); + sqlite3_close(db); + } + + char *sql = "SELECT * FROM Keys;"; -int sqlite_init() -{ - sqlite3 *db; - char *err_msg = 0; - - char *zen_db = memalloc(PATH_MAX); - char *data_dir = replace_home(CLIENT_DATA_DIR); - snprintf(zen_db, PATH_MAX, "%s/%s", data_dir, "data.db"); - free(data_dir); - if (access(zen_db, W_OK) != 0) { - /* If data file doesn't exist, most likely data dir won't exist too */ - mkdir_p(CLIENT_DATA_DIR); + if (sqlite3_exec(db, sql, get_users_callback, NULL, &err_msg) + != SQLITE_OK) { + error(0, "Failed to exec statement: %s", err_msg); + sqlite3_close(db); } - int rc = sqlite3_open(zen_db, &db); - - if (rc != SQLITE_OK) { - fprintf(stderr, "Cannot open database: %s\n", sqlite3_errmsg(db)); - sqlite3_close(db); - return 1; - } - - char *users_statement = "CREATE TABLE IF NOT EXISTS Users(Username TEXT, SharedKey TEXT, Test TEXT);"; - char *shared_key_statement = "SELECT * FROM Users;"; - char *messages_statement = "CREATE TABLE IF NOT EXISTS Messages(Username TEXT, );"; - //"INSERT INTO Users VALUES('night', 'test', '1');"; + sqlite3_close(db); + return; +} +/* + * Get shared key betweeen username + */ +uint8_t *get_sharedkey(uint8_t *username) +{ + sqlite3_stmt *statement; + uint8_t *shared_key = memalloc(SHARED_KEY_SIZE); + /* Make all bytes be 0 */ + memset(shared_key, 0, SHARED_KEY_SIZE); - rc = sqlite3_exec(db, users_statement, 0, 0, &err_msg); - - if (rc != SQLITE_OK) { - error(0, "SQL error: %s", err_msg); - sqlite3_free(err_msg); - } else { -/* error(0, "Table created successfully"); */ - } + if (sqlite3_open(zen_db_path, &db) != SQLITE_OK) { + error(0, "Cannot open database: %s", sqlite3_errmsg(db)); + sqlite3_close(db); + } + + char *sql = "SELECT SharedKey FROM Keys WHERE Username = ?;"; - // Select and print all entries - rc = sqlite3_exec(db, "SELECT * FROM Users", callback, NULL, &err_msg); - - if (rc != SQLITE_OK) { - error(0, "SQL error: %s\n", err_msg); - sqlite3_free(err_msg); - } + if (sqlite3_prepare_v2(db, sql, -1, &statement, NULL) != SQLITE_OK) { + error(0, "Failed to prepare statement: %s", sqlite3_errmsg(db)); + sqlite3_close(db); + } - sqlite3_close(db); - - return 0; + sqlite3_bind_text(statement, 1, username, strlen(username), SQLITE_STATIC); + + if (sqlite3_step(statement) == SQLITE_ROW) { + const void *blob = sqlite3_column_blob(statement, 0); + memcpy(shared_key, blob, SHARED_KEY_SIZE); + } else { + free(shared_key); + /* Set it to NULL so it can be returned */ + shared_key = NULL; + } + + sqlite3_finalize(statement); + sqlite3_close(db); + return shared_key; } +/* + * Saved shared key with username to database + */ +void save_sharedkey(uint8_t *username, uint8_t *shared_key) +{ + if (sqlite3_open(zen_db_path, &db) != SQLITE_OK) { + error(0, "Cannot open database: %s", sqlite3_errmsg(db)); + sqlite3_close(db); + } + + sqlite3_stmt *statement; + + /* Statement to execute with values to be replaced */ + char *sql = "INSERT OR REPLACE INTO Keys (Username,SharedKey)" + "VALUES (?,?);"; + printf("in db\n"); + print_bin(shared_key, SHARED_KEY_SIZE); + if (sqlite3_prepare_v2(db, sql, -1, &statement, NULL) != SQLITE_OK) { + error(0, "Failed to prepare statement: %s", sqlite3_errmsg(db)); + sqlite3_close(db); + } + sqlite3_bind_text(statement, 1, username, strlen(username), SQLITE_STATIC); + sqlite3_bind_blob(statement, 2, shared_key, SHARED_KEY_SIZE, SQLITE_STATIC); + + if (sqlite3_step(statement) != SQLITE_DONE) { + error(0, "Failed to execute statement"); + sqlite3_close(db); + } + sqlite3_finalize(statement); + sqlite3_close(db); + write_log(LOG_INFO, "Saved shared key with %s to database", username); +} + +void sqlite_init() +{ + char *err_msg; + + char *data_dir = replace_home(CLIENT_DATA_DIR); + snprintf(zen_db_path, PATH_MAX, "%s/%s/data.db", data_dir, USERNAME); + free(data_dir); + if (access(zen_db_path, W_OK) != 0) { + /* If data file doesn't exist, most likely data dir won't exist too */ + mkdir_p(zen_db_path); + } + + if (sqlite3_open(zen_db_path, &db) != SQLITE_OK) { + deinit(); + error(1, "Cannot open database: %s", sqlite3_errmsg(db)); + sqlite3_close(db); + } + + /* Create Keys Table if it is doesn't exist with Username being id */ + char *create_keys_table = "CREATE TABLE IF NOT EXISTS Keys(" + "Username TEXT NOT NULL, SharedKey BLOB NOT NULL," + "PRIMARY KEY(Username));"; + + if (sqlite3_exec(db, create_keys_table, 0, 0, &err_msg) != SQLITE_OK) { + error(0, "Cannot create Keys table: %s", err_msg); + sqlite3_free(err_msg); + } else { + write_log(LOG_INFO, "Keys Table created successfully"); + } + + sqlite3_close(db); +}