Key server and replace space with tab

This commit is contained in:
Night Kaly 2024-11-27 00:47:20 +00:00
parent eec8dc7ee2
commit 2fa6d40b0c
Signed by: night0721
SSH key fingerprint: SHA256:B/hgVwUoBpx5vdNsXl9w8XwZljA9766uk6T4ubZp5HM
4 changed files with 304 additions and 304 deletions

View file

@ -8,14 +8,14 @@ keypair_t *create_keypair(char *username)
username_padded[MAX_NAME], pk_hash[HASH_SIZE], pk_sign[SIGN_SIZE],
pk[PK_SIZE];
crypto_sign_keypair(pk_raw, sk);
crypto_sign_keypair(pk_raw, sk);
time_t current_time = time(NULL);
strcpy(username_padded, username);
size_t length = strlen(username);
if (length < MAX_NAME) {
/* Pad with null characters up to max length */
size_t length = strlen(username);
if (length < MAX_NAME) {
/* Pad with null characters up to max length */
memset(username_padded + length, 0, MAX_NAME - length);
} else {
error(0, "Username must be shorter than MAX_NAME");
@ -27,7 +27,7 @@ keypair_t *create_keypair(char *username)
memcpy(pk_data + PK_ED25519_SIZE + MAX_NAME, &current_time, TIME_SIZE);
crypto_generichash(pk_hash, HASH_SIZE, pk_data, PK_DATA_SIZE, NULL, 0);
crypto_sign_detached(pk_sign, NULL, pk_hash, HASH_SIZE, sk);
crypto_sign_detached(pk_sign, NULL, pk_hash, HASH_SIZE, sk);
memcpy(pk, pk_data, PK_DATA_SIZE);
memcpy(pk + PK_DATA_SIZE, pk_sign, SIGN_SIZE);
@ -79,36 +79,36 @@ keypair_t *get_keypair(char *username)
create_keypair(username);
}
FILE *keyf = fopen(keyf_path, "r");
if (!keyf) {
FILE *keyf = fopen(keyf_path, "r");
if (!keyf) {
error(1, "Error opening key file to read");
return NULL;
}
return NULL;
}
uint8_t pk[PK_SIZE], sk[SK_SIZE];
size_t bytes_read;
bytes_read = fread(pk, 1, PK_SIZE, keyf);
if (bytes_read != PK_SIZE) {
error(1, "Error reading public key from file, bytes_read(%zu)!=%d", bytes_read, PK_SIZE);
}
bytes_read = fread(pk, 1, PK_SIZE, keyf);
if (bytes_read != PK_SIZE) {
error(1, "Error reading public key from file, bytes_read(%zu)!=%d", bytes_read, PK_SIZE);
}
bytes_read = fread(sk, 1, SK_SIZE, keyf);
if (bytes_read != SK_SIZE) {
error(1, "Error reading secret key from file, bytes_read(%zu)!=%d", bytes_read, SK_SIZE);
}
fclose(keyf);
bytes_read = fread(sk, 1, SK_SIZE, keyf);
if (bytes_read != SK_SIZE) {
error(1, "Error reading secret key from file, bytes_read(%zu)!=%d", bytes_read, SK_SIZE);
}
fclose(keyf);
keypair_t *kp = memalloc(sizeof(keypair_t));
keypair_t *kp = memalloc(sizeof(keypair_t));
memcpy(kp->pk.raw, pk, PK_ED25519_SIZE);
memcpy(kp->pk.username, pk + PK_ED25519_SIZE, MAX_NAME);
memcpy(&kp->pk.creation, pk + PK_ED25519_SIZE + MAX_NAME, TIME_SIZE);
memcpy(kp->pk.signature, pk + PK_DATA_SIZE, SIGN_SIZE);
memcpy(kp->pk.raw, pk, PK_ED25519_SIZE);
memcpy(kp->pk.username, pk + PK_ED25519_SIZE, MAX_NAME);
memcpy(&kp->pk.creation, pk + PK_ED25519_SIZE + MAX_NAME, TIME_SIZE);
memcpy(kp->pk.signature, pk + PK_DATA_SIZE, SIGN_SIZE);
memcpy(kp->pk.full, pk, PK_SIZE);
memcpy(kp->sk, sk, SK_SIZE);
memcpy(kp->sk, sk, SK_SIZE);
return kp;
return kp;
}
/*
@ -117,7 +117,7 @@ keypair_t *get_keypair(char *username)
uint8_t *get_pk_from_ks(char *username)
{
size_t bin_len = PK_ED25519_SIZE;
unsigned char *bin = memalloc(bin_len);
unsigned char *bin = memalloc(bin_len);
/* TEMPORARY */
if (strcmp(username, "night") == 0) {
sodium_hex2bin(bin, bin_len, "e2f0287d9c23aed8404dd8ba407e7dff8abe40fa98f0b9adf74904978a5fcd50", PK_ED25519_SIZE * 2, NULL, NULL, NULL);

View file

@ -26,39 +26,39 @@ void print_packet(packet_t *pkt)
*/
int recv_packet(packet_t *pkt, int fd, uint8_t required_type)
{
int status = ZSM_STA_SUCCESS;
size_t bytes_read = 0;
int status = ZSM_STA_SUCCESS;
size_t bytes_read = 0;
/* Buffer to store header (status, type, length) */
/* Buffer to store header (status, type, length) */
size_t header_len = sizeof(pkt->status) + sizeof(pkt->type) + sizeof(pkt->length);
uint8_t header[header_len];
/* Read the entire packet header in one system call */
if ((bytes_read = recv(fd, header, header_len, 0)) != header_len) {
status = (bytes_read == 0) ? ZSM_STA_CLOSED_CONNECTION : ZSM_STA_READING_SOCKET;
error(0, "Error reading packet header from socket, bytes_read(%d)!=header_len(%d), status => %d",
uint8_t header[header_len];
/* Read the entire packet header in one system call */
if ((bytes_read = recv(fd, header, header_len, 0)) != header_len) {
status = (bytes_read == 0) ? ZSM_STA_CLOSED_CONNECTION : ZSM_STA_READING_SOCKET;
error(0, "Error reading packet header from socket, bytes_read(%d)!=header_len(%d), status => %d",
bytes_read, header_len, status);
return status;
}
return status;
}
/* Unpack the header */
memcpy(&pkt->status, &header[0], sizeof(pkt->status));
memcpy(&pkt->type, &header[sizeof(pkt->status)], sizeof(pkt->type));
memcpy(&pkt->length, &header[sizeof(pkt->status) + sizeof(pkt->type)], sizeof(pkt->length));
/* Unpack the header */
memcpy(&pkt->status, &header[0], sizeof(pkt->status));
memcpy(&pkt->type, &header[sizeof(pkt->status)], sizeof(pkt->type));
memcpy(&pkt->length, &header[sizeof(pkt->status) + sizeof(pkt->type)], sizeof(pkt->length));
/* Validate the packet type and length */
if (pkt->type > 0xFF || pkt->type < 0x0 || pkt->type != required_type) {
status = ZSM_STA_INVALID_TYPE;
error(0, "Invalid packet type: %d", pkt->type);
goto failure;
}
/* Validate the packet type and length */
if (pkt->type > 0xFF || pkt->type < 0x0 || pkt->type != required_type) {
status = ZSM_STA_INVALID_TYPE;
error(0, "Invalid packet type: %d", pkt->type);
goto failure;
}
if (pkt->length > MAX_DATA_LENGTH) {
status = ZSM_STA_TOO_LONG;
error(0, "Data too long: %d", pkt->length);
goto failure;
}
if (pkt->length > MAX_DATA_LENGTH) {
status = ZSM_STA_TOO_LONG;
error(0, "Data too long: %d", pkt->length);
goto failure;
}
/* If packet's length is 0, ignore its data and signature as it is information from server */
if (pkt->type != ZSM_TYP_INFO && pkt->length > 0) {
@ -88,17 +88,17 @@ int recv_packet(packet_t *pkt, int fd, uint8_t required_type)
/* Null terminate data so it can be print */
pkt->data[pkt->length] = '\0';
}
return status;
return status;
failure:;
packet_t *error_pkt = create_packet(status, ZSM_TYP_ERROR, 0, NULL, NULL);
if (send_packet(error_pkt, fd) != ZSM_STA_SUCCESS) {
/* Resend it? */
error(0, "Failed to send error packet. Error status => %d", status);
}
free_packet(error_pkt);
return status;
if (send_packet(error_pkt, fd) != ZSM_STA_SUCCESS) {
/* Resend it? */
error(0, "Failed to send error packet. Error status => %d", status);
}
free_packet(error_pkt);
return status;
}
/*
@ -107,13 +107,13 @@ failure:;
*/
packet_t *create_packet(uint8_t status, uint8_t type, uint32_t length, uint8_t *data, uint8_t *signature)
{
packet_t *pkt = memalloc(sizeof(packet_t));
pkt->status = status;
pkt->type = type;
pkt->length = length;
pkt->data = data;
pkt->signature = signature;
return pkt;
packet_t *pkt = memalloc(sizeof(packet_t));
pkt->status = status;
pkt->type = type;
pkt->length = length;
pkt->data = data;
pkt->signature = signature;
return pkt;
}
/*
@ -123,44 +123,44 @@ packet_t *create_packet(uint8_t status, uint8_t type, uint32_t length, uint8_t *
*/
int send_packet(packet_t *pkt, int fd)
{
int status = ZSM_STA_SUCCESS;
int status = ZSM_STA_SUCCESS;
size_t bytes_sent = 0;
/* Buffer to store header (status, type, length) */
size_t header_len = sizeof(pkt->status) + sizeof(pkt->type) + sizeof(pkt->length);
uint8_t header[header_len];
uint8_t header[header_len];
/* Pack the header */
memcpy(&header[0], &pkt->status, sizeof(pkt->status));
memcpy(&header[sizeof(pkt->status)], &pkt->type, sizeof(pkt->type));
memcpy(&header[sizeof(pkt->status) + sizeof(pkt->type)], &pkt->length, sizeof(pkt->length));
memcpy(&header[0], &pkt->status, sizeof(pkt->status));
memcpy(&header[sizeof(pkt->status)], &pkt->type, sizeof(pkt->type));
memcpy(&header[sizeof(pkt->status) + sizeof(pkt->type)], &pkt->length, sizeof(pkt->length));
/* Send the packet header in one system call */
if ((bytes_sent = send(fd, header, header_len, 0)) != header_len) {
status = ZSM_STA_WRITING_SOCKET;
error(0, "Error writing packet header to socket, bytes_sent(%d)!=header_len(%d), status => %d",
/* Send the packet header in one system call */
if ((bytes_sent = send(fd, header, header_len, 0)) != header_len) {
status = ZSM_STA_WRITING_SOCKET;
error(0, "Error writing packet header to socket, bytes_sent(%d)!=header_len(%d), status => %d",
bytes_sent, header_len, status);
goto failure;
}
}
if (pkt->type != ZSM_TYP_INFO && pkt->type != ZSM_TYP_ERROR && pkt->length > 0 && pkt->data != NULL) {
/* Buffer to store payload (data + signature) */
size_t payload_len = pkt->length + SIGN_SIZE;
uint8_t payload[payload_len];
/* Buffer to store payload (data + signature) */
size_t payload_len = pkt->length + SIGN_SIZE;
uint8_t payload[payload_len];
/* Pack the payload */
memcpy(payload, pkt->data, pkt->length);
memcpy(payload + pkt->length, pkt->signature, SIGN_SIZE);
/* Pack the payload */
memcpy(payload, pkt->data, pkt->length);
memcpy(payload + pkt->length, pkt->signature, SIGN_SIZE);
/* Send the payload (data + signature) in one system call */
if ((bytes_sent = send(fd, payload, payload_len, 0)) != payload_len) {
status = ZSM_STA_WRITING_SOCKET;
error(0, "Error writing packet body to socket, bytes_sent(%d)!=payload_len(%d), status => %d",
/* Send the payload (data + signature) in one system call */
if ((bytes_sent = send(fd, payload, payload_len, 0)) != payload_len) {
status = ZSM_STA_WRITING_SOCKET;
error(0, "Error writing packet body to socket, bytes_sent(%d)!=payload_len(%d), status => %d",
bytes_sent, payload_len, status);
goto failure;
}
}
return status;
goto failure;
}
}
return status;
failure:
/* Or we could resend it? */
@ -176,15 +176,15 @@ failure:
*/
void free_packet(packet_t *pkt)
{
if (pkt->type != ZSM_TYP_AUTH && pkt->type != ZSM_TYP_ERROR) {
if (pkt->type != ZSM_TYP_AUTH && pkt->type != ZSM_TYP_ERROR) {
if (pkt->signature != NULL) {
free(pkt->signature);
}
}
}
if (pkt->data != NULL) {
free(pkt->data);
}
free(pkt);
free(pkt);
}
/*
@ -208,7 +208,7 @@ int verify_packet(packet_t *pkt, int fd)
/* 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);
crypto_generichash(hash, HASH_SIZE, pkt->data, pkt->length, NULL, 0);
if (crypto_sign_verify_detached(pkt->signature, hash, HASH_SIZE, pk) != 0) {
/* Not match */
@ -218,7 +218,7 @@ int verify_packet(packet_t *pkt, int fd)
send_packet(error_pkt, fd);
free_packet(error_pkt);
return ZSM_STA_ERROR_INTEGRITY;
}
}
return ZSM_STA_SUCCESS;
}
@ -243,5 +243,5 @@ uint8_t *create_signature(uint8_t *data, uint32_t length, uint8_t *sk)
crypto_sign_detached(signature, NULL, hash, HASH_SIZE, sk);
}
return signature;
return signature;
}

View file

@ -8,42 +8,42 @@
*/
void error(int fatal, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
va_list args;
va_start(args, fmt);
/* to preserve errno */
int errsv = errno;
/* to preserve errno */
int errsv = errno;
/* Determine the length of the formatted error message */
va_list args_copy;
va_copy(args_copy, args);
size_t error_len = vsnprintf(NULL, 0, fmt, args_copy);
va_end(args_copy);
/* Determine the length of the formatted error message */
va_list args_copy;
va_copy(args_copy, args);
size_t error_len = vsnprintf(NULL, 0, fmt, args_copy);
va_end(args_copy);
/* 7 for [zsm], space and null */
char errorstr[error_len + 1];
vsnprintf(errorstr, error_len + 1, fmt, args);
fprintf(stderr, "[zsm] ");
/* 7 for [zsm], space and null */
char errorstr[error_len + 1];
vsnprintf(errorstr, error_len + 1, fmt, args);
fprintf(stderr, "[zsm] ");
if (errsv != 0 && errsv != EEXIST) {
perror(errorstr);
errno = 0;
} else {
fprintf(stderr, "%s\n", errorstr);
}
va_end(args);
if (fatal) exit(1);
if (errsv != 0 && errsv != EEXIST) {
perror(errorstr);
errno = 0;
} else {
fprintf(stderr, "%s\n", errorstr);
}
va_end(args);
if (fatal) exit(1);
}
void *memalloc(size_t size)
{
void *ptr = malloc(size);
if (!ptr) {
write_log(LOG_ERROR, "Error allocating memory");
return NULL;
}
return ptr;
void *ptr = malloc(size);
if (!ptr) {
write_log(LOG_ERROR, "Error allocating memory");
return NULL;
}
return ptr;
}
/*
@ -52,15 +52,15 @@ void *memalloc(size_t size)
*/
char *replace_home(char *str)
{
char *home = getenv("HOME");
if (home == NULL) {
char *home = getenv("HOME");
if (home == NULL) {
write_log(LOG_ERROR, "$HOME not defined");
return str;
}
char *newstr = memalloc(strlen(str) + strlen(home));
/* replace ~ with home */
snprintf(newstr, strlen(str) + strlen(home), "%s%s", home, str + 1);
return newstr;
return str;
}
char *newstr = memalloc(strlen(str) + strlen(home));
/* replace ~ with home */
snprintf(newstr, strlen(str) + strlen(home), "%s%s", home, str + 1);
return newstr;
}
/*
@ -70,62 +70,62 @@ char *replace_home(char *str)
*/
void mkdir_p(const char *file)
{
char *path = memalloc(PATH_MAX);
char dir_path[PATH_MAX];
char *path = memalloc(PATH_MAX);
char dir_path[PATH_MAX];
dir_path[0] = '\0';
if (file[0] == '~') {
char *home = getenv("HOME");
if (home == NULL) {
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, file + 1);
} else {
strcpy(path, file);
}
return;
}
/* replace ~ with home */
snprintf(path, PATH_MAX, "%s%s", home, file + 1);
} else {
strcpy(path, file);
}
/* fix first / not appearing in the string */
if (path[0] == '/')
/* fix first / not appearing in the string */
if (path[0] == '/')
strcat(dir_path, "/");
/* Find last occurrence of '/' */
char *last_slash = strrchr(path, '/');
/* Remove last slash */
if (last_slash != NULL) {
if (last_slash != NULL) {
path[last_slash - path] = '\0';
}
char *token = strtok(path, "/");
while (token != NULL) {
strcat(dir_path, token);
strcat(dir_path, "/");
while (token != NULL) {
strcat(dir_path, token);
strcat(dir_path, "/");
if (mkdir(dir_path, 0755) == -1) {
struct stat st;
if (stat(dir_path, &st) == 0 && S_ISDIR(st.st_mode)) {
/* Directory already exists, continue to the next dir */
token = strtok(NULL, "/");
continue;
}
if (mkdir(dir_path, 0755) == -1) {
struct stat st;
if (stat(dir_path, &st) == 0 && S_ISDIR(st.st_mode)) {
/* Directory already exists, continue to the next dir */
token = strtok(NULL, "/");
continue;
}
write_log(LOG_ERROR, "mkdir failed: %s", strerror(errno));
free(path);
return;
}
token = strtok(NULL, "/");
}
free(path);
return;
}
token = strtok(NULL, "/");
}
free(path);
return;
free(path);
return;
}
void write_log(int type, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
va_list args;
va_start(args, fmt);
char client_log[PATH_MAX];
char *data_dir = replace_home(CLIENT_DATA_DIR);
@ -153,13 +153,13 @@ void write_log(int type, const char *fmt, ...)
fprintf(log, "\n");
fclose(log);
}
va_end(args);
va_end(args);
}
void print_bin(const uint8_t *ptr, size_t length)
{
for (size_t i = 0; i < length; i++) {
printf("%02x ", ptr[i]);
}
printf("\n");
for (size_t i = 0; i < length; i++) {
printf("%02x ", ptr[i]);
}
printf("\n");
}

View file

@ -13,23 +13,23 @@ sqlite3 *db;
int init_db()
{
char *err_msg = NULL;
int rc = sqlite3_open("keys.db", &db);
if (rc != SQLITE_OK) {
fprintf(stderr, "Cannot open database: %s\n", sqlite3_errmsg(db));
return rc;
}
char *err_msg = NULL;
int rc = sqlite3_open("keys.db", &db);
if (rc != SQLITE_OK) {
fprintf(stderr, "Cannot open database: %s\n", sqlite3_errmsg(db));
return rc;
}
const char *sql = "CREATE TABLE IF NOT EXISTS keys (username TEXT PRIMARY KEY, publickey BLOB);";
rc = sqlite3_exec(db, sql, 0, 0, &err_msg);
const char *sql = "CREATE TABLE IF NOT EXISTS keys (username TEXT PRIMARY KEY, publickey BLOB);";
rc = sqlite3_exec(db, sql, 0, 0, &err_msg);
if (rc != SQLITE_OK) {
fprintf(stderr, "SQL error: %s\n", err_msg);
sqlite3_free(err_msg);
return rc;
}
if (rc != SQLITE_OK) {
fprintf(stderr, "SQL error: %s\n", err_msg);
sqlite3_free(err_msg);
return rc;
}
return SQLITE_OK;
return SQLITE_OK;
}
/*
@ -37,169 +37,169 @@ int init_db()
*/
int insert_publickey(const char *username, const unsigned char *pubkey, size_t pubkey_len)
{
sqlite3_stmt *stmt;
const char *sql = "INSERT OR REPLACE INTO keys(username, publickey) VALUES(?, ?)";
sqlite3_stmt *stmt;
const char *sql = "INSERT OR REPLACE INTO keys(username, publickey) VALUES(?, ?)";
int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);
if (rc != SQLITE_OK) {
fprintf(stderr, "Failed to prepare statement\n");
return rc;
}
int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);
if (rc != SQLITE_OK) {
fprintf(stderr, "Failed to prepare statement\n");
return rc;
}
sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC);
sqlite3_bind_blob(stmt, 2, publickey, pubkey_len, SQLITE_STATIC);
rc = sqlite3_step(stmt);
sqlite3_finalize(stmt);
sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC);
sqlite3_bind_blob(stmt, 2, publickey, pubkey_len, SQLITE_STATIC);
rc = sqlite3_step(stmt);
sqlite3_finalize(stmt);
return rc == SQLITE_DONE ? 0 : rc;
return rc == SQLITE_DONE ? 0 : rc;
}
/* Retrieve a public key from the database by username */
unsigned char *retrieve_publickey(const char *username, size_t *pubkey_len)
{
sqlite3_stmt *stmt;
const char *sql = "SELECT publickey FROM keys WHERE username = ?";
unsigned char *publickey = NULL;
sqlite3_stmt *stmt;
const char *sql = "SELECT publickey FROM keys WHERE username = ?";
unsigned char *publickey = NULL;
int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);
if (rc != SQLITE_OK) {
fprintf(stderr, "Failed to prepare statement\n");
return NULL;
}
int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);
if (rc != SQLITE_OK) {
fprintf(stderr, "Failed to prepare statement\n");
return NULL;
}
sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC);
rc = sqlite3_step(stmt);
sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC);
rc = sqlite3_step(stmt);
if (rc == SQLITE_ROW) {
const void *blob = sqlite3_column_blob(stmt, 0);
*publickey_len = sqlite3_column_bytes(stmt, 0);
publickey = (unsigned char *)malloc(*pubkey_len);
memcpy(publickey, blob, *pubkey_len);
}
if (rc == SQLITE_ROW) {
const void *blob = sqlite3_column_blob(stmt, 0);
*publickey_len = sqlite3_column_bytes(stmt, 0);
publickey = (unsigned char *)malloc(*pubkey_len);
memcpy(publickey, blob, *pubkey_len);
}
sqlite3_finalize(stmt);
return publickey;
sqlite3_finalize(stmt);
return publickey;
}
/* Handle REQUEST command: generate a new key pair and store the public key with username */
void handle_request(int clientfd, const char *username)
{
unsigned char pk[crypto_box_PUBLICKEYBYTES];
unsigned char sk[crypto_box_SECRETKEYBYTES];
unsigned char pk[crypto_box_PUBLICKEYBYTES];
unsigned char sk[crypto_box_SECRETKEYBYTES];
crypto_box_keypair(pk, sk); /* Generate key pair */
crypto_box_keypair(pk, sk); /* Generate key pair */
/* Store the public key with the username in the database */
if (insert_publickey(username, pk, crypto_box_PUBLICKEYBYTES) == 0) {
/* Convert the public key to hexadecimal string for client display */
char publickey_hex[crypto_box_PUBLICKEYBYTES * 2 + 1];
for (int i = 0; i < crypto_box_PUBLICKEYBYTES; i++) {
sprintf(publickey_hex + i * 2, "%02x", pk[i]);
}
send(clientfd, publickey_hex, strlen(pubkey_hex), 0);
send(clientfd, "\n", 1, 0);
} else {
send(clientfd, "ERROR\n", 6, 0);
}
/* Store the public key with the username in the database */
if (insert_publickey(username, pk, crypto_box_PUBLICKEYBYTES) == 0) {
/* Convert the public key to hexadecimal string for client display */
char publickey_hex[crypto_box_PUBLICKEYBYTES * 2 + 1];
for (int i = 0; i < crypto_box_PUBLICKEYBYTES; i++) {
sprintf(publickey_hex + i * 2, "%02x", pk[i]);
}
send(clientfd, publickey_hex, strlen(pubkey_hex), 0);
send(clientfd, "\n", 1, 0);
} else {
send(clientfd, "ERROR\n", 6, 0);
}
}
/* Handle RETRIEVE command: get public key by username */
void handle_retrieve(int clientfd, const char *username)
{
size_t publickey_len;
unsigned char *publickey = retrieve_pubkey(username, &pubkey_len);
size_t publickey_len;
unsigned char *publickey = retrieve_pubkey(username, &pubkey_len);
if (publickey) {
/* Convert the public key (BLOB) to hexadecimal string for client display */
char publickey_hex[pubkey_len * 2 + 1];
for (size_t i = 0; i < publickey_len; i++) {
sprintf(publickey_hex + i * 2, "%02x", pubkey[i]);
}
send(clientfd, publickey_hex, strlen(pubkey_hex), 0);
send(clientfd, "\n", 1, 0);
free(publickey);
} else {
send(clientfd, "NOT FOUND\n", 10, 0);
}
if (publickey) {
/* Convert the public key (BLOB) to hexadecimal string for client display */
char publickey_hex[pubkey_len * 2 + 1];
for (size_t i = 0; i < publickey_len; i++) {
sprintf(publickey_hex + i * 2, "%02x", pubkey[i]);
}
send(clientfd, publickey_hex, strlen(pubkey_hex), 0);
send(clientfd, "\n", 1, 0);
free(publickey);
} else {
send(clientfd, "NOT FOUND\n", 10, 0);
}
}
void handle_client(int clientfd)
{
char buffer[BUFSIZE];
ssize_t bytes_received;
char buffer[BUFSIZE];
ssize_t bytes_received;
while ((bytes_received = recv(clientfd, buffer, BUFSIZE - 1, 0)) > 0) {
buffer[bytes_received] = '\0';
while ((bytes_received = recv(clientfd, buffer, BUFSIZE - 1, 0)) > 0) {
buffer[bytes_received] = '\0';
if (strncmp(buffer, "REQUEST", 7) == 0) {
char username[BUFSIZE];
sscanf(buffer + 8, "%s", username); /* Get the username from the command */
handle_request(clientfd, username);
} else if (strncmp(buffer, "RETRIEVE", 8) == 0) {
char username[BUFSIZE];
sscanf(buffer + 9, "%s", username); /* Get the username from the command */
handle_retrieve(clientfd, username);
} else if (strncmp(buffer, "EXIT", 4) == 0) {
send(clientfd, "BYE\n", 4, 0);
break;
} else {
send(clientfd, "ERROR\n", 6, 0);
}
}
if (strncmp(buffer, "REQUEST", 7) == 0) {
char username[BUFSIZE];
sscanf(buffer + 8, "%s", username); /* Get the username from the command */
handle_request(clientfd, username);
} else if (strncmp(buffer, "RETRIEVE", 8) == 0) {
char username[BUFSIZE];
sscanf(buffer + 9, "%s", username); /* Get the username from the command */
handle_retrieve(clientfd, username);
} else if (strncmp(buffer, "EXIT", 4) == 0) {
send(clientfd, "BYE\n", 4, 0);
break;
} else {
send(clientfd, "ERROR\n", 6, 0);
}
}
close(clientfd);
close(clientfd);
}
int main()
{
if (sodium_init() < 0) {
fprintf(stderr, "Failed to initialize sodium\n");
return -1;
}
if (sodium_init() < 0) {
fprintf(stderr, "Failed to initialize sodium\n");
return -1;
}
if (init_db() != SQLITE_OK) {
fprintf(stderr, "Failed to initialize database\n");
return -1;
}
if (init_db() != SQLITE_OK) {
fprintf(stderr, "Failed to initialize database\n");
return -1;
}
int serverfd, clientfd;
struct sockaddr_in server_addr, client_addr;
socklen_t addr_len = sizeof(client_addr);
int serverfd, clientfd;
struct sockaddr_in server_addr, client_addr;
socklen_t addr_len = sizeof(client_addr);
if ((serverfd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("Socket failed");
return -1;
}
if ((serverfd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("Socket failed");
return -1;
}
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(PORT);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(PORT);
if (bind(serverfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("Bind failed");
close(serverfd);
return -1;
}
if (bind(serverfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("Bind failed");
close(serverfd);
return -1;
}
if (listen(serverfd, 3) < 0) {
perror("Listen failed");
close(serverfd);
return -1;
}
if (listen(serverfd, 3) < 0) {
perror("Listen failed");
close(serverfd);
return -1;
}
printf("Key server listening on port %d\n", PORT);
printf("Key server listening on port %d\n", PORT);
while (1) {
if ((clientfd = accept(serverfd, (struct sockaddr *)&client_addr, &addr_len)) < 0) {
perror("Accept failed");
continue;
}
while (1) {
if ((clientfd = accept(serverfd, (struct sockaddr *)&client_addr, &addr_len)) < 0) {
perror("Accept failed");
continue;
}
handle_client(clientfd);
}
handle_client(clientfd);
}
sqlite3_close(db);
close(serverfd);
return 0;
sqlite3_close(db);
close(serverfd);
return 0;
}