#! /bin/sh /usr/share/dpatch/dpatch-run ## ngx_http_auth_basic_valid_user-0.1.dpatch by Kirill A. Korinskiy ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: Implement valid_user, valid_user_max_size and valid_user_bucket_size @DPATCH@ diff --git a/src/http/modules/ngx_http_auth_basic_module.c b/src/http/modules/ngx_http_auth_basic_module.c index b09359d..5e2adb8 100644 --- a/src/http/modules/ngx_http_auth_basic_module.c +++ b/src/http/modules/ngx_http_auth_basic_module.c @@ -20,6 +20,9 @@ typedef struct { typedef struct { ngx_str_t realm; ngx_str_t user_file; + ngx_hash_t valid_user; + ngx_uint_t valid_user_max_size; + ngx_uint_t valid_user_bucket_size; } ngx_http_auth_basic_loc_conf_t; @@ -34,6 +37,8 @@ static char *ngx_http_auth_basic_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); static ngx_int_t ngx_http_auth_basic_init(ngx_conf_t *cf); static char *ngx_http_auth_basic(ngx_conf_t *cf, void *post, void *data); +static char *ngx_http_auth_basic_valid_user(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf); static ngx_conf_post_handler_pt ngx_http_auth_basic_p = ngx_http_auth_basic; @@ -56,6 +61,28 @@ static ngx_command_t ngx_http_auth_basic_commands[] = { offsetof(ngx_http_auth_basic_loc_conf_t, user_file), NULL }, + { ngx_string("auth_basic_valid_user"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF + |NGX_CONF_1MORE, + ngx_http_auth_basic_valid_user, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_auth_basic_loc_conf_t, valid_user), + NULL }, + + { ngx_string("auth_basic_valid_user_max_size"), + NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_MAIN_CONF_OFFSET, + offsetof(ngx_http_auth_basic_loc_conf_t, valid_user_max_size), + NULL }, + + { ngx_string("auth_basic_valid_user_bucket_size"), + NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_MAIN_CONF_OFFSET, + offsetof(ngx_http_auth_basic_loc_conf_t, valid_user_bucket_size), + NULL }, + ngx_null_command }; @@ -250,8 +277,19 @@ static ngx_int_t ngx_http_auth_basic_crypt_handler(ngx_http_request_t *r, ngx_http_auth_basic_ctx_t *ctx, ngx_str_t *passwd, ngx_str_t *realm) { - ngx_int_t rc; - u_char *encrypted; + u_char *encrypted; + ngx_int_t rc; + ngx_uint_t key; + ngx_http_auth_basic_loc_conf_t *alcf; + + alcf = ngx_http_get_module_loc_conf(r, ngx_http_auth_basic_module); + if (alcf->valid_user.size) { + key = ngx_hash_key_lc(r->headers_in.user.data, r->headers_in.user.len); + if (ngx_hash_find(&alcf->valid_user, key, r->headers_in.user.data, + r->headers_in.user.len) == NULL) { + return NGX_HTTP_UNAUTHORIZED; + } + } rc = ngx_crypt(r->pool, r->headers_in.passwd.data, passwd->data, &encrypted); @@ -337,6 +375,9 @@ ngx_http_auth_basic_create_loc_conf(ngx_conf_t *cf) return NGX_CONF_ERROR; } + conf->valid_user_max_size = NGX_CONF_UNSET_UINT; + conf->valid_user_bucket_size = NGX_CONF_UNSET_UINT; + return conf; } @@ -414,3 +455,59 @@ ngx_http_auth_basic(ngx_conf_t *cf, void *post, void *data) return NGX_CONF_OK; } + +static char * +ngx_http_auth_basic_valid_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + char *p = conf; + ngx_str_t *value; + ngx_uint_t i; + ngx_hash_t *valid_user; + ngx_hash_init_t hash; + ngx_array_t keys; + ngx_hash_key_t *key; + ngx_http_auth_basic_loc_conf_t *ablc = conf; + + valid_user = (ngx_hash_t*) (p + cmd->offset); + + if (valid_user->size) { + return "is duplicate"; + } + + if (ablc->valid_user_max_size == NGX_CONF_UNSET_UINT) { + ablc->valid_user_max_size = 512; + } + + if (ablc->valid_user_bucket_size == NGX_CONF_UNSET_UINT) { + ablc->valid_user_bucket_size = 64; + } + + hash.hash = valid_user; + hash.key = ngx_hash_key_lc; + hash.max_size = ablc->valid_user_max_size; + hash.bucket_size = ablc->valid_user_bucket_size; + hash.name = "auth_basic_valid_user"; + hash.pool = cf->pool; + hash.temp_pool = cf->pool; + + if (ngx_array_init(&keys, cf->pool, + cf->args->nelts - 1, sizeof(ngx_hash_key_t)) + == NGX_ERROR) { + return NGX_CONF_ERROR; + } + + value = cf->args->elts; + + for (i = 1; i < cf->args->nelts; i++) { + key = ngx_array_push(&keys); + key->key = value[i]; + key->key_hash = ngx_hash_key_lc(key->key.data, key->key.len); + key->value = &value[i]; + } + + if (ngx_hash_init(&hash, keys.elts, keys.nelts) != NGX_OK) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +}