X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/blobdiff_plain/3cfa791f1d74fdb3ea5ec61a89ec221d53388c9f..056e1ea46d3a0707ca0bb46af4abd429e55c4196:/chanserv/chanserv_relay.c diff --git a/chanserv/chanserv_relay.c b/chanserv/chanserv_relay.c index b234c1e6..16b9a9a7 100644 --- a/chanserv/chanserv_relay.c +++ b/chanserv/chanserv_relay.c @@ -2,33 +2,108 @@ #include "../control/control.h" #include "../lib/version.h" #include "../lib/irc_string.h" +#include "../core/config.h" +#include "../lib/hmac.h" +#include "../lib/strlfunc.h" +#include "../lib/cbc.h" #include "authlib.h" #include #include +#define KEY_BITS 256 +#define BLOCK_SIZE 16 + MODULE_VERSION(QVERSION); int csa_docheckhashpass(void *source, int cargc, char **cargv); int csa_docreateaccount(void *source, int cargc, char **cargv); int csa_dosettempemail(void *source, int cargc, char **cargv); +int csa_dosetemail(void *source, int cargc, char **cargv); int csa_doresendemail(void *source, int cargc, char **cargv); int csa_doactivateuser(void *source, int cargc, char **cargv); +int csa_doaddchan(void *source, int argc, char **argv); +static int decrypt_password(unsigned char *secret, int keybits, char *buf, int bufsize, char *encrypted); +static int hex_to_int(char *input, unsigned char *buf, int buflen); + +static unsigned char createaccountsecret[KEY_BITS / 8]; +static int createaccountsecret_ok = 0; + +static unsigned char hexlookup[256] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0x0b, 0x0c, + 0x0d, 0x0e, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + +static void relayfinishinit(int, void *); + +void relayfinishinit(int hooknum, void *arg) { + sstring *s; + + deregisterhook(HOOK_CHANSERV_DBLOADED, relayfinishinit); -void _init(void) { registercontrolhelpcmd("checkhashpass", NO_RELAY, 3, csa_docheckhashpass, "Usage: checkhashpass ?junk?"); - registercontrolhelpcmd("createaccount", NO_RELAY, 4, csa_docreateaccount, "Usage: createaccount "); - registercontrolhelpcmd("settempemail", NO_RELAY, 2, csa_dosettempemail, "Usage: settempemail "); - registercontrolhelpcmd("resendemail", NO_RELAY, 1, csa_doresendemail, "Usage: resendemail "); - registercontrolhelpcmd("activateuser", NO_RELAY, 1, csa_doactivateuser, "Usage: activateuser "); + registercontrolhelpcmd("settempemail", NO_RELAY, 2, csa_dosettempemail, "Usage: settempemail "); + registercontrolhelpcmd("setemail", NO_RELAY, 3, csa_dosetemail, "Usage: setmail "); + registercontrolhelpcmd("resendemail", NO_RELAY, 1, csa_doresendemail, "Usage: resendemail "); + registercontrolhelpcmd("activateuser", NO_RELAY, 1, csa_doactivateuser, "Usage: activateuser "); + registercontrolhelpcmd("addchan", NO_RELAY, 3, csa_doaddchan, "Usage: addchan "); + + s=getcopyconfigitem("chanserv","createaccountsecret","",128); + if(!s || !s->content || !s->content[0]) { + Error("chanserv_relay",ERR_WARNING,"createaccountsecret not set, createaccount disabled."); + } else if(s->length != KEY_BITS / 8 * 2 || !hex_to_int(s->content, createaccountsecret, sizeof(createaccountsecret))) { + Error("chanserv_relay",ERR_WARNING,"createaccountsecret must be a %d character hex string.", KEY_BITS / 8 * 2); + } else { + registercontrolhelpcmd("createaccount", NO_RELAY, 5, csa_docreateaccount, "Usage: createaccount "); + createaccountsecret_ok = 1; + } + + freesstring(s); +} + +void _init(void) { + registerhook(HOOK_CHANSERV_DBLOADED, relayfinishinit); + + if(chanservdb_ready) + relayfinishinit(HOOK_CHANSERV_DBLOADED, NULL); } void _fini(void) { deregistercontrolcmd("checkhashpass", csa_docheckhashpass); - deregistercontrolcmd("createaccount", csa_docreateaccount); deregistercontrolcmd("settempemail", csa_dosettempemail); + deregistercontrolcmd("setemail", csa_dosetemail); deregistercontrolcmd("resendemail", csa_doresendemail); deregistercontrolcmd("activateuser", csa_doactivateuser); + deregistercontrolcmd("addchan", csa_doaddchan); + + if(createaccountsecret_ok) + deregistercontrolcmd("createaccount", csa_docreateaccount); + + deregisterhook(HOOK_CHANSERV_DBLOADED, relayfinishinit); } int csa_docheckhashpass(void *source, int cargc, char **cargv) { @@ -123,6 +198,8 @@ static char *email_to_error(char *email) { } } + free(dupemail); + return NULL; } @@ -135,9 +212,12 @@ int csa_docreateaccount(void *source, int cargc, char **cargv) { int execute; char *error_username = NULL, *error_password = NULL, *error_email = NULL; char *username = NULL, *password = NULL, *email = NULL; + char account_info[512]; + char passbuf[512]; int do_create; + int activate; - if(cargc<4) { + if(cargc<5) { controlreply(sender, "CREATEACCOUNT FALSE args"); return CMD_ERROR; } @@ -147,8 +227,16 @@ int csa_docreateaccount(void *source, int cargc, char **cargv) { username = cargv[1]; if(strcmp(cargv[2], "0")) email = cargv[2]; - if(strcmp(cargv[3], "0")) - password = cargv[3]; + if(strcmp(cargv[3], "0")) { + int errorcode = decrypt_password(createaccountsecret, KEY_BITS, passbuf, sizeof(passbuf), cargv[3]); + if(errorcode) { + Error("chanserv_relay",ERR_WARNING,"createaccount unable to decrypt password, error code: %d", errorcode); + controlreply(sender, "CREATEACCOUNT FALSE args"); + return CMD_ERROR; + } + password = passbuf; + } + activate = cargv[4][0] == '1'; if(username) { if (findreguserbynick(username)) { @@ -165,8 +253,12 @@ int csa_docreateaccount(void *source, int cargc, char **cargv) { int r = csa_checkpasswordquality(password); if(r == QM_PWTOSHORT) { error_password = "passwordshort"; + } else if(r == QM_PWTOLONG) { + error_password = "passwordlong"; } else if(r == QM_PWTOWEAK) { error_password = "passwordweak"; + } else if(r == QM_PWINVALID) { + error_password = "passwordinvalid"; } else if(r != -1) { error_password = "passwordunknown"; } @@ -177,18 +269,24 @@ int csa_docreateaccount(void *source, int cargc, char **cargv) { do_create = 1; rup = csa_createaccount(username, password, email); - USetInactive(rup); - cs_log(sender,"CREATEACCOUNT created auth %s (%s)",rup->username,rup->email->content); + if(!activate) + USetInactive(rup); + + cs_log(sender,"CREATEACCOUNT created auth %s (%s) %s",rup->username,rup->email->content,activate?"(active)": "(inactive)"); csdb_createuser(rup); + snprintf(account_info, sizeof(account_info), " %u %lu", rup->ID, (unsigned long)rup->lastpasschange); - sendemail(rup); + if(!activate) + sendemail(rup); } else { + account_info[0] = '\0'; do_create = 0; } - controlreply(sender, "CREATEACCOUNT %s%s%s%s%s%s%s", + controlreply(sender, "CREATEACCOUNT %s%s%s%s%s%s%s%s", do_create ? "TRUE" : "FALSE", + account_info, email && error_email ? " " : "", email && error_email ? error_email : "", password && error_password ? " " : "", password && error_password ? error_password : "", username && error_username ? " " : "", username && error_username ? error_username : "" @@ -208,9 +306,9 @@ int csa_dosettempemail(void *source, int cargc, char **cargv) { return CMD_ERROR; } - rup = findreguserbynick(cargv[0]); + rup = findreguserbyID(atoi(cargv[0])); if(rup == NULL) { - controlreply(sender, "SETTEMPEMAIL FALSE usernamenotexist"); + controlreply(sender, "SETTEMPEMAIL FALSE useridnotexist"); return CMD_ERROR; } @@ -238,6 +336,64 @@ int csa_dosettempemail(void *source, int cargc, char **cargv) { return CMD_OK; } +int csa_dosetemail(void *source, int cargc, char **cargv) { + char *email; + char *error; + reguser *rup; + nick *sender=(nick *)source; + + if(cargc<3) { + controlreply(sender, "SETEMAIL FALSE args"); + return CMD_ERROR; + } + + rup = findreguserbyID(atoi(cargv[0])); + if(rup == NULL) { + controlreply(sender, "SETEMAIL FALSE useridnotexist"); + return CMD_ERROR; + } + + if(UHasStaffPriv(rup)) { + controlreply(sender, "SETEMAIL FALSE privuser"); + return CMD_ERROR; + } + + if(UHasSuspension(rup)) { + controlreply(sender, "SETEMAIL FALSE suspended"); + return CMD_ERROR; + } + + if(rup->lastpasschange > atoi(cargv[1])) { + controlreply(sender, "SETEMAIL FALSE passwordchanged"); + return CMD_ERROR; + } + + email = cargv[2]; + + if(!strcmp(email, rup->email->content)) { + /* setting to the same thing? fine! */ + controlreply(sender, "SETEMAIL TRUE"); + return CMD_OK; + } + + error = email_to_error(email); + if(error) { + controlreply(sender, "SETEMAIL FALSE %s", error); + return CMD_ERROR; + } + + freesstring(rup->email); + rup->email=getsstring(email,EMAILLEN); + cs_log(sender,"SETEMAIL OK username %s email %s",rup->username, rup->email->content); + + csdb_updateuser(rup); + sendemail(rup); + + controlreply(sender, "SETEMAIL TRUE"); + + return CMD_OK; +} + int csa_doresendemail(void *source, int cargc, char **cargv) { reguser *rup; nick *sender=(nick *)source; @@ -247,9 +403,9 @@ int csa_doresendemail(void *source, int cargc, char **cargv) { return CMD_ERROR; } - rup = findreguserbynick(cargv[0]); + rup = findreguserbyID(atoi(cargv[0])); if(rup == NULL) { - controlreply(sender, "RESENDEMAIL FALSE usernamenotexist"); + controlreply(sender, "RESENDEMAIL FALSE useridnotexist"); return CMD_ERROR; } @@ -274,9 +430,9 @@ int csa_doactivateuser(void *source, int cargc, char **cargv) { return CMD_ERROR; } - rup = findreguserbynick(cargv[0]); + rup = findreguserbyID(atoi(cargv[0])); if(rup == NULL) { - controlreply(sender, "ACTIVATEUSER FALSE usernamenotexist"); + controlreply(sender, "ACTIVATEUSER FALSE useridnotexist"); return CMD_ERROR; } @@ -293,3 +449,109 @@ int csa_doactivateuser(void *source, int cargc, char **cargv) { return CMD_OK; } + +int csa_doaddchan(void *source, int cargc, char **cargv) { + nick *sender=(nick *)source; + reguser *rup = getreguserfromnick(sender), *founder; + chanindex *cip; + short type; + regchan *rcp; + + if(cargc<3) { + controlreply(sender, "ADDCHAN FALSE args"); + return CMD_ERROR; + } + + if (*cargv[0] != '#' || strlen(cargv[0]) > CHANNELLEN) { + controlreply(sender, "ADDCHAN FALSE invalidchannel"); + return CMD_ERROR; + } + + if (!(cip=findorcreatechanindex(cargv[0]))) { + controlreply(sender, "ADDCHAN FALSE invalidchannel"); + return CMD_ERROR; + } + + founder = findreguserbyID(atoi(cargv[1])); + if(founder == NULL) { + controlreply(sender, "ADDCHAN FALSE useridnotexist"); + return CMD_ERROR; + } + + if(UIsInactive(founder)) { + controlreply(sender, "ADDCHAN FALSE accountinactive"); + return CMD_ERROR; + } + + for(type=CHANTYPES-1;type;type--) + if(!ircd_strcmp(chantypes[type]->content, cargv[2])) + break; + + if(!type) { + controlreply(sender, "ADDCHAN FALSE invalidchantype"); + return CMD_ERROR; + } + + rcp = cs_addchan(cip, sender, rup, founder, QCFLAG_JOINED | QCFLAG_AUTOOP | QCFLAG_BITCH | QCFLAG_FORCETOPIC | QCFLAG_PROTECT | QCFLAG_TOPICSAVE, CHANMODE_NOCTCP | CHANMODE_DELJOINS | CHANMODE_MODNOAUTH | CHANMODE_NONOTICE | CHANMODE_NOEXTMSG | CHANMODE_SINGLETARG | CHANMODE_TOPICLIMIT | CHANMODE_NOQUITMSG, 0, type); + if(!rcp) { + controlreply(sender, "ADDCHAN FALSE alreadyregistered"); + return CMD_ERROR; + } + + cs_log(sender, "ADDCHAN %s #%s %s %s", cip->name->content, founder->username, printflags(rcp->flags, rcflags), chantypes[type]->content); + controlreply(sender, "ADDCHAN TRUE %u", rcp->ID); + return CMD_OK; +} + +static int hex_to_int(char *input, unsigned char *buf, int buflen) { + int i; + for(i=0;i bufsize || ciphertextlen % BLOCK_SIZE != 0) + return 4; + + if(!hex_to_int(encrypted + BLOCK_SIZE * 2, (unsigned char *)buf, ciphertextlen)) + return 5; + + c = rijndaelcbc_init(secret, keybits, iv, 1); + + for(i=0;i