]>
jfr.im git - irc/quakenet/newserv.git/blob - chanserv/chanservcrypto.c
5 #include "../core/error.h"
6 #include "../core/config.h"
7 #include "../lib/prng.h"
8 #include "../lib/sha1.h"
9 #include "../lib/sha2.h"
10 #include "../lib/md5.h"
11 #include "../lib/hmac.h"
14 static sstring
*secret
, *codesecret
, *ticketsecret
;
16 static sstring
*combinesecret(char *str
) {
18 unsigned char digest
[32];
19 char hexbuf
[sizeof(digest
) * 2 + 1];
22 SHA256_Update(&ctx
, (unsigned char *)secret
->content
, secret
->length
);
23 SHA256_Update(&ctx
, (unsigned char *)":", 1);
24 SHA256_Update(&ctx
, (unsigned char *)str
, strlen(str
));
25 SHA256_Final(digest
, &ctx
);
28 SHA256_Update(&ctx
, digest
, sizeof(digest
));
29 SHA256_Final(digest
, &ctx
);
30 hmac_printhex(digest
, hexbuf
, sizeof(digest
));
32 return getsstring(hexbuf
, strlen(hexbuf
));
35 void chanservcryptoinit(void) {
38 FILE *e
= fopen(ENTROPYSOURCE
, "rb");
40 Error("chanserv",ERR_STOP
,"Unable to open entropy source.");
41 /* shouldn't be running now... */
44 ret
= fread(rng
.randrsl
, 1, sizeof(rng
.randrsl
), e
);
47 if(ret
!= sizeof(rng
.randrsl
)) {
48 Error("chanserv",ERR_STOP
,"Unable to read entropy.");
49 /* shouldn't be running now... */
54 secret
=getcopyconfigitem("chanserv","secret","",128);
55 if(!secret
|| !secret
->content
|| !secret
->content
[0]) {
56 unsigned char buf
[32];
57 char hexbuf
[sizeof(buf
) * 2 + 1];
59 Error("chanserv",ERR_WARNING
,"Shared secret not set, generating a random string...");
61 cs_getrandbytes(buf
, 32);
62 hmac_printhex(buf
, hexbuf
, sizeof(buf
));
63 secret
=getsstring(hexbuf
, strlen(hexbuf
));
65 codesecret
=combinesecret("codegenerator");
67 ticketsecret
=getcopyconfigitem("chanserv","ticketsecret","",256);
68 if(!ticketsecret
|| !ticketsecret
->content
|| !ticketsecret
->content
[0]) {
69 Error("chanserv",ERR_WARNING
,"Ticket secret not set, ticketauth disabled.");
70 freesstring(ticketsecret
);
76 void chanservcryptofree(void) {
78 freesstring(codesecret
);
79 freesstring(ticketsecret
);
82 ub4
cs_getrandint(void) {
86 void cs_getrandbytes(unsigned char *buf
, size_t bytes
) {
87 for(;bytes
>0;bytes
-=4,buf
+=4) {
88 ub4 b
= cs_getrandint();
93 const char *cs_cralgorithmlist(void) {
94 return "HMAC-MD5 HMAC-SHA-1 HMAC-SHA-256 LEGACY-MD5";
97 int crsha1(char *username
, const char *password
, const char *challenge
, const char *response
) {
101 unsigned char digest
[20];
102 char hexbuf
[sizeof(digest
) * 2 + 1];
105 /* not sure how this helps but the RFC says to do it... */
107 SHA1Update(&ctx
, (unsigned char *)password
, strlen(password
));
108 SHA1Final(digest
, &ctx
);
110 snprintf(buf
, sizeof(buf
), "%s:%s", username
, hmac_printhex(digest
, hexbuf
, sizeof(digest
)));
113 SHA1Update(&ctx
, (unsigned char *)buf
, strlen(buf
));
114 SHA1Final(digest
, &ctx
);
116 hmacsha1_init(&hmac
, (unsigned char *)hmac_printhex(digest
, hexbuf
, sizeof(digest
)), sizeof(digest
) * 2);
117 hmacsha1_update(&hmac
, (unsigned char *)challenge
, strlen(challenge
));
118 hmacsha1_final(&hmac
, digest
);
120 hmac_printhex(digest
, hexbuf
, sizeof(digest
));
122 if(!strcasecmp(hmac_printhex(digest
, hexbuf
, sizeof(digest
)), response
))
128 int crsha256(char *username
, const char *password
, const char *challenge
, const char *response
) {
132 unsigned char digest
[32];
133 char hexbuf
[sizeof(digest
) * 2 + 1];
136 /* not sure how this helps but the RFC says to do it... */
138 SHA256_Update(&ctx
, (unsigned char *)password
, strlen(password
));
139 SHA256_Final(digest
, &ctx
);
141 snprintf(buf
, sizeof(buf
), "%s:%s", username
, hmac_printhex(digest
, hexbuf
, sizeof(digest
)));
144 SHA256_Update(&ctx
, (unsigned char *)buf
, strlen(buf
));
145 SHA256_Final(digest
, &ctx
);
147 hmacsha256_init(&hmac
, (unsigned char *)hmac_printhex(digest
, hexbuf
, sizeof(digest
)), sizeof(digest
) * 2);
148 hmacsha256_update(&hmac
, (unsigned char *)challenge
, strlen(challenge
));
149 hmacsha256_final(&hmac
, digest
);
151 if(!strcasecmp(hmac_printhex(digest
, hexbuf
, sizeof(digest
)), response
))
157 int crmd5(char *username
, const char *password
, const char *challenge
, const char *response
) {
161 unsigned char digest
[16];
162 char hexbuf
[sizeof(digest
) * 2 + 1];
165 /* not sure how this helps but the RFC says to do it... */
167 MD5Update(&ctx
, (unsigned char *)password
, strlen(password
));
168 MD5Final(digest
, &ctx
);
170 snprintf(buf
, sizeof(buf
), "%s:%s", username
, hmac_printhex(digest
, hexbuf
, sizeof(digest
)));
173 MD5Update(&ctx
, (unsigned char *)buf
, strlen(buf
));
174 MD5Final(digest
, &ctx
);
176 hmacmd5_init(&hmac
, (unsigned char *)hmac_printhex(digest
, hexbuf
, sizeof(digest
)), sizeof(digest
) * 2);
177 hmacmd5_update(&hmac
, (unsigned char *)challenge
, strlen(challenge
));
178 hmacmd5_final(&hmac
, digest
);
180 if(!strcasecmp(hmac_printhex(digest
, hexbuf
, sizeof(digest
)), response
))
186 int crlegacymd5(char *username
, const char *password
, const char *challenge
, const char *response
) {
188 unsigned char digest
[16];
189 char hexbuf
[sizeof(digest
) * 2 + 1];
192 MD5Update(&ctx
, (unsigned char *)password
, strlen(password
));
193 MD5Update(&ctx
, (unsigned char *)" ", 1);
194 MD5Update(&ctx
, (unsigned char *)challenge
, strlen(challenge
));
195 MD5Final(digest
, &ctx
);
197 if(!strcasecmp(hmac_printhex(digest
, hexbuf
, sizeof(digest
)), response
))
203 CRAlgorithm
cs_cralgorithm(const char *algorithm
) {
204 if(!strcasecmp(algorithm
, "hmac-sha-1"))
207 if(!strcasecmp(algorithm
, "hmac-sha-256"))
210 if(!strcasecmp(algorithm
, "hmac-md5"))
213 if(!strcasecmp(algorithm
, "legacy-md5"))
219 char *cs_calcchallenge(const unsigned char *entropy
) {
220 unsigned char buf
[20];
221 static char hexbuf
[sizeof(buf
) * 2 + 1];
225 /* we can maybe add a salt here in the future */
226 SHA1Update(&ctx
, entropy
, ENTROPYLEN
);
227 SHA1Final(buf
, &ctx
);
229 hmac_printhex(buf
, hexbuf
, 16);
234 int cs_checkhashpass(const char *username
, const char *password
, const char *junk
, const char *hash
) {
236 unsigned char digest
[16];
237 char hexbuf
[sizeof(digest
) * 2 + 1], buf
[512];
239 snprintf(buf
, sizeof(buf
), "%s %s%s%s", username
, password
, junk
?" ":"", junk
?junk
:"");
242 MD5Update(&ctx
, (unsigned char *)buf
, strlen(buf
));
243 MD5Final(digest
, &ctx
);
245 if(strcasecmp(hash
, hmac_printhex(digest
, hexbuf
, sizeof(digest
))))
251 char *csc_generateresetcode(time_t lockuntil
, char *username
) {
252 unsigned char digest
[32];
253 static char hexbuf
[sizeof(digest
) * 2 + 1];
258 snprintf(buf
, sizeof(buf
), "%s:%lu", username
, lockuntil
);
261 SHA256_Update(&ctx
, (unsigned char *)buf
, strlen(buf
));
262 SHA256_Final(digest
, &ctx
);
264 hmac_printhex(digest
, hexbuf
, sizeof(digest
));
266 hmacsha256_init(&hmac
, (unsigned char *)codesecret
->content
, codesecret
->length
);
267 hmacsha256_update(&hmac
, (unsigned char *)hexbuf
, strlen(hexbuf
));
268 hmacsha256_final(&hmac
, digest
);
270 hmac_printhex(digest
, hexbuf
, sizeof(digest
));
275 int csc_verifyqticket(char *data
, char *digest
) {
277 unsigned char digestbuf
[32];
278 char hexbuf
[sizeof(digest
) * 2 + 1];
283 hmacsha256_init(&hmac
, (unsigned char *)ticketsecret
->content
, ticketsecret
->length
);
284 hmacsha256_update(&hmac
, (unsigned char *)data
, strlen(data
));
285 hmacsha256_final(&hmac
, digestbuf
);
287 hmac_printhex(digestbuf
, hexbuf
, sizeof(digestbuf
));
289 if(!strcasecmp(hexbuf
, digest
))