Key server and replace space with tab
This commit is contained in:
parent
eec8dc7ee2
commit
2fa6d40b0c
4 changed files with 304 additions and 304 deletions
|
@ -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, ¤t_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);
|
||||
|
|
140
src/lib/packet.c
140
src/lib/packet.c
|
@ -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;
|
||||
}
|
||||
|
|
152
src/lib/util.c
152
src/lib/util.c
|
@ -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");
|
||||
}
|
||||
|
|
264
src/zks/zks.c
264
src/zks/zks.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue