Add closed connection status, remove print_packet routine and revamp how send_packet and recv_packet works

This commit is contained in:
Night Kaly 2024-09-20 17:06:03 +01:00
parent 2801fad655
commit e50093283f
Signed by: night0721
GPG key ID: 957D67B8DB7A119B
2 changed files with 96 additions and 109 deletions

View file

@ -47,6 +47,7 @@
#define ZSM_STA_ERROR_INTEGRITY 0xC
#define ZSM_STA_UNAUTHORISED 0xD
#define ZSM_STA_AUTHORISED 0xE
#define ZSM_STA_CLOSED_CONNECTION 0xF
#define ADDRESS_SIZE MAX_NAME + 1 + 255 /* 1 for @, 255 for domain, defined in RFC 5321, Section 4.5.3.1.2 */
#define HASH_SIZE crypto_generichash_BYTES
@ -72,7 +73,6 @@ typedef struct message_t {
#include "key.h"
/* Utilities functions */
void print_packet(packet_t *msg);
int recv_packet(packet_t *pkt, int fd, uint8_t required_type);
packet_t *create_packet(uint8_t option, uint8_t type, uint32_t length, uint8_t *data, uint8_t *signature);
int send_packet(packet_t *msg, int fd);

View file

@ -2,25 +2,6 @@
#include "key.h"
#include "util.h"
void print_packet(packet_t *pkt)
{
printf("Status: %d\n", pkt->status);
printf("Type: %d\n", pkt->type);
printf("Length: %d\n", pkt->length);
if (pkt->length > 0) {
printf("Data:\n");
for (int i = 0; i < pkt->length; i++) {
printf("%d ", pkt->data[i]);
}
printf("\n");
printf("Signature:\n");
for (int i = 0; i < SIGN_SIZE; i++) {
printf("%d ", pkt->signature[i]);
}
printf("\n");
}
}
/*
* Requires manually free packet data
* pkt: packet to fill data in (must be created via create_packet)
@ -30,32 +11,36 @@ 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;
/* Read the packet components */
if (recv(fd, &pkt->status, sizeof(pkt->status), 0) < 0 ||
recv(fd, &pkt->type, sizeof(pkt->type), 0) < 0 ||
recv(fd, &pkt->length, sizeof(pkt->length), 0) < 0) {
status = ZSM_STA_READING_SOCKET;
error(0, "Error reading from socket");
/* 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",
bytes_read, header_len, 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));
#if DEBUG == 1
printf("==========PACKET RECEIVED==========\n");
printf("==========PACKET RECEIVED========\n");
printf("Status: %d\n", pkt->status);
#endif
if (pkt->type > 0xFF || pkt->type < 0x0) {
status = ZSM_STA_INVALID_TYPE;
error(0, "Invalid packet type");
goto failure;
}
#if DEBUG == 1
printf("Type: %d\n", pkt->type);
printf("Length: %d\n", pkt->length);
#endif
/* Not the same type as wanted to receive */
if (pkt->type != required_type) {
/* 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");
error(0, "Invalid packet type: %d", pkt->type);
goto failure;
}
@ -64,76 +49,44 @@ int recv_packet(packet_t *pkt, int fd, uint8_t required_type)
error(0, "Data too long: %d", pkt->length);
goto failure;
}
#if DEBUG == 1
printf("Length: %d\n", pkt->length);
#endif
size_t bytes_read = 0;
/* 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) {
pkt->data = memalloc((pkt->length + 1) * sizeof(char));
if (pkt->data == NULL) {
pkt->data = memalloc(pkt->length + 1);
pkt->signature = memalloc(SIGN_SIZE);
if (!pkt->data || !pkt->signature) {
status = ZSM_STA_MEMORY_ALLOCATION;
goto failure;
}
/* Read data from the socket */
if ((bytes_read = recv(fd, pkt->data, pkt->length, 0)) < 0) {
status = ZSM_STA_READING_SOCKET;
error(0, "Error reading from socket");
free(pkt->data);
goto failure;
}
if (bytes_read == 0) {
error(0, "Closed connection");
return ZSM_STA_READING_SOCKET;
}
if (bytes_read != pkt->length) {
status = ZSM_STA_INVALID_LENGTH;
error(0, "Invalid data length: bytes_read=%ld != pkt->length=%d", bytes_read, pkt->length);
size_t payload_len = pkt->length + SIGN_SIZE;
uint8_t payload[payload_len];
/* Read data and signature from the socket in one sys call */
if ((bytes_read = recv(fd, payload, payload_len, 0)) != payload_len) {
status = (bytes_read == 0) ? ZSM_STA_CLOSED_CONNECTION : ZSM_STA_READING_SOCKET;
error(0, "Error reading from socket, status => %d", status);
free(pkt->data);
free(pkt->signature);
goto failure;
}
/* Unpack paylaod */
memcpy(pkt->data, payload, pkt->length);
memcpy(pkt->signature, payload + pkt->length, SIGN_SIZE);
/* Null terminate data so it can be print */
pkt->data[pkt->length] = '\0';
#if DEBUG == 1
printf("Data:\n");
for (int i = 0; i < pkt->length; i++) {
printf("%d ", pkt->data[i]);
}
printf("\n");
#endif
pkt->signature = memalloc((SIGN_SIZE + 1) * sizeof(char));
if (pkt->signature == NULL) {
status = ZSM_STA_MEMORY_ALLOCATION;
goto failure;
}
if ((bytes_read = recv(fd, pkt->signature, SIGN_SIZE, 0)) < 0) {
status = ZSM_STA_READING_SOCKET;
error(0, "Error reading from socket");
free(pkt->data);
goto failure;
}
/* Don't check signature if the packet is emtpy */
if (pkt->length > 0 && bytes_read != SIGN_SIZE) {
status = ZSM_STA_INVALID_LENGTH;
error(0, "Invalid signature length: bytes_read=%ld != SIGN_SIZE(32)", bytes_read);
free(pkt->data);
goto failure;
}
pkt->signature[SIGN_SIZE] = '\0';
#if DEBUG == 1
print_bin(pkt->data, pkt->length);
printf("Signature:\n");
for (int i = 0; i < SIGN_SIZE; i++) {
printf("%d ", pkt->signature[i]);
}
printf("\n");
print_bin(pkt->signature, SIGN_SIZE);
#endif
}
#if DEBUG == 1
printf("==========END RECEIVING============\n");
printf("==========END RECEIVING==========\n");
#endif
return status;
@ -173,30 +126,64 @@ 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;
uint32_t length = pkt->length;
if (send(fd, &pkt->status, sizeof(pkt->status), 0) <= 0 ||
send(fd, &pkt->type, sizeof(pkt->type), 0) <= 0 ||
send(fd, &pkt->length, sizeof(pkt->length), 0) <= 0)
{
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];
/* 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));
/* 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->length > 0 && pkt->data != NULL) {
if (send(fd, pkt->data, length, 0) <= 0) goto failure;
if (send(fd, pkt->signature, SIGN_SIZE, 0) <= 0) goto failure;
/* 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);
/* 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;
}
}
#if DEBUG == 1
printf("==========PACKET SENT============\n");
print_packet(pkt);
printf("Status: %d\n", pkt->status);
printf("Type: %d\n", pkt->type);
printf("Length: %d\n", pkt->length);
if (pkt->length > 0) {
printf("Data:\n");
print_bin(pkt->data, pkt->length);
printf("Signature:\n");
print_bin(pkt->signature, SIGN_SIZE);
}
printf("==========END SENT===============\n");
#endif
return status;
failure:
/* Or we could resend it? */
status = ZSM_STA_WRITING_SOCKET;
error(0, "Error writing to socket");
free(pkt->data);
free_packet(pkt);
close(fd);
return status;
}
@ -233,14 +220,14 @@ int verify_packet(packet_t *pkt, int fd)
memcpy(from, pkt->data, MAX_NAME);
/* TODO: replace with db operations */
key_pair *kp_from = get_key_pair(from);
keypair_t *kp_from = get_keypair(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.bin) != 0) {
if (crypto_sign_verify_detached(pkt->signature, hash, HASH_SIZE, kp_from->pk.raw) != 0) {
/* Not match */
error(0, "Cannot verify data integrity");
packet_t *error_pkt = create_packet(ZSM_STA_ERROR_INTEGRITY, ZSM_TYP_ERROR, 0, NULL,
@ -270,7 +257,7 @@ uint8_t *create_signature(uint8_t *data, uint32_t length, secret_key *sk)
crypto_generichash(hash, HASH_SIZE,
data, length,
NULL, 0);
crypto_sign_detached(signature, NULL, hash, HASH_SIZE, sk->bin);
crypto_sign_detached(signature, NULL, hash, HASH_SIZE, sk->raw);
}
return signature;