upstream nginx-0.7.34
[nginx.git] / nginx / src / os / unix / ngx_user.c
1
2 /*
3  * Copyright (C) Igor Sysoev
4  */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9
10
11 /*
12  * Solaris has thread-safe crypt()
13  * Linux has crypt_r(); "struct crypt_data" is more than 128K
14  * FreeBSD needs the mutex to protect crypt()
15  *
16  * TODO:
17  *     ngx_crypt_init() to init mutex
18  */
19
20
21 #if (NGX_CRYPT)
22
23 #if (NGX_HAVE_GNU_CRYPT_R)
24
25 ngx_int_t
26 ngx_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
27 {
28     char               *value;
29     size_t              len;
30     ngx_err_t           err;
31     struct crypt_data   cd;
32
33     ngx_set_errno(0);
34
35     cd.initialized = 0;
36     /* work around the glibc bug */
37     cd.current_salt[0] = ~salt[0];
38
39     value = crypt_r((char *) key, (char *) salt, &cd);
40
41     err = ngx_errno;
42
43     if (err == 0) {
44         len = ngx_strlen(value);
45
46         *encrypted = ngx_pnalloc(pool, len);
47         if (*encrypted) {
48             ngx_memcpy(*encrypted, value, len + 1);
49             return NGX_OK;
50         }
51     }
52
53     ngx_log_error(NGX_LOG_CRIT, pool->log, err, "crypt_r() failed");
54
55     return NGX_ERROR;
56 }
57
58 #else
59
60 ngx_int_t
61 ngx_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
62 {
63     char       *value;
64     size_t      len;
65     ngx_err_t   err;
66
67 #if (NGX_THREADS && NGX_NONREENTRANT_CRYPT)
68
69     /* crypt() is a time consuming funtion, so we only try to lock */
70
71     if (ngx_mutex_trylock(ngx_crypt_mutex) != NGX_OK) {
72         return NGX_AGAIN;
73     }
74
75 #endif
76
77     ngx_set_errno(0);
78
79     value = crypt((char *) key, (char *) salt);
80
81     if (value) {
82         len = ngx_strlen(value);
83
84         *encrypted = ngx_pnalloc(pool, len);
85         if (*encrypted) {
86             ngx_memcpy(*encrypted, value, len + 1);
87         }
88
89 #if (NGX_THREADS && NGX_NONREENTRANT_CRYPT)
90         ngx_mutex_unlock(ngx_crypt_mutex);
91 #endif
92         return NGX_OK;
93     }
94
95     err = ngx_errno;
96
97 #if (NGX_THREADS && NGX_NONREENTRANT_CRYPT)
98     ngx_mutex_unlock(ngx_crypt_mutex);
99 #endif
100
101     ngx_log_error(NGX_LOG_CRIT, pool->log, err, "crypt() failed");
102
103     return NGX_ERROR;
104 }
105
106 #endif
107
108 #endif /* NGX_CRYPT */