aboutsummaryrefslogtreecommitdiff
path: root/src/backend/libpq/auth.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/libpq/auth.c')
-rw-r--r--src/backend/libpq/auth.c60
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;
}