]> jfr.im git - irc/quakenet/newserv.git/commitdiff
Add ticketauth functionality to Q.
authorChris Porter <redacted>
Mon, 10 Nov 2008 20:47:13 +0000 (20:47 +0000)
committerChris Porter <redacted>
Mon, 10 Nov 2008 20:47:13 +0000 (20:47 +0000)
chanserv/authcmds/login.c
chanserv/authcmds/ticketauth.c [new file with mode: 0644]
chanserv/chanserv.h
chanserv/chanserv_messages.h
chanserv/chanservcrypto.c

index efe24cd9bf5b9074f258eaafc38cdcd3cd2e5ed7..3f0b7db08ceb439bf76eb783bddccb361a985972 100644 (file)
 #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;
@@ -75,6 +73,16 @@ int csa_auth(void *source, int cargc, char **cargv, CRAlgorithm alg) {
     }
   }
 
+  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);
diff --git a/chanserv/authcmds/ticketauth.c b/chanserv/authcmds/ticketauth.c
new file mode 100644 (file)
index 0000000..ffe8bbd
--- /dev/null
@@ -0,0 +1,78 @@
+/* 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");
+}
index 0ca8f992e139a8a5ff13cc2ff6cda677d6e15304..32eae1a2df0d4624bfce067e8b0046085e841be0 100644 (file)
 #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 */
@@ -785,6 +786,7 @@ CRAlgorithm cs_cralgorithm(const char *algorithm);
 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);
index 0ae9fea853f31f967d1c006855e639efaaca84f2..c0c36754d1cab963d59a94da99921cbe2c491eda 100644 (file)
@@ -217,6 +217,11 @@ BeginMessages() {
   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
index 7906f8c7ca7eeac13e8c483adc2ebde72233dd83..605f3db66ef6cf1f2918a458cbefdba0b04e68a4 100644 (file)
@@ -11,7 +11,7 @@
 #include "../lib/hmac.h"
 
 static prngctx rng;
-static sstring *secret, *codesecret;
+static sstring *secret, *codesecret, *ticketsecret;
 
 static sstring *combinesecret(char *str) {
   SHA256_CTX ctx;
@@ -63,12 +63,20 @@ void chanservcryptoinit(void) {
     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) {
@@ -263,3 +271,23 @@ char *csc_generateresetcode(time_t lockuntil, char *username) {
 
   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;
+}