*
*
* CMDNAME: login
- * CMDLEVEL: QCMD_SECURE | QCMD_NOTAUTHED
+ * CMDLEVEL: QCMD_SECURE | QCMD_NOTAUTHED | QCMD_ALIAS
* CMDARGS: 2
* CMDDESC: Authenticates you on the bot.
* CMDFUNC: csa_doauth
* CMDPROTO: int csa_doauth(void *source, int cargc, char **cargv);
+ * CMDHELP: Usage: LOGIN <username> <password>
+ * CMDHELP: Authenticates you on the bot, where:
+ * CMDHELP: username - your username
+ * CMDHELP: password - your password
+ * CMDHELP: If you do not have a username and password, see HELLO.
+ * CMDHELP: Note: due to the sensitive nature of this command, you must send the message
+ * CMDHELP: to Q@CServe.quakenet.org when using it.
+ * CMDHELP: Note: the preferred way to authenticate is to use the /AUTH command.
*/
#include "../chanserv.h"
#include <stdio.h>
#include <string.h>
-int csa_doauth(void *source, int cargc, char **cargv) {
+int csa_auth(void *source, int cargc, char **cargv, CRAlgorithm alg) {
reguser *rup;
- activeuser* aup;
- nick *sender=source;
- nicklist *nl = NULL;
+ activeuser *aup;
+ nick *sender=source, *onp;
char userhost[USERLEN+HOSTLEN+2];
- int ucount=0;
+ int challenge=0;
+ char *authtype = "AUTH";
+ authname *anp;
+ int toomanyauths=0;
+ time_t now;
- if (cargc<2) {
+ if (alg) {
+ challenge=1;
+ authtype = "CHALLENGEAUTH";
+ } else if (cargc<2) {
chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "auth");
return CMD_ERROR;
}
aup->authattempts++;
if (aup->authattempts > MAXAUTHATTEMPT) {
if ((aup->authattempts % 100) == 0)
- chanservwallmessage("Warning: User %s!%s@%s attempted to auth %d times. Last attempt: AUTH %s %s",
- nl->np->nick, nl->np->ident, nl->np->host->name->content, cargv[0], cargv[1]);
+ chanservwallmessage("Warning: User %s!%s@%s attempted to auth %d times. Last attempt: %s %s %s",
+ sender->nick, sender->ident, sender->host->name->content, aup->authattempts, authtype, cargv[0], cargv[1]);
chanservstdmessage(sender, QM_AUTHFAIL);
- cs_log(sender,"AUTH FAIL too many auth attempts (last attempt: AUTH %s %s)",cargv[0], cargv[1]);
+ cs_log(sender,"%s FAIL too many auth attempts (last attempt: %s %s %s)", authtype, authtype, cargv[0], cargv[1]);
return CMD_ERROR;
}
if (!(rup=findreguserbynick(cargv[0]))) {
chanservstdmessage(sender, QM_AUTHFAIL);
- cs_log(sender,"AUTH FAIL bad username %s",cargv[0]);
+ cs_log(sender,"%s FAIL bad username %s",authtype,cargv[0]);
return CMD_ERROR;
}
- if (!checkpassword(rup, cargv[1])) {
+ if (!challenge) {
+ if (!checkpassword(rup, cargv[1])) {
+ chanservstdmessage(sender, QM_AUTHFAIL);
+ cs_log(sender,"%s FAIL username %s bad password %s",authtype,rup->username,cargv[1]);
+ return CMD_ERROR;
+ }
+ } else {
+ if (!checkresponse(rup, aup->entropy, cargv[1], alg)) {
+ chanservstdmessage(sender, QM_AUTHFAIL);
+ cs_log(sender,"%s FAIL username %s bad response",authtype,rup->username);
+ return CMD_ERROR;
+ }
+ }
+
+ /* This should never fail but do something other than crashing if it does. */
+ if (!(anp=findauthname(rup->ID))) {
chanservstdmessage(sender, QM_AUTHFAIL);
- cs_log(sender,"AUTH FAIL username %s bad password %s",rup->username,cargv[1]);
return CMD_ERROR;
}
- rup->lastauth=time(NULL);
+ /* Check for too many auths. Don't return immediately, since we will still warn
+ * other users on the acct in this case. */
+ if (!UHasHelperPriv(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;
+
+ /* Guarantee a unique auth timestamp for each account */
+ now=time(NULL);
+ 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->suspendreason=0;
}
- if (UIsNeedAuth(rup))
- rup->flags&=~(QUFLAG_NEEDAUTH);
csdb_updateuser(rup);
- if (UIsDelayedGline(rup)) {
- /* delayed-gline - schedule the user's squelching */
- deleteschedule(NULL, &chanservdgline, (void*)rup); /* icky, but necessary unless we stick more stuff in reguser structure */
- scheduleoneshot(time(NULL)+rand()%900, &chanservdgline, (void*)rup);
- }
- else if (UIsGline(rup)) {
- /* instant-gline - lets be lazy and set a schedule expiring now :) */
- deleteschedule(NULL, &chanservdgline, (void*)rup); /* icky, but necessary unless we stick more stuff in reguser structure */
- scheduleoneshot(time(NULL), &chanservdgline, (void*)rup);
- }
- else if (UIsSuspended(rup)) {
+ if (UIsSuspended(rup)) {
/* plain suspend */
chanservstdmessage(sender, QM_AUTHSUSPENDED);
- chanservstdmessage(sender, QM_REASON, rup->suspendreason->content);
- if (rup->suspendexp) {
- struct tm* tmp;
- char buf[200];
-
- tmp=gmtime(&(rup->suspendexp));
- strftime(buf, 15, "%d/%m/%y %H:%M", tmp);
- chanservstdmessage(sender, QM_EXPIRES, buf);
- }
+ if(rup->suspendreason)
+ chanservstdmessage(sender, QM_REASON, rup->suspendreason->content);
+ if (rup->suspendexp)
+ chanservstdmessage(sender, QM_EXPIRES, rup->suspendexp);
return CMD_ERROR;
}
- if (!UHasHelperPriv(rup) && !UIsNoAuthLimit(rup)) {
- for (nl=rup->nicks; nl; nl=nl->next)
- ucount++;
-
- if (ucount >= MAXAUTHCOUNT) {
- chanservstdmessage(sender, QM_TOOMANYAUTHS);
- return CMD_ERROR;
- }
- }
chanservstdmessage(sender, QM_AUTHOK, rup->username);
- cs_log(sender,"AUTH OK username %s", rup->username);
- localusersetaccount(sender, rup->username);
+
+ cs_log(sender,"%s OK username %s", authtype,rup->username);
+
+ localusersetaccount(sender, rup->username, rup->ID, cs_accountflagmap(rup), rup->lastauth);
return CMD_OK;
}
+
+int csa_doauth(void *source, int cargc, char **cargv) {
+ return csa_auth(source, cargc, cargv, NULL);
+}