1e18a033bSKonstantin Ananyev
2e18a033bSKonstantin Ananyev/*
3e18a033bSKonstantin Ananyev * Copyright (C) Igor Sysoev
4e18a033bSKonstantin Ananyev * Copyright (C) Nginx, Inc.
5e18a033bSKonstantin Ananyev */
6e18a033bSKonstantin Ananyev
7e18a033bSKonstantin Ananyev
8e18a033bSKonstantin Ananyev#include <ngx_config.h>
9e18a033bSKonstantin Ananyev#include <ngx_core.h>
10e18a033bSKonstantin Ananyev#include <ngx_http.h>
11e18a033bSKonstantin Ananyev#include <ngx_crypt.h>
12e18a033bSKonstantin Ananyev
13e18a033bSKonstantin Ananyev
14e18a033bSKonstantin Ananyev#define NGX_HTTP_AUTH_BUF_SIZE  2048
15e18a033bSKonstantin Ananyev
16e18a033bSKonstantin Ananyev
17e18a033bSKonstantin Ananyevtypedef struct {
18e18a033bSKonstantin Ananyev    ngx_str_t                 passwd;
19e18a033bSKonstantin Ananyev} ngx_http_auth_basic_ctx_t;
20e18a033bSKonstantin Ananyev
21e18a033bSKonstantin Ananyev
22e18a033bSKonstantin Ananyevtypedef struct {
23e18a033bSKonstantin Ananyev    ngx_http_complex_value_t  *realm;
24e18a033bSKonstantin Ananyev    ngx_http_complex_value_t   user_file;
25e18a033bSKonstantin Ananyev} ngx_http_auth_basic_loc_conf_t;
26e18a033bSKonstantin Ananyev
27e18a033bSKonstantin Ananyev
28e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_auth_basic_handler(ngx_http_request_t *r);
29e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_auth_basic_crypt_handler(ngx_http_request_t *r,
30e18a033bSKonstantin Ananyev    ngx_http_auth_basic_ctx_t *ctx, ngx_str_t *passwd, ngx_str_t *realm);
31e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_auth_basic_set_realm(ngx_http_request_t *r,
32e18a033bSKonstantin Ananyev    ngx_str_t *realm);
33e18a033bSKonstantin Ananyevstatic void ngx_http_auth_basic_close(ngx_file_t *file);
34e18a033bSKonstantin Ananyevstatic void *ngx_http_auth_basic_create_loc_conf(ngx_conf_t *cf);
35e18a033bSKonstantin Ananyevstatic char *ngx_http_auth_basic_merge_loc_conf(ngx_conf_t *cf,
36e18a033bSKonstantin Ananyev    void *parent, void *child);
37e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_auth_basic_init(ngx_conf_t *cf);
38e18a033bSKonstantin Ananyevstatic char *ngx_http_auth_basic_user_file(ngx_conf_t *cf, ngx_command_t *cmd,
39e18a033bSKonstantin Ananyev    void *conf);
40e18a033bSKonstantin Ananyev
41e18a033bSKonstantin Ananyev
42e18a033bSKonstantin Ananyevstatic ngx_command_t  ngx_http_auth_basic_commands[] = {
43e18a033bSKonstantin Ananyev
44e18a033bSKonstantin Ananyev    { ngx_string("auth_basic"),
45e18a033bSKonstantin Ananyev      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF
46e18a033bSKonstantin Ananyev                        |NGX_CONF_TAKE1,
47e18a033bSKonstantin Ananyev      ngx_http_set_complex_value_slot,
48e18a033bSKonstantin Ananyev      NGX_HTTP_LOC_CONF_OFFSET,
49e18a033bSKonstantin Ananyev      offsetof(ngx_http_auth_basic_loc_conf_t, realm),
50e18a033bSKonstantin Ananyev      NULL },
51e18a033bSKonstantin Ananyev
52e18a033bSKonstantin Ananyev    { ngx_string("auth_basic_user_file"),
53e18a033bSKonstantin Ananyev      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF
54e18a033bSKonstantin Ananyev                        |NGX_CONF_TAKE1,
55e18a033bSKonstantin Ananyev      ngx_http_auth_basic_user_file,
56e18a033bSKonstantin Ananyev      NGX_HTTP_LOC_CONF_OFFSET,
57e18a033bSKonstantin Ananyev      offsetof(ngx_http_auth_basic_loc_conf_t, user_file),
58e18a033bSKonstantin Ananyev      NULL },
59e18a033bSKonstantin Ananyev
60e18a033bSKonstantin Ananyev      ngx_null_command
61e18a033bSKonstantin Ananyev};
62e18a033bSKonstantin Ananyev
63e18a033bSKonstantin Ananyev
64e18a033bSKonstantin Ananyevstatic ngx_http_module_t  ngx_http_auth_basic_module_ctx = {
65e18a033bSKonstantin Ananyev    NULL,                                  /* preconfiguration */
66e18a033bSKonstantin Ananyev    ngx_http_auth_basic_init,              /* postconfiguration */
67e18a033bSKonstantin Ananyev
68e18a033bSKonstantin Ananyev    NULL,                                  /* create main configuration */
69e18a033bSKonstantin Ananyev    NULL,                                  /* init main configuration */
70e18a033bSKonstantin Ananyev
71e18a033bSKonstantin Ananyev    NULL,                                  /* create server configuration */
72e18a033bSKonstantin Ananyev    NULL,                                  /* merge server configuration */
73e18a033bSKonstantin Ananyev
74e18a033bSKonstantin Ananyev    ngx_http_auth_basic_create_loc_conf,   /* create location configuration */
75e18a033bSKonstantin Ananyev    ngx_http_auth_basic_merge_loc_conf     /* merge location configuration */
76e18a033bSKonstantin Ananyev};
77e18a033bSKonstantin Ananyev
78e18a033bSKonstantin Ananyev
79e18a033bSKonstantin Ananyevngx_module_t  ngx_http_auth_basic_module = {
80e18a033bSKonstantin Ananyev    NGX_MODULE_V1,
81e18a033bSKonstantin Ananyev    &ngx_http_auth_basic_module_ctx,       /* module context */
82e18a033bSKonstantin Ananyev    ngx_http_auth_basic_commands,          /* module directives */
83e18a033bSKonstantin Ananyev    NGX_HTTP_MODULE,                       /* module type */
84e18a033bSKonstantin Ananyev    NULL,                                  /* init master */
85e18a033bSKonstantin Ananyev    NULL,                                  /* init module */
86e18a033bSKonstantin Ananyev    NULL,                                  /* init process */
87e18a033bSKonstantin Ananyev    NULL,                                  /* init thread */
88e18a033bSKonstantin Ananyev    NULL,                                  /* exit thread */
89e18a033bSKonstantin Ananyev    NULL,                                  /* exit process */
90e18a033bSKonstantin Ananyev    NULL,                                  /* exit master */
91e18a033bSKonstantin Ananyev    NGX_MODULE_V1_PADDING
92e18a033bSKonstantin Ananyev};
93e18a033bSKonstantin Ananyev
94e18a033bSKonstantin Ananyev
95e18a033bSKonstantin Ananyevstatic ngx_int_t
96e18a033bSKonstantin Ananyevngx_http_auth_basic_handler(ngx_http_request_t *r)
97e18a033bSKonstantin Ananyev{
98e18a033bSKonstantin Ananyev    off_t                            offset;
99e18a033bSKonstantin Ananyev    ssize_t                          n;
100e18a033bSKonstantin Ananyev    ngx_fd_t                         fd;
101e18a033bSKonstantin Ananyev    ngx_int_t                        rc;
102e18a033bSKonstantin Ananyev    ngx_err_t                        err;
103e18a033bSKonstantin Ananyev    ngx_str_t                        pwd, realm, user_file;
104e18a033bSKonstantin Ananyev    ngx_uint_t                       i, level, login, left, passwd;
105e18a033bSKonstantin Ananyev    ngx_file_t                       file;
106e18a033bSKonstantin Ananyev    ngx_http_auth_basic_ctx_t       *ctx;
107e18a033bSKonstantin Ananyev    ngx_http_auth_basic_loc_conf_t  *alcf;
108e18a033bSKonstantin Ananyev    u_char                           buf[NGX_HTTP_AUTH_BUF_SIZE];
109e18a033bSKonstantin Ananyev    enum {
110e18a033bSKonstantin Ananyev        sw_login,
111e18a033bSKonstantin Ananyev        sw_passwd,
112e18a033bSKonstantin Ananyev        sw_skip
113e18a033bSKonstantin Ananyev    } state;
114e18a033bSKonstantin Ananyev
115e18a033bSKonstantin Ananyev    alcf = ngx_http_get_module_loc_conf(r, ngx_http_auth_basic_module);
116e18a033bSKonstantin Ananyev
117e18a033bSKonstantin Ananyev    if (alcf->realm == NULL || alcf->user_file.value.data == NULL) {
118e18a033bSKonstantin Ananyev        return NGX_DECLINED;
119e18a033bSKonstantin Ananyev    }
120e18a033bSKonstantin Ananyev
121e18a033bSKonstantin Ananyev    if (ngx_http_complex_value(r, alcf->realm, &realm) != NGX_OK) {
122e18a033bSKonstantin Ananyev        return NGX_ERROR;
123e18a033bSKonstantin Ananyev    }
124e18a033bSKonstantin Ananyev
125e18a033bSKonstantin Ananyev    if (realm.len == 3 && ngx_strncmp(realm.data, "off", 3) == 0) {
126e18a033bSKonstantin Ananyev        return NGX_DECLINED;
127e18a033bSKonstantin Ananyev    }
128e18a033bSKonstantin Ananyev
129e18a033bSKonstantin Ananyev    ctx = ngx_http_get_module_ctx(r, ngx_http_auth_basic_module);
130e18a033bSKonstantin Ananyev
131e18a033bSKonstantin Ananyev    if (ctx) {
132e18a033bSKonstantin Ananyev        return ngx_http_auth_basic_crypt_handler(r, ctx, &ctx->passwd,
133e18a033bSKonstantin Ananyev                                                 &realm);
134e18a033bSKonstantin Ananyev    }
135e18a033bSKonstantin Ananyev
136e18a033bSKonstantin Ananyev    rc = ngx_http_auth_basic_user(r);
137e18a033bSKonstantin Ananyev
138e18a033bSKonstantin Ananyev    if (rc == NGX_DECLINED) {
139e18a033bSKonstantin Ananyev
140e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
141e18a033bSKonstantin Ananyev                      "no user/password was provided for basic authentication");
142e18a033bSKonstantin Ananyev
143e18a033bSKonstantin Ananyev        return ngx_http_auth_basic_set_realm(r, &realm);
144e18a033bSKonstantin Ananyev    }
145e18a033bSKonstantin Ananyev
146e18a033bSKonstantin Ananyev    if (rc == NGX_ERROR) {
147e18a033bSKonstantin Ananyev        return NGX_HTTP_INTERNAL_SERVER_ERROR;
148e18a033bSKonstantin Ananyev    }
149e18a033bSKonstantin Ananyev
150e18a033bSKonstantin Ananyev    if (ngx_http_complex_value(r, &alcf->user_file, &user_file) != NGX_OK) {
151e18a033bSKonstantin Ananyev        return NGX_ERROR;
152e18a033bSKonstantin Ananyev    }
153e18a033bSKonstantin Ananyev
154e18a033bSKonstantin Ananyev    fd = ngx_open_file(user_file.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
155e18a033bSKonstantin Ananyev
156e18a033bSKonstantin Ananyev    if (fd == NGX_INVALID_FILE) {
157e18a033bSKonstantin Ananyev        err = ngx_errno;
158e18a033bSKonstantin Ananyev
159e18a033bSKonstantin Ananyev        if (err == NGX_ENOENT) {
160e18a033bSKonstantin Ananyev            level = NGX_LOG_ERR;
161e18a033bSKonstantin Ananyev            rc = NGX_HTTP_FORBIDDEN;
162e18a033bSKonstantin Ananyev
163e18a033bSKonstantin Ananyev        } else {
164e18a033bSKonstantin Ananyev            level = NGX_LOG_CRIT;
165e18a033bSKonstantin Ananyev            rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
166e18a033bSKonstantin Ananyev        }
167e18a033bSKonstantin Ananyev
168e18a033bSKonstantin Ananyev        ngx_log_error(level, r->connection->log, err,
169e18a033bSKonstantin Ananyev                      ngx_open_file_n " \"%s\" failed", user_file.data);
170e18a033bSKonstantin Ananyev
171e18a033bSKonstantin Ananyev        return rc;
172e18a033bSKonstantin Ananyev    }
173e18a033bSKonstantin Ananyev
174e18a033bSKonstantin Ananyev    ngx_memzero(&file, sizeof(ngx_file_t));
175e18a033bSKonstantin Ananyev
176e18a033bSKonstantin Ananyev    file.fd = fd;
177e18a033bSKonstantin Ananyev    file.name = user_file;
178e18a033bSKonstantin Ananyev    file.log = r->connection->log;
179e18a033bSKonstantin Ananyev
180e18a033bSKonstantin Ananyev    state = sw_login;
181e18a033bSKonstantin Ananyev    passwd = 0;
182e18a033bSKonstantin Ananyev    login = 0;
183e18a033bSKonstantin Ananyev    left = 0;
184e18a033bSKonstantin Ananyev    offset = 0;
185e18a033bSKonstantin Ananyev
186e18a033bSKonstantin Ananyev    for ( ;; ) {
187e18a033bSKonstantin Ananyev        i = left;
188e18a033bSKonstantin Ananyev
189e18a033bSKonstantin Ananyev        n = ngx_read_file(&file, buf + left, NGX_HTTP_AUTH_BUF_SIZE - left,
190e18a033bSKonstantin Ananyev                          offset);
191e18a033bSKonstantin Ananyev
192e18a033bSKonstantin Ananyev        if (n == NGX_ERROR) {
193e18a033bSKonstantin Ananyev            ngx_http_auth_basic_close(&file);
194e18a033bSKonstantin Ananyev            return NGX_HTTP_INTERNAL_SERVER_ERROR;
195e18a033bSKonstantin Ananyev        }
196e18a033bSKonstantin Ananyev
197e18a033bSKonstantin Ananyev        if (n == 0) {
198e18a033bSKonstantin Ananyev            break;
199e18a033bSKonstantin Ananyev        }
200e18a033bSKonstantin Ananyev
201e18a033bSKonstantin Ananyev        for (i = left; i < left + n; i++) {
202e18a033bSKonstantin Ananyev            switch (state) {
203e18a033bSKonstantin Ananyev
204e18a033bSKonstantin Ananyev            case sw_login:
205e18a033bSKonstantin Ananyev                if (login == 0) {
206e18a033bSKonstantin Ananyev
207e18a033bSKonstantin Ananyev                    if (buf[i] == '#' || buf[i] == CR) {
208e18a033bSKonstantin Ananyev                        state = sw_skip;
209e18a033bSKonstantin Ananyev                        break;
210e18a033bSKonstantin Ananyev                    }
211e18a033bSKonstantin Ananyev
212e18a033bSKonstantin Ananyev                    if (buf[i] == LF) {
213e18a033bSKonstantin Ananyev                        break;
214e18a033bSKonstantin Ananyev                    }
215e18a033bSKonstantin Ananyev                }
216e18a033bSKonstantin Ananyev
217e18a033bSKonstantin Ananyev                if (buf[i] != r->headers_in.user.data[login]) {
218e18a033bSKonstantin Ananyev                    state = sw_skip;
219e18a033bSKonstantin Ananyev                    break;
220e18a033bSKonstantin Ananyev                }
221e18a033bSKonstantin Ananyev
222e18a033bSKonstantin Ananyev                if (login == r->headers_in.user.len) {
223e18a033bSKonstantin Ananyev                    state = sw_passwd;
224e18a033bSKonstantin Ananyev                    passwd = i + 1;
225e18a033bSKonstantin Ananyev                }
226e18a033bSKonstantin Ananyev
227e18a033bSKonstantin Ananyev                login++;
228e18a033bSKonstantin Ananyev
229e18a033bSKonstantin Ananyev                break;
230e18a033bSKonstantin Ananyev
231e18a033bSKonstantin Ananyev            case sw_passwd:
232e18a033bSKonstantin Ananyev                if (buf[i] == LF || buf[i] == CR || buf[i] == ':') {
233e18a033bSKonstantin Ananyev                    buf[i] = '\0';
234e18a033bSKonstantin Ananyev
235e18a033bSKonstantin Ananyev                    ngx_http_auth_basic_close(&file);
236e18a033bSKonstantin Ananyev
237e18a033bSKonstantin Ananyev                    pwd.len = i - passwd;
238e18a033bSKonstantin Ananyev                    pwd.data = &buf[passwd];
239e18a033bSKonstantin Ananyev
240e18a033bSKonstantin Ananyev                    return ngx_http_auth_basic_crypt_handler(r, NULL, &pwd,
241e18a033bSKonstantin Ananyev                                                             &realm);
242e18a033bSKonstantin Ananyev                }
243e18a033bSKonstantin Ananyev
244e18a033bSKonstantin Ananyev                break;
245e18a033bSKonstantin Ananyev
246e18a033bSKonstantin Ananyev            case sw_skip:
247e18a033bSKonstantin Ananyev                if (buf[i] == LF) {
248e18a033bSKonstantin Ananyev                    state = sw_login;
249e18a033bSKonstantin Ananyev                    login = 0;
250e18a033bSKonstantin Ananyev                }
251e18a033bSKonstantin Ananyev
252e18a033bSKonstantin Ananyev                break;
253e18a033bSKonstantin Ananyev            }
254e18a033bSKonstantin Ananyev        }
255e18a033bSKonstantin Ananyev
256e18a033bSKonstantin Ananyev        if (state == sw_passwd) {
257e18a033bSKonstantin Ananyev            left = left + n - passwd;
258e18a033bSKonstantin Ananyev            ngx_memmove(buf, &buf[passwd], left);
259e18a033bSKonstantin Ananyev            passwd = 0;
260e18a033bSKonstantin Ananyev
261e18a033bSKonstantin Ananyev        } else {
262e18a033bSKonstantin Ananyev            left = 0;
263e18a033bSKonstantin Ananyev        }
264e18a033bSKonstantin Ananyev
265e18a033bSKonstantin Ananyev        offset += n;
266e18a033bSKonstantin Ananyev    }
267e18a033bSKonstantin Ananyev
268e18a033bSKonstantin Ananyev    ngx_http_auth_basic_close(&file);
269e18a033bSKonstantin Ananyev
270e18a033bSKonstantin Ananyev    if (state == sw_passwd) {
271e18a033bSKonstantin Ananyev        pwd.len = i - passwd;
272e18a033bSKonstantin Ananyev        pwd.data = ngx_pnalloc(r->pool, pwd.len + 1);
273e18a033bSKonstantin Ananyev        if (pwd.data == NULL) {
274e18a033bSKonstantin Ananyev            return NGX_HTTP_INTERNAL_SERVER_ERROR;
275e18a033bSKonstantin Ananyev        }
276e18a033bSKonstantin Ananyev
277e18a033bSKonstantin Ananyev        ngx_cpystrn(pwd.data, &buf[passwd], pwd.len + 1);
278e18a033bSKonstantin Ananyev
279e18a033bSKonstantin Ananyev        return ngx_http_auth_basic_crypt_handler(r, NULL, &pwd, &realm);
280e18a033bSKonstantin Ananyev    }
281e18a033bSKonstantin Ananyev
282e18a033bSKonstantin Ananyev    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
283e18a033bSKonstantin Ananyev                  "user \"%V\" was not found in \"%V\"",
284e18a033bSKonstantin Ananyev                  &r->headers_in.user, &user_file);
285e18a033bSKonstantin Ananyev
286e18a033bSKonstantin Ananyev    return ngx_http_auth_basic_set_realm(r, &realm);
287e18a033bSKonstantin Ananyev}
288e18a033bSKonstantin Ananyev
289e18a033bSKonstantin Ananyev
290e18a033bSKonstantin Ananyevstatic ngx_int_t
291e18a033bSKonstantin Ananyevngx_http_auth_basic_crypt_handler(ngx_http_request_t *r,
292e18a033bSKonstantin Ananyev    ngx_http_auth_basic_ctx_t *ctx, ngx_str_t *passwd, ngx_str_t *realm)
293e18a033bSKonstantin Ananyev{
294e18a033bSKonstantin Ananyev    ngx_int_t   rc;
295e18a033bSKonstantin Ananyev    u_char     *encrypted;
296e18a033bSKonstantin Ananyev
297e18a033bSKonstantin Ananyev    rc = ngx_crypt(r->pool, r->headers_in.passwd.data, passwd->data,
298e18a033bSKonstantin Ananyev                   &encrypted);
299e18a033bSKonstantin Ananyev
300e18a033bSKonstantin Ananyev    ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
301e18a033bSKonstantin Ananyev                   "rc: %i user: \"%V\" salt: \"%s\"",
302e18a033bSKonstantin Ananyev                   rc, &r->headers_in.user, passwd->data);
303e18a033bSKonstantin Ananyev
304e18a033bSKonstantin Ananyev    if (rc == NGX_OK) {
305e18a033bSKonstantin Ananyev        if (ngx_strcmp(encrypted, passwd->data) == 0) {
306e18a033bSKonstantin Ananyev            return NGX_OK;
307e18a033bSKonstantin Ananyev        }
308e18a033bSKonstantin Ananyev
309e18a033bSKonstantin Ananyev        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
310e18a033bSKonstantin Ananyev                       "encrypted: \"%s\"", encrypted);
311e18a033bSKonstantin Ananyev
312e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
313e18a033bSKonstantin Ananyev                      "user \"%V\": password mismatch",
314e18a033bSKonstantin Ananyev                      &r->headers_in.user);
315e18a033bSKonstantin Ananyev
316e18a033bSKonstantin Ananyev        return ngx_http_auth_basic_set_realm(r, realm);
317e18a033bSKonstantin Ananyev    }
318e18a033bSKonstantin Ananyev
319e18a033bSKonstantin Ananyev    if (rc == NGX_ERROR) {
320e18a033bSKonstantin Ananyev        return NGX_HTTP_INTERNAL_SERVER_ERROR;
321e18a033bSKonstantin Ananyev    }
322e18a033bSKonstantin Ananyev
323e18a033bSKonstantin Ananyev    /* rc == NGX_AGAIN */
324e18a033bSKonstantin Ananyev
325e18a033bSKonstantin Ananyev    if (ctx == NULL) {
326e18a033bSKonstantin Ananyev        ctx = ngx_palloc(r->pool, sizeof(ngx_http_auth_basic_ctx_t));
327e18a033bSKonstantin Ananyev        if (ctx == NULL) {
328e18a033bSKonstantin Ananyev            return NGX_HTTP_INTERNAL_SERVER_ERROR;
329e18a033bSKonstantin Ananyev        }
330e18a033bSKonstantin Ananyev
331e18a033bSKonstantin Ananyev        ngx_http_set_ctx(r, ctx, ngx_http_auth_basic_module);
332e18a033bSKonstantin Ananyev
333e18a033bSKonstantin Ananyev        ctx->passwd.len = passwd->len;
334e18a033bSKonstantin Ananyev        passwd->len++;
335e18a033bSKonstantin Ananyev
336e18a033bSKonstantin Ananyev        ctx->passwd.data = ngx_pstrdup(r->pool, passwd);
337e18a033bSKonstantin Ananyev        if (ctx->passwd.data == NULL) {
338e18a033bSKonstantin Ananyev            return NGX_HTTP_INTERNAL_SERVER_ERROR;
339e18a033bSKonstantin Ananyev        }
340e18a033bSKonstantin Ananyev
341e18a033bSKonstantin Ananyev    }
342e18a033bSKonstantin Ananyev
343e18a033bSKonstantin Ananyev    /* TODO: add mutex event */
344e18a033bSKonstantin Ananyev
345e18a033bSKonstantin Ananyev    return rc;
346e18a033bSKonstantin Ananyev}
347e18a033bSKonstantin Ananyev
348e18a033bSKonstantin Ananyev
349e18a033bSKonstantin Ananyevstatic ngx_int_t
350e18a033bSKonstantin Ananyevngx_http_auth_basic_set_realm(ngx_http_request_t *r, ngx_str_t *realm)
351e18a033bSKonstantin Ananyev{
352e18a033bSKonstantin Ananyev    size_t   len;
353e18a033bSKonstantin Ananyev    u_char  *basic, *p;
354e18a033bSKonstantin Ananyev
355e18a033bSKonstantin Ananyev    r->headers_out.www_authenticate = ngx_list_push(&r->headers_out.headers);
356e18a033bSKonstantin Ananyev    if (r->headers_out.www_authenticate == NULL) {
357e18a033bSKonstantin Ananyev        return NGX_HTTP_INTERNAL_SERVER_ERROR;
358e18a033bSKonstantin Ananyev    }
359e18a033bSKonstantin Ananyev
360e18a033bSKonstantin Ananyev    len = sizeof("Basic realm=\"\"") - 1 + realm->len;
361e18a033bSKonstantin Ananyev
362e18a033bSKonstantin Ananyev    basic = ngx_pnalloc(r->pool, len);
363e18a033bSKonstantin Ananyev    if (basic == NULL) {
364e18a033bSKonstantin Ananyev        return NGX_HTTP_INTERNAL_SERVER_ERROR;
365e18a033bSKonstantin Ananyev    }
366e18a033bSKonstantin Ananyev
367e18a033bSKonstantin Ananyev    p = ngx_cpymem(basic, "Basic realm=\"", sizeof("Basic realm=\"") - 1);
368e18a033bSKonstantin Ananyev    p = ngx_cpymem(p, realm->data, realm->len);
369e18a033bSKonstantin Ananyev    *p = '"';
370e18a033bSKonstantin Ananyev
371e18a033bSKonstantin Ananyev    r->headers_out.www_authenticate->hash = 1;
372e18a033bSKonstantin Ananyev    ngx_str_set(&r->headers_out.www_authenticate->key, "WWW-Authenticate");
373e18a033bSKonstantin Ananyev    r->headers_out.www_authenticate->value.data = basic;
374e18a033bSKonstantin Ananyev    r->headers_out.www_authenticate->value.len = len;
375e18a033bSKonstantin Ananyev
376e18a033bSKonstantin Ananyev    return NGX_HTTP_UNAUTHORIZED;
377e18a033bSKonstantin Ananyev}
378e18a033bSKonstantin Ananyev
379e18a033bSKonstantin Ananyevstatic void
380e18a033bSKonstantin Ananyevngx_http_auth_basic_close(ngx_file_t *file)
381e18a033bSKonstantin Ananyev{
382e18a033bSKonstantin Ananyev    if (ngx_close_file(file->fd) == NGX_FILE_ERROR) {
383e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, file->log, ngx_errno,
384e18a033bSKonstantin Ananyev                      ngx_close_file_n " \"%s\" failed", file->name.data);
385e18a033bSKonstantin Ananyev    }
386e18a033bSKonstantin Ananyev}
387e18a033bSKonstantin Ananyev
388e18a033bSKonstantin Ananyev
389e18a033bSKonstantin Ananyevstatic void *
390e18a033bSKonstantin Ananyevngx_http_auth_basic_create_loc_conf(ngx_conf_t *cf)
391e18a033bSKonstantin Ananyev{
392e18a033bSKonstantin Ananyev    ngx_http_auth_basic_loc_conf_t  *conf;
393e18a033bSKonstantin Ananyev
394e18a033bSKonstantin Ananyev    conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_auth_basic_loc_conf_t));
395e18a033bSKonstantin Ananyev    if (conf == NULL) {
396e18a033bSKonstantin Ananyev        return NULL;
397e18a033bSKonstantin Ananyev    }
398e18a033bSKonstantin Ananyev
399e18a033bSKonstantin Ananyev    return conf;
400e18a033bSKonstantin Ananyev}
401e18a033bSKonstantin Ananyev
402e18a033bSKonstantin Ananyev
403e18a033bSKonstantin Ananyevstatic char *
404e18a033bSKonstantin Ananyevngx_http_auth_basic_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
405e18a033bSKonstantin Ananyev{
406e18a033bSKonstantin Ananyev    ngx_http_auth_basic_loc_conf_t  *prev = parent;
407e18a033bSKonstantin Ananyev    ngx_http_auth_basic_loc_conf_t  *conf = child;
408e18a033bSKonstantin Ananyev
409e18a033bSKonstantin Ananyev    if (conf->realm == NULL) {
410e18a033bSKonstantin Ananyev        conf->realm = prev->realm;
411e18a033bSKonstantin Ananyev    }
412e18a033bSKonstantin Ananyev
413e18a033bSKonstantin Ananyev    if (conf->user_file.value.data == NULL) {
414e18a033bSKonstantin Ananyev        conf->user_file = prev->user_file;
415e18a033bSKonstantin Ananyev    }
416e18a033bSKonstantin Ananyev
417