3
* Copyright (C) Igor Sysoev
7
#include <ngx_config.h>
12
#define NGX_HTTP_AUTH_BUF_SIZE 2048
17
} ngx_http_auth_basic_ctx_t;
23
} ngx_http_auth_basic_loc_conf_t;
26
static ngx_int_t ngx_http_auth_basic_handler(ngx_http_request_t *r);
27
static ngx_int_t ngx_http_auth_basic_crypt_handler(ngx_http_request_t *r,
28
ngx_http_auth_basic_ctx_t *ctx, ngx_str_t *passwd, ngx_str_t *realm);
29
static ngx_int_t ngx_http_auth_basic_set_realm(ngx_http_request_t *r,
31
static void ngx_http_auth_basic_close(ngx_file_t *file);
32
static void *ngx_http_auth_basic_create_loc_conf(ngx_conf_t *cf);
33
static char *ngx_http_auth_basic_merge_loc_conf(ngx_conf_t *cf,
34
void *parent, void *child);
35
static ngx_int_t ngx_http_auth_basic_init(ngx_conf_t *cf);
36
static char *ngx_http_auth_basic(ngx_conf_t *cf, void *post, void *data);
39
static ngx_conf_post_handler_pt ngx_http_auth_basic_p = ngx_http_auth_basic;
41
static ngx_command_t ngx_http_auth_basic_commands[] = {
43
{ ngx_string("auth_basic"),
44
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF
46
ngx_conf_set_str_slot,
47
NGX_HTTP_LOC_CONF_OFFSET,
48
offsetof(ngx_http_auth_basic_loc_conf_t, realm),
49
&ngx_http_auth_basic_p },
51
{ ngx_string("auth_basic_user_file"),
52
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF
54
ngx_conf_set_str_slot,
55
NGX_HTTP_LOC_CONF_OFFSET,
56
offsetof(ngx_http_auth_basic_loc_conf_t, user_file),
63
static ngx_http_module_t ngx_http_auth_basic_module_ctx = {
64
NULL, /* preconfiguration */
65
ngx_http_auth_basic_init, /* postconfiguration */
67
NULL, /* create main configuration */
68
NULL, /* init main configuration */
70
NULL, /* create server configuration */
71
NULL, /* merge server configuration */
73
ngx_http_auth_basic_create_loc_conf, /* create location configuration */
74
ngx_http_auth_basic_merge_loc_conf /* merge location configuration */
78
ngx_module_t ngx_http_auth_basic_module = {
80
&ngx_http_auth_basic_module_ctx, /* module context */
81
ngx_http_auth_basic_commands, /* module directives */
82
NGX_HTTP_MODULE, /* module type */
83
NULL, /* init master */
84
NULL, /* init module */
85
NULL, /* init process */
86
NULL, /* init thread */
87
NULL, /* exit thread */
88
NULL, /* exit process */
89
NULL, /* exit master */
95
ngx_http_auth_basic_handler(ngx_http_request_t *r)
102
ngx_uint_t i, login, left, passwd;
104
ngx_http_auth_basic_ctx_t *ctx;
105
ngx_http_auth_basic_loc_conf_t *alcf;
106
u_char buf[NGX_HTTP_AUTH_BUF_SIZE];
113
alcf = ngx_http_get_module_loc_conf(r, ngx_http_auth_basic_module);
115
if (alcf->realm.len == 0 || alcf->user_file.len == 0) {
119
ctx = ngx_http_get_module_ctx(r, ngx_http_auth_basic_module);
122
return ngx_http_auth_basic_crypt_handler(r, ctx, &ctx->passwd,
126
rc = ngx_http_auth_basic_user(r);
128
if (rc == NGX_DECLINED) {
129
return ngx_http_auth_basic_set_realm(r, &alcf->realm);
132
if (rc == NGX_ERROR) {
133
return NGX_HTTP_INTERNAL_SERVER_ERROR;
136
fd = ngx_open_file(alcf->user_file.data, NGX_FILE_RDONLY, NGX_FILE_OPEN);
138
if (fd == NGX_INVALID_FILE) {
139
ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
140
ngx_open_file_n " \"%s\" failed", alcf->user_file.data);
141
return NGX_HTTP_INTERNAL_SERVER_ERROR;
144
ngx_memzero(&file, sizeof(ngx_file_t));
147
file.name = alcf->user_file;
148
file.log = r->connection->log;
157
n = ngx_read_file(&file, buf + left, NGX_HTTP_AUTH_BUF_SIZE - left,
160
if (n == NGX_ERROR) {
161
ngx_http_auth_basic_close(&file);
162
return NGX_HTTP_INTERNAL_SERVER_ERROR;
169
for (i = left; i < left + n; i++) {
173
if (login == 0 && buf[i] == '#') {
178
if (buf[i] != r->headers_in.user.data[login]) {
183
if (login == r->headers_in.user.len) {
193
if (buf[i] == LF || buf[i] == CR || buf[i] == ':') {
196
ngx_http_auth_basic_close(&file);
198
pwd.len = i - passwd;
199
pwd.data = &buf[passwd];
201
return ngx_http_auth_basic_crypt_handler(r, NULL, &pwd,
217
if (state == sw_passwd) {
218
left = left + n - passwd;
219
ngx_memcpy(buf, &buf[passwd], left);
229
ngx_http_auth_basic_close(&file);
231
return ngx_http_auth_basic_set_realm(r, &alcf->realm);
236
ngx_http_auth_basic_crypt_handler(ngx_http_request_t *r,
237
ngx_http_auth_basic_ctx_t *ctx, ngx_str_t *passwd, ngx_str_t *realm)
242
rc = ngx_crypt(r->pool, r->headers_in.passwd.data, passwd->data,
245
ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
246
"rc: %d user: \"%V\" salt: \"%s\"",
247
rc, &r->headers_in.user, passwd->data);
250
if (ngx_strcmp(encrypted, passwd->data) == 0) {
254
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
255
"encrypted: \"%s\"", encrypted);
257
return ngx_http_auth_basic_set_realm(r, realm);
260
if (rc == NGX_ERROR) {
261
return NGX_HTTP_INTERNAL_SERVER_ERROR;
264
/* rc == NGX_AGAIN */
267
ctx = ngx_palloc(r->pool, sizeof(ngx_http_auth_basic_ctx_t));
269
return NGX_HTTP_INTERNAL_SERVER_ERROR;
272
ngx_http_set_ctx(r, ctx, ngx_http_auth_basic_module);
274
ctx->passwd.len = passwd->len;
277
ctx->passwd.data = ngx_pstrdup(r->pool, passwd);
278
if (ctx->passwd.data == NULL) {
279
return NGX_HTTP_INTERNAL_SERVER_ERROR;
284
/* TODO: add mutex event */
291
ngx_http_auth_basic_set_realm(ngx_http_request_t *r, ngx_str_t *realm)
293
r->headers_out.www_authenticate = ngx_list_push(&r->headers_out.headers);
294
if (r->headers_out.www_authenticate == NULL) {
295
return NGX_HTTP_INTERNAL_SERVER_ERROR;
298
r->headers_out.www_authenticate->hash = 1;
299
r->headers_out.www_authenticate->key.len = sizeof("WWW-Authenticate") - 1;
300
r->headers_out.www_authenticate->key.data = (u_char *) "WWW-Authenticate";
301
r->headers_out.www_authenticate->value = *realm;
303
return NGX_HTTP_UNAUTHORIZED;
307
ngx_http_auth_basic_close(ngx_file_t *file)
309
if (ngx_close_file(file->fd) == NGX_FILE_ERROR) {
310
ngx_log_error(NGX_LOG_ALERT, file->log, ngx_errno,
311
ngx_close_file_n " \"%s\" failed", file->name.data);
317
ngx_http_auth_basic_create_loc_conf(ngx_conf_t *cf)
319
ngx_http_auth_basic_loc_conf_t *conf;
321
conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_auth_basic_loc_conf_t));
323
return NGX_CONF_ERROR;
331
ngx_http_auth_basic_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
333
ngx_http_auth_basic_loc_conf_t *prev = parent;
334
ngx_http_auth_basic_loc_conf_t *conf = child;
336
if (conf->realm.data == NULL) {
337
conf->realm = prev->realm;
340
if (conf->user_file.data) {
341
if (ngx_conf_full_name(cf->cycle, &conf->user_file) != NGX_OK) {
342
return NGX_CONF_ERROR;
346
conf->user_file = prev->user_file;
354
ngx_http_auth_basic_init(ngx_conf_t *cf)
356
ngx_http_handler_pt *h;
357
ngx_http_core_main_conf_t *cmcf;
359
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
361
h = ngx_array_push(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers);
366
*h = ngx_http_auth_basic_handler;
373
ngx_http_auth_basic(ngx_conf_t *cf, void *post, void *data)
375
ngx_str_t *realm = data;
380
if (ngx_strcmp(realm->data, "off") == 0) {
382
realm->data = (u_char *) "";
387
len = sizeof("Basic realm=\"") - 1 + realm->len + 1;
389
basic = ngx_palloc(cf->pool, len);
391
return NGX_CONF_ERROR;
394
p = ngx_cpymem(basic, "Basic realm=\"", sizeof("Basic realm=\"") - 1);
395
p = ngx_cpymem(p, realm->data, realm->len);