summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTest_User <hax@andrewyu.org>2023-05-05 23:34:55 -0400
committerTest_User <hax@andrewyu.org>2023-05-05 23:34:55 -0400
commit329ca8e8f40efdd7838d40435b5f113d2877c13c (patch)
treea71b82548acc60185a448261a0088fa7e925e948
parent9343cffa8c032d5b44fce89af7fc5d8709acd9aa (diff)
downloadcoupserv-329ca8e8f40efdd7838d40435b5f113d2877c13c.tar.gz
coupserv-329ca8e8f40efdd7838d40435b5f113d2877c13c.zip
Switch to gnutls, add handling of NICK, add responses to unknown/invalid/etc command, change a few other things
-rw-r--r--Makefile4
-rw-r--r--main.c20
-rw-r--r--network.c124
-rw-r--r--table.c42
-rw-r--r--tls.c56
-rw-r--r--tls.h6
6 files changed, 153 insertions, 99 deletions
diff --git a/Makefile b/Makefile
index 57a2bd6..078fdf3 100644
--- a/Makefile
+++ b/Makefile
@@ -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')
diff --git a/main.c b/main.c
index 8e0e97b..e95d750 100644
--- a/main.c
+++ b/main.c
@@ -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;
diff --git a/network.c b/network.c
index 3f4d8fa..70c58fe 100644
--- a/network.c
+++ b/network.c
@@ -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)}));
diff --git a/table.c b/table.c
index e9a6fab..5dbc290 100644
--- a/table.c
+++ b/table.c
@@ -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)
diff --git a/tls.c b/tls.c
index c643f3a..b173d82 100644
--- a/tls.c
+++ b/tls.c
@@ -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;
}
diff --git a/tls.h b/tls.h
index f338fff..c21e85f 100644
--- a/tls.h
+++ b/tls.h
@@ -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);