#include <stdio.h>
#include <string.h>
+int csa_completeauth(nick *sender, reguser *rup, char *authtype);
+
int csa_auth(void *source, int cargc, char **cargv, CRAlgorithm alg) {
reguser *rup;
activeuser *aup;
- nick *sender=source, *onp;
- char userhost[USERLEN+HOSTLEN+2];
+ nick *sender=source;
int challenge=0;
char *authtype = "AUTH";
- authname *anp;
- int toomanyauths=0;
- time_t now;
if (alg) {
challenge=1;
}
}
+ return csa_completeauth(sender, rup, authtype);
+}
+
+int csa_completeauth(nick *sender, reguser *rup, char *authtype) {
+ 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))) {
chanservstdmessage(sender, QM_AUTHFAIL);
--- /dev/null
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: ticketauth
+ * CMDLEVEL: QCMD_SECURE | QCMD_NOTAUTHED | QCMD_HIDDEN
+ * CMDARGS: 5
+ * CMDDESC: Authenticates you on the bot using a ticket.
+ * CMDFUNC: csa_doticketauth
+ * CMDPROTO: int csa_doticketauth(void *source, int cargc, char **cargv);
+ * CMDHELP: Usage: ticketauth <ticket>
+ * CMDHELP: This is an internal QuakeNet function, there's no point in
+ * CMDHELP: asking for details on how it works cos' you'll not get any!
+ */
+
+#include "../chanserv.h"
+#include <stdio.h>
+#include <time.h>
+
+int csa_completeauth(nick *sender, reguser *rup, char *authtype);
+
+int csa_doticketauth(void *source, int cargc, char **cargv) {
+ activeuser* aup;
+ time_t t;
+ nick *sender=(nick *)source;
+ long uid;
+ int ret;
+ reguser *rup;
+ time_t logintimestamp, expiry;
+ char buf[512], *digest, *junk;
+
+ if(cargc!=5) {
+ chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "ticketauth");
+ return CMD_ERROR;
+ }
+
+ if (!(aup=getactiveuserfromnick(sender)))
+ return CMD_ERROR;
+
+ t = time(NULL);
+
+ uid = atoi(cargv[0]);
+ logintimestamp = atoi(cargv[1]);
+ expiry = atoi(cargv[2]);
+ junk = cargv[3];
+ digest = cargv[4];
+
+ if(t < logintimestamp) {
+ chanservstdmessage(sender, QM_TICKETNOTYETVALID);
+ return CMD_ERROR;
+ }
+ if(t > expiry) {
+ chanservstdmessage(sender, QM_TICKETEXPIRED);
+ return CMD_ERROR;
+ }
+
+ snprintf(buf, sizeof(buf), "%ld %jd %jd %s", uid, (intmax_t)logintimestamp, (intmax_t)expiry, junk);
+
+ ret = csc_verifyqticket(buf, digest);
+ if(ret < 0) {
+ chanservstdmessage(sender, QM_CONFIGURATIONERROR);
+ return CMD_ERROR;
+ } else if(ret > 0) {
+ chanservstdmessage(sender, QM_INVALIDHMAC);
+ return CMD_ERROR;
+ }
+
+ if(!(rup=findreguserbyID(uid))) {
+ chanservstdmessage(sender, QM_UNKNOWNUSER, "??");
+ return CMD_ERROR;
+ }
+
+ if(rup->lastpasschange >= logintimestamp) {
+ chanservstdmessage(sender, QM_PASSEMAILCHANGED);
+ return CMD_ERROR;
+ }
+
+ return csa_completeauth(sender, rup, "TICKETAUTH");
+}
#define QCMD_STAFF 0x0200 /* Only available to staff */
#define QCMD_ALIAS 0x0100 /* Don't list on SHOWCOMMANDS */
+#define QCMD_HIDDEN QCMD_ALIAS
#define CS_INIT_DB 0x1 /* Loading database.. */
#define CS_INIT_NOUSER 0x2 /* Loaded DB, waiting for user to be created */
const char *cs_cralgorithmlist(void);
int cs_checkhashpass(const char *username, const char *password, const char *junk, const char *hash);
char *csc_generateresetcode(time_t lockuntil, char *username);
+int csc_verifyqticket(char *data, char *digest);
/* chanservuser.c */
void chanservreguser(void *arg);
msg(QM_CHANLEV_SUSPENDBY, "Suspended by: $0", "s"),
msg(QM_TRUNCATED, "Warning: list truncated to $0 items.", "d"),
msg(QM_WHOIS_PASSSET, "Pass last set : $0", "T"),
+ msg(QM_TICKETEXPIRED, "Sorry, you've taken too long to log in (ticket has expired).", ""),
+ msg(QM_TICKETNOTYETVALID, "The supplied login credentials are not valid (ticket not yet valid).", ""),
+ msg(QM_CONFIGURATIONERROR, "Configuration error, contact an IRC Operator.", ""),
+ msg(QM_INVALIDHMAC, "The supplied login credentials are not valid (bad HMAC).", ""),
+ msg(QM_PASSEMAILCHANGED, "Auth failed: account password has been changed since you logged in.", ""),
}
EndMessages()
#endif
#include "../lib/hmac.h"
static prngctx rng;
-static sstring *secret, *codesecret;
+static sstring *secret, *codesecret, *ticketsecret;
static sstring *combinesecret(char *str) {
SHA256_CTX ctx;
secret=getsstring(hexbuf, strlen(hexbuf));
}
codesecret=combinesecret("codegenerator");
+
+ ticketsecret=getcopyconfigitem("chanserv","ticketsecret","",256);
+ if(!ticketsecret || !ticketsecret->content || !ticketsecret->content[0]) {
+ Error("chanserv",ERR_WARNING,"Ticket secret not set, ticketauth disabled.");
+ freesstring(ticketsecret);
+ ticketsecret = NULL;
+ }
}
void chanservcryptofree(void) {
freesstring(secret);
freesstring(codesecret);
+ freesstring(ticketsecret);
}
ub4 cs_getrandint(void) {
return hexbuf;
}
+
+int csc_verifyqticket(char *data, char *digest) {
+ hmacsha256 hmac;
+ unsigned char digestbuf[32];
+ char hexbuf[sizeof(digest) * 2 + 1];
+
+ if(!ticketsecret)
+ return -1;
+
+ hmacsha256_init(&hmac, (unsigned char *)ticketsecret->content, ticketsecret->length);
+ hmacsha256_update(&hmac, (unsigned char *)data, strlen(data));
+ hmacsha256_final(&hmac, digestbuf);
+
+ hmac_printhex(digestbuf, hexbuf, sizeof(digestbuf));
+
+ if(!strcasecmp(hexbuf, digest))
+ return 0;
+
+ return 1;
+}