Add closed connection status, remove print_packet routine and revamp how send_packet and recv_packet works
This commit is contained in:
parent
2801fad655
commit
e50093283f
2 changed files with 96 additions and 109 deletions
|
@ -47,6 +47,7 @@
|
||||||
#define ZSM_STA_ERROR_INTEGRITY 0xC
|
#define ZSM_STA_ERROR_INTEGRITY 0xC
|
||||||
#define ZSM_STA_UNAUTHORISED 0xD
|
#define ZSM_STA_UNAUTHORISED 0xD
|
||||||
#define ZSM_STA_AUTHORISED 0xE
|
#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 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
|
#define HASH_SIZE crypto_generichash_BYTES
|
||||||
|
@ -72,7 +73,6 @@ typedef struct message_t {
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
|
|
||||||
/* Utilities functions */
|
/* Utilities functions */
|
||||||
void print_packet(packet_t *msg);
|
|
||||||
int recv_packet(packet_t *pkt, int fd, uint8_t required_type);
|
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);
|
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);
|
int send_packet(packet_t *msg, int fd);
|
||||||
|
|
205
lib/packet.c
205
lib/packet.c
|
@ -2,25 +2,6 @@
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "util.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
|
* Requires manually free packet data
|
||||||
* pkt: packet to fill data in (must be created via create_packet)
|
* 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 recv_packet(packet_t *pkt, int fd, uint8_t required_type)
|
||||||
{
|
{
|
||||||
int status = ZSM_STA_SUCCESS;
|
int status = ZSM_STA_SUCCESS;
|
||||||
|
size_t bytes_read = 0;
|
||||||
|
|
||||||
/* Read the packet components */
|
/* Buffer to store header (status, type, length) */
|
||||||
if (recv(fd, &pkt->status, sizeof(pkt->status), 0) < 0 ||
|
size_t header_len = sizeof(pkt->status) + sizeof(pkt->type) + sizeof(pkt->length);
|
||||||
recv(fd, &pkt->type, sizeof(pkt->type), 0) < 0 ||
|
uint8_t header[header_len];
|
||||||
recv(fd, &pkt->length, sizeof(pkt->length), 0) < 0) {
|
|
||||||
status = ZSM_STA_READING_SOCKET;
|
/* Read the entire packet header in one system call */
|
||||||
error(0, "Error reading from socket");
|
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
|
#if DEBUG == 1
|
||||||
printf("==========PACKET RECEIVED==========\n");
|
printf("==========PACKET RECEIVED========\n");
|
||||||
printf("Status: %d\n", pkt->status);
|
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("Type: %d\n", pkt->type);
|
||||||
|
printf("Length: %d\n", pkt->length);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Not the same type as wanted to receive */
|
/* Validate the packet type and length */
|
||||||
if (pkt->type != required_type) {
|
if (pkt->type > 0xFF || pkt->type < 0x0 || pkt->type != required_type) {
|
||||||
status = ZSM_STA_INVALID_TYPE;
|
status = ZSM_STA_INVALID_TYPE;
|
||||||
error(0, "Invalid packet type");
|
error(0, "Invalid packet type: %d", pkt->type);
|
||||||
goto failure;
|
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);
|
error(0, "Data too long: %d", pkt->length);
|
||||||
goto failure;
|
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 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) {
|
if (pkt->type != ZSM_TYP_INFO && pkt->length > 0) {
|
||||||
pkt->data = memalloc((pkt->length + 1) * sizeof(char));
|
pkt->data = memalloc(pkt->length + 1);
|
||||||
if (pkt->data == NULL) {
|
pkt->signature = memalloc(SIGN_SIZE);
|
||||||
|
|
||||||
|
if (!pkt->data || !pkt->signature) {
|
||||||
status = ZSM_STA_MEMORY_ALLOCATION;
|
status = ZSM_STA_MEMORY_ALLOCATION;
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read data from the socket */
|
size_t payload_len = pkt->length + SIGN_SIZE;
|
||||||
if ((bytes_read = recv(fd, pkt->data, pkt->length, 0)) < 0) {
|
uint8_t payload[payload_len];
|
||||||
status = ZSM_STA_READING_SOCKET;
|
|
||||||
error(0, "Error reading from socket");
|
/* Read data and signature from the socket in one sys call */
|
||||||
free(pkt->data);
|
if ((bytes_read = recv(fd, payload, payload_len, 0)) != payload_len) {
|
||||||
goto failure;
|
status = (bytes_read == 0) ? ZSM_STA_CLOSED_CONNECTION : ZSM_STA_READING_SOCKET;
|
||||||
}
|
error(0, "Error reading from socket, status => %d", status);
|
||||||
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);
|
|
||||||
free(pkt->data);
|
free(pkt->data);
|
||||||
|
free(pkt->signature);
|
||||||
goto failure;
|
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';
|
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
|
#if DEBUG == 1
|
||||||
printf("Signature:\n");
|
printf("Data:\n");
|
||||||
for (int i = 0; i < SIGN_SIZE; i++) {
|
print_bin(pkt->data, pkt->length);
|
||||||
printf("%d ", pkt->signature[i]);
|
printf("Signature:\n");
|
||||||
}
|
print_bin(pkt->signature, SIGN_SIZE);
|
||||||
printf("\n");
|
#endif
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#if DEBUG == 1
|
#if DEBUG == 1
|
||||||
printf("==========END RECEIVING============\n");
|
printf("==========END RECEIVING==========\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return status;
|
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 send_packet(packet_t *pkt, int fd)
|
||||||
{
|
{
|
||||||
int status = ZSM_STA_SUCCESS;
|
int status = ZSM_STA_SUCCESS;
|
||||||
uint32_t length = pkt->length;
|
size_t bytes_sent = 0;
|
||||||
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)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if DEBUG == 1
|
/* 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) {
|
||||||
|
/* 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");
|
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");
|
printf("==========END SENT===============\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
failure:
|
failure:
|
||||||
/* Or we could resend it? */
|
/* Or we could resend it? */
|
||||||
status = ZSM_STA_WRITING_SOCKET;
|
status = ZSM_STA_WRITING_SOCKET;
|
||||||
error(0, "Error writing to socket");
|
error(0, "Error writing to socket");
|
||||||
free(pkt->data);
|
free_packet(pkt);
|
||||||
close(fd);
|
close(fd);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -233,14 +220,14 @@ int verify_packet(packet_t *pkt, int fd)
|
||||||
memcpy(from, pkt->data, MAX_NAME);
|
memcpy(from, pkt->data, MAX_NAME);
|
||||||
|
|
||||||
/* TODO: replace with db operations */
|
/* 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 confidentiality by signature */
|
||||||
/* Verify data integrity by hash */
|
/* Verify data integrity by hash */
|
||||||
uint8_t hash[HASH_SIZE];
|
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, kp_from->pk.bin) != 0) {
|
if (crypto_sign_verify_detached(pkt->signature, hash, HASH_SIZE, kp_from->pk.raw) != 0) {
|
||||||
/* Not match */
|
/* Not match */
|
||||||
error(0, "Cannot verify data integrity");
|
error(0, "Cannot verify data integrity");
|
||||||
packet_t *error_pkt = create_packet(ZSM_STA_ERROR_INTEGRITY, ZSM_TYP_ERROR, 0, NULL,
|
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,
|
crypto_generichash(hash, HASH_SIZE,
|
||||||
data, length,
|
data, length,
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
crypto_sign_detached(signature, NULL, hash, HASH_SIZE, sk->bin);
|
crypto_sign_detached(signature, NULL, hash, HASH_SIZE, sk->raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
return signature;
|
return signature;
|
||||||
|
|
Loading…
Reference in a new issue