diff options
author | Glenn Strauss <gstrauss@gluelogic.com> | 2019-03-05 22:31:41 -0500 |
---|---|---|
committer | Glenn Strauss <gstrauss@gluelogic.com> | 2019-03-07 00:32:17 -0500 |
commit | b9e2be50c9772d6c886c2213933da2a6e9bdea6b (patch) | |
tree | 0386ce37c500dee23a28770d47e58f039f882266 /src/mod_authn_file.c | |
parent | 1fb0d7e295669d59b56679868df8f8724d4dc5af (diff) | |
download | lighttpd-git-b9e2be50c9772d6c886c2213933da2a6e9bdea6b.tar.gz |
[mod_auth] HTTP Auth Digest algorithm=SHA-256
(also support Digest algorithm=SHA-512-256 if library support present)
enable additional algorithms by configuring lighttpd.conf auth.require
with new optional keyword "algorithm" => "MD5|SHA-256"
default algorithm remains MD5 if "algorithm" not specified
Tested with: curl --digest -u "user:pass" ... (which supports SHA-256)
x-ref:
"HTTP Digest Access Authentication"
https://tools.ietf.org/html/rfc7616
Diffstat (limited to 'src/mod_authn_file.c')
-rw-r--r-- | src/mod_authn_file.c | 109 |
1 files changed, 75 insertions, 34 deletions
diff --git a/src/mod_authn_file.c b/src/mod_authn_file.c index e3a38cb2..6264d62c 100644 --- a/src/mod_authn_file.c +++ b/src/mod_authn_file.c @@ -197,6 +197,64 @@ static int mod_authn_file_patch_connection(server *srv, connection *con, plugin_ #undef PATCH + + +#ifdef USE_OPENSSL_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 SHA512_256_DIGEST_LENGTH +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); + #ifdef USE_OPENSSL_CRYPTO + else if (ai->dalgo & HTTP_AUTH_DIGEST_SHA256) + mod_authn_file_digest_sha256(ai, pw, pwlen); + #ifdef SHA512_256_DIGEST_LENGTH + else if (ai->dalgo & HTTP_AUTH_DIGEST_SHA512_256) + mod_authn_file_digest_sha512_256(ai, pw, pwlen); + #endif + #endif +} + + + + static int mod_authn_file_htdigest_get_loop(server *srv, FILE *fp, const buffer *auth_fn, http_auth_info_t *ai) { char f_user[1024]; @@ -280,12 +338,12 @@ static handler_t mod_authn_file_htdigest_digest(server *srv, connection *con, vo } static handler_t mod_authn_file_htdigest_basic(server *srv, connection *con, void *p_d, const http_auth_require_t *require, const buffer *username, const char *pw) { - li_MD5_CTX Md5Ctx; - unsigned char HA1[16]; - http_auth_info_t ai; - ai.dalgo = HTTP_AUTH_DIGEST_MD5; - ai.dlen = HTTP_AUTH_DIGEST_MD5_BINLEN; + unsigned char htdigest[sizeof(ai.digest)]; + + /* supports single choice of algorithm for digest stored in htdigest file */ + ai.dalgo = (require->algorithm & ~HTTP_AUTH_DIGEST_SESS); + ai.dlen = http_auth_digest_len(ai.dalgo); ai.username = username->ptr; ai.ulen = buffer_string_length(username); ai.realm = require->realm->ptr; @@ -293,15 +351,12 @@ static handler_t mod_authn_file_htdigest_basic(server *srv, connection *con, voi if (mod_authn_file_htdigest_get(srv, con, p_d, &ai)) return HANDLER_ERROR; - li_MD5_Init(&Md5Ctx); - li_MD5_Update(&Md5Ctx, CONST_BUF_LEN(username)); - li_MD5_Update(&Md5Ctx, CONST_STR_LEN(":")); - li_MD5_Update(&Md5Ctx, CONST_BUF_LEN(require->realm)); - li_MD5_Update(&Md5Ctx, CONST_STR_LEN(":")); - li_MD5_Update(&Md5Ctx, (unsigned char *)pw, strlen(pw)); - li_MD5_Final(HA1, &Md5Ctx); + if (ai.dlen > sizeof(htdigest)) return HANDLER_ERROR;/*(should not happen)*/ + memcpy(htdigest, ai.digest, ai.dlen); /*(save digest before reuse of ai)*/ + + mod_authn_file_digest(&ai, pw, strlen(pw)); - return (0 == memcmp(HA1, ai.digest, ai.dlen) + return (0 == memcmp(htdigest, ai.digest, ai.dlen) && http_auth_match_rules(require, username->ptr, NULL, NULL)) ? HANDLER_GO_ON : HANDLER_ERROR; @@ -310,11 +365,11 @@ static handler_t mod_authn_file_htdigest_basic(server *srv, connection *con, voi -static int mod_authn_file_htpasswd_get(server *srv, const buffer *auth_fn, const buffer *username, buffer *password) { +static int mod_authn_file_htpasswd_get(server *srv, const buffer *auth_fn, const char *username, size_t userlen, buffer *password) { FILE *fp; char f_user[1024]; - if (buffer_is_empty(username)) return -1; + if (NULL == username) return -1; if (buffer_string_is_empty(auth_fn)) return -1; fp = fopen(auth_fn->ptr, "r"); @@ -350,8 +405,7 @@ static int mod_authn_file_htpasswd_get(server *srv, const buffer *auth_fn, const u_len = f_pwd - f_user; f_pwd++; - if (buffer_string_length(username) == u_len && - (0 == strncmp(username->ptr, f_user, u_len))) { + if (userlen == u_len && 0 == memcmp(username, f_user, u_len)) { /* found */ size_t pwd_len = strlen(f_pwd); @@ -370,26 +424,15 @@ static int mod_authn_file_htpasswd_get(server *srv, const buffer *auth_fn, const static handler_t mod_authn_file_plain_digest(server *srv, connection *con, void *p_d, http_auth_info_t *ai) { plugin_data *p = (plugin_data *)p_d; - buffer *username_buf = buffer_init(); buffer *password_buf = buffer_init();/* password-string from auth-backend */ int rc; mod_authn_file_patch_connection(srv, con, p); - buffer_copy_string_len(username_buf, ai->username, ai->ulen); - rc = mod_authn_file_htpasswd_get(srv, p->conf.auth_plain_userfile, username_buf, password_buf); + rc = mod_authn_file_htpasswd_get(srv, p->conf.auth_plain_userfile, ai->username, ai->ulen, password_buf); if (0 == rc) { /* generate password from plain-text */ - li_MD5_CTX Md5Ctx; - li_MD5_Init(&Md5Ctx); - li_MD5_Update(&Md5Ctx, (unsigned char *)username_buf->ptr, buffer_string_length(username_buf)); - li_MD5_Update(&Md5Ctx, CONST_STR_LEN(":")); - li_MD5_Update(&Md5Ctx, (unsigned char *)ai->realm, ai->rlen); - li_MD5_Update(&Md5Ctx, CONST_STR_LEN(":")); - li_MD5_Update(&Md5Ctx, (unsigned char *)password_buf->ptr, buffer_string_length(password_buf)); - li_MD5_Final(ai->digest, &Md5Ctx); + mod_authn_file_digest(ai, CONST_BUF_LEN(password_buf)); } buffer_free(password_buf); - buffer_free(username_buf); - UNUSED(con); return (0 == rc) ? HANDLER_GO_ON : HANDLER_ERROR; } @@ -398,12 +441,11 @@ static handler_t mod_authn_file_plain_basic(server *srv, connection *con, void * buffer *password_buf = buffer_init();/* password-string from auth-backend */ int rc; mod_authn_file_patch_connection(srv, con, p); - rc = mod_authn_file_htpasswd_get(srv, p->conf.auth_plain_userfile, username, password_buf); + rc = mod_authn_file_htpasswd_get(srv, p->conf.auth_plain_userfile, CONST_BUF_LEN(username), password_buf); if (0 == rc) { rc = http_auth_const_time_memeq(CONST_BUF_LEN(password_buf), pw, strlen(pw)) ? 0 : -1; } buffer_free(password_buf); - UNUSED(con); return 0 == rc && http_auth_match_rules(require, username->ptr, NULL, NULL) ? HANDLER_GO_ON : HANDLER_ERROR; @@ -623,7 +665,7 @@ static handler_t mod_authn_file_htpasswd_basic(server *srv, connection *con, voi buffer *password = buffer_init();/* password-string from auth-backend */ int rc; mod_authn_file_patch_connection(srv, con, p); - rc = mod_authn_file_htpasswd_get(srv, p->conf.auth_htpasswd_userfile, username, password); + rc = mod_authn_file_htpasswd_get(srv, p->conf.auth_htpasswd_userfile, CONST_BUF_LEN(username), password); if (0 == rc) { char sample[256]; rc = -1; @@ -719,7 +761,6 @@ static handler_t mod_authn_file_htpasswd_basic(server *srv, connection *con, voi #endif } buffer_free(password); - UNUSED(con); return 0 == rc && http_auth_match_rules(require, username->ptr, NULL, NULL) ? HANDLER_GO_ON : HANDLER_ERROR; |