summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/standard/crypt.c188
-rw-r--r--ext/standard/php_crypt.h1
2 files changed, 103 insertions, 86 deletions
diff --git a/ext/standard/crypt.c b/ext/standard/crypt.c
index 9a1fcf1f69..a592a4b37c 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 crypt_execute(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,52 @@ PHP_FUNCTION(crypt)
struct php_crypt_extended_data buffer;
if (salt[0]=='$' && salt[1]=='1' && salt[2]=='$') {
- char output[MD5_HASH_MAX_LEN];
-
- RETURN_STRING(php_md5_crypt_r(str, salt, output), 1);
+ char output[MD5_HASH_MAX_LEN], *out;
+
+ out = php_md5_crypt_r(password, salt, output);
+ if (out) {
+ *result = (char *) emalloc(MD5_HASH_MAX_LEN + 1);
+ memcpy(*result, out, MD5_HASH_MAX_LEN);
+ *result[MD5_HASH_MAX_LEN] = 0;
+ 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
- + strlen(salt) + 1 + 43 + 1);
+ + PHP_MAX_SALT_LEN + 43 + 1);
output = emalloc(needed);
- salt[salt_in_len] = '\0';
- crypt_res = php_sha512_crypt_r(str, salt, output, needed);
+ crypt_res = php_sha512_crypt_r(password, salt, output, needed);
if (!crypt_res) {
- if (salt[0]=='*' && salt[1]=='0') {
- RETVAL_STRING("*1", 1);
- } else {
- RETVAL_STRING("*0", 1);
- }
+ memset(output, 0, needed);
+ efree(output);
+ return FAILURE;
} else {
- RETVAL_STRING(output, 1);
+ *result = output;
+ return SUCCESS;
}
-
- memset(output, 0, PHP_MAX_SALT_LEN + 1);
- 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
- + strlen(salt) + 1 + 43 + 1);
+ + PHP_MAX_SALT_LEN + 43 + 1);
output = emalloc(needed);
- salt[salt_in_len] = '\0';
- crypt_res = php_sha256_crypt_r(str, salt, output, needed);
+ crypt_res = php_sha256_crypt_r(password, salt, output, needed);
if (!crypt_res) {
- if (salt[0]=='*' && salt[1]=='0') {
- RETVAL_STRING("*1", 1);
- } else {
- RETVAL_STRING("*0", 1);
- }
+ memset(output, 0, needed);
+ efree(output);
+ return FAILURE;
} else {
- RETVAL_STRING(output, 1);
+ *result = output;
+ return SUCCESS;
}
-
- memset(output, 0, PHP_MAX_SALT_LEN + 1);
- efree(output);
} else if (
salt[0] == '$' &&
salt[1] == '2' &&
@@ -251,31 +213,33 @@ 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);
+ int result_len;
+ result_len = strlen(output);
+ *result = emalloc(result_len + 1);
+ memcpy(*result, output, result_len);
+ (*result)[result_len] = 0;
+ 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);
+ int result_len;
+ result_len = strlen(crypt_res);
+ *result = emalloc(result_len + 1);
+ memcpy(*result, crypt_res, result_len);
+ (*result)[result_len] = 0;
+ return SUCCESS;
}
}
}
@@ -291,21 +255,73 @@ 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);
+ int result_len;
+ result_len = strlen(crypt_res);
+ *result = emalloc(result_len + 1);
+ memcpy(*result, crypt_res, result_len);
+ (*result)[result_len] = '\0';
+ 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 (crypt_execute(str, str_len, salt, salt_in_len, &result) == FAILURE) {
+ if (salt[0] == '*' && salt[1] == '0') {
+ RETURN_STRING("*1", 1);
+ } else {
+ RETURN_STRING("*0", 1);
+ }
+ }
+ RETVAL_STRING(result, 1);
+ efree(result);
+}
+/* }}} */
#endif
/*
diff --git a/ext/standard/php_crypt.h b/ext/standard/php_crypt.h
index 93b232896a..1dffb0bc3e 100644
--- a/ext/standard/php_crypt.h
+++ b/ext/standard/php_crypt.h
@@ -23,6 +23,7 @@
#ifndef PHP_CRYPT_H
#define PHP_CRYPT_H
+PHPAPI int crypt_execute(const char *password, const int pass_len, const char *salt, int salt_len, char **result);
PHP_FUNCTION(crypt);
#if HAVE_CRYPT
PHP_MINIT_FUNCTION(crypt);