diff options
Diffstat (limited to 'src/backend/libpq/auth.c')
-rw-r--r-- | src/backend/libpq/auth.c | 60 |
1 files changed, 40 insertions, 20 deletions
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index dd7de7c3a4e..cb30fc7b714 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -688,6 +688,24 @@ recv_password_packet(Port *port) (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("invalid password packet size"))); + /* + * Don't allow an empty password. Libpq treats an empty password the same + * as no password at all, and won't even try to authenticate. But other + * clients might, so allowing it would be confusing. + * + * Note that this only catches an empty password sent by the client in + * plaintext. There's also a check in CREATE/ALTER USER that prevents an + * empty string from being stored as a user's password in the first place. + * We rely on that for MD5 and SCRAM authentication, but we still need + * this check here, to prevent an empty password from being used with + * authentication methods that check the password against an external + * system, like PAM, LDAP and RADIUS. + */ + if (buf.len == 1) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PASSWORD), + errmsg("empty password returned by client"))); + /* Do not echo password to logs, for security. */ elog(DEBUG5, "received password packet"); @@ -2081,12 +2099,6 @@ pam_passwd_conv_proc(int num_msg, const struct pam_message **msg, */ goto fail; } - if (strlen(passwd) == 0) - { - ereport(LOG, - (errmsg("empty password returned by client"))); - goto fail; - } } if ((reply[i].resp = strdup(passwd)) == NULL) goto fail; @@ -2277,6 +2289,8 @@ CheckBSDAuth(Port *port, char *user) */ retval = auth_userokay(user, NULL, "auth-postgresql", passwd); + pfree(passwd); + if (!retval) return STATUS_ERROR; @@ -2407,16 +2421,12 @@ CheckLDAPAuth(Port *port) if (passwd == NULL) return STATUS_EOF; /* client wouldn't send password */ - if (strlen(passwd) == 0) - { - ereport(LOG, - (errmsg("empty password returned by client"))); - return STATUS_ERROR; - } - if (InitializeLDAPConnection(port, &ldap) == STATUS_ERROR) + { /* Error message already sent */ + pfree(passwd); return STATUS_ERROR; + } if (port->hba->ldapbasedn) { @@ -2448,6 +2458,7 @@ CheckLDAPAuth(Port *port) { ereport(LOG, (errmsg("invalid character in user name for LDAP authentication"))); + pfree(passwd); return STATUS_ERROR; } } @@ -2464,6 +2475,7 @@ CheckLDAPAuth(Port *port) ereport(LOG, (errmsg("could not perform initial LDAP bind for ldapbinddn \"%s\" on server \"%s\": %s", port->hba->ldapbinddn, port->hba->ldapserver, ldap_err2string(r)))); + pfree(passwd); return STATUS_ERROR; } @@ -2488,6 +2500,7 @@ CheckLDAPAuth(Port *port) ereport(LOG, (errmsg("could not search LDAP for filter \"%s\" on server \"%s\": %s", filter, port->hba->ldapserver, ldap_err2string(r)))); + pfree(passwd); pfree(filter); return STATUS_ERROR; } @@ -2508,6 +2521,7 @@ CheckLDAPAuth(Port *port) count, filter, port->hba->ldapserver, count))); + pfree(passwd); pfree(filter); ldap_msgfree(search_message); return STATUS_ERROR; @@ -2523,6 +2537,7 @@ CheckLDAPAuth(Port *port) ereport(LOG, (errmsg("could not get dn for the first entry matching \"%s\" on server \"%s\": %s", filter, port->hba->ldapserver, ldap_err2string(error)))); + pfree(passwd); pfree(filter); ldap_msgfree(search_message); return STATUS_ERROR; @@ -2543,6 +2558,7 @@ CheckLDAPAuth(Port *port) ereport(LOG, (errmsg("could not unbind after searching for user \"%s\" on server \"%s\": %s", fulluser, port->hba->ldapserver, ldap_err2string(error)))); + pfree(passwd); pfree(fulluser); return STATUS_ERROR; } @@ -2553,6 +2569,7 @@ CheckLDAPAuth(Port *port) */ if (InitializeLDAPConnection(port, &ldap) == STATUS_ERROR) { + pfree(passwd); pfree(fulluser); /* Error message already sent */ @@ -2573,10 +2590,12 @@ CheckLDAPAuth(Port *port) ereport(LOG, (errmsg("LDAP login failed for user \"%s\" on server \"%s\": %s", fulluser, port->hba->ldapserver, ldap_err2string(r)))); + pfree(passwd); pfree(fulluser); return STATUS_ERROR; } + pfree(passwd); pfree(fulluser); return STATUS_OK; @@ -2720,17 +2739,11 @@ CheckRADIUSAuth(Port *port) if (passwd == NULL) return STATUS_EOF; /* client wouldn't send password */ - if (strlen(passwd) == 0) - { - ereport(LOG, - (errmsg("empty password returned by client"))); - return STATUS_ERROR; - } - if (strlen(passwd) > RADIUS_MAX_PASSWORD_LENGTH) { ereport(LOG, (errmsg("RADIUS authentication does not support passwords longer than %d characters", RADIUS_MAX_PASSWORD_LENGTH))); + pfree(passwd); return STATUS_ERROR; } @@ -2756,9 +2769,15 @@ CheckRADIUSAuth(Port *port) *------ */ if (ret == STATUS_OK) + { + pfree(passwd); return STATUS_OK; + } else if (ret == STATUS_EOF) + { + pfree(passwd); return STATUS_ERROR; + } /* * secret, port and identifiers either have length 0 (use default), @@ -2775,6 +2794,7 @@ CheckRADIUSAuth(Port *port) } /* No servers left to try, so give up */ + pfree(passwd); return STATUS_ERROR; } |