From: Chris Porter Date: Mon, 10 Jul 2017 21:42:15 +0000 (+0100) Subject: CHANSERV: add REMOTEAUTH command X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/commitdiff_plain/refs/pull/58/head CHANSERV: add REMOTEAUTH command --- diff --git a/chanserv/authcmds/auth.c b/chanserv/authcmds/auth.c index ab9ce227..3adc7f35 100644 --- a/chanserv/authcmds/auth.c +++ b/chanserv/authcmds/auth.c @@ -80,82 +80,18 @@ int csa_auth(void *source, int cargc, char **cargv, CRAlgorithm alg) { return csa_completeauth(sender, rup, authtype); } +int csa_doauth(void *source, int cargc, char **cargv) { + return csa_auth(source, cargc, cargv, NULL); +} + int csa_completeauth(nick *sender, reguser *rup, char *authtype) { - int toomanyauths=0; - time_t now, oldlastauth; - char userhost[USERLEN+HOSTLEN+2]; - nick *onp; void *args[2]; - authname *anp; - - /* This should never fail but do something other than crashing if it does. */ - if (!(anp=findauthname(rup->ID))) { - chanservstdmessage(sender, QM_AUTHFAIL); - return CMD_ERROR; - } - - /* Check for too many auths. Don't return immediately, since we will still warn - * other users on the acct in this case. */ - if (!UHasStaffPriv(rup) && !UIsNoAuthLimit(rup)) { - if (anp->usercount >= MAXAUTHCOUNT) { - chanservstdmessage(sender, QM_TOOMANYAUTHS); - toomanyauths=1; - } - } - - for (onp=anp->nicks;onp;onp=onp->nextbyauthname) { - if (toomanyauths) { - chanservstdmessage(onp, QM_OTHERUSERAUTHEDLIMIT, sender->nick, sender->ident, sender->host->name->content, MAXAUTHCOUNT); - } else { - chanservstdmessage(onp, QM_OTHERUSERAUTHED, sender->nick, sender->ident, sender->host->name->content); - } - } - - if (toomanyauths) - return CMD_ERROR; + time_t oldlastauth; - now=time(NULL); - - if (UHasSuspension(rup) && rup->suspendexp && (now >= rup->suspendexp)) { - /* suspension has expired, remove it */ - rup->flags&=(~(QUFLAG_SUSPENDED|QUFLAG_GLINE|QUFLAG_DELAYEDGLINE)); - rup->suspendby=0; - rup->suspendexp=0; - freesstring(rup->suspendreason); - rup->suspendreason=0; - csdb_updateuser(rup); - } - - if (UIsSuspended(rup)) { - /* plain suspend */ - chanservstdmessage(sender, QM_AUTHSUSPENDED); - if(rup->suspendreason) - chanservstdmessage(sender, QM_REASON, rup->suspendreason->content); - if (rup->suspendexp) - chanservstdmessage(sender, QM_EXPIRES, rup->suspendexp); - return CMD_ERROR; - } - if (UIsInactive(rup)) { - chanservstdmessage(sender, QM_INACTIVEACCOUNT); - return CMD_ERROR; - } - - /* Guarantee a unique auth timestamp for each account */ oldlastauth=rup->lastauth; - - if (rup->lastauth < now) - rup->lastauth=now; - else - rup->lastauth++; - - sprintf(userhost,"%s@%s",sender->ident,sender->host->name->content); - if (rup->lastuserhost) - freesstring(rup->lastuserhost); - rup->lastuserhost=getsstring(userhost,USERLEN+HOSTLEN+1); - - csdb_updateuser(rup); - cs_log(sender,"%s OK username %s", authtype,rup->username); + if(!csa_completeauth2(rup, sender->nick, sender->ident, sender->host->name->content, authtype, chanservstdmessage, sender)) + return CMD_ERROR; localusersetaccount(sender, rup->username, rup->ID, cs_accountflagmap(rup), rup->lastauth); @@ -163,11 +99,8 @@ int csa_completeauth(nick *sender, reguser *rup, char *authtype) { args[0]=sender; args[1]=(void *)oldlastauth; + /* note: not triggered for REMOTEAUTH */ triggerhook(HOOK_CHANSERV_AUTH, args); return CMD_OK; } - -int csa_doauth(void *source, int cargc, char **cargv) { - return csa_auth(source, cargc, cargv, NULL); -} diff --git a/chanserv/authlib.c b/chanserv/authlib.c index 6ff0d386..def32b61 100644 --- a/chanserv/authlib.c +++ b/chanserv/authlib.c @@ -197,3 +197,80 @@ reguser *csa_createaccount(char *username, char *password, char *email) { return rup; } + +int csa_completeauth2(reguser *rup, char *nickname, char *ident, char *hostname, char *authtype, void (*reply)(nick *, int, ...), nick *reply_to) { + int toomanyauths=0; + time_t now; + char userhost[USERLEN+HOSTLEN+2]; + nick *onp; + authname *anp; + + /* This should never fail but do something other than crashing if it does. */ + if (!(anp=findauthname(rup->ID))) { + reply(reply_to, QM_AUTHFAIL); + return 0; + } + + /* Check for too many auths. Don't return immediately, since we will still warn + * other users on the acct in this case. */ + if (!UHasStaffPriv(rup) && !UIsNoAuthLimit(rup)) { + if (anp->usercount >= MAXAUTHCOUNT) { + reply(reply_to, QM_TOOMANYAUTHS); + toomanyauths=1; + } + } + + for (onp=anp->nicks;onp;onp=onp->nextbyauthname) { + if (toomanyauths) { + chanservstdmessage(onp, QM_OTHERUSERAUTHEDLIMIT, nickname, ident, hostname, MAXAUTHCOUNT); + } else { + chanservstdmessage(onp, QM_OTHERUSERAUTHED, nickname, ident, hostname); + } + } + + if (toomanyauths) + return 0; + + now=time(NULL); + + if (UHasSuspension(rup) && rup->suspendexp && (now >= rup->suspendexp)) { + /* suspension has expired, remove it */ + rup->flags&=(~(QUFLAG_SUSPENDED|QUFLAG_GLINE|QUFLAG_DELAYEDGLINE)); + rup->suspendby=0; + rup->suspendexp=0; + freesstring(rup->suspendreason); + rup->suspendreason=0; + csdb_updateuser(rup); + } + + if (UIsSuspended(rup)) { + /* plain suspend */ + reply(reply_to, QM_AUTHSUSPENDED); + if(rup->suspendreason) + reply(reply_to, QM_REASON, rup->suspendreason->content); + if (rup->suspendexp) + reply(reply_to, QM_EXPIRES, rup->suspendexp); + return 0; + } + if (UIsInactive(rup)) { + reply(reply_to, QM_INACTIVEACCOUNT); + return 0; + } + + /* Guarantee a unique auth timestamp for each account */ + if (rup->lastauth < now) + rup->lastauth=now; + else + rup->lastauth++; + + sprintf(userhost,"%s@%s",ident,hostname); + if (rup->lastuserhost) + freesstring(rup->lastuserhost); + rup->lastuserhost=getsstring(userhost,USERLEN+HOSTLEN+1); + + csdb_updateuser(rup); + + cs_log(NULL,"%s!%s@%s [noauth] %s OK username %s",nickname,ident,hostname,authtype,rup->username); + + return 1; +} diff --git a/chanserv/authlib.h b/chanserv/authlib.h index 246d6d79..a6868f13 100644 --- a/chanserv/authlib.h +++ b/chanserv/authlib.h @@ -13,3 +13,4 @@ int csa_checkaccountname_r(char *accountname); int csa_checkeboy_r(char *eboy); int csa_checkpasswordquality(char *password); reguser *csa_createaccount(char *username, char *password, char *email); +int csa_completeauth2(reguser *rup, char *nickname, char *ident, char *hostname, char *authtype, void (*reply)(nick *, int, ...), nick *reply_to); diff --git a/chanserv/chanserv.h b/chanserv/chanserv.h index bd5c613c..6b94adb1 100644 --- a/chanserv/chanserv.h +++ b/chanserv/chanserv.h @@ -851,6 +851,7 @@ void chanservwallmessage(char *message, ... ) __attribute__ ((format (printf, 1, void chanservcommandinit(); void chanservcommandclose(); void chanservstdmessage(nick *np, int messageid, ... ); +void chanservstdvmessage(nick *np, reguser *rup, int messageid, int max_line_len, void (*callback)(nick *, char *), va_list va); void chanservaddcommand(char *command, int flags, int maxparams, CommandHandler handler, char *description, const char *help); void chanservremovecommand(char *command, CommandHandler handler); void chanservaddctcpcommand(char *command, CommandHandler hander); diff --git a/chanserv/chanserv_relay.c b/chanserv/chanserv_relay.c index 6180612e..d7464431 100644 --- a/chanserv/chanserv_relay.c +++ b/chanserv/chanserv_relay.c @@ -23,6 +23,8 @@ 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); +int csa_doremoteauth(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); @@ -71,6 +73,7 @@ void relayfinishinit(int hooknum, void *arg) { 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 "); + registercontrolhelpcmd("remoteauth", NO_RELAY, 6, csa_doremoteauth, "Usage: remoteauth "); s=getcopyconfigitem("chanserv","createaccountsecret","",128); if(!s || !s->content || !s->content[0]) { @@ -135,6 +138,59 @@ int csa_docheckhashpass(void *source, int cargc, char **cargv) { return CMD_OK; } +static void controlremotereply(nick *target, char *message) { + controlreply(target, "CHECKHASHPASS FAIL text %s", message); +} + +static void remote_reply(nick *sender, int message_id, ...) { + va_list va; + va_start(va, message_id); + chanservstdvmessage(sender, NULL, message_id, -1 * (int)(strlen("CHECKHASHPASS FAIL text ")), controlremotereply, va); + va_end(va); +} + +int csa_doremoteauth(void *source, int cargc, char **cargv) { + nick *sender=(nick *)source; + reguser *rup; + + if(cargc<6) { + controlreply(sender, "REMOTEAUTH FAIL args"); + controlreply(sender, "REMOTEAUTH END"); + return CMD_ERROR; + } + + char *account = cargv[0]; + char *digest = cargv[1]; + char *junk = cargv[2]; + char *nick = cargv[3]; + char *ident = cargv[4]; + char *hostname = cargv[5]; + + if (!(rup=findreguserbynick(account))) { + controlreply(sender, "REMOTEAUTH FAIL user"); + controlreply(sender, "REMOTEAUTH END"); + return CMD_ERROR; + } + + if(!checkhashpass(rup, junk, digest)) { + controlreply(sender, "REMOTEAUTH FAIL digest"); + controlreply(sender, "REMOTEAUTH END"); + return CMD_ERROR; + } + + if (!csa_completeauth2(rup, nick, ident, hostname, "REMOTEAUTH", remote_reply, sender)) { + controlreply(sender, "REMOTEAUTH END"); + return CMD_ERROR; + } + + /* username:ts:authid */ + controlreply(sender, "REMOTEAUTH OK %s %ld %ld", rup->username, rup->lastauth ? rup->lastauth : getnettime(), rup->ID); + + /* note: NO HOOK_CHANSERV_AUTH */ + + return CMD_OK; +} + static char *email_to_error(char *email) { maildomain *mdp, *smdp; char *local; diff --git a/chanserv/chanservuser.c b/chanserv/chanservuser.c index 04280500..b606f363 100644 --- a/chanserv/chanservuser.c +++ b/chanserv/chanservuser.c @@ -355,27 +355,28 @@ void chanservjoinchan(channel *cp) { } } -void chanservstdmessage(nick *np, int messageid, ... ) { +static void __chanservstdvmessage(nick *np, reguser *rup, int messageid, int max_line_len, void (*callback)(nick *, char *), ...) { + va_list va; + va_start(va, callback); + chanservstdvmessage(np, rup, messageid, max_line_len, callback, va); + va_end(va); +} + +void chanservstdvmessage(nick *np, reguser *rup, int messageid, int max_line_len, void (*callback)(nick *, char *), va_list va) { char buf[5010]; char buf2[512]; - int notice; - reguser *rup; int language; - va_list va, va2; + va_list va2; char *message, *messageargs; char *bp2,*bp; int len; - if (getreguserfromnick(np) == NULL) { - notice=1; + if(max_line_len <= 0) + max_line_len = 490 + max_line_len; + + if (rup == NULL) { language=0; } else { - rup=getreguserfromnick(np); - if(UIsNotice(rup)) { - notice=1; - } else { - notice=0; - } language=rup->languageid; } @@ -389,29 +390,22 @@ void chanservstdmessage(nick *np, int messageid, ... ) { messageargs=defaultmessages[messageid*2+1]; - va_start(va,messageid); va_copy(va2, va); q9vsnprintf(buf,5000,message,messageargs,va); - va_end(va); len=0; bp2=buf2; for (bp=buf; ;bp++) { /* We send something if we hit a \n, fill the buffer or run out of source */ - if (*bp=='\n' || len>490 || !*bp) { + if (*bp=='\n' || len>max_line_len || !*bp) { if (*bp && *bp!='\n') { bp--; } *bp2='\0'; - if (chanservnick && *buf2) { - if (notice) { - sendnoticetouser(chanservnick,np,"%s",buf2); - } else { - sendmessagetouser(chanservnick,np,"%s",buf2); - } - } + if (chanservnick && *buf2) + callback(np, buf2); /* If we ran out of buffer, get out here */ if (!*bp) @@ -429,12 +423,33 @@ void chanservstdmessage(nick *np, int messageid, ... ) { if (messageid==QM_NOTENOUGHPARAMS) { char *command=va_arg(va2, char *); cs_sendhelp(np, command, 1); - chanservstdmessage(np, QM_TYPEHELPFORHELP, command); + __chanservstdvmessage(np, rup, QM_TYPEHELPFORHELP, max_line_len, callback, command); } va_end(va2); } +static void message_callback(nick *np, char *buf) { + sendmessagetouser(chanservnick,np,"%s",buf); +} + +static void notice_callback(nick *np, char *buf) { + sendnoticetouser(chanservnick,np,"%s",buf); +} + +void chanservstdmessage(nick *np, int messageid, ...) { + reguser *rup; + va_list va; + int notice; + + rup = getreguserfromnick(np); + notice = rup == NULL ? 1 : UIsNotice(rup); + + va_start(va, messageid); + chanservstdvmessage(np, rup, messageid, 0, notice ? notice_callback : message_callback, va); + va_end(va); +} + void chanservsendmessage_real(nick *np, int oneline, char *message, ... ) { char buf[5010]; /* Very large buffer.. */ char buf2[512], *bp, *bp2; diff --git a/core/hooks.h b/core/hooks.h index c728c2e5..36358965 100644 --- a/core/hooks.h +++ b/core/hooks.h @@ -69,7 +69,7 @@ /* 501 spare for now */ #define HOOK_CHANSERV_RUNNING 502 /* No arg */ -#define HOOK_CHANSERV_AUTH 503 /* Argument is void*[2] (nick *, lastauth) */ +#define HOOK_CHANSERV_AUTH 503 /* Argument is void*[2] (nick *, lastauth) */ /* note: not triggered for REMOTEAUTH */ #define HOOK_CHANSERV_PWCHANGE 504 /* Argument is nick * */ #define HOOK_CHANSERV_CHANLEVMOD 505 /* Argument is void*[3] (nick *, regchanuser *, oldflags) */ #define HOOK_CHANSERV_CHANLEVDUMP 506 /* Argument is nick * */