Annotation of embedaddon/php/ext/standard/crypt.c, revision 1.1.1.4

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      4:    +----------------------------------------------------------------------+
1.1.1.4 ! misho       5:    | Copyright (c) 1997-2014 The PHP Group                                |
1.1       misho       6:    +----------------------------------------------------------------------+
                      7:    | This source file is subject to version 3.01 of the PHP license,      |
                      8:    | that is bundled with this package in the file LICENSE, and is        |
                      9:    | available through the world-wide-web at the following url:           |
                     10:    | http://www.php.net/license/3_01.txt                                  |
                     11:    | If you did not receive a copy of the PHP license and are unable to   |
                     12:    | obtain it through the world-wide-web, please send a note to          |
                     13:    | license@php.net so we can mail you a copy immediately.               |
                     14:    +----------------------------------------------------------------------+
                     15:    | Authors: Stig Bakken <ssb@php.net>                                   |
                     16:    |          Zeev Suraski <zeev@zend.com>                                |
                     17:    |          Rasmus Lerdorf <rasmus@php.net>                             |
                     18:    |          Pierre Joye <pierre@php.net>                                |
                     19:    +----------------------------------------------------------------------+
                     20: */
                     21: 
1.1.1.2   misho      22: /* $Id$ */
1.1       misho      23: 
                     24: #include <stdlib.h>
                     25: 
                     26: #include "php.h"
                     27: #if HAVE_CRYPT
                     28: 
                     29: #if HAVE_UNISTD_H
                     30: #include <unistd.h>
                     31: #endif
                     32: #if PHP_USE_PHP_CRYPT_R
                     33: # include "php_crypt_r.h"
                     34: # include "crypt_freesec.h"
                     35: #else
                     36: # if HAVE_CRYPT_H
                     37: #  if defined(CRYPT_R_GNU_SOURCE) && !defined(_GNU_SOURCE)
                     38: #   define _GNU_SOURCE
                     39: #  endif
                     40: #  include <crypt.h>
                     41: # endif
                     42: #endif
                     43: #if TM_IN_SYS_TIME
                     44: #include <sys/time.h>
                     45: #else
                     46: #include <time.h>
                     47: #endif
                     48: #if HAVE_STRING_H
                     49: #include <string.h>
                     50: #else
                     51: #include <strings.h>
                     52: #endif
                     53: 
                     54: #ifdef PHP_WIN32
                     55: #include <process.h>
                     56: #endif
                     57: 
                     58: #include "php_lcg.h"
                     59: #include "php_crypt.h"
                     60: #include "php_rand.h"
                     61: 
                     62: /* The capabilities of the crypt() function is determined by the test programs
                     63:  * run by configure from aclocal.m4.  They will set PHP_STD_DES_CRYPT,
                     64:  * PHP_EXT_DES_CRYPT, PHP_MD5_CRYPT and PHP_BLOWFISH_CRYPT as appropriate
                     65:  * for the target platform. */
                     66: 
                     67: #if PHP_STD_DES_CRYPT
                     68: #define PHP_MAX_SALT_LEN 2
                     69: #endif
                     70: 
                     71: #if PHP_EXT_DES_CRYPT
                     72: #undef PHP_MAX_SALT_LEN
                     73: #define PHP_MAX_SALT_LEN 9
                     74: #endif
                     75: 
                     76: #if PHP_MD5_CRYPT
                     77: #undef PHP_MAX_SALT_LEN
                     78: #define PHP_MAX_SALT_LEN 12
                     79: #endif
                     80: 
                     81: #if PHP_BLOWFISH_CRYPT
                     82: #undef PHP_MAX_SALT_LEN
                     83: #define PHP_MAX_SALT_LEN 60
                     84: #endif
                     85: 
                     86: #if PHP_SHA512_CRYPT
                     87: #undef PHP_MAX_SALT_LEN
                     88: #define PHP_MAX_SALT_LEN 123
                     89: #endif
                     90: 
                     91: 
                     92: /* If the configure-time checks fail, we provide DES.
                     93:  * XXX: This is a hack. Fix the real problem! */
                     94: 
                     95: #ifndef PHP_MAX_SALT_LEN
                     96: #define PHP_MAX_SALT_LEN 2
                     97: #undef PHP_STD_DES_CRYPT
                     98: #define PHP_STD_DES_CRYPT 1
                     99: #endif
                    100: 
                    101: #define PHP_CRYPT_RAND php_rand(TSRMLS_C)
                    102: 
                    103: PHP_MINIT_FUNCTION(crypt) /* {{{ */
                    104: {
                    105:        REGISTER_LONG_CONSTANT("CRYPT_SALT_LENGTH", PHP_MAX_SALT_LEN, CONST_CS | CONST_PERSISTENT);
                    106:        REGISTER_LONG_CONSTANT("CRYPT_STD_DES", PHP_STD_DES_CRYPT, CONST_CS | CONST_PERSISTENT);
                    107:        REGISTER_LONG_CONSTANT("CRYPT_EXT_DES", PHP_EXT_DES_CRYPT, CONST_CS | CONST_PERSISTENT);
                    108:        REGISTER_LONG_CONSTANT("CRYPT_MD5", PHP_MD5_CRYPT, CONST_CS | CONST_PERSISTENT);
                    109:        REGISTER_LONG_CONSTANT("CRYPT_BLOWFISH", PHP_BLOWFISH_CRYPT, CONST_CS | CONST_PERSISTENT);
                    110: 
                    111: #ifdef PHP_SHA256_CRYPT
                    112:    REGISTER_LONG_CONSTANT("CRYPT_SHA256", PHP_SHA256_CRYPT, CONST_CS | CONST_PERSISTENT);
                    113: #endif
                    114: 
                    115: #ifdef PHP_SHA512_CRYPT
                    116:    REGISTER_LONG_CONSTANT("CRYPT_SHA512", PHP_SHA512_CRYPT, CONST_CS | CONST_PERSISTENT);
                    117: #endif
                    118: 
                    119: #if PHP_USE_PHP_CRYPT_R
                    120:        php_init_crypt_r();
                    121: #endif
                    122: 
                    123:        return SUCCESS;
                    124: }
                    125: /* }}} */
                    126: 
                    127: PHP_MSHUTDOWN_FUNCTION(crypt) /* {{{ */
                    128: {
                    129: #if PHP_USE_PHP_CRYPT_R
                    130:        php_shutdown_crypt_r();
                    131: #endif
                    132: 
                    133:        return SUCCESS;
                    134: }
                    135: /* }}} */
                    136: 
                    137: static unsigned char itoa64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
                    138: 
                    139: static void php_to64(char *s, long v, int n) /* {{{ */
                    140: {
                    141:        while (--n >= 0) {
                    142:                *s++ = itoa64[v&0x3f];
                    143:                v >>= 6;
                    144:        }
                    145: }
                    146: /* }}} */
                    147: 
                    148: /* {{{ proto string crypt(string str [, string salt])
                    149:    Hash a string */
                    150: PHP_FUNCTION(crypt)
                    151: {
                    152:        char salt[PHP_MAX_SALT_LEN + 1];
                    153:        char *str, *salt_in = NULL;
                    154:        int str_len, salt_in_len = 0;
                    155:        char *crypt_res;
                    156:        salt[0] = salt[PHP_MAX_SALT_LEN] = '\0';
                    157: 
                    158:        /* This will produce suitable results if people depend on DES-encryption
                    159:         * available (passing always 2-character salt). At least for glibc6.1 */
                    160:        memset(&salt[1], '$', PHP_MAX_SALT_LEN - 1);
                    161: 
                    162:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &str, &str_len, &salt_in, &salt_in_len) == FAILURE) {
                    163:                return;
                    164:        }
                    165: 
                    166:        if (salt_in) {
                    167:                memcpy(salt, salt_in, MIN(PHP_MAX_SALT_LEN, salt_in_len));
                    168:        }
                    169: 
                    170:        /* The automatic salt generation covers standard DES, md5-crypt and Blowfish (simple) */
                    171:        if (!*salt) {
                    172: #if PHP_MD5_CRYPT
                    173:                strncpy(salt, "$1$", PHP_MAX_SALT_LEN);
                    174:                php_to64(&salt[3], PHP_CRYPT_RAND, 4);
                    175:                php_to64(&salt[7], PHP_CRYPT_RAND, 4);
                    176:                strncpy(&salt[11], "$", PHP_MAX_SALT_LEN - 11);
                    177: #elif PHP_STD_DES_CRYPT
                    178:                php_to64(&salt[0], PHP_CRYPT_RAND, 2);
                    179:                salt[2] = '\0';
                    180: #endif
                    181:                salt_in_len = strlen(salt);
                    182:        } else {
                    183:                salt_in_len = MIN(PHP_MAX_SALT_LEN, salt_in_len);
                    184:        }
                    185: 
                    186: /* Windows (win32/crypt) has a stripped down version of libxcrypt and 
                    187:        a CryptoApi md5_crypt implementation */
                    188: #if PHP_USE_PHP_CRYPT_R
                    189:        {
                    190:                struct php_crypt_extended_data buffer;
                    191: 
                    192:                if (salt[0]=='$' && salt[1]=='1' && salt[2]=='$') {
                    193:                        char output[MD5_HASH_MAX_LEN];
                    194: 
                    195:                        RETURN_STRING(php_md5_crypt_r(str, salt, output), 1);
                    196:                } else if (salt[0]=='$' && salt[1]=='6' && salt[2]=='$') {
                    197:                        const char sha512_salt_prefix[] = "$6$";
                    198:                        const char sha512_rounds_prefix[] = "rounds=";
                    199:                        char *output;
                    200:                        int needed = (sizeof(sha512_salt_prefix) - 1
                    201:                                                + sizeof(sha512_rounds_prefix) + 9 + 1
1.1.1.3   misho     202:                                                + salt_in_len + 1 + 86 + 1);
1.1.1.2   misho     203:                        output = emalloc(needed);
1.1       misho     204:                        salt[salt_in_len] = '\0';
                    205: 
                    206:                        crypt_res = php_sha512_crypt_r(str, salt, output, needed);
                    207:                        if (!crypt_res) {
                    208:                                if (salt[0]=='*' && salt[1]=='0') {
                    209:                                        RETVAL_STRING("*1", 1);
                    210:                                } else {
                    211:                                        RETVAL_STRING("*0", 1);
                    212:                                }
                    213:                        } else {
                    214:                                RETVAL_STRING(output, 1);
                    215:                        }
                    216: 
1.1.1.3   misho     217:                        memset(output, 0, needed);
1.1       misho     218:                        efree(output);
                    219:                } else if (salt[0]=='$' && salt[1]=='5' && salt[2]=='$') {
                    220:                        const char sha256_salt_prefix[] = "$5$";
                    221:                        const char sha256_rounds_prefix[] = "rounds=";
                    222:                        char *output;
                    223:                        int needed = (sizeof(sha256_salt_prefix) - 1
                    224:                                                + sizeof(sha256_rounds_prefix) + 9 + 1
1.1.1.3   misho     225:                                                + salt_in_len + 1 + 43 + 1);
1.1.1.2   misho     226:                        output = emalloc(needed);
1.1       misho     227:                        salt[salt_in_len] = '\0';
                    228: 
                    229:                        crypt_res = php_sha256_crypt_r(str, salt, output, needed);
                    230:                        if (!crypt_res) {
                    231:                                if (salt[0]=='*' && salt[1]=='0') {
                    232:                                        RETVAL_STRING("*1", 1);
                    233:                                } else {
                    234:                                        RETVAL_STRING("*0", 1);
                    235:                                }
                    236:                        } else {
                    237:                                RETVAL_STRING(output, 1);
                    238:                        }
                    239: 
1.1.1.3   misho     240:                        memset(output, 0, needed);
1.1       misho     241:                        efree(output);
                    242:                } else if (
                    243:                                salt[0] == '$' &&
                    244:                                salt[1] == '2' &&
                    245:                                salt[2] >= 'a' && salt[2] <= 'z' &&
                    246:                                salt[3] == '$' &&
                    247:                                salt[4] >= '0' && salt[4] <= '3' &&
                    248:                                salt[5] >= '0' && salt[5] <= '9' &&
                    249:                                salt[6] == '$') {
                    250:                        char output[PHP_MAX_SALT_LEN + 1];
                    251: 
                    252:                        memset(output, 0, PHP_MAX_SALT_LEN + 1);
                    253: 
                    254:                        crypt_res = php_crypt_blowfish_rn(str, salt, output, sizeof(output));
                    255:                        if (!crypt_res) {
                    256:                                if (salt[0]=='*' && salt[1]=='0') {
                    257:                                        RETVAL_STRING("*1", 1);
                    258:                                } else {
                    259:                                        RETVAL_STRING("*0", 1);
                    260:                                }
                    261:                        } else {
                    262:                                RETVAL_STRING(output, 1);
                    263:                        }
                    264: 
                    265:                        memset(output, 0, PHP_MAX_SALT_LEN + 1);
                    266:                } else {
                    267:                        memset(&buffer, 0, sizeof(buffer));
                    268:                        _crypt_extended_init_r();
                    269: 
                    270:                        crypt_res = _crypt_extended_r(str, salt, &buffer);
                    271:                        if (!crypt_res) {
                    272:                                if (salt[0]=='*' && salt[1]=='0') {
                    273:                                        RETURN_STRING("*1", 1);
                    274:                                } else {
                    275:                                        RETURN_STRING("*0", 1);
                    276:                                }
                    277:                        } else {
                    278:                                RETURN_STRING(crypt_res, 1);
                    279:                        }
                    280:                }
                    281:        }
                    282: #else
                    283: 
                    284: # if defined(HAVE_CRYPT_R) && (defined(_REENTRANT) || defined(_THREAD_SAFE))
                    285:        {
                    286: #  if defined(CRYPT_R_STRUCT_CRYPT_DATA)
                    287:                struct crypt_data buffer;
                    288:                memset(&buffer, 0, sizeof(buffer));
                    289: #  elif defined(CRYPT_R_CRYPTD)
                    290:                CRYPTD buffer;
                    291: #  else
                    292: #    error Data struct used by crypt_r() is unknown. Please report.
                    293: #  endif
                    294:                crypt_res = crypt_r(str, salt, &buffer);
                    295:                if (!crypt_res) {
                    296:                                if (salt[0]=='*' && salt[1]=='0') {
                    297:                                        RETURN_STRING("*1", 1);
                    298:                                } else {
                    299:                                        RETURN_STRING("*0", 1);
                    300:                                }
                    301:                } else {
                    302:                        RETURN_STRING(crypt_res, 1);
                    303:                }
                    304:        }
                    305: # endif
                    306: #endif
                    307: }
                    308: /* }}} */
                    309: #endif
                    310: 
                    311: /*
                    312:  * Local variables:
                    313:  * tab-width: 4
                    314:  * c-basic-offset: 4
                    315:  * End:
                    316:  * vim600: sw=4 ts=4 fdm=marker
                    317:  * vim<600: sw=4 ts=4
                    318:  */

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