diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | main.c | 20 | ||||
-rw-r--r-- | network.c | 124 | ||||
-rw-r--r-- | table.c | 42 | ||||
-rw-r--r-- | tls.c | 56 | ||||
-rw-r--r-- | tls.h | 6 |
6 files changed, 153 insertions, 99 deletions
@@ -28,9 +28,9 @@ #INCLUDEFLAGS = -CFLAGS += $(INCLUDEFLAGS) -D_REENTRANT -ggdb3 +CFLAGS += $(INCLUDEFLAGS) -D_REENTRANT -ggdb3 -Wall -Wextra -Wno-unused-parameter $(shell pkg-config gnutls --cflags) -LDFLAGS = -lssl -lcrypto +LDFLAGS = -lssl -lcrypto $(shell pkg-config gnutls --libs) DEPS = $(shell $(CC) $(INCLUDEFLAGS) -MM -MT $(1).o $(1).c | sed -z 's/\\\n //g') @@ -26,8 +26,10 @@ // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. -#include <openssl/ssl.h> +#include <gnutls/gnutls.h> #include <string.h> +#include <stdlib.h> +#include <stdio.h> #include "network.h" #include "config.h" @@ -41,10 +43,20 @@ int main(void) { struct string full_msg = {malloc(0), 0}; while (1) { uint8_t data[512]; - uint64_t new_len = SSL_read(ssl, data, 512); + uint64_t new_len; + { + int len; + do { + len = gnutls_record_recv(session, data, 512); + } while (len == GNUTLS_E_AGAIN || len == GNUTLS_E_INTERRUPTED); + if (len < 0) + new_len = 0; + else + new_len = len; + } if (new_len == 0) { - puts("Disconnected."); + WRITES(1, STRING("Disconnected.\n")); return 0; } @@ -60,7 +72,7 @@ int main(void) { void *tmp = realloc(full_msg.data, full_msg.len+new_len); if (tmp == 0 && full_msg.len+new_len != 0) { - puts("OOM... currently just exiting bc there's no automatic reconnect in here yet, and the only sane solution to this is resyncing."); + WRITES(2, STRING("OOM... currently just exiting bc there's no automatic reconnect in here yet, and the only sane solution to this is resyncing.\n")); return 1; } full_msg.data = tmp; @@ -26,7 +26,7 @@ // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. -#include <openssl/ssl.h> +#include <gnutls/gnutls.h> #include <netdb.h> #include <string.h> #include <arpa/inet.h> @@ -74,7 +74,7 @@ int ping_handler(struct string sender, uint64_t argc, struct string *argv) { } uint64_t len = 1 + argv[1].len + 6 + argv[1].len + 1 + sender.len + 1; - uint8_t msg[len]; + char msg[len]; uint64_t offset = 0; msg[0] = ':'; offset++; @@ -90,7 +90,10 @@ int ping_handler(struct string sender, uint64_t argc, struct string *argv) { offset += sender.len; msg[offset] = '\n'; - SSL_write(ssl, msg, len); + struct string m; + m.data = msg; + m.len = len; + SEND(m); return 0; } @@ -230,6 +233,7 @@ int uid_handler(struct string sender, uint64_t argc, struct string *argv) { if (!nick.data) goto uid_handler_free_server; nick.len = argv[2].len; + memcpy(nick.data, argv[2].data, argv[2].len); struct string hostname; hostname.data = malloc(argv[3].len); @@ -381,8 +385,8 @@ int kill_handler(struct string sender, uint64_t argc, struct string *argv) { return 1; } - uint8_t current_time[21]; // C HaxServ will be deprecated long before we reach 20-digit timestamps - snprintf(current_time, 21, "%d", time(NULL)); + char current_time[21]; // C HaxServ will be deprecated long before we reach 20-digit timestamps + snprintf(current_time, 21, "%ld", time(NULL)); SEND(STRING("UID 1HC000000 ")); SEND(((struct string){current_time, strlen(current_time)})); SEND(STRING(" ")); @@ -408,6 +412,45 @@ int kill_handler(struct string sender, uint64_t argc, struct string *argv) { return 0; } +int nick_handler(struct string sender, uint64_t argc, struct string *argv) { + if (argc < 2) { + WRITES(2, STRING("Invalid NICK recieved! (Missing parameters)\n")); + return 1; + } + + struct user_info *info = get_table_index(user_list, sender); + if (!info) { + WRITES(2, STRING("NICK: Unknown user!\n")); + return 1; + } + + void *tmp = malloc(argv[0].len); + if (!tmp) { + WRITES(2, STRING("OOM! (nick_handler)\n")); + return 1; + } + memcpy(tmp, argv[0].data, argv[0].len); + + free(info->nick.data); + info->nick.data = tmp; + info->nick.len = argv[0].len; + + if (argv[1].len > 20) { + WRITES(2, STRING("Invalid NICK recieved! (Timestamp too long)\n")); + return 1; + } + + uint8_t err; + uint64_t ts = str_to_unsigned(argv[1], &err); + if (err) { + WRITES(2, STRING("Invalid NICK recieved! (Invalid timestamp)\n")); + return 1; + } + info->nick_ts = ts; + + return 0; +} + int privmsg_handler(struct string sender, uint64_t argc, struct string *argv) { if (argc < 2) { WRITES(2, STRING("Invalid PRIVMSG recieved (Missing parameters)\n")); @@ -421,21 +464,16 @@ int privmsg_handler(struct string sender, uint64_t argc, struct string *argv) { uint64_t offset; if (argv[0].data[0] == '#') { - if (argv[1].len < command_prefix.len || memcmp(argv[1].data, command_prefix.data, command_prefix.len) != 0) { - WRITES(1, STRING("Message is not a command.\n")); - return 0; // not for us - } + if (argv[1].len < command_prefix.len || memcmp(argv[1].data, command_prefix.data, command_prefix.len) != 0) + return 0; offset = command_prefix.len; } else { offset = 0; } - if (offset >= argv[1].len || argv[1].data[offset] == ' ') { - // TODO: complain about empty command - WRITES(1, STRING("Command is empty?\n")); + if (offset >= argv[1].len || argv[1].data[offset] == ' ') return 0; - } uint64_t command_argc = 0; uint64_t old_offset = offset; @@ -475,21 +513,50 @@ int privmsg_handler(struct string sender, uint64_t argc, struct string *argv) { if (cmd->privs.len != 0 && sender.len != 3) { // servers always count as oper :P struct user_info *user = get_table_index(user_list, sender); if (!user) { - // TODO: complain about unknown user - WRITES(1, STRING("User is unknown!\n")); - return 0; + WRITES(2, STRING("User is unknown!\n")); + + SEND(STRING(":1HC000000 NOTICE ")); + if (argv[0].data[0] == '#') + SEND(argv[0]); + else + SEND(sender); + SEND(STRING(" :You don't seem to exist... and neither do I!\n")); + + return 1; // have already desynced } if (user->opertype.len != cmd->privs.len || memcmp(user->opertype.data, cmd->privs.data, cmd->privs.len)) { // TODO: complain about missing privs - WRITES(1, STRING("User lacks privs for this command!\n")); + SEND(STRING(":1HC000000 NOTICE ")); + if (argv[0].data[0] == '#') + SEND(argv[0]); + else + SEND(sender); + SEND(STRING(" :You are not authorized to execute this command.\n")); + return 0; } } - WRITES(1, STRING("Executing command ")); - WRITES(1, command_argv[0]); - write(1, "\n", 1); + SEND(STRING(":1HC000000 PRIVMSG ")); + SEND(log_channel); + if (sender.len == 3) { + SEND(STRING(" :Server ")); + SEND(sender); + } else { + struct user_info *user = get_table_index(user_list, sender); + if (user) { + SEND(STRING(" :User ")); + SEND(user->nick); + } else { + SEND(STRING(" :An unknown user (something desycned... this shouldn't happen)")); + } + } + + SEND(STRING(" executes `")); + SEND(argv[1]); + SEND(STRING("'\n")); + return cmd->func(sender, argv[1], argv[0], command_argc, command_argv); } else { // TODO: complain about remote access @@ -497,10 +564,14 @@ int privmsg_handler(struct string sender, uint64_t argc, struct string *argv) { return 0; } } else { - // TODO: complain about unknown command - WRITES(1, STRING("Command is unknown!\n")); - WRITES(1, command_argv[0]); - write(1, "\n", 1); + SEND(STRING(":1HC000000 NOTICE ")); + if (argv[0].data[0] == '#') + SEND(argv[0]); + else + SEND(sender); + SEND(STRING(" :Unknown command: " "\x03" "04")); + SEND(argv[1]); + SEND(STRING("\n")); return 0; } } @@ -517,6 +588,7 @@ int initservernetwork(void) { set_table_index(&network_commands, STRING("PRIVMSG"), &privmsg_handler); set_table_index(&network_commands, STRING("QUIT"), &quit_handler); set_table_index(&network_commands, STRING("KILL"), &kill_handler); + set_table_index(&network_commands, STRING("NICK"), &nick_handler); init_user_commands(); @@ -531,8 +603,8 @@ int initservernetwork(void) { SEND(send_password); SEND(STRING(" 0 1HC :HaxServ\n")); SEND(STRING("BURST ")); - uint8_t current_time[21]; // C HaxServ will be deprecated long before we reach 20-digit timestamps - snprintf(current_time, 21, "%d", time(NULL)); + char current_time[21]; // C HaxServ will be deprecated long before we reach 20-digit timestamps + snprintf(current_time, 21, "%ld", time(NULL)); SEND(((struct string){current_time, strlen(current_time)})); SEND(STRING("\nUID 1HC000000 ")); SEND(((struct string){current_time, strlen(current_time)})); @@ -53,8 +53,10 @@ static inline int compare(struct string a, struct string b) { } static inline uint64_t search(struct table tbl, struct string name, uint8_t *exists) { - if (tbl.len == 0) + if (tbl.len == 0) { + *exists = 0; return 0; + } size_t low = 0, high = tbl.len - 1; @@ -97,7 +99,7 @@ static inline uint64_t search(struct table tbl, struct string name, uint8_t *exi } int set_table_index(struct table *tbl, struct string name, void *ptr) { - uint8_t exists, err; + uint8_t exists; uint64_t index = search(*tbl, name, &exists); if (index == tbl->len) { @@ -135,42 +137,16 @@ int set_table_index(struct table *tbl, struct string name, void *ptr) { } void * get_table_index(struct table tbl, struct string name) { - if (tbl.len == 0) + uint8_t exists; + uint64_t index = search(tbl, name, &exists); + if (!exists) return 0; - size_t low = 0, high = tbl.len - 1; - - size_t mid = high/2; - - while (low != high) { - int val = compare(tbl.array[mid].name, name); - if (val == 0) { - return tbl.array[mid].ptr; - } else if (val > 0) { - low = mid + 1; - if (mid > low) - return 0; - if (low > high) - low = high; - } else { - high = mid - 1; - if (mid < high) - return 0; - if (high < low) - high = low; - } - - mid = low + ((high-low)/2); - } - - if (compare(tbl.array[mid].name, name) == 0) - return tbl.array[mid].ptr; - else - return 0; + return tbl.array[index].ptr; } void * remove_table_index(struct table *tbl, struct string name) { - uint8_t exists, err; + uint8_t exists; uint64_t index = search(*tbl, name, &exists); if (!exists) @@ -26,9 +26,7 @@ // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. -#include <openssl/ssl.h> -#include <openssl/err.h> -#include <openssl/x509v3.h> +#include <gnutls/gnutls.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> @@ -36,59 +34,55 @@ #include "network.h" #include "config.h" #include "types.h" +#include "tls.h" -SSL *ssl; -SSL_CTX *ctx; +gnutls_session_t session; int fd; int connect_tls(void) { // TODO: free used things on failure - SSL_library_init(); - SSL_load_error_strings(); - - const SSL_METHOD *method = TLS_client_method(); - if (method == NULL) + if (gnutls_global_init() < 0) return 1; - ctx = SSL_CTX_new(method); - if (ctx == NULL) + gnutls_certificate_credentials_t xcred; // TODO: if we reconnect + if (gnutls_certificate_allocate_credentials(&xcred) < 0) return 2; - SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION); - - int success = SSL_CTX_load_verify_locations(ctx, X509_get_default_cert_file(), NULL); - success |= SSL_CTX_load_verify_locations(ctx, NULL, X509_get_default_cert_dir()); - if (!success) + if (gnutls_certificate_set_x509_system_trust(xcred) < 0) return 3; - fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (fd == -1) + if (gnutls_init(&session, GNUTLS_CLIENT) < 0) return 4; - ssl = SSL_new(ctx); - if (ssl == NULL) + if (gnutls_server_name_set(session, GNUTLS_NAME_DNS, address.data, address.len) < 0) return 5; - X509_VERIFY_PARAM *param = SSL_get0_param(ssl); - X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_WILDCARDS); - if (!X509_VERIFY_PARAM_set1_host(param, address.data, address.len)) + if (gnutls_set_default_priority(session) < 0) return 6; - SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL); + if (gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred) < 0) + return 7; + gnutls_session_set_verify_cert(session, address.data, 0); + + fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (fd == -1) + return 8; struct sockaddr sockaddr; resolve(address.data, port.data, &sockaddr); int ret = connect(fd, &sockaddr, sizeof(sockaddr)); if (ret != 0) - return 7; + return 9; - if (SSL_set_fd(ssl, fd) != 1) - return 8; + gnutls_transport_set_int(session, fd); + gnutls_handshake_set_timeout(session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); - ret = SSL_connect(ssl); - if (ret != 1) - return 9; + do { + ret = gnutls_handshake(session); + } while (ret < 0 && gnutls_error_is_fatal(ret) == 0); + if (ret < 0) + return 10; return 0; } @@ -26,10 +26,10 @@ // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. -#include <openssl/ssl.h> +#include <gnutls/gnutls.h> -#define SEND(x) SSL_write(ssl, x.data, x.len) +#define SEND(x) gnutls_record_send(session, x.data, x.len) -extern SSL *ssl; +extern gnutls_session_t session; extern int connect_tls(void); |