Annotation of embedaddon/nginx/src/core/ngx_crypt.c, revision 1.1.1.1

1.1       misho       1: 
                      2: /*
                      3:  * Copyright (C) Maxim Dounin
                      4:  */
                      5: 
                      6: 
                      7: #include <ngx_config.h>
                      8: #include <ngx_core.h>
                      9: #include <ngx_crypt.h>
                     10: #include <ngx_md5.h>
                     11: #if (NGX_HAVE_SHA1)
                     12: #include <ngx_sha1.h>
                     13: #endif
                     14: 
                     15: 
                     16: #if (NGX_CRYPT)
                     17: 
                     18: static ngx_int_t ngx_crypt_apr1(ngx_pool_t *pool, u_char *key, u_char *salt,
                     19:     u_char **encrypted);
                     20: static ngx_int_t ngx_crypt_plain(ngx_pool_t *pool, u_char *key, u_char *salt,
                     21:     u_char **encrypted);
                     22: 
                     23: #if (NGX_HAVE_SHA1)
                     24: 
                     25: static ngx_int_t ngx_crypt_ssha(ngx_pool_t *pool, u_char *key, u_char *salt,
                     26:     u_char **encrypted);
                     27: static ngx_int_t ngx_crypt_sha(ngx_pool_t *pool, u_char *key, u_char *salt,
                     28:     u_char **encrypted);
                     29: 
                     30: #endif
                     31: 
                     32: 
                     33: static u_char *ngx_crypt_to64(u_char *p, uint32_t v, size_t n);
                     34: 
                     35: 
                     36: ngx_int_t
                     37: ngx_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
                     38: {
                     39:     if (ngx_strncmp(salt, "$apr1$", sizeof("$apr1$") - 1) == 0) {
                     40:         return ngx_crypt_apr1(pool, key, salt, encrypted);
                     41: 
                     42:     } else if (ngx_strncmp(salt, "{PLAIN}", sizeof("{PLAIN}") - 1) == 0) {
                     43:         return ngx_crypt_plain(pool, key, salt, encrypted);
                     44: 
                     45: #if (NGX_HAVE_SHA1)
                     46:     } else if (ngx_strncmp(salt, "{SSHA}", sizeof("{SSHA}") - 1) == 0) {
                     47:         return ngx_crypt_ssha(pool, key, salt, encrypted);
                     48: 
                     49:     } else if (ngx_strncmp(salt, "{SHA}", sizeof("{SHA}") - 1) == 0) {
                     50:         return ngx_crypt_sha(pool, key, salt, encrypted);
                     51: #endif
                     52:     }
                     53: 
                     54:     /* fallback to libc crypt() */
                     55: 
                     56:     return ngx_libc_crypt(pool, key, salt, encrypted);
                     57: }
                     58: 
                     59: 
                     60: static ngx_int_t
                     61: ngx_crypt_apr1(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
                     62: {
                     63:     ngx_int_t          n;
                     64:     ngx_uint_t         i;
                     65:     u_char            *p, *last, final[16];
                     66:     size_t             saltlen, keylen;
                     67:     ngx_md5_t          md5, ctx1;
                     68: 
                     69:     /* Apache's apr1 crypt is Paul-Henning Kamp's md5 crypt with $apr1$ magic */
                     70: 
                     71:     keylen = ngx_strlen(key);
                     72: 
                     73:     /* true salt: no magic, max 8 chars, stop at first $ */
                     74: 
                     75:     salt += sizeof("$apr1$") - 1;
                     76:     last = salt + 8;
                     77:     for (p = salt; *p && *p != '$' && p < last; p++) { /* void */ }
                     78:     saltlen = p - salt;
                     79: 
                     80:     /* hash key and salt */
                     81: 
                     82:     ngx_md5_init(&md5);
                     83:     ngx_md5_update(&md5, key, keylen);
                     84:     ngx_md5_update(&md5, (u_char *) "$apr1$", sizeof("$apr1$") - 1);
                     85:     ngx_md5_update(&md5, salt, saltlen);
                     86: 
                     87:     ngx_md5_init(&ctx1);
                     88:     ngx_md5_update(&ctx1, key, keylen);
                     89:     ngx_md5_update(&ctx1, salt, saltlen);
                     90:     ngx_md5_update(&ctx1, key, keylen);
                     91:     ngx_md5_final(final, &ctx1);
                     92: 
                     93:     for (n = keylen; n > 0; n -= 16) {
                     94:         ngx_md5_update(&md5, final, n > 16 ? 16 : n);
                     95:     }
                     96: 
                     97:     ngx_memzero(final, sizeof(final));
                     98: 
                     99:     for (i = keylen; i; i >>= 1) {
                    100:         if (i & 1) {
                    101:             ngx_md5_update(&md5, final, 1);
                    102: 
                    103:         } else {
                    104:             ngx_md5_update(&md5, key, 1);
                    105:         }
                    106:     }
                    107: 
                    108:     ngx_md5_final(final, &md5);
                    109: 
                    110:     for (i = 0; i < 1000; i++) {
                    111:         ngx_md5_init(&ctx1);
                    112: 
                    113:         if (i & 1) {
                    114:             ngx_md5_update(&ctx1, key, keylen);
                    115: 
                    116:         } else {
                    117:             ngx_md5_update(&ctx1, final, 16);
                    118:         }
                    119: 
                    120:         if (i % 3) {
                    121:             ngx_md5_update(&ctx1, salt, saltlen);
                    122:         }
                    123: 
                    124:         if (i % 7) {
                    125:             ngx_md5_update(&ctx1, key, keylen);
                    126:         }
                    127: 
                    128:         if (i & 1) {
                    129:             ngx_md5_update(&ctx1, final, 16);
                    130: 
                    131:         } else {
                    132:             ngx_md5_update(&ctx1, key, keylen);
                    133:         }
                    134: 
                    135:         ngx_md5_final(final, &ctx1);
                    136:     }
                    137: 
                    138:     /* output */
                    139: 
                    140:     *encrypted = ngx_pnalloc(pool, sizeof("$apr1$") - 1 + saltlen + 1 + 22 + 1);
                    141:     if (*encrypted == NULL) {
                    142:         return NGX_ERROR;
                    143:     }
                    144: 
                    145:     p = ngx_cpymem(*encrypted, "$apr1$", sizeof("$apr1$") - 1);
                    146:     p = ngx_copy(p, salt, saltlen);
                    147:     *p++ = '$';
                    148: 
                    149:     p = ngx_crypt_to64(p, (final[ 0]<<16) | (final[ 6]<<8) | final[12], 4);
                    150:     p = ngx_crypt_to64(p, (final[ 1]<<16) | (final[ 7]<<8) | final[13], 4);
                    151:     p = ngx_crypt_to64(p, (final[ 2]<<16) | (final[ 8]<<8) | final[14], 4);
                    152:     p = ngx_crypt_to64(p, (final[ 3]<<16) | (final[ 9]<<8) | final[15], 4);
                    153:     p = ngx_crypt_to64(p, (final[ 4]<<16) | (final[10]<<8) | final[ 5], 4);
                    154:     p = ngx_crypt_to64(p, final[11], 2);
                    155:     *p = '\0';
                    156: 
                    157:     return NGX_OK;
                    158: }
                    159: 
                    160: 
                    161: static u_char *
                    162: ngx_crypt_to64(u_char *p, uint32_t v, size_t n)
                    163: {
                    164:     static u_char   itoa64[] =
                    165:         "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
                    166: 
                    167:     while (n--) {
                    168:        *p++ = itoa64[v & 0x3f];
                    169:        v >>= 6;
                    170:     }
                    171: 
                    172:     return p;
                    173: }
                    174: 
                    175: 
                    176: static ngx_int_t
                    177: ngx_crypt_plain(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
                    178: {
                    179:     size_t   len;
                    180:     u_char  *p;
                    181: 
                    182:     len = ngx_strlen(key);
                    183: 
                    184:     *encrypted = ngx_pnalloc(pool, sizeof("{PLAIN}") - 1 + len + 1);
                    185:     if (*encrypted == NULL) {
                    186:         return NGX_ERROR;
                    187:     }
                    188: 
                    189:     p = ngx_cpymem(*encrypted, "{PLAIN}", sizeof("{PLAIN}") - 1);
                    190:     ngx_memcpy(p, key, len + 1);
                    191: 
                    192:     return NGX_OK;
                    193: }
                    194: 
                    195: 
                    196: #if (NGX_HAVE_SHA1)
                    197: 
                    198: static ngx_int_t
                    199: ngx_crypt_ssha(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
                    200: {
                    201:     size_t       len;
                    202:     ngx_int_t    rc;
                    203:     ngx_str_t    encoded, decoded;
                    204:     ngx_sha1_t   sha1;
                    205: 
                    206:     /* "{SSHA}" base64(SHA1(key salt) salt) */
                    207: 
                    208:     /* decode base64 salt to find out true salt */
                    209: 
                    210:     encoded.data = salt + sizeof("{SSHA}") - 1;
                    211:     encoded.len = ngx_strlen(encoded.data);
                    212: 
                    213:     len = ngx_max(ngx_base64_decoded_length(encoded.len), 20);
                    214: 
                    215:     decoded.data = ngx_pnalloc(pool, len);
                    216:     if (decoded.data == NULL) {
                    217:         return NGX_ERROR;
                    218:     }
                    219: 
                    220:     rc = ngx_decode_base64(&decoded, &encoded);
                    221: 
                    222:     if (rc != NGX_OK || decoded.len < 20) {
                    223:         decoded.len = 20;
                    224:     }
                    225: 
                    226:     /* update SHA1 from key and salt */
                    227: 
                    228:     ngx_sha1_init(&sha1);
                    229:     ngx_sha1_update(&sha1, key, ngx_strlen(key));
                    230:     ngx_sha1_update(&sha1, decoded.data + 20, decoded.len - 20);
                    231:     ngx_sha1_final(decoded.data, &sha1);
                    232: 
                    233:     /* encode it back to base64 */
                    234: 
                    235:     len = sizeof("{SSHA}") - 1 + ngx_base64_encoded_length(decoded.len) + 1;
                    236: 
                    237:     *encrypted = ngx_pnalloc(pool, len);
                    238:     if (*encrypted == NULL) {
                    239:         return NGX_ERROR;
                    240:     }
                    241: 
                    242:     encoded.data = ngx_cpymem(*encrypted, "{SSHA}", sizeof("{SSHA}") - 1);
                    243:     ngx_encode_base64(&encoded, &decoded);
                    244:     encoded.data[encoded.len] = '\0';
                    245: 
                    246:     return NGX_OK;
                    247: }
                    248: 
                    249: 
                    250: static ngx_int_t
                    251: ngx_crypt_sha(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
                    252: {
                    253:     size_t      len;
                    254:     ngx_str_t   encoded, decoded;
                    255:     ngx_sha1_t  sha1;
                    256:     u_char      digest[20];
                    257: 
                    258:     /* "{SHA}" base64(SHA1(key)) */
                    259: 
                    260:     decoded.len = sizeof(digest);
                    261:     decoded.data = digest;
                    262: 
                    263:     ngx_sha1_init(&sha1);
                    264:     ngx_sha1_update(&sha1, key, ngx_strlen(key));
                    265:     ngx_sha1_final(digest, &sha1);
                    266: 
                    267:     len = sizeof("{SHA}") - 1 + ngx_base64_encoded_length(decoded.len) + 1;
                    268: 
                    269:     *encrypted = ngx_pnalloc(pool, len);
                    270:     if (*encrypted == NULL) {
                    271:         return NGX_ERROR;
                    272:     }
                    273: 
                    274:     encoded.data = ngx_cpymem(*encrypted, "{SHA}", sizeof("{SHA}") - 1);
                    275:     ngx_encode_base64(&encoded, &decoded);
                    276:     encoded.data[encoded.len] = '\0';
                    277: 
                    278:     return NGX_OK;
                    279: }
                    280: 
                    281: #endif /* NGX_HAVE_SHA1 */
                    282: 
                    283: #endif /* NGX_CRYPT */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>