#include "irc.h"
#include "ircfmt.h"
+#include "passwd.h"
struct dynarr databuf;
}
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[]) {
} 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;
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);
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]);
--- /dev/null
+#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 <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <crypt.h>
+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