diff options
Diffstat (limited to '')
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | client_network.c | 158 | ||||
-rw-r--r-- | config.h | 2 | ||||
-rw-r--r-- | main.c | 174 | ||||
-rw-r--r-- | network.h | 16 | ||||
-rw-r--r-- | server_network.c (renamed from network.c) | 31 |
6 files changed, 364 insertions, 25 deletions
@@ -30,14 +30,14 @@ CFLAGS += $(INCLUDEFLAGS) -D_REENTRANT -ggdb3 -Wall -Wextra -Wno-unused-parameter $(shell pkg-config gnutls --cflags) -LDFLAGS = -lssl -lcrypto $(shell pkg-config gnutls --libs) +LDFLAGS = -lpthread $(shell pkg-config gnutls --libs) DEPS = $(shell $(CC) $(INCLUDEFLAGS) -MM -MT $(1).o $(1).c | sed -z 's/\\\n //g') .PHONY: all clean cleanall release all: haxserv -haxserv: main.o network.o commands.o table.o config.o tls.o utils.o +haxserv: main.o server_network.o client_network.o commands.o table.o config.o tls.o utils.o $(CC) $^ -o $@ $(LDFLAGS) %.o: %.c @@ -45,7 +45,9 @@ haxserv: main.o network.o commands.o table.o config.o tls.o utils.o $(call DEPS,main) -$(call DEPS,network) +$(call DEPS,server_network) + +$(call DEPS,client_network) $(call DEPS,commands) diff --git a/client_network.c b/client_network.c new file mode 100644 index 0000000..05e0787 --- /dev/null +++ b/client_network.c @@ -0,0 +1,158 @@ +// Client 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 <arpa/inet.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <sys/socket.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +#include "network.h" +#include "config.h" +#include "types.h" +#include "table.h" +#include "tls.h" + +// TODO: Lock sends (everywhere) + +struct table client_network_commands = {0}; +struct string client_nick = {0}; +uint8_t client_connected; + +int client_nick_handler(uint64_t argc, struct string *argv) { + if (argc < 1) + return 1; + + void *tmp = malloc(argv[0].len); + if (!tmp) + return 1; + memcpy(tmp, argv[0].data, argv[0].len); + + free(client_nick.data); + + client_nick.data = tmp; + client_nick.len = argv[0].len; + + if (client_connected) { + SEND(STRING(":1HC000001 NICK ")); + SEND(client_nick); + SEND(STRING(" ")); + char current_time[22]; + snprintf(current_time, 22, "%ld", time(NULL)); + SEND(((struct string){current_time, strlen(current_time)})); + SEND(STRING("\n")); + } + + return 0; +} + +int client_user_handler(uint64_t argc, struct string *argv) { + if (argc < 4) + return 1; + + if (client_nick.len == 0) + return 1; + + char current_time[22]; + snprintf(current_time, 22, "%ld", time(NULL)); + SEND(STRING("UID 1HC000001 ")); + SEND(((struct string){current_time, strlen(current_time)})); + SEND(STRING(" ")); + SEND(client_nick); + SEND(STRING(" ")); + SEND(client_hostmask); + SEND(STRING(" ")); + SEND(client_hostmask); + SEND(STRING(" ")); + SEND(argv[0]); + SEND(STRING(" 192.168.1.1 ")); + SEND(((struct string){current_time, strlen(current_time)})); + SEND(STRING(" +k :")); + SEND(argv[3]); + SEND(STRING("\n")); + + SENDCLIENT(STRING(":hax.irc.andrewyu.org 001 me :Welcome to the LibreIRC IRC Network\n")); + SENDCLIENT(STRING(":hax.irc.andrewyu.org 002 me :Your host is hax.irc.andrewyu.org, running a totally not sus IRCd\n")); + SENDCLIENT(STRING(":hax.irc.andrewyu.org 003 me :This server was created 02:51:36 Apr 03 2023")); + SENDCLIENT(STRING(":hax.irc.andrewyu.org 004 me irc.andrewyu.org InspIRCd-3 BDGHILNORSTWcdghikorswxz ABCDEFGHIJKLMNOPQRSTXYZabcdefghijklmnopqrstuvwz :BEFHIJLXYZabdefghjkloqvw")); + SENDCLIENT(STRING(":hax.irc.andrewyu.org 005 me ACCEPT=100 AWAYLEN=200 BOT=B CALLERID=g CASEMAPPING=ascii CHANLIMIT=#:20 CHANMODES=IXZbegw,k,BEFHJLdfjl,ACDGKMNOPQRSTcimnprstuz CHANNELLEN=60 CHANTYPES=# ELIST=CMNTU ESILENCE=CcdiNnPpTtx EXCEPTS=e :are supported by this server")); + SENDCLIENT(STRING(":hax.irc.andrewyu.org 005 me EXTBAN=,ACNOQRSTUacjmnprswz HOSTLEN=64 INVEX=I KEYLEN=32 KICKLEN=300 LINELEN=512 MAXLIST=I:1000,X:1000,b:1000,e:1000,g:1000,w:1000 MAXTARGETS=20 MODES=20 MONITOR=30 NAMELEN=130 NAMESX NETWORK=LibreIRC :are supported by this server")); + SENDCLIENT(STRING(":hax.irc.andrewyu.org 005 me NICKLEN=30 OVERRIDE=O PREFIX=(Yqaohv)!~&@%+ REMOVE SAFELIST SECURELIST=60 SILENCE=100 STATUSMSG=!~&@%+ TOPICLEN=330 UHNAMES USERIP USERLEN=10 USERMODES=,,s,BDGHILNORSTWcdghikorwxz :are supported by this server")); + SENDCLIENT(STRING(":hax.irc.andrewyu.org 005 me WATCH=32 WHOX :are supported by this server")); + + client_connected = 1; + + return 0; +} + +int client_join_handler(uint64_t argc, struct string *argv) { + if (argc < 1) + return 1; + + SEND(STRING(":1HC FJOIN ")); + SEND(argv[0]); + SEND(STRING(" ")); + char current_time[22]; + snprintf(current_time, 22, "%ld", time(NULL)); + SEND(((struct string){current_time, strlen(current_time)})); + SEND(STRING(" + :,1HC000001\n")); + + return 0; +} + +int client_fd = -1; + +int client_listen_fd; +int initclientnetwork(void) { + client_network_commands.array = malloc(0); + + set_table_index(&client_network_commands, STRING("NICK"), &client_nick_handler); + set_table_index(&client_network_commands, STRING("USER"), &client_user_handler); + set_table_index(&client_network_commands, STRING("JOIN"), &client_join_handler); + + client_nick.data = malloc(0); + + client_listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (client_listen_fd < 0) + return 1; + + struct sockaddr_in localhost = { + .sin_family = AF_INET, + .sin_port = htons(6667), + }; + inet_pton(AF_INET, "127.0.0.1", &localhost.sin_addr); // this is indeed localhost for mine, and I have no intent to change this + bind(client_listen_fd, (struct sockaddr*)&localhost, sizeof(localhost)); + + listen(client_listen_fd, 1); + + return 0; +} @@ -43,3 +43,5 @@ extern struct string prejoin_channels[]; extern uint64_t num_prejoin_channels; extern struct string command_prefix; + +extern struct string client_hostmask; @@ -30,6 +30,7 @@ #include <string.h> #include <stdlib.h> #include <stdio.h> +#include <pthread.h> #include "network.h" #include "config.h" @@ -37,12 +38,181 @@ #include "tls.h" #include "types.h" +void *client_loop(void *ign) { + while (1) { + struct string full_msg = {.data = malloc(0), .len = 0}; + WRITES(1, STRING("Yay\n")); + client_fd = accept(client_listen_fd, NULL, NULL); + listen(client_listen_fd, 0); + client_connected = 0; + client_nick.data = malloc(0); + while (1) { + char data[512]; + uint64_t new_len = read(client_fd, data, 512); + + if (new_len == 0) { + goto disconnect_client; + } + + uint8_t found = 0; + uint64_t msg_len; + for (uint64_t i = 0; i < new_len; i++) { + if (data[i] == '\n') { + found = 1; + msg_len = i + full_msg.len; + break; + } + } + + void *tmp = realloc(full_msg.data, full_msg.len+new_len); + if (tmp == 0 && full_msg.len+new_len != 0) { + WRITES(2, STRING("OOM... disconnect client.\n")); + goto disconnect_client; + } + full_msg.data = tmp; + + memcpy(full_msg.data+full_msg.len, data, new_len); + + full_msg.len += new_len; + + if (!found) + continue; + + while (1) { + WRITES(1, STRING("Recvd: ")); + write(1, full_msg.data, msg_len+1); // +1: \n + if (full_msg.data[msg_len - 1] == '\r') + msg_len--; + + uint64_t offset = 0; + while (offset < msg_len && full_msg.data[offset] == ' ') + offset++; + + if (offset == msg_len) { + puts("Protocol violation: No command."); + goto disconnect_client; + } + + struct string command; + command.data = full_msg.data+offset; + found = 0; + for (uint64_t i = offset; i < msg_len; i++) { + if (full_msg.data[i] == ' ') { + found = 1; + command.len = i - offset; + offset = i; + break; + } + } + if (!found) { + command.len = msg_len - offset; + offset = msg_len; + } + + while (offset < msg_len && full_msg.data[offset] == ' ') + offset++; + + uint64_t argc = 0; + uint64_t old_offset = offset; + if (offset < msg_len) { + while (offset < msg_len) { + if (full_msg.data[offset] == ':') { + argc++; + break; + } + + while (offset < msg_len && full_msg.data[offset] != ' ') + offset++; + + argc++; + + while (offset < msg_len && full_msg.data[offset] == ' ') + offset++; + } + } + offset = old_offset; + + struct string argv[argc]; + if (offset < msg_len) { + uint64_t i = 0; + while (offset < msg_len) { + if (full_msg.data[offset] == ':') { + argv[i].data = full_msg.data+offset+1; + argv[i].len = msg_len - offset - 1; + break; + } + + argv[i].data = full_msg.data+offset; + uint64_t start = offset; + + while (offset < msg_len && full_msg.data[offset] != ' ') + offset++; + + argv[i].len = offset - start; + + while (offset < msg_len && full_msg.data[offset] == ' ') + offset++; + + i++; + } + } + + int (*func)(uint64_t argc, struct string *argv) = get_table_index(client_network_commands, command); + + if (func == 0) { + WRITES(2, STRING("WARNING: Command is unknown, ignoring...\n")); + } else { + int err = func(argc, argv); + if (err) { + WRITES(1, STRING("Disconnecting client by result of the network command handler...\n")); + goto disconnect_client; + } + } + write(1, "\n", 1); + + if (full_msg.data[msg_len] == '\r') + msg_len++; + memmove(full_msg.data, full_msg.data+msg_len+1, full_msg.len - msg_len - 1); + full_msg.len -= msg_len+1; + + found = 0; + for (uint64_t i = 0; i < full_msg.len; i++) { + if (full_msg.data[i] == '\n') { + found = 1; + msg_len = i; + break; + } + } + + if (found == 0) { + void *tmp = realloc(full_msg.data, full_msg.len); + if (tmp == 0 && full_msg.len != 0) { + puts("AAAAAAAAA (OOM shrinking allocated data?)"); + goto disconnect_client; + } + full_msg.data = tmp; + + break; + } + } + } + disconnect_client: + close(client_fd); + free(full_msg.data); + listen(client_listen_fd, 1); + } +} + +pthread_t client_thread_id; int main(void) { initservernetwork(); + initclientnetwork(); + + pthread_create(&client_thread_id, NULL, client_loop, NULL); struct string full_msg = {malloc(0), 0}; while (1) { - uint8_t data[512]; + char data[512]; uint64_t new_len; { int len; @@ -190,7 +360,7 @@ int main(void) { } } - int (*func)(struct string source, uint64_t argc, struct string *argv) = get_table_index(network_commands, command); + int (*func)(struct string source, uint64_t argc, struct string *argv) = get_table_index(server_network_commands, command); if (func == 0) { WRITES(2, STRING("WARNING: Command is unknown, ignoring...\n")); @@ -59,9 +59,19 @@ struct user_info { struct table metadata; }; -extern struct table network_commands; +extern struct table server_network_commands; +extern struct table client_network_commands; extern struct table server_list; extern struct table user_list; -int resolve(char* address, char* port, struct sockaddr *server); -int initservernetwork(void); +extern int client_fd; +extern int client_listen_fd; +extern struct string client_nick; +extern uint8_t client_connected; + +extern int resolve(char* address, char* port, struct sockaddr *server); + +extern int initservernetwork(void); +extern int initclientnetwork(void); + +#define SENDCLIENT(x) write(client_fd, x.data, x.len) diff --git a/network.c b/server_network.c index 70c58fe..0d7beb4 100644 --- a/network.c +++ b/server_network.c @@ -1,4 +1,4 @@ -// Network command handlers for HaxServ +// Server network command handlers for HaxServ // // Written by: Test_User <hax@andrewyu.org> // @@ -28,11 +28,11 @@ #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 <string.h> #include <stdlib.h> #include <stdio.h> @@ -63,7 +63,7 @@ int resolve(char *address, char *port, struct sockaddr *sockaddr) { return success; } -struct table network_commands = {0}; +struct table server_network_commands = {0}; struct table server_list = {0}; struct table user_list = {0}; @@ -90,10 +90,7 @@ int ping_handler(struct string sender, uint64_t argc, struct string *argv) { offset += sender.len; msg[offset] = '\n'; - struct string m; - m.data = msg; - m.len = len; - SEND(m); + SEND(((struct string){msg, len})); return 0; } @@ -577,18 +574,18 @@ int privmsg_handler(struct string sender, uint64_t argc, struct string *argv) { } int initservernetwork(void) { - network_commands.array = malloc(0); + server_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); + set_table_index(&server_network_commands, STRING("PING"), &ping_handler); + set_table_index(&server_network_commands, STRING("SERVER"), &server_handler); + set_table_index(&server_network_commands, STRING("UID"), &uid_handler); + set_table_index(&server_network_commands, STRING("OPERTYPE"), &opertype_handler); + set_table_index(&server_network_commands, STRING("PRIVMSG"), &privmsg_handler); + set_table_index(&server_network_commands, STRING("QUIT"), &quit_handler); + set_table_index(&server_network_commands, STRING("KILL"), &kill_handler); + set_table_index(&server_network_commands, STRING("NICK"), &nick_handler); init_user_commands(); @@ -625,7 +622,7 @@ int initservernetwork(void) { SEND(((struct string){current_time, strlen(current_time)})); SEND(STRING(" + :,1HC000000\nMODE ")); SEND(prejoin_channels[i]); - SEND(STRING(" +o 1HC000000\n")); + SEND(STRING(" +k 1HC000000\n:1HC000000 OPERTYPE Admin\n")); } SEND(STRING("ENDBURST\n")); |