summaryrefslogtreecommitdiff
path: root/ext/standard/crypt.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/standard/crypt.c')
-rw-r--r--ext/standard/crypt.c185
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
/*