|
39 | 39 | #include "php_pgsql.h"
|
40 | 40 | #include "php_globals.h"
|
41 | 41 | #include "zend_exceptions.h"
|
| 42 | +#include "zend_attributes.h" |
42 | 43 |
|
43 | 44 | #ifdef HAVE_PGSQL
|
44 | 45 |
|
@@ -401,6 +402,47 @@ static bool _php_pgsql_identifier_is_escaped(const char *identifier, size_t len)
|
401 | 402 | return true;
|
402 | 403 | }
|
403 | 404 |
|
| 405 | +#ifndef HAVE_PG_CHANGE_PASSWORD |
| 406 | +static PGresult *PQchangePassword(PGconn *conn, const char *user, const char *passwd) |
| 407 | +{ |
| 408 | + /** |
| 409 | + * It is more appropriate to let the configured password encryption algorithm |
| 410 | + * being picked up, so we pass NULL |
| 411 | + */ |
| 412 | + char *enc = PQencryptPasswordConn(conn, passwd, user, NULL); |
| 413 | + |
| 414 | + if (!enc) { |
| 415 | + return NULL; |
| 416 | + } |
| 417 | + |
| 418 | + char *fmtenc = PQescapeLiteral(conn, enc, strlen(enc)); |
| 419 | + PQfreemem(enc); |
| 420 | + |
| 421 | + if (!fmtenc) { |
| 422 | + return NULL; |
| 423 | + } |
| 424 | + |
| 425 | + char *fmtuser = PQescapeIdentifier(conn, user, strlen(user)); |
| 426 | + |
| 427 | + if (!fmtuser) { |
| 428 | + PQfreemem(fmtenc); |
| 429 | + return NULL; |
| 430 | + } |
| 431 | + |
| 432 | + char *query; |
| 433 | + |
| 434 | + spprintf(&query, 0, "ALTER USER %s PASSWORD %s", fmtuser, fmtenc); |
| 435 | + |
| 436 | + PGresult *pg_result = PQexec(conn, query); |
| 437 | + |
| 438 | + efree(query); |
| 439 | + PQfreemem(fmtuser); |
| 440 | + PQfreemem(fmtenc); |
| 441 | + |
| 442 | + return pg_result; |
| 443 | +} |
| 444 | +#endif |
| 445 | + |
404 | 446 | /* {{{ PHP_INI */
|
405 | 447 | PHP_INI_BEGIN()
|
406 | 448 | 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)
|
6048 | 6090 | }
|
6049 | 6091 | /* }}} */
|
6050 | 6092 |
|
| 6093 | +PHP_FUNCTION(pg_change_password) |
| 6094 | +{ |
| 6095 | + zval *pgsql_link; |
| 6096 | + pgsql_link_handle *link; |
| 6097 | + PGresult *pg_result; |
| 6098 | + zend_string *user, *passwd; |
| 6099 | + |
| 6100 | + ZEND_PARSE_PARAMETERS_START(3, 3) |
| 6101 | + Z_PARAM_OBJECT_OF_CLASS(pgsql_link, pgsql_link_ce) |
| 6102 | + Z_PARAM_STR(user) |
| 6103 | + Z_PARAM_STR(passwd) |
| 6104 | + ZEND_PARSE_PARAMETERS_END(); |
| 6105 | + |
| 6106 | + if (ZSTR_LEN(user) == 0) { |
| 6107 | + zend_argument_value_error(2, "cannot be empty"); |
| 6108 | + RETURN_THROWS(); |
| 6109 | + } |
| 6110 | + |
| 6111 | + /* it is technically possible, but better to disallow it */ |
| 6112 | + if (ZSTR_LEN(passwd) == 0) { |
| 6113 | + zend_argument_value_error(3, "cannot be empty"); |
| 6114 | + RETURN_THROWS(); |
| 6115 | + } |
| 6116 | + |
| 6117 | + link = Z_PGSQL_LINK_P(pgsql_link); |
| 6118 | + CHECK_PGSQL_LINK(link); |
| 6119 | + |
| 6120 | + pg_result = PQchangePassword(link->conn, ZSTR_VAL(user), ZSTR_VAL(passwd)); |
| 6121 | + RETVAL_BOOL(PQresultStatus(pg_result) == PGRES_COMMAND_OK); |
| 6122 | + PQclear(pg_result); |
| 6123 | +} |
| 6124 | + |
6051 | 6125 | #endif
|
0 commit comments