X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/blobdiff_plain/fc30cfc274083108c7114f2d9673dd5a735f1591..28aa186de14dc4fa7488866e70beb6ae933dde79:/chanserv/chanservcrypto.c diff --git a/chanserv/chanservcrypto.c b/chanserv/chanservcrypto.c index 80561f86..ba40f437 100644 --- a/chanserv/chanservcrypto.c +++ b/chanserv/chanservcrypto.c @@ -1,15 +1,37 @@ #include +#include #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 || !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;