diff options
Diffstat (limited to 'ext/standard/crypt.c')
-rw-r--r-- | ext/standard/crypt.c | 185 |
1 files changed, 90 insertions, 95 deletions
diff --git a/ext/standard/crypt.c b/ext/standard/crypt.c index c6e0351af2..113a5bd0f5 100644 --- a/ext/standard/crypt.c +++ b/ext/standard/crypt.c @@ -145,44 +145,9 @@ static void php_to64(char *s, long v, int n) /* {{{ */ } /* }}} */ -/* {{{ proto string crypt(string str [, string salt]) - Hash a string */ -PHP_FUNCTION(crypt) +PHPAPI int php_crypt(const char *password, const int pass_len, const char *salt, int salt_len, char **result) { - char salt[PHP_MAX_SALT_LEN + 1]; - char *str, *salt_in = NULL; - int str_len, salt_in_len = 0; char *crypt_res; - salt[0] = salt[PHP_MAX_SALT_LEN] = '\0'; - - /* This will produce suitable results if people depend on DES-encryption - * available (passing always 2-character salt). At least for glibc6.1 */ - memset(&salt[1], '$', PHP_MAX_SALT_LEN - 1); - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &str, &str_len, &salt_in, &salt_in_len) == FAILURE) { - return; - } - - if (salt_in) { - memcpy(salt, salt_in, MIN(PHP_MAX_SALT_LEN, salt_in_len)); - } - - /* The automatic salt generation covers standard DES, md5-crypt and Blowfish (simple) */ - if (!*salt) { -#if PHP_MD5_CRYPT - strncpy(salt, "$1$", PHP_MAX_SALT_LEN); - php_to64(&salt[3], PHP_CRYPT_RAND, 4); - php_to64(&salt[7], PHP_CRYPT_RAND, 4); - strncpy(&salt[11], "$", PHP_MAX_SALT_LEN - 11); -#elif PHP_STD_DES_CRYPT - php_to64(&salt[0], PHP_CRYPT_RAND, 2); - salt[2] = '\0'; -#endif - salt_in_len = strlen(salt); - } else { - salt_in_len = MIN(PHP_MAX_SALT_LEN, salt_in_len); - } - /* Windows (win32/crypt) has a stripped down version of libxcrypt and a CryptoApi md5_crypt implementation */ #if PHP_USE_PHP_CRYPT_R @@ -190,55 +155,44 @@ PHP_FUNCTION(crypt) struct php_crypt_extended_data buffer; if (salt[0]=='$' && salt[1]=='1' && salt[2]=='$') { - char output[MD5_HASH_MAX_LEN]; + char output[MD5_HASH_MAX_LEN], *out; - RETURN_STRING(php_md5_crypt_r(str, salt, output), 1); + out = php_md5_crypt_r(password, salt, output); + if (out) { + *result = estrdup(out); + return SUCCESS; + } + return FAILURE; } else if (salt[0]=='$' && salt[1]=='6' && salt[2]=='$') { - const char sha512_salt_prefix[] = "$6$"; - const char sha512_rounds_prefix[] = "rounds="; char *output; - int needed = (sizeof(sha512_salt_prefix) - 1 - + sizeof(sha512_rounds_prefix) + 9 + 1 - + salt_in_len + 1 + 86 + 1); - output = emalloc(needed); - salt[salt_in_len] = '\0'; + output = emalloc(PHP_MAX_SALT_LEN); - crypt_res = php_sha512_crypt_r(str, salt, output, needed); + crypt_res = php_sha512_crypt_r(password, salt, output, PHP_MAX_SALT_LEN); if (!crypt_res) { - if (salt[0]=='*' && salt[1]=='0') { - RETVAL_STRING("*1", 1); - } else { - RETVAL_STRING("*0", 1); - } + memset(output, 0, PHP_MAX_SALT_LEN); + efree(output); + return FAILURE; } else { - RETVAL_STRING(output, 1); + *result = estrdup(output); + memset(output, 0, PHP_MAX_SALT_LEN); + efree(output); + return SUCCESS; } - - memset(output, 0, needed); - efree(output); } else if (salt[0]=='$' && salt[1]=='5' && salt[2]=='$') { - const char sha256_salt_prefix[] = "$5$"; - const char sha256_rounds_prefix[] = "rounds="; char *output; - int needed = (sizeof(sha256_salt_prefix) - 1 - + sizeof(sha256_rounds_prefix) + 9 + 1 - + salt_in_len + 1 + 43 + 1); - output = emalloc(needed); - salt[salt_in_len] = '\0'; + output = emalloc(PHP_MAX_SALT_LEN); - crypt_res = php_sha256_crypt_r(str, salt, output, needed); + crypt_res = php_sha256_crypt_r(password, salt, output, PHP_MAX_SALT_LEN); if (!crypt_res) { - if (salt[0]=='*' && salt[1]=='0') { - RETVAL_STRING("*1", 1); - } else { - RETVAL_STRING("*0", 1); - } + memset(output, 0, PHP_MAX_SALT_LEN); + efree(output); + return FAILURE; } else { - RETVAL_STRING(output, 1); + *result = estrdup(output); + memset(output, 0, PHP_MAX_SALT_LEN); + efree(output); + return SUCCESS; } - - memset(output, 0, needed); - efree(output); } else if ( salt[0] == '$' && salt[1] == '2' && @@ -251,31 +205,25 @@ PHP_FUNCTION(crypt) memset(output, 0, PHP_MAX_SALT_LEN + 1); - crypt_res = php_crypt_blowfish_rn(str, salt, output, sizeof(output)); + crypt_res = php_crypt_blowfish_rn(password, salt, output, sizeof(output)); if (!crypt_res) { - if (salt[0]=='*' && salt[1]=='0') { - RETVAL_STRING("*1", 1); - } else { - RETVAL_STRING("*0", 1); - } + memset(output, 0, PHP_MAX_SALT_LEN + 1); + return FAILURE; } else { - RETVAL_STRING(output, 1); + *result = estrdup(output); + memset(output, 0, PHP_MAX_SALT_LEN + 1); + return SUCCESS; } - - memset(output, 0, PHP_MAX_SALT_LEN + 1); } else { memset(&buffer, 0, sizeof(buffer)); _crypt_extended_init_r(); - crypt_res = _crypt_extended_r(str, salt, &buffer); + crypt_res = _crypt_extended_r(password, salt, &buffer); if (!crypt_res) { - if (salt[0]=='*' && salt[1]=='0') { - RETURN_STRING("*1", 1); - } else { - RETURN_STRING("*0", 1); - } + return FAILURE; } else { - RETURN_STRING(crypt_res, 1); + *result = estrdup(crypt_res); + return SUCCESS; } } } @@ -291,21 +239,68 @@ PHP_FUNCTION(crypt) # else # error Data struct used by crypt_r() is unknown. Please report. # endif - crypt_res = crypt_r(str, salt, &buffer); + crypt_res = crypt_r(password, salt, &buffer); if (!crypt_res) { - if (salt[0]=='*' && salt[1]=='0') { - RETURN_STRING("*1", 1); - } else { - RETURN_STRING("*0", 1); - } + return FAILURE; } else { - RETURN_STRING(crypt_res, 1); + *result = estrdup(crypt_res); + return SUCCESS; } } # endif #endif } /* }}} */ + + +/* {{{ proto string crypt(string str [, string salt]) + Hash a string */ +PHP_FUNCTION(crypt) +{ + char salt[PHP_MAX_SALT_LEN + 1]; + char *str, *salt_in = NULL, *result = NULL; + int str_len, salt_in_len = 0; + salt[0] = salt[PHP_MAX_SALT_LEN] = '\0'; + + /* This will produce suitable results if people depend on DES-encryption + * available (passing always 2-character salt). At least for glibc6.1 */ + memset(&salt[1], '$', PHP_MAX_SALT_LEN - 1); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &str, &str_len, &salt_in, &salt_in_len) == FAILURE) { + return; + } + + if (salt_in) { + memcpy(salt, salt_in, MIN(PHP_MAX_SALT_LEN, salt_in_len)); + } + + /* The automatic salt generation covers standard DES, md5-crypt and Blowfish (simple) */ + if (!*salt) { +#if PHP_MD5_CRYPT + strncpy(salt, "$1$", PHP_MAX_SALT_LEN); + php_to64(&salt[3], PHP_CRYPT_RAND, 4); + php_to64(&salt[7], PHP_CRYPT_RAND, 4); + strncpy(&salt[11], "$", PHP_MAX_SALT_LEN - 11); +#elif PHP_STD_DES_CRYPT + php_to64(&salt[0], PHP_CRYPT_RAND, 2); + salt[2] = '\0'; +#endif + salt_in_len = strlen(salt); + } else { + salt_in_len = MIN(PHP_MAX_SALT_LEN, salt_in_len); + } + salt[salt_in_len] = '\0'; + + if (php_crypt(str, str_len, salt, salt_in_len, &result) == FAILURE) { + if (salt[0] == '*' && salt[1] == '0') { + RETURN_STRING("*1", 1); + } else { + RETURN_STRING("*0", 1); + } + } + RETURN_STRING(result, 0); +} +/* }}} */ #endif /* |