From: Egor Date: Sun, 8 May 2022 08:42:10 +0000 (+0300) Subject: add oper passwords X-Git-Url: https://git.patchysicp.xyz/?a=commitdiff_plain;h=977d24124711ee8880a3e23471b91f737acff997;p=patchyircd.git add oper passwords --- diff --git a/.gitignore b/.gitignore index a1987c9..b1f688a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ ircd ircd.exe config.mk +setpass +ops.txt diff --git a/Makefile b/Makefile index c37657c..b9705a9 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ HEADERS:=$(wildcard *.h NetSock/*.h) -include config.mk .PHONY: all clean -all: $(TARGET) $(if $(CC.w32),$(TARGET).exe,) +all: $(TARGET) $(if $(CC.w32),$(TARGET).exe,) setpass clean: $(RM) $(TARGET) $(TARGET).exe @@ -12,3 +12,5 @@ $(TARGET): $(SOURCES) $(HEADERS) $(CC) $(CFLAGS) $(LDFLAGS) $(SOURCES) $(LDLIBS) -o $@ $(TARGET).exe: $(SOURCES) $(HEADERS) $(CC.w32) $(CFLAGS.w32) $(LDFLAGS.w32) $(SOURCES) $(LDLIBS.w32) -o $@ +setpass: tools/setpass.c passwd.c passwd.h + $(CC) $(CFLAGS) $(LDFLAGS) tools/setpass.c passwd.c $(LDLIBS) -o $@ diff --git a/NetSock/netsock.c b/NetSock/netsock.c index f928f91..0b9a43a 100644 --- a/NetSock/netsock.c +++ b/NetSock/netsock.c @@ -80,7 +80,6 @@ ssize_t send_log(SOCKET socket, const char *buffer, size_t length, int flags) { ssize_t recv_log(SOCKET socket, char *buffer, size_t length, int flags) { ssize_t bytesRead = recv(socket,buffer,length,flags); if(bytesRead > 0) { - buffer[bytesRead] = 0; printf("CLIENT %"PRISocket": %.*s", socket, (int)length, (char*)buffer); fflush(stdout); } diff --git a/irc.c b/irc.c index 9cc0223..d9f3b11 100644 --- a/irc.c +++ b/irc.c @@ -1,5 +1,6 @@ #include "irc.h" #include "ircfmt.h" +#include "passwd.h" struct dynarr databuf; @@ -118,12 +119,13 @@ int parsePacket(struct client_data *client) { } args[argc] = NULL; } - printf("parsed message: %s", command); - for (int i = 0; i < argc; i++){ - printf(" %d:%s", i, args[i]); - if (i == argc-1) - printf("\n"); + printf("parsed %"PRISocket": %s", client->FD, command); + if (strcmp(command, "PASS") != 0 && strcmp(command, "OPER") != 0) { + for (int i = 0; i < argc; i++){ + printf(" %d:%s", i, args[i]); + } } + printf("\n"); return processPacket(client, source, command, argc, args); } int processPacket(struct client_data *client, char *source, char *command, int argc, char *args[]) { @@ -203,6 +205,42 @@ int processPacket(struct client_data *client, char *source, char *command, int a } else if(strcmp(command, "MOTD") == 0) { // Send welcome sendMOTD(client); + } else if(strcmp(command, "OPER") == 0) { + if (!is_registered(client)) + return err_notregistered(client), sendbuf(client), 0; + if (argc < 2) // FIXME: error message + return 0; + stringlower(args[0]); + int res = password_check(args[0], args[1], "ops.txt"); + memset(args[1], 0, strlen(args[1])); + if (res == -1) { + copy_strf(&databuf, ":%s 464 %s :Password incorrect\r\n", hostname, client->nick); + sendbuf(client); + } else { + client->umode |= UMODE_OPER; + copy_strf(&databuf, ":%s 381 %s :You are now an IRC operator\r\n", hostname, client->nick); + sendbuf(client); + copy_strf(&databuf, ":%s MODE %s +o\r\n", hostname, client->nick); + sendbuf(client); + } + } else if(strcmp(command, "JEDGAR") == 0) { + if (!is_registered(client)) + return err_notregistered(client), sendbuf(client), 0; + if (!(client->umode & UMODE_OPER)) { + copy_strf(&databuf, ":%s 481 %s :Permission Denied- You're not an IRC operator\r\n", hostname, client->nick); + sendbuf(client); + return 0; + } + if (argc < 1) + return 0; + struct channel *chan = findChannel(args[0]); + if (!chan) + return 0; // TODO: error message + if (!trie_get(&chan->members, client->key)) + return 0; // TODO: error message + trie_set(&chan->o, client->key, client, NULL); + copy_strf(&databuf, ":cia!cia@cia.gov MODE %s +o %s\r\n", chan->name, client->nick); + sendbuf_chan(chan); } else if(strcmp(command, "JOIN") == 0) { if (!is_registered(client)) return err_notregistered(client), sendbuf(client), 0; @@ -360,6 +398,13 @@ int processPacket(struct client_data *client, char *source, char *command, int a copy_strf(&databuf, ":%s MODE %s %si\n", hostname, client->nick, is_plus?"+":"-"); sendbuf(client); break; + case 'o': + if (!is_plus) { + SETBIT(cl->umode, UMODE_OPER, is_plus); + copy_strf(&databuf, ":%s MODE %s %so\n", hostname, client->nick, is_plus?"+":"-"); + sendbuf(client); + } + break; default: copy_strf(&databuf, ":%s 501 %s :Unknown MODE flag\n", hostname, client->nick); sendbuf(client); @@ -370,6 +415,8 @@ int processPacket(struct client_data *client, char *source, char *command, int a struct channel *chan = findChannel(nick); if (!chan) return err_nosuchchannel(client, nick), sendbuf(client), 0; + if (!trie_get(&chan->o, client->key) + return 0; // TODO: error if (argc == 2) { // Type A channel modes if (!strcmp(args[1], "+b")) { copy_strf(&databuf, ":%s 368 %s %s :End of channel ban list\n", hostname, client->nick, args[1]); diff --git a/net.c b/net.c index d02795c..e3e6cd6 100644 --- a/net.c +++ b/net.c @@ -79,7 +79,7 @@ void recvProc(struct client_data *cl) { while(1){ // I hate you if(cl->bufLen == cl->bufCap) { killConnection(cl, false); return; } - bytesRead = recv_log(cl->FD,cl->buf + cl->bufLen,cl->bufCap - cl->bufLen, 0); + bytesRead = recv(cl->FD,cl->buf + cl->bufLen,cl->bufCap - cl->bufLen, 0); switch(bytesRead){ // Disconnect case 0: diff --git a/passwd.c b/passwd.c new file mode 100644 index 0000000..88d83d4 --- /dev/null +++ b/passwd.c @@ -0,0 +1,93 @@ +#ifdef _WIN32 +int password_set(const char *key, const char *pw, const char *fn, const char *tmpfn) +{ + return -1; +} +int password_check(const char *key, const char *pw, const char *fn) +{ + return -1; +} +#else +#include +#include +#include +#include +int password_set(const char *key, const char *pw, const char *fn, const char *tmpfn) +{ + const char *hash; + { + char salt[20]; + char ubytes[16]; + if (getentropy(ubytes, 16) == -1) + return -1; + salt[0] = '$'; + salt[1] = '6'; + salt[2] = '$'; + for (int i = 0; i < 16; i++) + salt[3+i] = + "./0123456789ABCDEFGHIJKLMNOPQRST" + "UVWXYZabcdefghijklmnopqrstuvwxyz"[ubytes[i]&63]; + salt[19] = '\0'; + hash = crypt(pw, salt); + if (!hash || *hash == '*') + return -1; + } + + FILE *fi = fopen(fn, "rb"); + if (!fi) + return -1; + FILE *fo = fopen(tmpfn, "wb"); + if (!fo) { + fclose(fi); + return -1; + } + + int keylen = strlen(key); + char buf[1024]; + while (fgets(buf, 1024, fi)) { + if (buf[keylen] != ':' || memcmp(buf, key, keylen) != 0) { + if (fputs(buf, fo) == -1) { + fclose(fi); + fclose(fo); + remove(tmpfn); + return -1; + } + } + } + fclose(fi); + if (fprintf(fo, "%s:%s\n", key, hash) == -1) { + fclose(fo); + remove(tmpfn); + return -1; + } + if (fclose(fo) == EOF) { + remove(tmpfn); + return -1; + } + if (rename(tmpfn, fn) == -1) + return -1; + return 0; +} +int password_check(const char *key, const char *pw, const char *fn) +{ + // NOTE: there are probably a lot of timing leaks in here + FILE *fi = fopen(fn, "rb"); + if (!fi) + return -1; + int keylen = strlen(key); + char buf[1024]; + while (fgets(buf, 1024, fi)) { + if (buf[keylen] == ':' && memcmp(buf, key, keylen) == 0) { + int len = strlen(buf); + if (buf[len-1] == '\n') + buf[len-1] = '\0'; + const char *hash = crypt(pw, &buf[keylen+1]); + int rv = hash && !strcmp(hash, &buf[keylen+1]); + fclose(fi); + return -!rv; + } + } + fclose(fi); + return -1; +} +#endif diff --git a/passwd.h b/passwd.h new file mode 100644 index 0000000..564de7f --- /dev/null +++ b/passwd.h @@ -0,0 +1,5 @@ +#ifndef PASSWD_H_ +#define PASSWD_H_ +int password_set(const char *key, const char *pw, const char *fn, const char *tmpfn); +int password_check(const char *key, const char *pw, const char *fn); +#endif diff --git a/tools/setpass.c b/tools/setpass.c new file mode 100644 index 0000000..c3c6dd8 --- /dev/null +++ b/tools/setpass.c @@ -0,0 +1,11 @@ +#include +#include "../passwd.h" +int main(int argc, char **argv) +{ + if (argc < 3) + return 1; + char *pass = getpass("password: "); + if (!pass) + return 1; + return -password_set(argv[1], pass, argv[2], "setpass.tmp"); +}