mirror of
https://github.com/php/php-src.git
synced 2024-09-21 09:57:23 +00:00
ext/pgsql: adding pg_change_password functionality.
handy call to change an user password while taking care transparently of the password's encryption. close GH-14262
This commit is contained in:
parent
1d38656b6d
commit
9aa3a0d702
1
NEWS
1
NEWS
@ -186,6 +186,7 @@ PHP NEWS
|
||||
(David Carlier)
|
||||
. Added pg_result_memory_size to get the query result memory usage.
|
||||
(KentarouTakeda)
|
||||
. Added pg_change_password to alter an user's password. (David Carlier)
|
||||
|
||||
- Phar:
|
||||
. Fixed bug GH-12532 (PharData created from zip has incorrect timestamp).
|
||||
|
@ -513,6 +513,10 @@ PHP 8.4 UPGRADE NOTES
|
||||
. Added pcntl_getqos_class to get the QoS level (aka performance and related
|
||||
energy consumption) of the current process and pcntl_setqos_class to set it.
|
||||
|
||||
- PGSQL:
|
||||
. Added pg_change_password to alter a given user's password. It handles
|
||||
transparently the password encryption from the database settings.
|
||||
|
||||
- Sodium:
|
||||
. Added the sodium_crypto_aead_aegis128l_*() and sodium_crypto_aead_aegis256l_*()
|
||||
functions to support the AEGIS family of authenticated encryption algorithms,
|
||||
|
@ -67,6 +67,7 @@ if test "$PHP_PGSQL" != "no"; then
|
||||
AC_CHECK_LIB(pq, lo_truncate64, AC_DEFINE(HAVE_PG_LO64,1,[PostgreSQL 9.3 or later]))
|
||||
AC_CHECK_LIB(pq, PQsetErrorContextVisibility, AC_DEFINE(HAVE_PG_CONTEXT_VISIBILITY,1,[PostgreSQL 9.6 or later]))
|
||||
AC_CHECK_LIB(pq, PQresultMemorySize, AC_DEFINE(HAVE_PG_RESULT_MEMORY_SIZE,1,[PostgreSQL 12 or later]))
|
||||
AC_CHECK_LIB(pq, PQchangePassword, AC_DEFINE(HAVE_PG_CHANGE_PASSWORD,1,[PostgreSQL 17 or later]))
|
||||
LIBS=$old_LIBS
|
||||
LDFLAGS=$old_LDFLAGS
|
||||
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "php_pgsql.h"
|
||||
#include "php_globals.h"
|
||||
#include "zend_exceptions.h"
|
||||
#include "zend_attributes.h"
|
||||
|
||||
#ifdef HAVE_PGSQL
|
||||
|
||||
@ -401,6 +402,47 @@ static bool _php_pgsql_identifier_is_escaped(const char *identifier, size_t len)
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef HAVE_PG_CHANGE_PASSWORD
|
||||
static PGresult *PQchangePassword(PGconn *conn, const char *user, const char *passwd)
|
||||
{
|
||||
/**
|
||||
* It is more appropriate to let the configured password encryption algorithm
|
||||
* being picked up, so we pass NULL
|
||||
*/
|
||||
char *enc = PQencryptPasswordConn(conn, passwd, user, NULL);
|
||||
|
||||
if (!enc) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *fmtenc = PQescapeLiteral(conn, enc, strlen(enc));
|
||||
PQfreemem(enc);
|
||||
|
||||
if (!fmtenc) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *fmtuser = PQescapeIdentifier(conn, user, strlen(user));
|
||||
|
||||
if (!fmtuser) {
|
||||
PQfreemem(fmtenc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *query;
|
||||
|
||||
spprintf(&query, 0, "ALTER USER %s PASSWORD %s", fmtuser, fmtenc);
|
||||
|
||||
PGresult *pg_result = PQexec(conn, query);
|
||||
|
||||
efree(query);
|
||||
PQfreemem(fmtuser);
|
||||
PQfreemem(fmtenc);
|
||||
|
||||
return pg_result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* {{{ PHP_INI */
|
||||
PHP_INI_BEGIN()
|
||||
STD_PHP_INI_BOOLEAN( "pgsql.allow_persistent", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_persistent, zend_pgsql_globals, pgsql_globals)
|
||||
@ -6048,4 +6090,36 @@ PHP_FUNCTION(pg_select)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
PHP_FUNCTION(pg_change_password)
|
||||
{
|
||||
zval *pgsql_link;
|
||||
pgsql_link_handle *link;
|
||||
PGresult *pg_result;
|
||||
zend_string *user, *passwd;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(3, 3)
|
||||
Z_PARAM_OBJECT_OF_CLASS(pgsql_link, pgsql_link_ce)
|
||||
Z_PARAM_STR(user)
|
||||
Z_PARAM_STR(passwd)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
if (ZSTR_LEN(user) == 0) {
|
||||
zend_argument_value_error(2, "cannot be empty");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
/* it is technically possible, but better to disallow it */
|
||||
if (ZSTR_LEN(passwd) == 0) {
|
||||
zend_argument_value_error(3, "cannot be empty");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
link = Z_PGSQL_LINK_P(pgsql_link);
|
||||
CHECK_PGSQL_LINK(link);
|
||||
|
||||
pg_result = PQchangePassword(link->conn, ZSTR_VAL(user), ZSTR_VAL(passwd));
|
||||
RETVAL_BOOL(PQresultStatus(pg_result) == PGRES_COMMAND_OK);
|
||||
PQclear(pg_result);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -947,6 +947,8 @@ namespace {
|
||||
#ifdef HAVE_PG_RESULT_MEMORY_SIZE
|
||||
function pg_result_memory_size(PgSql\Result $result): int {}
|
||||
#endif
|
||||
|
||||
function pg_change_password(PgSql\Connection $connection, string $user, #[\SensitiveParameter] string $password): bool {}
|
||||
}
|
||||
|
||||
namespace PgSql {
|
||||
|
13
ext/pgsql/pgsql_arginfo.h
generated
13
ext/pgsql/pgsql_arginfo.h
generated
@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: e06a7116c1048975cbb348ffcdb36c9b65cee659 */
|
||||
* Stub hash: c5cb23b6536c1908d3dcc804f5fa176323f4db07 */
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_pg_connect, 0, 1, PgSql\\Connection, MAY_BE_FALSE)
|
||||
ZEND_ARG_TYPE_INFO(0, connection_string, IS_STRING, 0)
|
||||
@ -465,6 +465,12 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pg_result_memory_size, 0, 1, IS_
|
||||
ZEND_END_ARG_INFO()
|
||||
#endif
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pg_change_password, 0, 3, _IS_BOOL, 0)
|
||||
ZEND_ARG_OBJ_INFO(0, connection, PgSql\\Connection, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, user, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, password, IS_STRING, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_FUNCTION(pg_connect);
|
||||
ZEND_FUNCTION(pg_pconnect);
|
||||
ZEND_FUNCTION(pg_connect_poll);
|
||||
@ -562,6 +568,7 @@ ZEND_FUNCTION(pg_set_error_context_visibility);
|
||||
#if defined(HAVE_PG_RESULT_MEMORY_SIZE)
|
||||
ZEND_FUNCTION(pg_result_memory_size);
|
||||
#endif
|
||||
ZEND_FUNCTION(pg_change_password);
|
||||
|
||||
static const zend_function_entry ext_functions[] = {
|
||||
ZEND_FE(pg_connect, arginfo_pg_connect)
|
||||
@ -684,6 +691,7 @@ static const zend_function_entry ext_functions[] = {
|
||||
#if defined(HAVE_PG_RESULT_MEMORY_SIZE)
|
||||
ZEND_FE(pg_result_memory_size, arginfo_pg_result_memory_size)
|
||||
#endif
|
||||
ZEND_FE(pg_change_password, arginfo_pg_change_password)
|
||||
ZEND_FE_END
|
||||
};
|
||||
|
||||
@ -810,6 +818,9 @@ static void register_pgsql_symbols(int module_number)
|
||||
#if defined(HAVE_PG_CONTEXT_VISIBILITY)
|
||||
REGISTER_LONG_CONSTANT("PGSQL_SHOW_CONTEXT_ALWAYS", PQSHOW_CONTEXT_ALWAYS, CONST_PERSISTENT);
|
||||
#endif
|
||||
|
||||
|
||||
zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_change_password", sizeof("pg_change_password") - 1), 2, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0);
|
||||
}
|
||||
|
||||
static zend_class_entry *register_class_PgSql_Connection(void)
|
||||
|
29
ext/pgsql/tests/changepassword.phpt
Normal file
29
ext/pgsql/tests/changepassword.phpt
Normal file
@ -0,0 +1,29 @@
|
||||
--TEST--
|
||||
Changing user password with pg_change_password
|
||||
--EXTENSIONS--
|
||||
pgsql
|
||||
--SKIPIF--
|
||||
<?php include("inc/skipif.inc"); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
include('inc/config.inc');
|
||||
|
||||
$conn = pg_connect($conn_str);
|
||||
|
||||
try {
|
||||
pg_change_password($conn, "", "pass");
|
||||
} catch (\ValueError $e) {
|
||||
echo $e->getMessage() . PHP_EOL;
|
||||
}
|
||||
try {
|
||||
pg_change_password($conn, "user", "");
|
||||
} catch (\ValueError $e) {
|
||||
echo $e->getMessage() . PHP_EOL;
|
||||
}
|
||||
|
||||
var_dump(pg_change_password($conn, "inexistent_user", "postitpwd"));
|
||||
?>
|
||||
--EXPECT--
|
||||
pg_change_password(): Argument #2 ($user) cannot be empty
|
||||
pg_change_password(): Argument #3 ($password) cannot be empty
|
||||
bool(false)
|
Loading…
Reference in New Issue
Block a user