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_cycle_t
*cycle
);
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 ngx_http_module_t ngx_http_auth_basic_module_ctx
= {
64 NULL
, /* preconfiguration */
65 NULL
, /* 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 ngx_http_auth_basic_init
, /* 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_ERR
, 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_cycle_t
*cycle
)
356 ngx_http_handler_pt
*h
;
357 ngx_http_core_main_conf_t
*cmcf
;
359 cmcf
= ngx_http_cycle_get_module_main_conf(cycle
, 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
);