From 32d75fadbf193218d0be42ca91b7688f1854f6e4 Mon Sep 17 00:00:00 2001 From: Test_User Date: Sat, 6 May 2023 03:03:58 -0400 Subject: Start adding client support --- network.c | 634 -------------------------------------------------------------- 1 file changed, 634 deletions(-) delete mode 100644 network.c (limited to 'network.c') diff --git a/network.c b/network.c deleted file mode 100644 index 70c58fe..0000000 --- a/network.c +++ /dev/null @@ -1,634 +0,0 @@ -// Network command handlers for HaxServ -// -// Written by: Test_User -// -// This is free and unencumbered software released into the public -// domain. -// -// Anyone is free to copy, modify, publish, use, compile, sell, or -// distribute this software, either in source code form or as a compiled -// binary, for any purpose, commercial or non-commercial, and by any -// means. -// -// In jurisdictions that recognize copyright laws, the author or authors -// of this software dedicate any and all copyright interest in the -// software to the public domain. We make this dedication for the benefit -// of the public at large and to the detriment of our heirs and -// successors. We intend this dedication to be an overt act of -// relinquishment in perpetuity of all present and future rights to this -// software under copyright law. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "network.h" -#include "types.h" -#include "table.h" -#include "tls.h" -#include "config.h" -#include "utils.h" -#include "commands.h" - -int resolve(char *address, char *port, struct sockaddr *sockaddr) { - int success; - struct addrinfo hints = {0}, *info; - - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - hints.ai_flags = AI_NUMERICSERV | AI_ADDRCONFIG; - - success = getaddrinfo(address, port, &hints, &info); - - if (success == 0) { - *sockaddr = *(info->ai_addr); - freeaddrinfo(info); - } - - return success; -} - -struct table network_commands = {0}; -struct table server_list = {0}; -struct table user_list = {0}; - -int ping_handler(struct string sender, uint64_t argc, struct string *argv) { - if (argc < 2) { - puts("Invalid PING recieved! (Missing parameters)"); - return 1; - } - - uint64_t len = 1 + argv[1].len + 6 + argv[1].len + 1 + sender.len + 1; - char msg[len]; - uint64_t offset = 0; - msg[0] = ':'; - offset++; - memcpy(msg+offset, argv[1].data, argv[1].len); - offset += argv[1].len; - memcpy(msg+offset, " PONG ", 6); - offset += 6; - memcpy(msg+offset, argv[1].data, argv[1].len); - offset += argv[1].len; - msg[offset] = ' '; - offset++; - memcpy(msg+offset, sender.data, sender.len); - offset += sender.len; - msg[offset] = '\n'; - - struct string m; - m.data = msg; - m.len = len; - SEND(m); - - return 0; -} - -int server_handler(struct string sender, uint64_t argc, struct string *argv) { - if (argc < 5) { - puts("Invalid SERVER recieved! (Missing parameters)"); - return 1; - } - - if (argv[2].len > 20) { - puts("Invalid SERVER recieved! (Distance too large)"); - return 1; - } - - uint8_t err; - uint64_t distance = str_to_unsigned(argv[2], &err); - if (err) { - puts("Invalid SERVER recieved! (Invalid distance given)"); - return 1; - } - - if (sender.len != 0) { - struct remote_server *from = get_table_index(server_list, sender); - if (!from) { - puts("Invalid SERVER recieved! (Unknown source)"); - return 1; - } - - distance += from->distance + 1; - } - - struct string address; - address.data = malloc(argv[0].len); - if (address.data == 0) - goto server_handler_oom; - - address.len = argv[0].len; - memcpy(address.data, argv[0].data, argv[0].len); - - struct string name; - name.data = malloc(argv[4].len); - if (name.data == 0) - goto server_handler_free_address; - - name.len = argv[4].len; - memcpy(name.data, argv[4].data, argv[4].len); - - struct remote_server *server = malloc(sizeof(*server)); - if (server == 0) - goto server_handler_free_name; - - struct string via; - if (sender.len != 0) { // connected to the sender - via.data = malloc(sender.len); - if (!via.data) - goto server_handler_free_server; - - via.len = sender.len; - memcpy(via.data, sender.data, sender.len); - } else { // connected directly to us - via = (struct string){0}; - } - - *server = (struct remote_server){ - .name = name, - .address = address, - .distance = distance, - .via = via, - }; - - if (set_table_index(&server_list, argv[3], server) != 0) - goto server_handler_free_via; - - return 0; - - server_handler_free_via: - if (sender.len != 0) - free(via.data); - server_handler_free_server: - free(server); - server_handler_free_name: - free(name.data); - server_handler_free_address: - free(address.data); - server_handler_oom: - puts("OOM! (server_handler)"); - - return 1; -} - -int uid_handler(struct string sender, uint64_t argc, struct string *argv) { - if (argc < 10) { - puts("Invalid UID recieved! (Missing parameters)"); - return 1; - } - - if (argv[1].len > 20 || argv[7].len > 20) { - puts("Invalid UID recieved! (Timestamp too long)"); - return 1; - } - - if (sender.len == 0) { - puts("Invalid UID recieved! (No source)"); - return 1; - } - - if (get_table_index(user_list, argv[0])) { - WRITES(2, STRING("Invalid UID revieved! (Attempted to create already-existing user)\n")); - return 1; - } - - // TODO: modes - - uint8_t err; - uint64_t nick_ts = str_to_unsigned(argv[1], &err); - if (err) { - puts("Invalid UID recieved! (Invalid nick timestamp)"); - return 1; - } - - uint64_t user_ts = str_to_unsigned(argv[7], &err); - if (err) { - puts("Invalid UID recieved! (Invalid user timestamp)"); - return 1; - } - - struct string server; - server.data = malloc(sender.len); - if (!server.data) - goto uid_handler_oom; - server.len = sender.len; - memcpy(server.data, sender.data, sender.len); - - struct string nick; - nick.data = malloc(argv[2].len); - 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); - if (!hostname.data) - goto uid_handler_free_nick; - hostname.len = argv[3].len; - memcpy(hostname.data, argv[3].data, argv[3].len); - - struct string vhost; - vhost.data = malloc(argv[4].len); - if (!vhost.data) - goto uid_handler_free_hostname; - vhost.len = argv[4].len; - memcpy(vhost.data, argv[4].data, argv[4].len); - - struct string ident; - ident.data = malloc(argv[5].len); - if (!ident.data) - goto uid_handler_free_vhost; - ident.len = argv[5].len; - memcpy(ident.data, argv[5].data, argv[5].len); - - struct string ip; - ip.data = malloc(argv[6].len); - if (!ip.data) - goto uid_handler_free_ident; - ip.len = argv[6].len; - memcpy(ip.data, argv[6].data, argv[6].len); - - struct string realname; - realname.data = malloc(argv[argc - 1].len); - if (!realname.data) - goto uid_handler_free_ip; - realname.len = argv[argc - 1].len; - memcpy(realname.data, argv[argc - 1].data, argv[argc - 1].len); - - struct user_info *user = malloc(sizeof(*user)); - if (!user) - goto uid_handler_free_realname; - - *user = (struct user_info){ - .nick_ts = nick_ts, - .user_ts = user_ts, - .server = server, - .nick = nick, - .hostname = hostname, - .vhost = vhost, - .ident = ident, - .ip = ip, - .realname = realname, - .metadata = (struct table){.array = malloc(0), .len = 0}, - }; - - if (set_table_index(&user_list, argv[0], user) != 0) - goto uid_handler_free_user; - - return 0; - - uid_handler_free_user: - free(user); - uid_handler_free_realname: - free(realname.data); - uid_handler_free_ip: - free(ip.data); - uid_handler_free_ident: - free(ident.data); - uid_handler_free_vhost: - free(vhost.data); - uid_handler_free_hostname: - free(hostname.data); - uid_handler_free_nick: - free(nick.data); - uid_handler_free_server: - free(server.data); - uid_handler_oom: - puts("OOM! (uid_handler)"); - - return 1; -} - -int opertype_handler(struct string sender, uint64_t argc, struct string *argv) { - if (argc < 1) { - WRITES(2, STRING("Invalid OPERTYPE recieved! (Missing parameters)\n")); - return 1; - } - - if (sender.len == 0) { - WRITES(2, STRING("Invalid OPERTYPE recieved! (No source)\n")); - return 1; - } - - struct user_info *user = get_table_index(user_list, sender); - if (!user) { - WRITES(2, STRING("Server ")); - WRITES(2, sender); - WRITES(2, STRING(" attempted to set OPERTYPE on a nonexistent user!\n")); - return 1; - } - - struct string opertype = {.data = malloc(argv[0].len), .len = argv[0].len}; - if (!opertype.data) { - WRITES(2, STRING("OOM! (opertype_handler)\n")); - return 1; - } - memcpy(opertype.data, argv[0].data, argv[0].len); - - if (user->opertype.len) - free(user->opertype.data); - - user->opertype = opertype; - - return 0; -} - -int quit_handler(struct string sender, uint64_t argc, struct string *argv) { - struct user_info *info = remove_table_index(&user_list, sender); - if (!info) { - WRITES(2, STRING("QUIT: Unknown user!\n")); - return 1; - } - - free(info->server.data); - free(info->nick.data); - if (info->opertype.len) - free(info->opertype.data); - - // TODO: metadata - free(info->metadata.array); - free(info->realname.data); - free(info->hostname.data); - free(info->ip.data); - free(info->vhost.data); - free(info); - - return 0; -} - -int kill_handler(struct string sender, uint64_t argc, struct string *argv) { - if (argc < 2) { - WRITES(2, STRING("Invalid KILL recieved! (Missing parameters)\n")); - return 1; - } - -// TODO: Get accurate list of what got killed, what to rejoin, etc - - struct string id = STRING("1HC000000"); - if (argv[0].len != id.len || memcmp(argv[0].data, id.data, id.len) != 0) { - WRITES(2, STRING("Invalid KILL recieved! (Unknown user)\n")); - return 1; - } - - 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(" ")); - SEND(nick); - SEND(STRING(" ")); - SEND(hostmask); - SEND(STRING(" ")); - SEND(hostmask); - SEND(STRING(" HaxServ 192.168.1.1 ")); - SEND(((struct string){current_time, strlen(current_time)})); - SEND(STRING(" +k :HaxServ\n:1HC000000 OPERTYPE Admin\n")); - - for (uint64_t i = 0; i < num_prejoin_channels; i++) { - SEND(STRING("FJOIN ")); - SEND(prejoin_channels[i]); - SEND(STRING(" ")); - SEND(((struct string){current_time, strlen(current_time)})); - SEND(STRING(" + :,1HC000000\nMODE ")); - SEND(prejoin_channels[i]); - SEND(STRING(" +o 1HC000000\n")); - } - - 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")); - return 1; - } - - if (sender.len == 0) { - WRITES(2, STRING("Invalid PRIVMSG recieved (No source)\n")); - return 1; - } - - 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) - return 0; - - offset = command_prefix.len; - } else { - offset = 0; - } - - if (offset >= argv[1].len || argv[1].data[offset] == ' ') - return 0; - - uint64_t command_argc = 0; - uint64_t old_offset = offset; - while (offset < argv[1].len) { - while (offset < argv[1].len && argv[1].data[offset] != ' ') - offset++; - - command_argc++; - - while (offset < argv[1].len && argv[1].data[offset] == ' ') - offset++; - } - offset = old_offset; - - struct string command_argv[command_argc]; // argv[0] in this case is the command itself, unlike network command handlers... might change one of these two later to match - uint64_t i = 0; - while (offset < argv[1].len) { - command_argv[i].data = argv[1].data+offset; - uint64_t start = offset; - - while (offset < argv[1].len && argv[1].data[offset] != ' ') - offset++; - - command_argv[i].len = offset - start; - - while (offset < argv[1].len && argv[1].data[offset] == ' ') - offset++; - - i++; - } - - argv[1].data += old_offset; - argv[1].len -= old_offset; - struct command_def *cmd = get_table_index(user_commands, command_argv[0]); - if (cmd) { - if (!cmd->local_only) { - 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) { - 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 - 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; - } - } - - 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 - WRITES(1, STRING("Not executing local-only command from a remote source!\n")); - return 0; - } - } else { - 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; - } -} - -int initservernetwork(void) { - network_commands.array = malloc(0); - server_list.array = malloc(0); - user_list.array = malloc(0); - - set_table_index(&network_commands, STRING("PING"), &ping_handler); - set_table_index(&network_commands, STRING("SERVER"), &server_handler); - set_table_index(&network_commands, STRING("UID"), &uid_handler); - set_table_index(&network_commands, STRING("OPERTYPE"), &opertype_handler); - 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(); - - int retval = connect_tls(); - if (retval != 0) { - printf("connect_tls(): %d\n", retval); - return 1; - } - - // probably inefficient to be calling SSL_write this frequently, but also less effort - SEND(STRING("SERVER hax.irc.andrewyu.org ")); - SEND(send_password); - SEND(STRING(" 0 1HC :HaxServ\n")); - SEND(STRING("BURST ")); - 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)})); - SEND(STRING(" ")); - SEND(nick); - SEND(STRING(" ")); - SEND(hostmask); - SEND(STRING(" ")); - SEND(hostmask); - SEND(STRING(" HaxServ 192.168.1.1 ")); - SEND(((struct string){current_time, strlen(current_time)})); - SEND(STRING(" +k :HaxServ\n:1HC000000 OPERTYPE Admin\n")); - - for (uint64_t i = 0; i < num_prejoin_channels; i++) { - SEND(STRING("FJOIN ")); - SEND(prejoin_channels[i]); - SEND(STRING(" ")); - SEND(((struct string){current_time, strlen(current_time)})); - SEND(STRING(" + :,1HC000000\nMODE ")); - SEND(prejoin_channels[i]); - SEND(STRING(" +o 1HC000000\n")); - } - - SEND(STRING("ENDBURST\n")); - - return 0; -} -- cgit v1.2.3