summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--package.xml15
-rw-r--r--php_xpass.h2
-rw-r--r--tests/crypt_checksalt.phpt12
-rw-r--r--tests/crypt_gensalt.phpt25
-rw-r--r--tests/crypt_preferred_method.phpt9
-rw-r--r--tests/password_compat.phpt22
-rw-r--r--xpass.c56
-rw-r--r--xpass.stub.php58
-rw-r--r--xpass_arginfo.h45
9 files changed, 239 insertions, 5 deletions
diff --git a/package.xml b/package.xml
index 4b0cafa..b47f016 100644
--- a/package.xml
+++ b/package.xml
@@ -18,8 +18,8 @@ distributions, using extended crypt library (libxcrypt):
</lead>
<date>2024-09-09</date>
<version>
- <release>1.0.1dev</release>
- <api>1.0.0</api>
+ <release>1.1.0dev</release>
+ <api>1.1.0</api>
</version>
<stability>
<release>stable</release>
@@ -27,7 +27,9 @@ distributions, using extended crypt library (libxcrypt):
</stability>
<license uri="https://www.php.net/license/3_01.txt" filesource="LICENSE">PHP-3.01</license>
<notes>
--
+- add crypt_gensalt(?string $salt = null, int $count = 0): ?string {}
+- add crypt_preferred_method(): ?string {}
+- add crypt_checksalt(string $salt): int {}
</notes>
<contents>
<dir name="/">
@@ -35,11 +37,18 @@ distributions, using extended crypt library (libxcrypt):
<file name="config.m4" role="src"/>
<file name="php_xpass.h" role="src" />
<file name="xpass.c" role="src"/>
+ <file name="xpass.stub.php" role="src"/>
+ <file name="xpass_arginfo.h" role="src"/>
<!-- documentation -->
<file name="CREDITS" role="doc"/>
<file name="LICENSE" role="doc"/>
<file name="README.md" role="doc"/>
+ <!-- tests -->
<dir name ="tests">
+ <file name="crypt_checksalt.phpt" role="test"/>
+ <file name="crypt_gensalt.phpt" role="test"/>
+ <file name="crypt_preferred_method.phpt" role="test"/>
+ <file name="password_compat.phpt" role="test"/>
<file name="sha512.phpt" role="test"/>
<file name="xpass.phpt" role="test"/>
<file name="yescrypt.phpt" role="test"/>
diff --git a/php_xpass.h b/php_xpass.h
index 05fbf79..6b1f0f2 100644
--- a/php_xpass.h
+++ b/php_xpass.h
@@ -22,7 +22,7 @@
extern zend_module_entry xpass_module_entry;
#define phpext_xpass_ptr &xpass_module_entry
-#define PHP_XPASS_VERSION "1.0.1-dev"
+#define PHP_XPASS_VERSION "1.1.0-dev"
#define PHP_XPASS_AUTHOR "Remi Collet"
#define PHP_XPASS_LICENSE "PHP-3.01"
diff --git a/tests/crypt_checksalt.phpt b/tests/crypt_checksalt.phpt
new file mode 100644
index 0000000..4fbd8bf
--- /dev/null
+++ b/tests/crypt_checksalt.phpt
@@ -0,0 +1,12 @@
+--TEST--
+Test crypt_checksalt
+--FILE--
+<?php
+var_dump(crypt_checksalt(crypt_gensalt(XPASS_CRYPT_STD_DES)) === CRYPT_SALT_METHOD_LEGACY);
+var_dump(crypt_checksalt(crypt_gensalt()) === CRYPT_SALT_OK);
+var_dump(crypt_checksalt("!not_a_valid_hash") === CRYPT_SALT_INVALID);
+?>
+--EXPECT--
+bool(true)
+bool(true)
+bool(true)
diff --git a/tests/crypt_gensalt.phpt b/tests/crypt_gensalt.phpt
new file mode 100644
index 0000000..b838a04
--- /dev/null
+++ b/tests/crypt_gensalt.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Test crypt_gensalt
+--FILE--
+<?php
+var_dump(crypt_gensalt(XPASS_CRYPT_STD_DES));
+var_dump(crypt_gensalt(XPASS_CRYPT_EXT_DES));
+var_dump(crypt_gensalt(XPASS_CRYPT_MD5));
+var_dump(crypt_gensalt(XPASS_CRYPT_BLOWFISH));
+var_dump(crypt_gensalt(XPASS_CRYPT_SHA256));
+var_dump(crypt_gensalt(XPASS_CRYPT_SHA512));
+var_dump(crypt_gensalt(XPASS_CRYPT_SCRYPT));
+var_dump(crypt_gensalt(XPASS_CRYPT_GOST_YESCRYPT));
+var_dump(crypt_gensalt(XPASS_CRYPT_YESCRYPT));
+
+?>
+--EXPECTF--
+string(2) "%s"
+string(9) "_%s"
+string(11) "$1$%s"
+string(29) "$2y$%s"
+string(19) "$5$%s"
+string(19) "$6$%s"
+string(36) "$7$%s"
+string(30) "$gy$%s"
+string(29) "$y$j%s"
diff --git a/tests/crypt_preferred_method.phpt b/tests/crypt_preferred_method.phpt
new file mode 100644
index 0000000..f222639
--- /dev/null
+++ b/tests/crypt_preferred_method.phpt
@@ -0,0 +1,9 @@
+--TEST--
+Test crypt_preferred_method
+--FILE--
+<?php
+var_dump(crypt_preferred_method());
+?>
+--EXPECTF--
+string(%d) "$%s$"
+
diff --git a/tests/password_compat.phpt b/tests/password_compat.phpt
new file mode 100644
index 0000000..3dd6ad2
--- /dev/null
+++ b/tests/password_compat.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Test crypt compatibility with password_hash
+--FILE--
+<?php
+$secret = 'mysecret';
+
+/* generate with password_hash, check with both */
+$h = password_hash($secret, PASSWORD_BCRYPT);
+var_dump($h, password_verify($secret, $h), $h===crypt($secret, $h));
+
+/* generate with crypt, check with both */
+$h = crypt($secret, crypt_gensalt(XPASS_CRYPT_BLOWFISH));
+var_dump($h, password_verify($secret, $h), $h===crypt($secret, $h));
+?>
+--EXPECTF--
+string(60) "$2y$%s$%s"
+bool(true)
+bool(true)
+string(60) "$2y$%s$%s"
+bool(true)
+bool(true)
+
diff --git a/xpass.c b/xpass.c
index bab404a..cb16131 100644
--- a/xpass.c
+++ b/xpass.c
@@ -26,6 +26,8 @@
#include "php_xpass.h"
#include <crypt.h>
+#include "xpass_arginfo.h"
+
/* {{{ PHP_RINIT_FUNCTION */
PHP_RINIT_FUNCTION(xpass)
{
@@ -149,8 +151,60 @@ static const php_password_algo xpass_algo_yescrypt = {
NULL,
};
+/* {{{ Generates a salt for algo */
+PHP_FUNCTION(crypt_gensalt)
+{
+ char salt[CRYPT_GENSALT_OUTPUT_SIZE + 1];
+ char *prefix = NULL;
+ size_t prefix_len = 0;
+ zend_long count = 0;
+
+ ZEND_PARSE_PARAMETERS_START(0, 2)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_STRING(prefix, prefix_len)
+ Z_PARAM_LONG(count)
+ ZEND_PARSE_PARAMETERS_END();
+
+ if (crypt_gensalt_rn(prefix, (unsigned long)count, NULL, 0, salt, CRYPT_GENSALT_OUTPUT_SIZE)) {
+ RETURN_STRING(salt);
+ }
+ RETURN_NULL();
+}
+/* }}} */
+
+/* {{{ Get preferred hasing method prefix */
+PHP_FUNCTION(crypt_preferred_method)
+{
+ const char *prefix;
+
+ ZEND_PARSE_PARAMETERS_NONE();
+
+ prefix = crypt_preferred_method();
+ if (prefix) {
+ RETURN_STRING(prefix);
+ }
+ RETURN_NULL();
+}
+/* }}} */
+
+/* {{{ Determine whether the user's passphrase should be re-hashed using the currently preferred hashing method */
+PHP_FUNCTION(crypt_checksalt)
+{
+ char *prefix;
+ size_t prefix_len;
+
+ ZEND_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_STRING(prefix, prefix_len)
+ ZEND_PARSE_PARAMETERS_END();
+
+ RETURN_LONG(crypt_checksalt(prefix));
+}
+/* }}} */
+
PHP_MINIT_FUNCTION(xpass) /* {{{ */ {
+ register_xpass_symbols(module_number);
+
#ifdef HAVE_CRYPT_SHA512
if (FAILURE == php_password_algo_register("6", &xpass_algo_sha512)) {
return FAILURE;
@@ -172,7 +226,7 @@ PHP_MINIT_FUNCTION(xpass) /* {{{ */ {
zend_module_entry xpass_module_entry = {
STANDARD_MODULE_HEADER,
"xpass", /* Extension name */
- NULL, /* zend_function_entry */
+ ext_functions, /* zend_function_entry */
PHP_MINIT(xpass), /* PHP_MINIT - Module initialization */
NULL, /* PHP_MSHUTDOWN - Module shutdown */
PHP_RINIT(xpass), /* PHP_RINIT - Request initialization */
diff --git a/xpass.stub.php b/xpass.stub.php
new file mode 100644
index 0000000..4038b41
--- /dev/null
+++ b/xpass.stub.php
@@ -0,0 +1,58 @@
+<?php
+
+/** @generate-class-entries */
+
+/* use XPASS prefix to avoid conflicts with standard constants */
+
+/** @var string */
+const XPASS_CRYPT_STD_DES = '';
+/** @var string */
+const XPASS_CRYPT_EXT_DES = '_';
+/** @var string */
+const XPASS_CRYPT_MD5 = '$1$';
+/** @var string */
+const XPASS_CRYPT_BLOWFISH = '$2y$';
+/** @var string */
+const XPASS_CRYPT_SHA256 = '$5$';
+/** @var string */
+const XPASS_CRYPT_SHA512 = '$6$';
+/** @var string */
+const XPASS_CRYPT_SCRYPT = '$7$';
+/** @var string */
+const XPASS_CRYPT_GOST_YESCRYPT = '$gy$';
+/** @var string */
+const XPASS_CRYPT_YESCRYPT = '$y$';
+
+/**
+ * @var int
+ * @cvalue CRYPT_SALT_OK
+ */
+const CRYPT_SALT_OK = UNKNOWN;
+/**
+ * @var int
+ * @cvalue CRYPT_SALT_INVALID
+ */
+const CRYPT_SALT_INVALID = UNKNOWN;
+/**
+ * @var int
+ * @cvalue CRYPT_SALT_METHOD_DISABLED
+ */
+const CRYPT_SALT_METHOD_DISABLED = UNKNOWN;
+/**
+ * @var int
+ * @cvalue CRYPT_SALT_METHOD_LEGACY
+ */
+const CRYPT_SALT_METHOD_LEGACY = UNKNOWN;
+/**
+ * @var int
+ * @cvalue CRYPT_SALT_TOO_CHEAP
+ */
+const CRYPT_SALT_TOO_CHEAP = UNKNOWN;
+
+
+function crypt_gensalt(?string $salt = null, int $count = 0): ?string {}
+
+function crypt_preferred_method(): ?string {}
+
+function crypt_checksalt(string $salt): int {}
+
diff --git a/xpass_arginfo.h b/xpass_arginfo.h
new file mode 100644
index 0000000..dcd9a50
--- /dev/null
+++ b/xpass_arginfo.h
@@ -0,0 +1,45 @@
+/* This is a generated file, edit the .stub.php file instead.
+ * Stub hash: 6a2b53f488db292839749c125a6d81f89316e9c9 */
+
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_crypt_gensalt, 0, 0, IS_STRING, 1)
+ ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, salt, IS_STRING, 1, "null")
+ ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, count, IS_LONG, 0, "0")
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_crypt_preferred_method, 0, 0, IS_STRING, 1)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_crypt_checksalt, 0, 1, IS_LONG, 0)
+ ZEND_ARG_TYPE_INFO(0, salt, IS_STRING, 0)
+ZEND_END_ARG_INFO()
+
+
+ZEND_FUNCTION(crypt_gensalt);
+ZEND_FUNCTION(crypt_preferred_method);
+ZEND_FUNCTION(crypt_checksalt);
+
+
+static const zend_function_entry ext_functions[] = {
+ ZEND_FE(crypt_gensalt, arginfo_crypt_gensalt)
+ ZEND_FE(crypt_preferred_method, arginfo_crypt_preferred_method)
+ ZEND_FE(crypt_checksalt, arginfo_crypt_checksalt)
+ ZEND_FE_END
+};
+
+static void register_xpass_symbols(int module_number)
+{
+ REGISTER_STRING_CONSTANT("XPASS_CRYPT_STD_DES", "", CONST_PERSISTENT);
+ REGISTER_STRING_CONSTANT("XPASS_CRYPT_EXT_DES", "_", CONST_PERSISTENT);
+ REGISTER_STRING_CONSTANT("XPASS_CRYPT_MD5", "$1$", CONST_PERSISTENT);
+ REGISTER_STRING_CONSTANT("XPASS_CRYPT_BLOWFISH", "$2y$", CONST_PERSISTENT);
+ REGISTER_STRING_CONSTANT("XPASS_CRYPT_SHA256", "$5$", CONST_PERSISTENT);
+ REGISTER_STRING_CONSTANT("XPASS_CRYPT_SHA512", "$6$", CONST_PERSISTENT);
+ REGISTER_STRING_CONSTANT("XPASS_CRYPT_SCRYPT", "$7$", CONST_PERSISTENT);
+ REGISTER_STRING_CONSTANT("XPASS_CRYPT_GOST_YESCRYPT", "$gy$", CONST_PERSISTENT);
+ REGISTER_STRING_CONSTANT("XPASS_CRYPT_YESCRYPT", "$y$", CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("CRYPT_SALT_OK", CRYPT_SALT_OK, CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("CRYPT_SALT_INVALID", CRYPT_SALT_INVALID, CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("CRYPT_SALT_METHOD_DISABLED", CRYPT_SALT_METHOD_DISABLED, CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("CRYPT_SALT_METHOD_LEGACY", CRYPT_SALT_METHOD_LEGACY, CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("CRYPT_SALT_TOO_CHEAP", CRYPT_SALT_TOO_CHEAP, CONST_PERSISTENT);
+}