[multiple] use <algo>_iov() digest funcs

reduce code duplication
make it easier to add new algos

mod_authn_file:
- leverage r->tmp_buf instead of temporary allocating buffer_init()
- mod_authn_file_htpasswd_basic()
  - compare binary SHA1 (shorter) rather than base64 (longer)
  - split crypt() from mod_authn_file_htpasswd_basic() to separate func
  - apr_md5_encode() modifications for slightly better performance
master
Glenn Strauss 2 years ago
parent 396a923066
commit c987bec18e

@ -65,11 +65,8 @@ li_hmac_md5 (unsigned char digest[MD5_DIGEST_LENGTH],
const void * const secret, const uint32_t slen,
const unsigned char * const msg, const uint32_t mlen)
{
li_MD5_CTX Md5Ctx;
li_MD5_Init(&Md5Ctx);
li_MD5_Update(&Md5Ctx, secret, slen);
li_MD5_Update(&Md5Ctx, msg, mlen);
li_MD5_Final(digest, &Md5Ctx);
struct const_iovec iov[] = { { secret, slen }, { msg, mlen } };
MD5_iov(digest, iov, sizeof(iov)/sizeof(*iov));
return 1;
}

@ -30,6 +30,10 @@ documentation and/or software.
#include "algo_md5.h"
#define li_MD5_CTX MD5_CTX
#define li_MD5_Init MD5_Init
#define li_MD5_Update MD5_Update
#define li_MD5_Final MD5_Final
#define UINT4 uint32_t
#define UINT2 uint16_t

@ -35,15 +35,15 @@ typedef struct {
uint32_t state[4]; /* state (ABCD) */
uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
} li_MD5_CTX;
} MD5_CTX;
#ifndef MD5_DIGEST_LENGTH
#define MD5_DIGEST_LENGTH 16
#endif
void li_MD5_Init (li_MD5_CTX *);
void li_MD5_Update (li_MD5_CTX *, const void *, unsigned int);
void li_MD5_Final (unsigned char [MD5_DIGEST_LENGTH], li_MD5_CTX *);
void MD5_Init (MD5_CTX *);
void MD5_Update (MD5_CTX *, const void *, unsigned int);
void MD5_Final (unsigned char [MD5_DIGEST_LENGTH], MD5_CTX *);
#else /* USE_LIB_CRYPTO_MD5 */

@ -843,240 +843,90 @@ static handler_t mod_auth_check_basic(request_st * const r, void *p_d, const str
}
#ifdef USE_LIB_CRYPTO
static void mod_auth_digest_mutate_sha256(http_auth_info_t *ai, const char *m, const char *uri, const char *nonce, const char *cnonce, const char *nc, const char *qop) {
SHA256_CTX ctx;
char a1[HTTP_AUTH_DIGEST_SHA256_BINLEN*2+1];
char a2[HTTP_AUTH_DIGEST_SHA256_BINLEN*2+1];
if (ai->dalgo & HTTP_AUTH_DIGEST_SESS) {
SHA256_Init(&ctx);
li_tohex(a1, sizeof(a1), (const char *)ai->digest, ai->dlen);
SHA256_Update(&ctx, (unsigned char *)a1, sizeof(a1)-1);
SHA256_Update(&ctx, CONST_STR_LEN(":"));
SHA256_Update(&ctx, (unsigned char *)nonce, strlen(nonce));
SHA256_Update(&ctx, CONST_STR_LEN(":"));
SHA256_Update(&ctx, (unsigned char *)cnonce, strlen(cnonce));
SHA256_Final(ai->digest, &ctx);
}
li_tohex(a1, sizeof(a1), (const char *)ai->digest, ai->dlen);
/* calculate H(A2) */
SHA256_Init(&ctx);
SHA256_Update(&ctx, (unsigned char *)m, strlen(m));
SHA256_Update(&ctx, CONST_STR_LEN(":"));
SHA256_Update(&ctx, (unsigned char *)uri, strlen(uri));
#if 0
/* qop=auth-int not supported, already checked in caller */
if (qop && buffer_eq_icase_ss(qop, strlen(qop), CONST_STR_LEN("auth-int"))){
SHA256_Update(&ctx, CONST_STR_LEN(":"));
SHA256_Update(&ctx, (unsigned char *) [body checksum], ai->dlen*2);
}
static void mod_auth_digest_mutate(http_auth_info_t *ai, const char *m, const char *uri, const char *nonce, const char *cnonce, const char *nc, const char *qop) {
li_md_iov_fn digest_iov = MD5_iov;
/* (ai->dalgo & HTTP_AUTH_DIGEST_MD5) default */
#ifdef USE_LIB_CRYPTO
if (ai->dalgo & HTTP_AUTH_DIGEST_SHA256)
digest_iov = SHA256_iov;
#ifdef USE_LIB_CRYPTO_SHA512_256
else if (ai->dalgo & HTTP_AUTH_DIGEST_SHA512_256)
digest_iov = SHA512_256_iov;
#endif
#endif
SHA256_Final(ai->digest, &ctx);
li_tohex(a2, sizeof(a2), (const char *)ai->digest, ai->dlen);
/* calculate response */
SHA256_Init(&ctx);
SHA256_Update(&ctx, (unsigned char *)a1, sizeof(a1)-1);
SHA256_Update(&ctx, CONST_STR_LEN(":"));
SHA256_Update(&ctx, (unsigned char *)nonce, strlen(nonce));
SHA256_Update(&ctx, CONST_STR_LEN(":"));
if (qop && *qop) {
SHA256_Update(&ctx, (unsigned char *)nc, strlen(nc));
SHA256_Update(&ctx, CONST_STR_LEN(":"));
SHA256_Update(&ctx, (unsigned char *)cnonce, strlen(cnonce));
SHA256_Update(&ctx, CONST_STR_LEN(":"));
SHA256_Update(&ctx, (unsigned char *)qop, strlen(qop));
SHA256_Update(&ctx, CONST_STR_LEN(":"));
}
SHA256_Update(&ctx, (unsigned char *)a2, sizeof(a2)-1);
SHA256_Final(ai->digest, &ctx);
}
static void mod_auth_digest_nonce_sha256(buffer *b, time_t cur_ts, int rnd, const buffer *secret) {
SHA256_CTX ctx;
size_t len;
unsigned char h[HTTP_AUTH_DIGEST_SHA256_BINLEN];
char hh[HTTP_AUTH_DIGEST_SHA256_BINLEN*2+1];
force_assert(sizeof(hh) >= LI_ITOSTRING_LENGTH);
SHA256_Init(&ctx);
len = li_itostrn(hh, sizeof(hh), cur_ts);
SHA256_Update(&ctx, (unsigned char *)hh, len);
len = li_itostrn(hh, sizeof(hh), rnd);
SHA256_Update(&ctx, (unsigned char *)hh, len);
if (secret) {
len = buffer_clen(secret);
SHA256_Update(&ctx, (unsigned char *)secret->ptr, len);
}
SHA256_Final(h, &ctx);
li_tohex(hh, sizeof(hh), (const char *)h, sizeof(h));
buffer_append_string_len(b, hh, sizeof(hh)-1);
}
#ifdef USE_LIB_CRYPTO_SHA512_256
static void mod_auth_digest_mutate_sha512_256(http_auth_info_t *ai, const char *m, const char *uri, const char *nonce, const char *cnonce, const char *nc, const char *qop) {
SHA512_CTX ctx;
char a1[HTTP_AUTH_DIGEST_SHA512_256_BINLEN*2+1];
char a2[HTTP_AUTH_DIGEST_SHA512_256_BINLEN*2+1];
if (ai->dalgo & HTTP_AUTH_DIGEST_SESS) {
SHA512_256_Init(&ctx);
li_tohex(a1, sizeof(a1), (const char *)ai->digest, ai->dlen);
SHA512_256_Update(&ctx, (unsigned char *)a1, sizeof(a1)-1);
SHA512_256_Update(&ctx, CONST_STR_LEN(":"));
SHA512_256_Update(&ctx, (unsigned char *)nonce, strlen(nonce));
SHA512_256_Update(&ctx, CONST_STR_LEN(":"));
SHA512_256_Update(&ctx, (unsigned char *)cnonce, strlen(cnonce));
SHA512_256_Final(ai->digest, &ctx);
}
size_t n;
struct const_iovec iov[11];
char a1[MD_DIGEST_LENGTH_MAX*2+8]; /*(+1 for li_tohex(); +8 for align)*/
char a2[MD_DIGEST_LENGTH_MAX*2+8]; /*(+1 for li_tohex(); +8 for align)*/
li_tohex(a1, sizeof(a1), (const char *)ai->digest, ai->dlen);
/* calculate H(A2) */
SHA512_256_Init(&ctx);
SHA512_256_Update(&ctx, (unsigned char *)m, strlen(m));
SHA512_256_Update(&ctx, CONST_STR_LEN(":"));
SHA512_256_Update(&ctx, (unsigned char *)uri, strlen(uri));
#if 0
/* qop=auth-int not supported, already checked in caller */
if (qop && buffer_eq_icase_ss(qop, strlen(qop), CONST_STR_LEN("auth-int"))){
SHA512_256_Update(&ctx, CONST_STR_LEN(":"));
SHA512_256_Update(&ctx, (unsigned char *)[body checksum], ai->dlen*2);
}
#endif
SHA512_256_Final(ai->digest, &ctx);
li_tohex(a2, sizeof(a2), (const char *)ai->digest, ai->dlen);
/* calculate response */
SHA512_256_Init(&ctx);
SHA512_256_Update(&ctx, (unsigned char *)a1, sizeof(a1)-1);
SHA512_256_Update(&ctx, CONST_STR_LEN(":"));
SHA512_256_Update(&ctx, (unsigned char *)nonce, strlen(nonce));
SHA512_256_Update(&ctx, CONST_STR_LEN(":"));
if (qop && *qop) {
SHA512_256_Update(&ctx, (unsigned char *)nc, strlen(nc));
SHA512_256_Update(&ctx, CONST_STR_LEN(":"));
SHA512_256_Update(&ctx, (unsigned char *)cnonce, strlen(cnonce));
SHA512_256_Update(&ctx, CONST_STR_LEN(":"));
SHA512_256_Update(&ctx, (unsigned char *)qop, strlen(qop));
SHA512_256_Update(&ctx, CONST_STR_LEN(":"));
}
SHA512_256_Update(&ctx, (unsigned char *)a2, sizeof(a2)-1);
SHA512_256_Final(ai->digest, &ctx);
}
static void mod_auth_digest_nonce_sha512_256(buffer *b, time_t cur_ts, int rnd, const buffer *secret) {
SHA512_CTX ctx;
size_t len;
unsigned char h[HTTP_AUTH_DIGEST_SHA512_256_BINLEN];
char hh[HTTP_AUTH_DIGEST_SHA512_256_BINLEN*2+1];
force_assert(sizeof(hh) >= LI_ITOSTRING_LENGTH);
SHA512_256_Init(&ctx);
len = li_itostrn(hh, sizeof(hh), cur_ts);
SHA512_256_Update(&ctx, (unsigned char *)hh, len);
len = li_itostrn(hh, sizeof(hh), rnd);
SHA512_256_Update(&ctx, (unsigned char *)hh, len);
if (secret) {
len = buffer_clen(secret);
SHA512_256_Update(&ctx, (unsigned char *)secret->ptr, len);
}
SHA512_256_Final(h, &ctx);
li_tohex(hh, sizeof(hh), (const char *)h, sizeof(h));
buffer_append_string_len(b, hh, sizeof(hh)-1);
}
#endif /* USE_LIB_CRYPTO_SHA512_256 */
#endif /* USE_LIB_CRYPTO */
static void mod_auth_digest_mutate_md5(http_auth_info_t *ai, const char *m, const char *uri, const char *nonce, const char *cnonce, const char *nc, const char *qop) {
li_MD5_CTX ctx;
char a1[HTTP_AUTH_DIGEST_MD5_BINLEN*2+1];
char a2[HTTP_AUTH_DIGEST_MD5_BINLEN*2+1];
if (ai->dalgo & HTTP_AUTH_DIGEST_SESS) {
li_MD5_Init(&ctx);
/* http://www.rfc-editor.org/errata_search.php?rfc=2617
* Errata ID: 1649 */
iov[0].iov_base = a1;
iov[0].iov_len = ai->dlen*2;
iov[1].iov_base = ":";
iov[1].iov_len = 1;
iov[2].iov_base = nonce;
iov[2].iov_len = strlen(nonce);
iov[3].iov_base = ":";
iov[3].iov_len = 1;
iov[4].iov_base = cnonce;
iov[4].iov_len = strlen(cnonce);
digest_iov(ai->digest, iov, 5);
li_tohex(a1, sizeof(a1), (const char *)ai->digest, ai->dlen);
li_MD5_Update(&ctx, (unsigned char *)a1, sizeof(a1)-1);
li_MD5_Update(&ctx, CONST_STR_LEN(":"));
li_MD5_Update(&ctx, (unsigned char *)nonce, strlen(nonce));
li_MD5_Update(&ctx, CONST_STR_LEN(":"));
li_MD5_Update(&ctx, (unsigned char *)cnonce, strlen(cnonce));
li_MD5_Final(ai->digest, &ctx);
}
li_tohex(a1, sizeof(a1), (const char *)ai->digest, ai->dlen);
/* calculate H(A2) */
li_MD5_Init(&ctx);
li_MD5_Update(&ctx, (unsigned char *)m, strlen(m));
li_MD5_Update(&ctx, CONST_STR_LEN(":"));
li_MD5_Update(&ctx, (unsigned char *)uri, strlen(uri));
iov[0].iov_base = m;
iov[0].iov_len = strlen(m);
iov[1].iov_base = ":";
iov[1].iov_len = 1;
iov[2].iov_base = uri;
iov[2].iov_len = strlen(uri);
n = 3;
#if 0
/* qop=auth-int not supported, already checked in caller */
if (qop && buffer_eq_icase_ss(qop, strlen(qop), CONST_STR_LEN("auth-int"))){
li_MD5_Update(&ctx, CONST_STR_LEN(":"));
li_MD5_Update(&ctx, (unsigned char *) [body checksum], ai->dlen*2);
iov[3].iov_base = ":";
iov[3].iov_len = 1;
iov[4].iov_base = [body checksum];
iov[4].iov_len = ai->dlen*2;
n = 5;
}
#endif
li_MD5_Final(ai->digest, &ctx);
digest_iov(ai->digest, iov, n);
li_tohex(a2, sizeof(a2), (const char *)ai->digest, ai->dlen);
/* calculate response */
li_MD5_Init(&ctx);
li_MD5_Update(&ctx, (unsigned char *)a1, sizeof(a1)-1);
li_MD5_Update(&ctx, CONST_STR_LEN(":"));
li_MD5_Update(&ctx, (unsigned char *)nonce, strlen(nonce));
li_MD5_Update(&ctx, CONST_STR_LEN(":"));
iov[0].iov_base = a1;
iov[0].iov_len = ai->dlen*2;
iov[1].iov_base = ":";
iov[1].iov_len = 1;
iov[2].iov_base = nonce;
iov[2].iov_len = strlen(nonce);
iov[3].iov_base = ":";
iov[3].iov_len = 1;
n = 4;
if (qop && *qop) {
li_MD5_Update(&ctx, (unsigned char *)nc, strlen(nc));
li_MD5_Update(&ctx, CONST_STR_LEN(":"));
li_MD5_Update(&ctx, (unsigned char *)cnonce, strlen(cnonce));
li_MD5_Update(&ctx, CONST_STR_LEN(":"));
li_MD5_Update(&ctx, (unsigned char *)qop, strlen(qop));
li_MD5_Update(&ctx, CONST_STR_LEN(":"));
iov[4].iov_base = nc;
iov[4].iov_len = strlen(nc);
iov[5].iov_base = ":";
iov[5].iov_len = 1;
iov[6].iov_base = cnonce;
iov[6].iov_len = strlen(cnonce);
iov[7].iov_base = ":";
iov[7].iov_len = 1;
iov[8].iov_base = qop;
iov[8].iov_len = strlen(qop);
iov[9].iov_base = ":";
iov[9].iov_len = 1;
n = 10;
}
li_MD5_Update(&ctx, (unsigned char *)a2, sizeof(a2)-1);
li_MD5_Final(ai->digest, &ctx);
}
static void mod_auth_digest_nonce_md5(buffer *b, time_t cur_ts, int rnd, const buffer *secret) {
li_MD5_CTX ctx;
size_t len;
unsigned char h[HTTP_AUTH_DIGEST_MD5_BINLEN];
char hh[HTTP_AUTH_DIGEST_MD5_BINLEN*2+1];
force_assert(sizeof(hh) >= LI_ITOSTRING_LENGTH);
li_MD5_Init(&ctx);
len = li_itostrn(hh, sizeof(hh), cur_ts);
li_MD5_Update(&ctx, (unsigned char *)hh, len);
len = li_itostrn(hh, sizeof(hh), rnd);
li_MD5_Update(&ctx, (unsigned char *)hh, len);
if (secret) {
len = buffer_clen(secret);
li_MD5_Update(&ctx, (unsigned char *)secret->ptr, len);
}
li_MD5_Final(h, &ctx);
li_tohex(hh, sizeof(hh), (const char *)h, sizeof(h));
buffer_append_string_len(b, hh, sizeof(hh)-1);
}
static void mod_auth_digest_mutate(http_auth_info_t *ai, const char *m, const char *uri, const char *nonce, const char *cnonce, const char *nc, const char *qop) {
if (ai->dalgo & HTTP_AUTH_DIGEST_MD5)
mod_auth_digest_mutate_md5(ai, m, uri, nonce, cnonce, nc, qop);
#ifdef USE_LIB_CRYPTO
else if (ai->dalgo & HTTP_AUTH_DIGEST_SHA256)
mod_auth_digest_mutate_sha256(ai, m, uri, nonce, cnonce, nc, qop);
#ifdef USE_LIB_CRYPTO_SHA512_256
else if (ai->dalgo & HTTP_AUTH_DIGEST_SHA512_256)
mod_auth_digest_mutate_sha512_256(ai, m, uri, nonce, cnonce, nc, qop);
#endif
#endif
iov[n].iov_base = a2;
iov[n].iov_len = ai->dlen*2;
digest_iov(ai->digest, iov, n+1);
}
static void mod_auth_append_nonce(buffer *b, time_t cur_ts, const struct http_auth_require_t *require, int dalgo, int *rndptr) {
@ -1093,22 +943,51 @@ static void mod_auth_append_nonce(buffer *b, time_t cur_ts, const struct http_au
buffer_append_uint_hex(b, (uintmax_t)rnd);
buffer_append_string_len(b, CONST_STR_LEN(":"));
}
size_t n;
struct const_iovec iov[3];
#if 0
char a1[LI_ITOSTRING_LENGTH];
char a2[LI_ITOSTRING_LENGTH];
iov[0].iov_base = a1;
iov[0].iov_len = li_itostrn(a1, sizeof(a1), cur_ts);
iov[1].iov_base = a2;
iov[1].iov_len = li_itostrn(a2, sizeof(a2), rnd);
#else
iov[0].iov_base = &cur_ts;
iov[0].iov_len = sizeof(cur_ts);
iov[1].iov_base = &rnd;
iov[1].iov_len = sizeof(rnd);
#endif
n = 2;
if (nonce_secret) {
iov[2].iov_base = nonce_secret->ptr;
iov[2].iov_len = buffer_clen(nonce_secret);
n = 3;
}
unsigned char h[MD_DIGEST_LENGTH_MAX];
switch (dalgo) {
#ifdef USE_LIB_CRYPTO
#ifdef USE_LIB_CRYPTO_SHA512_256
case HTTP_AUTH_DIGEST_SHA512_256:
mod_auth_digest_nonce_sha512_256(b, cur_ts, rnd, nonce_secret);
SHA512_256_iov(h, iov, n);
n = HTTP_AUTH_DIGEST_SHA512_256_BINLEN;
break;
#endif
case HTTP_AUTH_DIGEST_SHA256:
mod_auth_digest_nonce_sha256(b, cur_ts, rnd, nonce_secret);
SHA256_iov(h, iov, n);
n = HTTP_AUTH_DIGEST_SHA256_BINLEN;
break;
#endif
/*case HTTP_AUTH_DIGEST_MD5:*/
default:
mod_auth_digest_nonce_md5(b, cur_ts, rnd, nonce_secret);
MD5_iov(h, iov, n);
n = HTTP_AUTH_DIGEST_MD5_BINLEN;
break;
}
li_tohex(buffer_extend(b, n*2), n*2+1, (const char *)h, n);
}
static void mod_auth_digest_www_authenticate(buffer *b, time_t cur_ts, const struct http_auth_require_t *require, int nonce_stale) {
@ -1190,7 +1069,7 @@ static handler_t mod_auth_check_digest(request_st * const r, void *p_d, const st
int i;
buffer *b;
http_auth_info_t ai;
unsigned char rdigest[HTTP_AUTH_DIGEST_SHA256_BINLEN];
unsigned char rdigest[MD_DIGEST_LENGTH_MAX];
/* init pointers */

@ -383,51 +383,33 @@ mod_authn_dbi_password_cmp (const char *userpw, unsigned long userpwlen, http_au
#if defined(HAVE_CRYPT_R) || defined(HAVE_CRYPT)
if (userpwlen >= 3 && userpw[0] == '$')
return mod_authn_crypt_cmp(reqpw, userpw, userpwlen);
else
#endif
if (32 == userpwlen) {
/* plain md5 */
MD5_CTX ctx;
unsigned char HA1[16];
unsigned char md5pw[16];
MD5_Init(&ctx);
MD5_Update(&ctx, (unsigned char *)ai->username, ai->ulen);
MD5_Update(&ctx, CONST_STR_LEN(":"));
MD5_Update(&ctx, (unsigned char *)ai->realm, ai->rlen);
MD5_Update(&ctx, CONST_STR_LEN(":"));
MD5_Update(&ctx, (unsigned char *)reqpw, strlen(reqpw));
MD5_Final(HA1, &ctx);
/*(compare 16-byte MD5 binary instead of converting to hex strings
* in order to then have to do case-insensitive hex str comparison)*/
return (0 == li_hex2bin(md5pw, sizeof(md5pw), userpw, 32))
? ck_memeq_const_time_fixed_len(HA1, md5pw, sizeof(md5pw)) ? 0 : 1
: -1;
}
const struct const_iovec iov[] = {
{ ai->username, ai->ulen }
,{ ":", 1 }
,{ ai->realm, ai->rlen }
,{ ":", 1 }
,{ reqpw, strlen(reqpw) }
};
unsigned char HA1[MD_DIGEST_LENGTH_MAX];
unsigned char pwbin[MD_DIGEST_LENGTH_MAX];
if (32 == userpwlen)
MD5_iov(HA1, iov, sizeof(iov)/sizeof(*iov));
#ifdef USE_LIB_CRYPTO
else if (64 == userpwlen) {
SHA256_CTX ctx;
unsigned char HA1[32];
unsigned char shapw[32];
SHA256_Init(&ctx);
SHA256_Update(&ctx, (unsigned char *)ai->username, ai->ulen);
SHA256_Update(&ctx, CONST_STR_LEN(":"));
SHA256_Update(&ctx, (unsigned char *)ai->realm, ai->rlen);
SHA256_Update(&ctx, CONST_STR_LEN(":"));
SHA256_Update(&ctx, (unsigned char *)reqpw, strlen(reqpw));
SHA256_Final(HA1, &ctx);
/*(compare 32-byte binary digest instead of converting to hex strings
* in order to then have to do case-insensitive hex str comparison)*/
return (0 == li_hex2bin(shapw, sizeof(shapw), userpw, 64))
? ck_memeq_const_time_fixed_len(HA1, shapw, sizeof(shapw)) ? 0 : 1
: -1;
}
else if (64 == userpwlen)
SHA256_iov(HA1, iov, sizeof(iov)/sizeof(*iov));
#endif
else
return -1;
return -1;
/*(compare 32-byte binary digest instead of converting to hex strings
* in order to then have to do case-insensitive hex str comparison)*/
return (0 == li_hex2bin(pwbin, sizeof(pwbin), userpw, userpwlen))
? ck_memeq_const_time_fixed_len(HA1, pwbin, userpwlen>>1) ? 0 : 1
: -1;
}

@ -166,57 +166,27 @@ SETDEFAULTS_FUNC(mod_authn_file_set_defaults) {
#ifdef USE_LIB_CRYPTO
static void mod_authn_file_digest_sha256(http_auth_info_t *ai, const char *pw, size_t pwlen) {
SHA256_CTX ctx;
SHA256_Init(&ctx);
SHA256_Update(&ctx, (const unsigned char *)ai->username, ai->ulen);
SHA256_Update(&ctx, CONST_STR_LEN(":"));
SHA256_Update(&ctx, (const unsigned char *)ai->realm, ai->rlen);
SHA256_Update(&ctx, CONST_STR_LEN(":"));
SHA256_Update(&ctx, (const unsigned char *)pw, pwlen);
SHA256_Final(ai->digest, &ctx);
}
#ifdef USE_LIB_CRYPTO_SHA512_256
static void mod_authn_file_digest_sha512_256(http_auth_info_t *ai, const char *pw, size_t pwlen) {
SHA512_CTX ctx;
SHA512_256_Init(&ctx);
SHA512_256_Update(&ctx, (const unsigned char *)ai->username, ai->ulen);
SHA512_256_Update(&ctx, CONST_STR_LEN(":"));
SHA512_256_Update(&ctx, (const unsigned char *)ai->realm, ai->rlen);
SHA512_256_Update(&ctx, CONST_STR_LEN(":"));
SHA512_256_Update(&ctx, (const unsigned char *)pw, pwlen);
SHA512_256_Final(ai->digest, &ctx);
}
#endif
#endif
static void mod_authn_file_digest_md5(http_auth_info_t *ai, const char *pw, size_t pwlen) {
li_MD5_CTX ctx;
li_MD5_Init(&ctx);
li_MD5_Update(&ctx, (const unsigned char *)ai->username, ai->ulen);
li_MD5_Update(&ctx, CONST_STR_LEN(":"));
li_MD5_Update(&ctx, (const unsigned char *)ai->realm, ai->rlen);
li_MD5_Update(&ctx, CONST_STR_LEN(":"));
li_MD5_Update(&ctx, (const unsigned char *)pw, pwlen);
li_MD5_Final(ai->digest, &ctx);
}
static void mod_authn_file_digest(http_auth_info_t *ai, const char *pw, size_t pwlen) {
if (ai->dalgo & HTTP_AUTH_DIGEST_MD5)
mod_authn_file_digest_md5(ai, pw, pwlen);
li_md_iov_fn digest_iov = MD5_iov;
/* (ai->dalgo & HTTP_AUTH_DIGEST_MD5) default */
#ifdef USE_LIB_CRYPTO
else if (ai->dalgo & HTTP_AUTH_DIGEST_SHA256)
mod_authn_file_digest_sha256(ai, pw, pwlen);
if (ai->dalgo & HTTP_AUTH_DIGEST_SHA256)
digest_iov = SHA256_iov;
#ifdef USE_LIB_CRYPTO_SHA512_256
else if (ai->dalgo & HTTP_AUTH_DIGEST_SHA512_256)
mod_authn_file_digest_sha512_256(ai, pw, pwlen);
digest_iov = SHA512_256_iov;
#endif
#endif
struct const_iovec iov[] = {
{ ai->username, ai->ulen }
,{ ":", 1 }
,{ ai->realm, ai->rlen }
,{ ":", 1 }
,{ pw, pwlen }
};
digest_iov(ai->digest, iov, sizeof(iov)/sizeof(*iov));
}
@ -390,32 +360,34 @@ static int mod_authn_file_htpasswd_get(const buffer *auth_fn, const char *userna
static handler_t mod_authn_file_plain_digest(request_st * const r, void *p_d, http_auth_info_t * const ai) {
plugin_data *p = (plugin_data *)p_d;
buffer *password_buf = buffer_init();/* password-string from auth-backend */
int rc;
mod_authn_file_patch_config(r, p);
rc = mod_authn_file_htpasswd_get(p->conf.auth_plain_userfile, ai->username, ai->ulen, password_buf, r->conf.errh);
if (0 == rc) {
/* generate password from plain-text */
mod_authn_file_digest(ai, BUF_PTR_LEN(password_buf));
}
ck_memzero(password_buf->ptr, password_buf->size);
buffer_free(password_buf);
return (0 == rc) ? HANDLER_GO_ON : HANDLER_ERROR;
buffer * const tb = r->tmp_buf; /* password-string from auth-backend */
int rc = mod_authn_file_htpasswd_get(p->conf.auth_plain_userfile,
ai->username, ai->ulen, tb,
r->conf.errh);
if (0 != rc) return HANDLER_ERROR;
/* generate password digest from plain-text */
mod_authn_file_digest(ai, BUF_PTR_LEN(tb));
size_t tblen = (buffer_clen(tb) + 63) & ~63u;
buffer_clear(tb);
ck_memzero(tb->ptr, tblen < tb->size ? tblen : tb->size);
return HANDLER_GO_ON;
}
static handler_t mod_authn_file_plain_basic(request_st * const r, void *p_d, const http_auth_require_t * const require, const buffer * const username, const char * const pw) {
plugin_data *p = (plugin_data *)p_d;
buffer *password_buf = buffer_init();/* password-string from auth-backend */
int rc;
mod_authn_file_patch_config(r, p);
rc = mod_authn_file_htpasswd_get(p->conf.auth_plain_userfile, BUF_PTR_LEN(username), password_buf, r->conf.errh);
buffer * const tb = r->tmp_buf; /* password-string from auth-backend */
int rc = mod_authn_file_htpasswd_get(p->conf.auth_plain_userfile,
BUF_PTR_LEN(username), tb,
r->conf.errh);
if (0 == rc) {
rc = ck_memeq_const_time(BUF_PTR_LEN(password_buf), pw, strlen(pw))
? 0
: -1;
rc = ck_memeq_const_time(BUF_PTR_LEN(tb), pw, strlen(pw)) ? 0 : -1;
size_t tblen = (buffer_clen(tb) + 63) & ~63u;
buffer_clear(tb);
ck_memzero(tb->ptr, tblen < tb->size ? tblen : tb->size);
}
ck_memzero(password_buf->ptr, password_buf->size);
buffer_free(password_buf);
return 0 == rc && http_auth_match_rules(require, username->ptr, NULL, NULL)
? HANDLER_GO_ON
: HANDLER_ERROR;
@ -426,6 +398,7 @@ static handler_t mod_authn_file_plain_basic(request_st * const r, void *p_d, con
/**
* the $apr1$ handling is taken from apache 1.3.x
* XXX: code has since been modified for slightly better performance
*/
/*
@ -459,201 +432,151 @@ static void to64(char *s, unsigned long v, int n)
}
}
static void apr_md5_encode(const char *pw, const char *salt, char *result, size_t nbytes) {
/*
* Minimum size is 8 bytes for salt, plus 1 for the trailing NUL,
* plus 4 for the '$' separators, plus the password hash itself.
* Let's leave a goodly amount of leeway.
*/
static size_t apr_md5_encode(const char *pw, const char *salt, char *result, size_t nbytes) {
force_assert(nbytes >= 37); /*(nbytes should be >= 37)*/
char passwd[120], *p;
const char *sp, *ep;
unsigned char final[APR_MD5_DIGESTSIZE];
ssize_t sl, pl, i;
li_MD5_CTX ctx, ctx1;
unsigned long l;
const size_t pwlen = strlen(pw);
ssize_t sl;
/*
* Refine the salt first. It's possible we were given an already-hashed
* string as the salt argument, so extract the actual salt value from it
* if so. Otherwise just use the string up to the first '$' as the salt.
*/
sp = salt;
#if 0 /*(already checked and stepped-over in caller)*/
/*
* If it starts with the magic string, then skip that.
*/
if (!strncmp(sp, APR1_ID, strlen(APR1_ID))) {
sp += strlen(APR1_ID);
if (!strncmp(salt, APR1_ID, sizeof(APR1_ID)-1)) {
salt += sizeof(APR1_ID)-1;
}
#endif
/*
* It stops at the first '$' or 8 chars, whichever comes first
* Get the length of the true salt
*/
for (ep = sp; (*ep != '\0') && (*ep != '$') && (ep < (sp + 8)); ep++) {
continue;
}
/*
* Get the length of the true salt
* It stops at the first '$' or 8 chars, whichever comes first
*/
sl = ep - sp;
for (sl = 0; sl < 8 && salt[sl] != '$' && salt[sl] != '\0'; ++sl) ;
/* result begins with "$apr1$salt$" */
memcpy(result, APR1_ID, sizeof(APR1_ID)-1);
memcpy(result+sizeof(APR1_ID)-1, salt, sl);
result[sizeof(APR1_ID)-1+sl] = '$';
MD5_CTX ctx;
unsigned char final[APR_MD5_DIGESTSIZE];
MD5_Init(&ctx);
MD5_Update(&ctx, pw, pwlen);
MD5_Update(&ctx, salt, sl);
MD5_Update(&ctx, pw, pwlen);
MD5_Final(final, &ctx);
/*
* 'Time to make the doughnuts..'
*/
li_MD5_Init(&ctx);
MD5_Init(&ctx);
/*
* The password first, since that is what is most unknown
*/
li_MD5_Update(&ctx, pw, strlen(pw));
MD5_Update(&ctx, pw, pwlen);
#if 0
/*
* Then our magic string
*/
li_MD5_Update(&ctx, APR1_ID, strlen(APR1_ID));
MD5_Update(&ctx, APR1_ID, sizeof(APR1_ID)-1);
/*
* Then the raw salt
*/
li_MD5_Update(&ctx, sp, sl);
MD5_Update(&ctx, salt, sl);
#else
MD5_Update(&ctx, result, sizeof(APR1_ID)-1 + sl);
#endif
/*
* Then just as many characters of the MD5(pw, salt, pw)
*/
li_MD5_Init(&ctx1);
li_MD5_Update(&ctx1, pw, strlen(pw));
li_MD5_Update(&ctx1, sp, sl);
li_MD5_Update(&ctx1, pw, strlen(pw));
li_MD5_Final(final, &ctx1);
for (pl = strlen(pw); pl > 0; pl -= APR_MD5_DIGESTSIZE) {
li_MD5_Update(&ctx, final,
(pl > APR_MD5_DIGESTSIZE) ? APR_MD5_DIGESTSIZE : pl);
for (ssize_t pl = pwlen; pl > 0; pl -= APR_MD5_DIGESTSIZE) {
MD5_Update(&ctx, final,
(pl > APR_MD5_DIGESTSIZE) ? APR_MD5_DIGESTSIZE : pl);
}
/*
* Don't leave anything around in vm they could use.
*/
memset(final, 0, sizeof(final));
/*ck_memzero(final, sizeof(final));*/
final[0] = 0; /*(preserve behavior for loop below)*/
/*
* Then something really weird...
*/
for (i = strlen(pw); i != 0; i >>= 1) {
if (i & 1) {
li_MD5_Update(&ctx, final, 1);
}
else {
li_MD5_Update(&ctx, pw, 1);
}
for (size_t i = pwlen; i != 0; i >>= 1) {
MD5_Update(&ctx, (i & 1) ? (char *)final : pw, 1);
}
/*
* Now make the output string. We know our limitations, so we
* can use the string routines without bounds checking.
*/
strcpy(passwd, APR1_ID);
strncat(passwd, sp, sl);
strcat(passwd, "$");
li_MD5_Final(final, &ctx);
MD5_Final(final, &ctx);
/*
* And now, just to make sure things don't run too fast..
* On a 60 Mhz Pentium this takes 34 msec, so you would
* need 30 seconds to build a 1000 entry dictionary...
*/
for (i = 0; i < 1000; i++) {
li_MD5_Init(&ctx1);
for (int i = 0; i < 1000; ++i) {
MD5_Init(&ctx);
if (i & 1) {
li_MD5_Update(&ctx1, pw, strlen(pw));
MD5_Update(&ctx, pw, pwlen);
}
else {
li_MD5_Update(&ctx1, final, APR_MD5_DIGESTSIZE);
MD5_Update(&ctx, final, APR_MD5_DIGESTSIZE);
}
if (i % 3) {
li_MD5_Update(&ctx1, sp, sl);
MD5_Update(&ctx, salt, sl);
}
if (i % 7) {
li_MD5_Update(&ctx1, pw, strlen(pw));
MD5_Update(&ctx, pw, pwlen);
}
if (i & 1) {
li_MD5_Update(&ctx1, final, APR_MD5_DIGESTSIZE);
MD5_Update(&ctx, final, APR_MD5_DIGESTSIZE);
}
else {
li_MD5_Update(&ctx1, pw, strlen(pw));
MD5_Update(&ctx, pw, pwlen);
}
li_MD5_Final(final,&ctx1);
MD5_Final(final,&ctx);
}
p = passwd + strlen(passwd);
/*
* Now make the output string. (nbytes checked at top of func)
* Maximum result size below is 37:
* 6 for APR_ID, <= 8 for salt, 1 for '$', 22 for password hash
*/
l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p, l, 4); p += 4;
l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p, l, 4); p += 4;
l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p, l, 4); p += 4;
l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p, l, 4); p += 4;
l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p, l, 4); p += 4;
l = final[11] ; to64(p, l, 2); p += 2;
*p = '\0';
result += sizeof(APR1_ID)-1 + sl + 1;
to64(result, (final[ 0]<<16) | (final[ 6]<<8) | final[12], 4);
to64(result+4, (final[ 1]<<16) | (final[ 7]<<8) | final[13], 4);
to64(result+8, (final[ 2]<<16) | (final[ 8]<<8) | final[14], 4);
to64(result+12, (final[ 3]<<16) | (final[ 9]<<8) | final[15], 4);
to64(result+16, (final[ 4]<<16) | (final[10]<<8) | final[ 5], 4);
to64(result+20, final[11] , 2);
/*
* Don't leave anything around in vm they could use.
*/
ck_memzero(final, sizeof(final));
/* FIXME
*/
#define apr_cpystrn strncpy
apr_cpystrn(result, passwd, nbytes - 1);
}
static void apr_sha_encode(const char *pw, char *result, size_t nbytes) {
unsigned char digest[20];
size_t base64_written;
SHA_CTX sha1;
SHA1_Init(&sha1);
SHA1_Update(&sha1, (const unsigned char *) pw, strlen(pw));
SHA1_Final(digest, &sha1);
memset(result, 0, nbytes);
/* need 5 bytes for "{SHA}", 28 for base64 (3 bytes -> 4 bytes) of SHA1 (20 bytes), 1 terminating */
if (nbytes < 5 + 28 + 1) return;
memcpy(result, "{SHA}", 5);
base64_written = li_to_base64(result + 5, nbytes - 5, digest, 20, BASE64_STANDARD);
force_assert(base64_written == 28);
result[5 + base64_written] = '\0'; /* terminate string */
return (sizeof(APR1_ID)-1 + sl + 1 + 22);
}
static handler_t mod_authn_file_htpasswd_basic(request_st * const r, void *p_d, const http_auth_require_t * const require, const buffer * const username, const char * const pw) {
plugin_data *p = (plugin_data *)p_d;
buffer *password = buffer_init();/* password-string from auth-backend */
int rc;
mod_authn_file_patch_config(r, p);
rc = mod_authn_file_htpasswd_get(p->conf.auth_htpasswd_userfile, BUF_PTR_LEN(username), password, r->conf.errh);
if (0 == rc) {
char sample[256];
rc = -1;
if (!strncmp(password->ptr, APR1_ID, strlen(APR1_ID))) {
/*
* The hash was created using $apr1$ custom algorithm.
*/
apr_md5_encode(pw, password->ptr, sample, sizeof(sample));
rc = strcmp(sample, password->ptr);
}
else if (0 == strncmp(password->ptr, "{SHA}", 5)) {
apr_sha_encode(pw, sample, sizeof(sample));
rc = strcmp(sample, password->ptr);
}
#if defined(HAVE_CRYPT_R) || defined(HAVE_CRYPT)
/* a simple DES password is 2 + 11 characters. everything else should be longer. */
else if (buffer_clen(password) >= 13) {
#if defined(HAVE_CRYPT_R) || defined(HAVE_CRYPT)
static int mod_authn_file_crypt_cmp(const buffer * const password, const char * const pw) {
int rc = -1;
char *crypted;
char sample[256];
#if 0 && defined(HAVE_CRYPT_R)
struct crypt_data crypt_tmp_data;
#ifdef _AIX
@ -663,9 +586,10 @@ static handler_t mod_authn_file_htpasswd_basic(request_st * const r, void *p_d,
#endif
#endif
#ifdef USE_LIB_CRYPTO_MD4 /*(for MD4_*() (e.g. MD4_Update()))*/
/*(caller checked buffer_clen(passwd) >= 13)*/
if (0 == memcmp(password->ptr, CONST_STR_LEN("$1+ntlm$"))) {
/* CRYPT-MD5-NTLM algorithm
* This algorithm allows for the construction of (slight more)
* This algorithm allows for the construction of (slightly more)
* secure, salted password hashes from an environment where only
* legacy NTLM hashes are available and where it is not feasible
* to re-hash all the passwords with the MD5-based crypt(). */
@ -681,10 +605,6 @@ static handler_t mod_authn_file_htpasswd_basic(request_st * const r, void *p_d,
&& pwlen < sizeof(sample)) {
/* compute NTLM hash and convert to lowercase hex chars
* (require lc hex chars from li_tohex()) */
char ntlmhash[16];
char ntlmhex[33]; /*(sizeof(ntlmhash)*2 + 1)*/
MD4_CTX c;
MD4_Init(&c);
if (pwlen) {
/*(reuse sample buffer to encode pw into UCS-2LE)
*(Note: assumes pw input in ISO-8859-1) */
@ -693,9 +613,10 @@ static handler_t mod_authn_file_htpasswd_basic(request_st * const r, void *p_d,
sample[i] = pw[(i >> 1)];
sample[i+1] = 0;
}
MD4_Update(&c, (unsigned char *)sample, pwlen);
}
MD4_Final((unsigned char *)ntlmhash, &c);
char ntlmhash[MD4_DIGEST_LENGTH];
char ntlmhex[MD4_DIGEST_LENGTH*2+1];
MD4_once((unsigned char *)ntlmhash, sample, pwlen);
li_tohex(ntlmhex,sizeof(ntlmhex),ntlmhash,sizeof(ntlmhash));
/*(reuse sample buffer for salt (FYI: expect slen == 8))*/
@ -725,11 +646,51 @@ static handler_t mod_authn_file_htpasswd_basic(request_st * const r, void *p_d,
rc = strcmp(password->ptr, crypted);
}
}
}
#endif
ck_memzero(sample, sizeof(sample));
return rc;
}
#endif
static handler_t mod_authn_file_htpasswd_basic(request_st * const r, void *p_d, const http_auth_require_t * const require, const buffer * const username, const char * const pw) {
plugin_data *p = (plugin_data *)p_d;
mod_authn_file_patch_config(r, p);
buffer * const tb = r->tmp_buf; /* password-string from auth-backend */
int rc = mod_authn_file_htpasswd_get(p->conf.auth_htpasswd_userfile,
BUF_PTR_LEN(username), tb,
r->conf.errh);
if (0 != rc) return HANDLER_ERROR;
uint32_t tblen = buffer_clen(tb);
rc = -1;
if (tblen >= 5 && 0 == memcmp(tb->ptr, "{SHA}", 5)) {
/* 32 == (5 for "{SHA}" + 28 for base64 of SHA1 (20 bytes)) */
unsigned char digest[SHA_DIGEST_LENGTH*2];
SHA1_once(digest+SHA_DIGEST_LENGTH, pw, strlen(pw));
rc = SHA_DIGEST_LENGTH
== li_base64_dec(digest, sizeof(digest),
tb->ptr+5, tblen-5, BASE64_STANDARD)
&& ck_memeq_const_time_fixed_len(digest, digest+SHA_DIGEST_LENGTH,
SHA_DIGEST_LENGTH);
rc = !rc; /* (0 == rc) for match */
ck_memzero(digest, sizeof(digest));
}
ck_memzero(password->ptr, password->size);
buffer_free(password);
else if (tblen >= 6 && 0 == memcmp(tb->ptr, "$apr1$", 6)) {
char sample[40]; /*(see comments at end of apr_md5_encode())*/
rc = tblen == apr_md5_encode(pw, tb->ptr+6, sample, sizeof(sample))
&& ck_memeq_const_time_fixed_len(sample, tb->ptr, tblen);
rc = !rc; /* (0 == rc) for match */
ck_memzero(sample, sizeof(sample));
}
#if defined(HAVE_CRYPT_R) || defined(HAVE_CRYPT)
/* simple DES password is 2 + 11 characters;
* everything else should be longer */
else if (tblen >= 13) {
rc = mod_authn_file_crypt_cmp(tb, pw);
}
#endif
tblen = (tblen + 63) & ~63u;
buffer_clear(tb);
ck_memzero(tb->ptr, tblen < tb->size ? tblen : tb->size);
return 0 == rc && http_auth_match_rules(require, username->ptr, NULL, NULL)
? HANDLER_GO_ON
: HANDLER_ERROR;

@ -306,13 +306,9 @@ static int mod_authn_mysql_password_cmp(const char *userpw, unsigned long userpw
#endif
if (32 == userpwlen) {
/* plain md5 */
li_MD5_CTX Md5Ctx;
unsigned char HA1[16];
unsigned char md5pw[16];
li_MD5_Init(&Md5Ctx);
li_MD5_Update(&Md5Ctx, (unsigned char *)reqpw, strlen(reqpw));
li_MD5_Final(HA1, &Md5Ctx);
unsigned char HA1[MD5_DIGEST_LENGTH];
unsigned char md5pw[MD5_DIGEST_LENGTH];
MD5_once(HA1, reqpw, strlen(reqpw));
/*(compare 16-byte MD5 binary instead of converting to hex strings
* in order to then have to do case-insensitive hex str comparison)*/

@ -18,15 +18,7 @@
#include "log.h"
#include "plugin.h"
#define HASHLEN 16
typedef unsigned char HASH[HASHLEN];
#define HASHHEXLEN 32
typedef char HASHHEX[HASHHEXLEN+1];
int f_crypto_md5(lua_State *L) {
li_MD5_CTX Md5Ctx;
HASH HA1;
char hex[33];
int n = lua_gettop(L);
size_t s_len;
const char *s;
@ -43,11 +35,11 @@ int f_crypto_md5(lua_State *L) {
s = lua_tolstring(L, 1, &s_len);
li_MD5_Init(&Md5Ctx);
li_MD5_Update(&Md5Ctx, (unsigned char *) s, (unsigned int) s_len);
li_MD5_Final(HA1, &Md5Ctx);
char HA1[MD5_DIGEST_LENGTH];
MD5_once((unsigned char *)HA1, s, s_len);
li_tohex(hex, sizeof(hex), (const char*) HA1, 16);
char hex[MD5_DIGEST_LENGTH*2+1];
li_tohex(hex, sizeof(hex), HA1, sizeof(HA1));
lua_pushstring(L, hex);

@ -135,11 +135,10 @@ static int secdl_verify_mac(plugin_config *config, const char* protected_path, c
break;
case SECDL_MD5:
{
li_MD5_CTX Md5Ctx;
const char *ts_str;
const char *rel_uri;
unsigned char HA1[16];
unsigned char md5bin[16];
unsigned char HA1[MD5_DIGEST_LENGTH];
unsigned char md5bin[MD5_DIGEST_LENGTH];
if (0 != li_hex2bin(md5bin, sizeof(md5bin), mac, maclen)) return 0;
@ -153,11 +152,12 @@ static int secdl_verify_mac(plugin_config *config, const char* protected_path, c
ts_str = protected_path + 1;
rel_uri = ts_str + 8;
li_MD5_Init(&Md5Ctx);
li_MD5_Update(&Md5Ctx, BUF_PTR_LEN(config->secret));
li_MD5_Update(&Md5Ctx, rel_uri, strlen(rel_uri));
li_MD5_Update(&Md5Ctx, ts_str, 8);
li_MD5_Final(HA1, &Md5Ctx);
struct const_iovec iov[] = {
{ BUF_PTR_LEN(config->secret) }
,{ rel_uri, strlen(rel_uri) }
,{ ts_str, 8 }
};
MD5_iov(HA1, iov, sizeof(iov)/sizeof(*iov));
return ck_memeq_const_time_fixed_len((char *)HA1,
(char *)md5bin,sizeof(md5bin));

@ -156,33 +156,25 @@ SETDEFAULTS_FUNC(mod_usertrack_set_defaults) {
__attribute_noinline__
static handler_t mod_usertrack_set_cookie(request_st * const r, plugin_data * const p) {
buffer *cookie;
size_t len;
unsigned char h[16];
li_MD5_CTX Md5Ctx;
char hh[LI_ITOSTRING_LENGTH];
/* generate shared-secret */
/* (reference mod_auth.c) */
int rnd = li_rand_pseudo();
struct const_iovec iov[] = {
{ BUF_PTR_LEN(&r->uri.path) }
,{ "+", 1 }
,{ &log_epoch_secs, sizeof(log_epoch_secs) }
,{ &rnd, sizeof(rnd) }
};
unsigned char h[MD5_DIGEST_LENGTH];
MD5_iov(h, iov, sizeof(iov)/sizeof(*iov));
/* set a cookie */
cookie = r->tmp_buf;
buffer * const cookie = r->tmp_buf;
buffer_clear(cookie);
buffer_append_str2(cookie, BUF_PTR_LEN(p->conf.cookie_name),
CONST_STR_LEN("="));
/* taken from mod_auth.c */
/* generate shared-secret */
li_MD5_Init(&Md5Ctx);
li_MD5_Update(&Md5Ctx, BUF_PTR_LEN(&r->uri.path));
li_MD5_Update(&Md5Ctx, CONST_STR_LEN("+"));
len = li_itostrn(hh, sizeof(hh), log_epoch_secs);
li_MD5_Update(&Md5Ctx, (unsigned char *)hh, len);
len = li_itostrn(hh, sizeof(hh), li_rand_pseudo());
li_MD5_Update(&Md5Ctx, (unsigned char *)hh, len);
li_MD5_Final(h, &Md5Ctx);
buffer_append_string_encoded_hex_lc(cookie, (char *)h, 16);
buffer_append_string_encoded_hex_lc(cookie, (char *)h, sizeof(h));
/* usertrack.cookie-attrs, if set, replaces all other attrs */
if (p->conf.cookie_attrs) {

@ -686,7 +686,6 @@ static int get_key_number(uint32_t *ret, const buffer *b) {
static int create_MD5_sum(request_st * const r) {
uint32_t buf[4]; /* MD5 binary hash len */
li_MD5_CTX ctx;
const buffer *key1 =
http_header_request_get(r, HTTP_HEADER_OTHER, CONST_STR_LEN("Sec-WebSocket-Key1"));
@ -707,9 +706,8 @@ static int create_MD5_sum(request_st * const r) {
ws_htole32((unsigned char *)(buf+0), buf[0]);
ws_htole32((unsigned char *)(buf+1), buf[1]);
#endif
li_MD5_Init(&ctx);
li_MD5_Update(&ctx, buf, sizeof(buf));
li_MD5_Final((unsigned char *)buf, &ctx); /*(overwrite buf[] with result)*/
/*(overwrite buf[] with result)*/
MD5_once((unsigned char *)buf, buf, sizeof(buf));
chunkqueue_append_mem(&r->write_queue, (char *)buf, sizeof(buf));
return 0;
}

Loading…
Cancel
Save