mirror of
https://github.com/nginx/nginx.git
synced 2024-12-26 17:01:07 -06:00
"$apr1", "{PLAIN}", and "{SSHA}" password methods in auth basic module
patch by Maxim Dounin
This commit is contained in:
parent
ffc7271250
commit
5dc5945ccf
@ -43,6 +43,7 @@ if [ $USE_SHA1 = YES ]; then
|
||||
|
||||
if [ $USE_OPENSSL = YES ]; then
|
||||
have=NGX_HAVE_OPENSSL_SHA1_H . auto/have
|
||||
have=NGX_HAVE_SHA1 . auto/have
|
||||
SHA1=YES
|
||||
SHA1_LIB=OpenSSL
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
if [ $SHA1 != NONE ]; then
|
||||
|
||||
have=NGX_HAVE_SHA1 . auto/have
|
||||
CORE_INCS="$CORE_INCS $SHA1"
|
||||
|
||||
case "$NGX_CC_NAME" in
|
||||
@ -41,7 +42,7 @@ else
|
||||
# FreeBSD
|
||||
|
||||
ngx_feature="sha1 in system md library"
|
||||
ngx_feature_name=
|
||||
ngx_feature_name=NGX_HAVE_SHA1
|
||||
ngx_feature_run=no
|
||||
ngx_feature_incs="#include <sha.h>"
|
||||
ngx_feature_path=
|
||||
|
@ -197,6 +197,8 @@ if [ $HTTP_RANDOM_INDEX = YES ]; then
|
||||
fi
|
||||
|
||||
if [ $HTTP_AUTH_BASIC = YES ]; then
|
||||
USE_MD5=YES
|
||||
USE_SHA1=YES
|
||||
have=NGX_CRYPT . auto/have
|
||||
HTTP_MODULES="$HTTP_MODULES $HTTP_AUTH_BASIC_MODULE"
|
||||
HTTP_SRCS="$HTTP_SRCS $HTTP_AUTH_BASIC_SRCS"
|
||||
|
@ -34,7 +34,8 @@ CORE_DEPS="src/core/nginx.h \
|
||||
src/core/ngx_cycle.h \
|
||||
src/core/ngx_conf_file.h \
|
||||
src/core/ngx_resolver.h \
|
||||
src/core/ngx_open_file_cache.h"
|
||||
src/core/ngx_open_file_cache.h \
|
||||
src/core/ngx_crypt.h"
|
||||
|
||||
|
||||
CORE_SRCS="src/core/nginx.c \
|
||||
@ -64,7 +65,8 @@ CORE_SRCS="src/core/nginx.c \
|
||||
src/core/ngx_cpuinfo.c \
|
||||
src/core/ngx_conf_file.c \
|
||||
src/core/ngx_resolver.c \
|
||||
src/core/ngx_open_file_cache.c"
|
||||
src/core/ngx_open_file_cache.c \
|
||||
src/core/ngx_crypt.c"
|
||||
|
||||
|
||||
REGEX_DEPS=src/core/ngx_regex.h
|
||||
|
234
src/core/ngx_crypt.c
Normal file
234
src/core/ngx_crypt.c
Normal file
@ -0,0 +1,234 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Maxim Dounin
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_md5.h>
|
||||
#if (NGX_HAVE_SHA1)
|
||||
#include <ngx_sha1.h>
|
||||
#endif
|
||||
|
||||
|
||||
static ngx_int_t ngx_crypt_apr1(ngx_pool_t *pool, u_char *key, u_char *salt,
|
||||
u_char **encrypted);
|
||||
static ngx_int_t ngx_crypt_plain(ngx_pool_t *pool, u_char *key, u_char *salt,
|
||||
u_char **encrypted);
|
||||
|
||||
#if (NGX_HAVE_SHA1)
|
||||
|
||||
static ngx_int_t ngx_crypt_ssha(ngx_pool_t *pool, u_char *key, u_char *salt,
|
||||
u_char **encrypted);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static u_char *ngx_crypt_to64(u_char *p, uint32_t v, size_t n);
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
|
||||
{
|
||||
if (ngx_strncmp(salt, "$apr1$", sizeof("$apr1$") - 1) == 0) {
|
||||
return ngx_crypt_apr1(pool, key, salt, encrypted);
|
||||
|
||||
} else if (ngx_strncmp(salt, "{PLAIN}", sizeof("{PLAIN}") - 1) == 0) {
|
||||
return ngx_crypt_plain(pool, key, salt, encrypted);
|
||||
|
||||
#if (NGX_HAVE_SHA1)
|
||||
} else if (ngx_strncmp(salt, "{SSHA}", sizeof("{SSHA}") - 1) == 0) {
|
||||
return ngx_crypt_ssha(pool, key, salt, encrypted);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* fallback to libc crypt() */
|
||||
|
||||
return ngx_libc_crypt(pool, key, salt, encrypted);
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_crypt_apr1(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
|
||||
{
|
||||
ngx_int_t n;
|
||||
ngx_uint_t i;
|
||||
u_char *p, *last, final[16];
|
||||
size_t saltlen, keylen;
|
||||
ngx_md5_t md5, ctx1;
|
||||
|
||||
/* Apache's apr1 crypt is Paul-Henning Kamp's md5 crypt with $apr1$ magic */
|
||||
|
||||
keylen = ngx_strlen(key);
|
||||
|
||||
/* true salt: no magic, max 8 chars, stop at first $ */
|
||||
|
||||
salt += sizeof("$apr1$") - 1;
|
||||
last = salt + 8;
|
||||
for (p = salt; *p && *p != '$' && p < last; p++) { /* void */ }
|
||||
saltlen = p - salt;
|
||||
|
||||
/* hash key and salt */
|
||||
|
||||
ngx_md5_init(&md5);
|
||||
ngx_md5_update(&md5, key, keylen);
|
||||
ngx_md5_update(&md5, "$apr1$", sizeof("$apr1$") - 1);
|
||||
ngx_md5_update(&md5, salt, saltlen);
|
||||
|
||||
ngx_md5_init(&ctx1);
|
||||
ngx_md5_update(&ctx1, key, keylen);
|
||||
ngx_md5_update(&ctx1, salt, saltlen);
|
||||
ngx_md5_update(&ctx1, key, keylen);
|
||||
ngx_md5_final(final, &ctx1);
|
||||
|
||||
for (n = keylen; n > 0; n -= 16) {
|
||||
ngx_md5_update(&md5, final, n > 16 ? 16 : n);
|
||||
}
|
||||
|
||||
ngx_memzero(final, sizeof(final));
|
||||
|
||||
for (i = keylen; i; i >>= 1) {
|
||||
if (i & 1) {
|
||||
ngx_md5_update(&md5, final, 1);
|
||||
|
||||
} else {
|
||||
ngx_md5_update(&md5, key, 1);
|
||||
}
|
||||
}
|
||||
|
||||
ngx_md5_final(final, &md5);
|
||||
|
||||
for (i = 0; i < 1000; i++) {
|
||||
ngx_md5_init(&ctx1);
|
||||
|
||||
if (i & 1) {
|
||||
ngx_md5_update(&ctx1, key, keylen);
|
||||
|
||||
} else {
|
||||
ngx_md5_update(&ctx1, final, 16);
|
||||
}
|
||||
|
||||
if (i % 3) {
|
||||
ngx_md5_update(&ctx1, salt, saltlen);
|
||||
}
|
||||
|
||||
if (i % 7) {
|
||||
ngx_md5_update(&ctx1, key, keylen);
|
||||
}
|
||||
|
||||
if (i & 1) {
|
||||
ngx_md5_update(&ctx1, final, 16);
|
||||
|
||||
} else {
|
||||
ngx_md5_update(&ctx1, key, keylen);
|
||||
}
|
||||
|
||||
ngx_md5_final(final, &ctx1);
|
||||
}
|
||||
|
||||
/* output */
|
||||
|
||||
*encrypted = ngx_pnalloc(pool, sizeof("$apr1$") - 1 + saltlen + 16 + 1);
|
||||
if (*encrypted == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
p = ngx_cpymem(*encrypted, "$apr1$", sizeof("$apr1$") - 1);
|
||||
p = ngx_copy(p, salt, saltlen);
|
||||
*p++ = '$';
|
||||
|
||||
p = ngx_crypt_to64(p, (final[ 0]<<16) | (final[ 6]<<8) | final[12], 4);
|
||||
p = ngx_crypt_to64(p, (final[ 1]<<16) | (final[ 7]<<8) | final[13], 4);
|
||||
p = ngx_crypt_to64(p, (final[ 2]<<16) | (final[ 8]<<8) | final[14], 4);
|
||||
p = ngx_crypt_to64(p, (final[ 3]<<16) | (final[ 9]<<8) | final[15], 4);
|
||||
p = ngx_crypt_to64(p, (final[ 4]<<16) | (final[10]<<8) | final[ 5], 4);
|
||||
p = ngx_crypt_to64(p, final[11], 2);
|
||||
*p = '\0';
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static u_char *
|
||||
ngx_crypt_to64(u_char *p, uint32_t v, size_t n)
|
||||
{
|
||||
static u_char itoa64[] =
|
||||
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
while (n--) {
|
||||
*p++ = itoa64[v & 0x3f];
|
||||
v >>= 6;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_crypt_plain(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
|
||||
{
|
||||
size_t len;
|
||||
u_char *p;
|
||||
|
||||
len = ngx_strlen(key);
|
||||
|
||||
*encrypted = ngx_pnalloc(pool, sizeof("{PLAIN}") - 1 + len + 1);
|
||||
if (*encrypted == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
p = ngx_cpymem(*encrypted, "{PLAIN}", sizeof("{PLAIN}") - 1);
|
||||
ngx_memcpy(p, key, len + 1);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
#if (NGX_HAVE_SHA1)
|
||||
|
||||
static ngx_int_t
|
||||
ngx_crypt_ssha(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
|
||||
{
|
||||
size_t len;
|
||||
ngx_str_t encoded, decoded;
|
||||
ngx_sha1_t sha1;
|
||||
|
||||
/* "{SSHA}" base64(SHA1(key salt) salt) */
|
||||
|
||||
/* decode base64 salt to find out true salt */
|
||||
|
||||
encoded.data = salt + sizeof("{SSHA}") - 1;
|
||||
encoded.len = ngx_strlen(encoded.data);
|
||||
|
||||
decoded.data = ngx_pnalloc(pool, ngx_base64_decoded_length(encoded.len));
|
||||
if (decoded.data == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_decode_base64(&decoded, &encoded);
|
||||
|
||||
/* update SHA1 from key and salt */
|
||||
|
||||
ngx_sha1_init(&sha1);
|
||||
ngx_sha1_update(&sha1, key, ngx_strlen(key));
|
||||
ngx_sha1_update(&sha1, decoded.data + 20, decoded.len - 20);
|
||||
ngx_sha1_final(decoded.data, &sha1);
|
||||
|
||||
/* encode it back to base64 */
|
||||
|
||||
len = sizeof("{SSHA}") - 1 + ngx_base64_encoded_length(decoded.len) + 1;
|
||||
|
||||
*encrypted = ngx_pnalloc(pool, len);
|
||||
if (*encrypted == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
encoded.data = ngx_cpymem(*encrypted, "{SSHA}", sizeof("{SSHA}") - 1);
|
||||
ngx_encode_base64(&encoded, &decoded);
|
||||
encoded.data[encoded.len] = '\0';
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
#endif /* NGX_HAVE_SHA1 */
|
19
src/core/ngx_crypt.h
Normal file
19
src/core/ngx_crypt.h
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_CRYPT_H_INCLUDED_
|
||||
#define _NGX_CRYPT_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
ngx_int_t ngx_crypt(ngx_pool_t *pool, u_char *key, u_char *salt,
|
||||
u_char **encrypted);
|
||||
|
||||
|
||||
#endif /* _NGX_CRYPT_H_INCLUDED_ */
|
@ -7,6 +7,7 @@
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
#include <ngx_crypt.h>
|
||||
|
||||
|
||||
#define NGX_HTTP_AUTH_BUF_SIZE 2048
|
||||
|
@ -23,7 +23,7 @@
|
||||
#if (NGX_HAVE_GNU_CRYPT_R)
|
||||
|
||||
ngx_int_t
|
||||
ngx_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
|
||||
ngx_libc_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
|
||||
{
|
||||
char *value;
|
||||
size_t len;
|
||||
@ -58,7 +58,7 @@ ngx_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
|
||||
#else
|
||||
|
||||
ngx_int_t
|
||||
ngx_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
|
||||
ngx_libc_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
|
||||
{
|
||||
char *value;
|
||||
size_t len;
|
||||
|
@ -16,7 +16,7 @@ typedef uid_t ngx_uid_t;
|
||||
typedef gid_t ngx_gid_t;
|
||||
|
||||
|
||||
ngx_int_t ngx_crypt(ngx_pool_t *pool, u_char *key, u_char *salt,
|
||||
ngx_int_t ngx_libc_crypt(ngx_pool_t *pool, u_char *key, u_char *salt,
|
||||
u_char **encrypted);
|
||||
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
#if (NGX_CRYPT)
|
||||
|
||||
ngx_int_t
|
||||
ngx_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
|
||||
ngx_libc_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
|
||||
{
|
||||
/* STUB: a plain text password */
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
#define ngx_gid_t ngx_int_t
|
||||
|
||||
|
||||
ngx_int_t ngx_crypt(ngx_pool_t *pool, u_char *key, u_char *salt,
|
||||
ngx_int_t ngx_libc_crypt(ngx_pool_t *pool, u_char *key, u_char *salt,
|
||||
u_char **encrypted);
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user