network: cleanup and improve network handling

- Merge encoded / plain messge handling to ensure fixes land in both
- Fix some potential resource leaks spotted by Coverity

[cleanup commit message]
[fix merge conflicts]
Signed-off-by: Nick Hainke <vincent@systemli.org>
This commit is contained in:
Ian Clowes 2022-01-31 10:53:59 +00:00 committed by Nick Hainke
parent 0eca0fae0b
commit 0a962bea1f
5 changed files with 117 additions and 95 deletions

View file

@ -15,16 +15,10 @@ int init_socket_runopts(const char *_ip, int _port, int _multicast_socket);
/** /**
* Send message via network. * Send message via network.
* @param msg * @param msg
* @param is_enc
* @return * @return
*/ */
int send_string(char *msg); int send_string(char *msg, bool is_enc);
/**
* Send encrypted message via network.
* @param msg
* @return
*/
int send_string_enc(char *msg);
/** /**
* Close socket. * Close socket.

View file

@ -20,6 +20,8 @@ int setup_broadcast_socket(const char *_broadcast_ip, unsigned short _broadcast_
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (void *) &broadcast_permission, if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (void *) &broadcast_permission,
sizeof(broadcast_permission)) < 0) { sizeof(broadcast_permission)) < 0) {
dawnlog_error("Failed to create socket.\n"); dawnlog_error("Failed to create socket.\n");
// FIXME: Is close() required?
close(sock);
return -1; return -1;
} }

View file

@ -1,6 +1,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include "utils.h" #include "utils.h"
#include "multicastsocket.h" #include "multicastsocket.h"
@ -30,12 +31,16 @@ int setup_multicast_socket(const char *_multicast_ip, unsigned short _multicast_
SO_REUSEADDR, SO_REUSEADDR,
&loop, sizeof(loop)) < 0) { &loop, sizeof(loop)) < 0) {
dawnlog_perror("setsockopt:SO_REUSEADDR"); dawnlog_perror("setsockopt:SO_REUSEADDR");
// FIXME: Is close() required?
close(sock);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (bind(sock, if (bind(sock,
(struct sockaddr *) addr, (struct sockaddr *) addr,
sizeof(*addr)) < 0) { sizeof(*addr)) < 0) {
dawnlog_perror("bind"); dawnlog_perror("bind");
// FIXME: Is close() required?
close(sock);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -46,6 +51,8 @@ int setup_multicast_socket(const char *_multicast_ip, unsigned short _multicast_
IP_MULTICAST_LOOP, IP_MULTICAST_LOOP,
&loop, sizeof(loop)) < 0) { &loop, sizeof(loop)) < 0) {
dawnlog_perror("setsockopt:IP_MULTICAST_LOOP"); dawnlog_perror("setsockopt:IP_MULTICAST_LOOP");
// FIXME: Is close() required?
close(sock);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -54,6 +61,8 @@ int setup_multicast_socket(const char *_multicast_ip, unsigned short _multicast_
command.imr_interface.s_addr = htonl (INADDR_ANY); command.imr_interface.s_addr = htonl (INADDR_ANY);
if (command.imr_multiaddr.s_addr == -1) { if (command.imr_multiaddr.s_addr == -1) {
dawnlog_perror("Wrong multicast address!\n"); dawnlog_perror("Wrong multicast address!\n");
// FIXME: Is close() required?
close(sock);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (setsockopt(sock, if (setsockopt(sock,
@ -61,6 +70,8 @@ int setup_multicast_socket(const char *_multicast_ip, unsigned short _multicast_
IP_ADD_MEMBERSHIP, IP_ADD_MEMBERSHIP,
&command, sizeof(command)) < 0) { &command, sizeof(command)) < 0) {
dawnlog_perror("setsockopt:IP_ADD_MEMBERSHIP"); dawnlog_perror("setsockopt:IP_ADD_MEMBERSHIP");
// FIXME: Is close() required?
close(sock);
} }
return sock; return sock;
} }

View file

@ -62,115 +62,130 @@ int init_socket_runopts(const char *_ip, int _port, int _multicast_socket) {
return 0; return 0;
} }
void *receive_msg(void *args) { // TODO: Will all messages arrive in a single read? Borrow looping partial read from tcpsocket.c?
static void* receive_msg_inner(void* args, bool is_enc) {
while (1) { while (1) {
if ((recv_string_len = recv_string_len = recvfrom(sock, recv_string, MAX_RECV_STRING, 0, NULL, 0);
recvfrom(sock, recv_string, MAX_RECV_STRING, 0, NULL, 0)) < 0) {
//FIXME: Next few lines look a bit mangled, with odd strlen() tests, etc...
if (recv_string_len < 0) {
dawnlog_error("Could not receive message!"); dawnlog_error("Could not receive message!");
continue; continue;
} }
if (strlen(recv_string) <= 0) { if (recv_string_len == 0) {
return 0; return 0;
} }
recv_string[recv_string_len] = '\0';
dawnlog_debug("Received network message: %s\n", recv_string); char* final_msg = NULL;
handle_network_msg(recv_string); if (!is_enc)
{
final_msg = recv_string;
}
else
{
size_t gcrypt_max_len = B64_DECODE_LEN(strlen(recv_string));
char* gcrypt_buf = dawn_malloc(gcrypt_max_len);
if (!gcrypt_buf) {
dawnlog_error("Received network error: not enough memory\n");
return 0;
}
size_t gcrypt_len = b64_decode(recv_string, gcrypt_buf, gcrypt_max_len);
final_msg = gcrypt_decrypt_msg(gcrypt_buf, gcrypt_len);
dawn_free(gcrypt_buf);
gcrypt_buf = NULL;
if (!final_msg) {
dawnlog_error("Received network error: not enough memory\n");
return 0;
}
}
dawnlog_debug("Received network message: %s\n", final_msg);
handle_network_msg(final_msg);
if (is_enc)
{
dawn_free(final_msg);
final_msg = NULL;
}
} }
} }
void* receive_msg(void* args) {
return receive_msg_inner(args, false);
}
void *receive_msg_enc(void *args) { void *receive_msg_enc(void *args) {
while (1) { return receive_msg_inner(args, true);
if ((recv_string_len =
recvfrom(sock, recv_string, MAX_RECV_STRING, 0, NULL, 0)) < 0) {
dawnlog_error("Could not receive message!\n");
continue;
}
if (strlen(recv_string) <= 0) {
return 0;
}
recv_string[recv_string_len] = '\0';
char *base64_dec_str = dawn_malloc(B64_DECODE_LEN(strlen(recv_string)));
if (!base64_dec_str){
dawnlog_error("Received network error: not enough memory\n");
return 0;
}
int base64_dec_length = b64_decode(recv_string, base64_dec_str, B64_DECODE_LEN(strlen(recv_string)));
char *dec = gcrypt_decrypt_msg(base64_dec_str, base64_dec_length);
if (!dec){
dawn_free(base64_dec_str);
base64_dec_str = NULL;
dawnlog_error("Received network error: not enough memory\n");
return 0;
}
dawnlog_debug("Received network message: %s\n", dec);
dawn_free(base64_dec_str);
base64_dec_str = NULL;
handle_network_msg(dec);
dawn_free(dec);
dec = NULL;
}
} }
int send_string(char *msg) { int send_string(char *msg, bool is_enc) {
pthread_mutex_lock(&send_mutex);
size_t msglen = strlen(msg);
if (sendto(sock,
msg,
msglen,
0,
(struct sockaddr *) &addr,
sizeof(addr)) < 0) {
dawnlog_perror("sendto()");
pthread_mutex_unlock(&send_mutex);
exit(EXIT_FAILURE);
}
pthread_mutex_unlock(&send_mutex);
return 0;
}
int send_string_enc(char *msg) {
pthread_mutex_lock(&send_mutex); pthread_mutex_lock(&send_mutex);
int length_enc; char* final_msg = NULL;
size_t msglen = strlen(msg); size_t msglen = 0;
char *enc = gcrypt_encrypt_msg(msg, msglen + 1, &length_enc);
if (!enc){ if (!is_enc)
dawnlog_error("sendto() error: not enough memory\n"); {
pthread_mutex_unlock(&send_mutex); // Include NUL terminator in message
exit(EXIT_FAILURE); final_msg = msg;
} msglen = strlen(msg) + 1;
char *base64_enc_str = dawn_malloc(B64_ENCODE_LEN(length_enc));
if (!base64_enc_str){
dawn_free(enc);
enc = NULL;
dawnlog_error("sendto() error: not enough memory\n");
pthread_mutex_unlock(&send_mutex);
exit(EXIT_FAILURE);
} }
size_t base64_enc_length = b64_encode(enc, length_enc, base64_enc_str, B64_ENCODE_LEN(length_enc)); else
{
int gcrypt_len = 0;
// Include NUL terminator in encrypted message
char* gcrypt_buf = gcrypt_encrypt_msg(msg, strlen(msg) + 1, &gcrypt_len);
if (!gcrypt_buf) {
dawnlog_error("sendto() error: not enough memory\n");
pthread_mutex_unlock(&send_mutex);
exit(EXIT_FAILURE);
}
size_t b64_max_len = B64_ENCODE_LEN(gcrypt_len);
char* final_msg = dawn_malloc(b64_max_len);
if (!final_msg) {
dawnlog_error("sendto() error: not enough memory\n");
dawn_free(gcrypt_buf);
gcrypt_buf = NULL;
pthread_mutex_unlock(&send_mutex);
exit(EXIT_FAILURE);
}
// very important to use actual length of string because of '\0' in encrypted msg
msglen = b64_encode(gcrypt_buf, gcrypt_len, final_msg, b64_max_len);
dawn_free(gcrypt_buf);
gcrypt_buf = NULL;
}
if (sendto(sock, if (sendto(sock,
base64_enc_str, final_msg,
base64_enc_length, // very important to use actual length of string because of '\0' in encrypted msg msglen,
0, 0,
(struct sockaddr *) &addr, (struct sockaddr*)&addr,
sizeof(addr)) < 0) { sizeof(addr)) < 0) {
dawnlog_perror("sendto()"); dawnlog_perror("sendto()");
// Tidy up probbaly unnecessary if we're exiting, but...
if (is_enc)
dawn_free(final_msg);
pthread_mutex_unlock(&send_mutex); pthread_mutex_unlock(&send_mutex);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
dawn_free(base64_enc_str);
base64_enc_str = NULL; if (is_enc)
dawn_free(enc); {
enc = NULL; dawn_free(final_msg);
final_msg = NULL;
}
pthread_mutex_unlock(&send_mutex); pthread_mutex_unlock(&send_mutex);
return 0; return 0;
} }

View file

@ -605,9 +605,9 @@ int send_blob_attr_via_network(struct blob_attr* msg, char* method) {
send_tcp(str); send_tcp(str);
} else { } else {
if (network_config.use_symm_enc) { if (network_config.use_symm_enc) {
send_string_enc(str); send_string(str, true);
} else { } else {
send_string(str); send_string(str, false);
} }
} }