New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix shadow auth for users defined under [users] section #706
Changes from all commits
bb88725
ae4e16f
b4eedc4
c8d3118
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -387,6 +387,36 @@ PgUser *add_user(const char *name, const char *passwd) | |
return user; | ||
} | ||
|
||
/* find original or preconfigured user given the login user */ | ||
PgUser *find_original_user(PgUser *login_user) | ||
{ | ||
/* | ||
* The original user will either be the current login user, a preconfigured user via | ||
* ini file [users] section, a preconfigured user via global auth_file, a PAM user, | ||
* a user attached to a database via auth_query, a forced user with user= entry via | ||
* ini file [databases] section, or not exist yet if the user has never connected. | ||
*/ | ||
PgUser *original_user = find_user(login_user->name); | ||
char *tmp_passwd; | ||
|
||
/* add new login user to reload their configurations at runtime */ | ||
if (original_user == NULL) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure I understand what this is needed for. Can you add a test showing what you mean with the RELOAD behaviour that you want to support? i.e. one that fails without this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
put_in_order(&login_user->head, &user_list, cmp_user); | ||
aatree_insert(&user_tree, (uintptr_t)login_user->name, &login_user->tree_node); | ||
return login_user; | ||
} | ||
|
||
/* original user is no longer preconfigured and won't send auth queries on future login */ | ||
if (original_user->is_preconfigured) | ||
original_user->is_preconfigured = false; | ||
|
||
tmp_passwd = strdup(login_user->passwd); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
safe_strcpy(original_user->passwd, tmp_passwd, sizeof(original_user->passwd)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Copy over password of new login user to account for a single user that may have different passwords for multiple databases. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So you are copying every time in case a user has a different password in different databases? I think even with this code that could lead to problems, because the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated the PR.
Semantically, this should be clearer since it models reality, where each database may have different passwords per user. Storing user passwords in each There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change seems to somehow have been reverted on your branch. Possibly due to a rebase. |
||
free(tmp_passwd); | ||
|
||
return original_user; | ||
} | ||
|
||
/* add or update db users */ | ||
PgUser *add_db_user(PgDatabase *db, const char *name, const char *passwd) | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -185,6 +185,8 @@ psql -X -p $PG_PORT -d p0 -c "select * from pg_user" | grep pswcheck > /dev/null | |
psql -X -o /dev/null -p $PG_PORT -c "create user pswcheck with superuser createdb password 'pgbouncer-check';" p0 || exit 1 | ||
psql -X -o /dev/null -p $PG_PORT -c "create user someuser with password 'anypasswd';" p0 || exit 1 | ||
psql -X -o /dev/null -p $PG_PORT -c "create user maxedout;" p0 || exit 1 | ||
psql -X -o /dev/null -p $PG_PORT -c "create user shadowuser1 with password 'bar';" p0 || exit 1 | ||
psql -X -o /dev/null -p $PG_PORT -c "create user shadowuser2 with password 'foo';" p0 || exit 1 | ||
psql -X -o /dev/null -p $PG_PORT -c "create user longpass with password '$long_password';" p0 || exit 1 | ||
if $pg_supports_scram; then | ||
psql -X -o /dev/null -p $PG_PORT -c "set password_encryption = 'md5'; create user muser1 password 'foo';" p0 || exit 1 | ||
|
@@ -931,6 +933,48 @@ test_password_server() { | |
return 0 | ||
} | ||
|
||
# test password authentication from PgBouncer to PostgreSQL server using | ||
# auth_query to retrieve user's shadow password from pg_shadow | ||
test_shadow_password_server_login() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These test cases are reproducible examples of bug (they fail without the fix): #484 |
||
$have_getpeereid || return 77 | ||
|
||
admin "set auth_type='md5'" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you think it makes sense to include the same tests also for scram auth? |
||
admin "set auth_user='pswcheck'" | ||
|
||
# plain-text password of auth_user in userlist.txt | ||
curuser=`psql -X -d "dbname=authdb user=pswcheck password=pgbouncer-check" -tAq -c "select current_user;"` | ||
echo "curuser=$curuser" | ||
test "$curuser" = "pswcheck" || return 1 | ||
|
||
# user with correct password from PostgreSQL server | ||
curuser=`psql -X -d "dbname=authdb user=shadowuser1 password=bar" -tAq -c "select current_user;"` | ||
echo "curuser=$curuser" | ||
test "$curuser" = "shadowuser1" || return 1 | ||
# user with wrong password from PostgreSQL server | ||
curuser=`psql -X -d "dbname=authdb user=shadowuser1 password=badpasswd" -tAq -c "select current_user;"` | ||
echo "curuser=$curuser" | ||
test "$curuser" = "" || return 1 | ||
|
||
# user defined in ini [users] section with correct password from PostgreSQL server | ||
curuser=`psql -X -d "dbname=authdb user=shadowuser2 password=foo" -tAq -c "select current_user;"` | ||
echo "curuser=$curuser" | ||
test "$curuser" = "shadowuser2" || return 1 | ||
# user defined in ini [users] section with wrong password from PostgreSQL server | ||
curuser2=`psql -X -d "dbname=authdb user=shadowuser2 password=badpasswd" -tAq -c "select current_user;"` | ||
echo "curuser2=$curuser2" | ||
test "$curuser2" = "" || return 1 | ||
|
||
# auth_user defined in ini [users] section with correct password from PostgreSQL server | ||
admin "set auth_user='shadowuser2'" | ||
curuser=`psql -X -d "dbname=authdb user=shadowuser2 password=foo" -tAq -c "select current_user;"` | ||
echo "curuser=$curuser" | ||
test "$curuser" = "shadowuser2" || return 1 | ||
|
||
admin "set auth_type='trust'" | ||
|
||
return 0 | ||
} | ||
|
||
# test plain-text password authentication from client to PgBouncer | ||
test_password_client() { | ||
$have_getpeereid || return 77 | ||
|
@@ -1445,6 +1489,7 @@ test_server_lifetime | |
test_server_idle_timeout | ||
test_query_timeout | ||
test_idle_transaction_timeout | ||
test_shadow_password_server_login | ||
test_server_connect_timeout_establish | ||
test_server_connect_timeout_reject | ||
test_server_check_delay | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function name isn't really descriptive of what this function is doing, especially the
put_in_order
call.