aboutsummaryrefslogtreecommitdiff
path: root/network.c
diff options
context:
space:
mode:
authorTest_User <hax@andrewyu.org>2023-05-06 03:03:58 -0400
committerTest_User <hax@andrewyu.org>2023-05-06 03:03:58 -0400
commit32d75fadbf193218d0be42ca91b7688f1854f6e4 (patch)
treebacc1c35036a0b38fe63f6cffeb711be43cc7ae3 /network.c
parent329ca8e8f40efdd7838d40435b5f113d2877c13c (diff)
downloadcoupserv-32d75fadbf193218d0be42ca91b7688f1854f6e4.tar.gz
coupserv-32d75fadbf193218d0be42ca91b7688f1854f6e4.zip
Start adding client support
Diffstat (limited to 'network.c')
-rw-r--r--network.c634
1 files changed, 0 insertions, 634 deletions
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 <hax@andrewyu.org>
-//
-// 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 <gnutls/gnutls.h>
-#include <netdb.h>
-#include <string.h>
-#include <arpa/inet.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#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;
-}