From da83b513b21c88f58bf0c2e56c2e46359535e160 Mon Sep 17 00:00:00 2001 From: Will Fitch Date: Sat, 18 Jan 2014 19:24:22 -0500 Subject: Fix #62479: Some chars not parsed in passwords This fixes an issue where backslashes and spaces aren't correctly parsed for passwords. --- ext/pdo_pgsql/pgsql_driver.c | 31 ++++++++++++++++++++-- ext/pdo_pgsql/tests/bug62479.phpt | 56 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 ext/pdo_pgsql/tests/bug62479.phpt (limited to 'ext/pdo_pgsql') diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c index 6aa8814d86..3be9359216 100644 --- a/ext/pdo_pgsql/pgsql_driver.c +++ b/ext/pdo_pgsql/pgsql_driver.c @@ -1039,6 +1039,7 @@ static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_ pdo_pgsql_db_handle *H; int ret = 0; char *conn_str, *p, *e; + char *tmp_pass; long connect_timeout = 30; H = pecalloc(1, sizeof(pdo_pgsql_db_handle), dbh->is_persistent); @@ -1060,18 +1061,44 @@ static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_ connect_timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, 30 TSRMLS_CC); } + if (dbh->password) { + if (dbh->password[0] != '\'' && dbh->password[strlen(dbh->password) - 1] != '\'') { + char *pwd = dbh->password; + int pos = 1; + + tmp_pass = safe_emalloc(2, strlen(dbh->password), 3); + tmp_pass[0] = '\''; + + while (*pwd != '\0') { + if (*pwd == '\\' || *pwd == '\'') { + tmp_pass[pos++] = '\\'; + } + + tmp_pass[pos++] = *pwd++; + } + + tmp_pass[pos++] = '\''; + tmp_pass[pos] = '\0'; + } else { + tmp_pass = dbh->password; + } + } + /* support both full connection string & connection string + login and/or password */ if (dbh->username && dbh->password) { - spprintf(&conn_str, 0, "%s user=%s password=%s connect_timeout=%ld", dbh->data_source, dbh->username, dbh->password, connect_timeout); + spprintf(&conn_str, 0, "%s user=%s password=%s connect_timeout=%ld", dbh->data_source, dbh->username, tmp_pass, connect_timeout); } else if (dbh->username) { spprintf(&conn_str, 0, "%s user=%s connect_timeout=%ld", dbh->data_source, dbh->username, connect_timeout); } else if (dbh->password) { - spprintf(&conn_str, 0, "%s password=%s connect_timeout=%ld", dbh->data_source, dbh->password, connect_timeout); + spprintf(&conn_str, 0, "%s password=%s connect_timeout=%ld", dbh->data_source, tmp_pass, connect_timeout); } else { spprintf(&conn_str, 0, "%s connect_timeout=%ld", (char *) dbh->data_source, connect_timeout); } H->server = PQconnectdb(conn_str); + if (dbh->password && tmp_pass != dbh->password) { + efree(tmp_pass); + } efree(conn_str); diff --git a/ext/pdo_pgsql/tests/bug62479.phpt b/ext/pdo_pgsql/tests/bug62479.phpt new file mode 100644 index 0000000000..2e19f15002 --- /dev/null +++ b/ext/pdo_pgsql/tests/bug62479.phpt @@ -0,0 +1,56 @@ +--TEST-- +PDO PgSQL Bug #62479 (PDO-psql cannot connect if password contains spaces) +--SKIPIF-- +query($testQuery); +$testQuery = "DROP USER pdo_$rand"; +$db->query($testQuery); +?> +--FILE-- +setAttribute(PDO::ATTR_EMULATE_PREPARES, true); +$rand = rand(5, 400); +$user = "pdo_$rand"; +$template = "CREATE USER $user WITH PASSWORD '%s'"; +$dropUser = "DROP USER $user"; +$testQuery = 'SELECT 1 as verification'; + +// Create temp user with space in password +$sql = sprintf($template, 'my password'); +$pdo->query($sql); +$testConn = new PDO($_ENV['PDOTEST_DSN'], $user, "my password"); +$result = $testConn->query($testQuery)->fetch(); +$check = $result[0]; +var_dump($check); + +// Remove the user +$pdo->query($dropUser); + +// Create a user with a space and single quote +$sql = sprintf($template, "my pass''word"); +$pdo->query($sql); + +$testConn = new PDO($_ENV['PDOTEST_DSN'], $user, "my pass'word"); +$result = $testConn->query($testQuery)->fetch(); +$check = $result[0]; +var_dump($check); + +// Remove the user +$pdo->query($dropUser); +?> +--EXPECT-- +int(1) +int(1) + -- cgit v1.2.1