]> jfr.im git - irc/quakenet/newserv.git/blobdiff - chanserv/chanservcrypto.c
Merge chanserv-live into default.
[irc/quakenet/newserv.git] / chanserv / chanservcrypto.c
index 80561f863046d7cc44c3d3077a3fc8f2d741e2e9..455b226526c592476d0acfc88828b789adfb0d41 100644 (file)
@@ -1,15 +1,37 @@
 #include <stdio.h>
+#include <strings.h>
 
 #include "chanserv.h"
 #include "../core/error.h"
+#include "../core/config.h"
 #include "../lib/prng.h"
 #include "../lib/sha1.h"
 #include "../lib/sha2.h"
 #include "../lib/md5.h"
 #include "../lib/hmac.h"
 
-prngctx rng;
+static prngctx rng;
+static sstring *secret, *codesecret, *ticketsecret;
 
+static sstring *combinesecret(char *str) {
+  SHA256_CTX ctx;
+  unsigned char digest[32];
+  char hexbuf[sizeof(digest) * 2 + 1];
+
+  SHA256_Init(&ctx);
+  SHA256_Update(&ctx, (unsigned char *)secret->content, secret->length);
+  SHA256_Update(&ctx, (unsigned char *)":", 1);
+  SHA256_Update(&ctx, (unsigned char *)str, strlen(str));
+  SHA256_Final(digest, &ctx);    
+
+  SHA256_Init(&ctx);
+  SHA256_Update(&ctx, digest, sizeof(digest));
+  SHA256_Final(digest, &ctx);    
+  hmac_printhex(digest, hexbuf, sizeof(digest));
+
+  return getsstring(hexbuf, strlen(hexbuf));
+}
 void chanservcryptoinit(void) {
   int ret;
 
@@ -28,6 +50,33 @@ void chanservcryptoinit(void) {
   }
 
   prnginit(&rng, 1);
+
+  secret=getcopyconfigitem("chanserv","secret","",128);
+  if(!secret || !secret->content || !secret->content[0]) {
+    unsigned char buf[32];
+    char hexbuf[sizeof(buf) * 2 + 1];
+    freesstring(secret);
+    Error("chanserv",ERR_WARNING,"Shared secret not set, generating a random string...");
+
+    cs_getrandbytes(buf, 32);
+    hmac_printhex(buf, hexbuf, sizeof(buf));
+    secret=getsstring(hexbuf, strlen(hexbuf));
+  }
+  codesecret=combinesecret("codegenerator");
+
+  ticketsecret=getcopyconfigitem("chanserv","ticketsecret","",256);
+  if(!ticketsecret || !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) {
@@ -42,7 +91,7 @@ void cs_getrandbytes(unsigned char *buf, size_t bytes) {
 }
 
 const char *cs_cralgorithmlist(void) {
-  return "HMAC-MD5 HMAC-SHA-1 HMAC-SHA-256";
+  return "HMAC-MD5 HMAC-SHA-1 HMAC-SHA-256 LEGACY-MD5";
 }
 
 int crsha1(char *username, const char *password, const char *challenge, const char *response) {
@@ -70,7 +119,7 @@ int crsha1(char *username, const char *password, const char *challenge, const ch
 
   hmac_printhex(digest, hexbuf, sizeof(digest));
 
-  if(!strcasecmp(hmac_printhex(digest, hexbuf, sizeof(digest)), response))
+  if(!hmac_strcmp(hmac_printhex(digest, hexbuf, sizeof(digest)), response))
     return 1;
 
   return 0;
@@ -99,7 +148,7 @@ int crsha256(char *username, const char *password, const char *challenge, const
   hmacsha256_update(&hmac, (unsigned char *)challenge, strlen(challenge));
   hmacsha256_final(&hmac, digest);
 
-  if(!strcasecmp(hmac_printhex(digest, hexbuf, sizeof(digest)), response))
+  if(!hmac_strcmp(hmac_printhex(digest, hexbuf, sizeof(digest)), response))
     return 1;
 
   return 0;
@@ -128,7 +177,24 @@ int crmd5(char *username, const char *password, const char *challenge, const cha
   hmacmd5_update(&hmac, (unsigned char *)challenge, strlen(challenge));
   hmacmd5_final(&hmac, digest);
 
-  if(!strcasecmp(hmac_printhex(digest, hexbuf, sizeof(digest)), response))
+  if(!hmac_strcmp(hmac_printhex(digest, hexbuf, sizeof(digest)), response))
+    return 1;
+
+  return 0;
+}
+
+int crlegacymd5(char *username, const char *password, const char *challenge, const char *response) {
+  MD5Context ctx;
+  unsigned char digest[16];
+  char hexbuf[sizeof(digest) * 2 + 1];
+
+  MD5Init(&ctx);
+  MD5Update(&ctx, (unsigned char *)password, strlen(password));
+  MD5Update(&ctx, (unsigned char *)" ", 1);
+  MD5Update(&ctx, (unsigned char *)challenge, strlen(challenge));
+  MD5Final(digest, &ctx);
+
+  if(!hmac_strcmp(hmac_printhex(digest, hexbuf, sizeof(digest)), response))
     return 1;
 
   return 0;
@@ -144,6 +210,9 @@ CRAlgorithm cs_cralgorithm(const char *algorithm) {
   if(!strcasecmp(algorithm, "hmac-md5"))
     return crmd5;
 
+  if(!strcasecmp(algorithm, "legacy-md5"))
+    return crlegacymd5;
+
   return 0;
 }
 
@@ -157,7 +226,7 @@ char *cs_calcchallenge(const unsigned char *entropy) {
   SHA1Update(&ctx, entropy, ENTROPYLEN);
   SHA1Final(buf, &ctx);
 
-  hmac_printhex(buf, hexbuf, sizeof(buf));
+  hmac_printhex(buf, hexbuf, 16);
 
   return hexbuf;
 }
@@ -173,7 +242,51 @@ int cs_checkhashpass(const char *username, const char *password, const char *jun
   MD5Update(&ctx, (unsigned char *)buf, strlen(buf));
   MD5Final(digest, &ctx);
 
-  if(strcasecmp(hash, hmac_printhex(digest, hexbuf, sizeof(digest))))
+  if(hmac_strcmp(hash, hmac_printhex(digest, hexbuf, sizeof(digest))))
+    return 0;
+
+  return 1;
+}
+
+char *csc_generateresetcode(time_t lockuntil, char *username) {
+  unsigned char digest[32];
+  static char hexbuf[sizeof(digest) * 2 + 1];
+  hmacsha256 hmac;
+  SHA256_CTX ctx;
+  char buf[1024];
+
+  snprintf(buf, sizeof(buf), "%s:%lu", username, lockuntil);
+
+  SHA256_Init(&ctx);
+  SHA256_Update(&ctx, (unsigned char *)buf, strlen(buf));
+  SHA256_Final(digest, &ctx);
+
+  hmac_printhex(digest, hexbuf, sizeof(digest));
+
+  hmacsha256_init(&hmac, (unsigned char *)codesecret->content, codesecret->length);
+  hmacsha256_update(&hmac, (unsigned char *)hexbuf, strlen(hexbuf));
+  hmacsha256_final(&hmac, digest);
+
+  hmac_printhex(digest, hexbuf, sizeof(digest));
+
+  return hexbuf;
+}
+
+int csc_verifyqticket(char *data, char *digest) {
+  hmacsha256 hmac;
+  unsigned char digestbuf[32];
+  char hexbuf[sizeof(digestbuf) * 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(!hmac_strcmp(hexbuf, digest))
     return 0;
 
   return 1;