Hi,
When trying to bind to ldapd using a dn which has an invalid
userPassword entry, e.eg. a “defective” SHA valus like “{SHA}alpha”,
ldapd currently returns 1 (Operations Error).
The patch below changes this to 49 (Invalid Credentials).
There are basically two reasons for this:
1. The userPassword is a multi-valued attribute, i.e. there can be more
than one in an ldap entry. Now when you have a valid and a defective
entry and the binding user supplies a password which does not match
the valid entry you get different results whether the defective entry
comes last (return value 1) or not (return value 49). When the
supplied password matches the valid entry the bind succeeds
independent of order.
A change to return value 49 gets consistent results.
For a single userPassword entry 49 also is not wrong, as the supplied
password still doesn't match the entry (even if it is defective).
2. RFC 4511 defines the result code “Operations Error” as follows:
“operationsError (1)
Indicates that the operation is not properly sequenced with
relation to other operations (of same or different type).
For example, this code is returned if the client attempts to
StartTLS [RFC4346] while there are other uncompleted
operations or if a TLS layer was already installed.”
A defective password entry in no way is an operations error of the
ldapd server. Also I don't think it is the server's job to take care
of the correctness of password entries. There is no provision in the
LDAP RFCs to stop one from entering an incorrect entry. I checked
this with other directory servers: 389, apache ds, and openldap. All
three accept incorrect entries and all three return 49 (Invalid
Credentials) on bind attempts.
Best regards
Robert
-----------------------------------------------
commit e9fe05bf15bf216ea7759cd64f17103008e1b69e (master)
from: Robert Klein <[email protected]>
date: Sun Mar 1 15:49:40 2020 UTC
ldapd: fix return values for illegal passwords
diff 7a641edbd5c2c2686d4a80fd730967f00e58e681
f62b80b397c780e8273b5cc67d544b951c4c9d1f
blob - f8debff7a2d6a0feb9cf984905de385b029b8744
blob + 094a8360e326ac7956c54a7dc8380df81c23efa5
--- usr.sbin/ldapd/auth.c
+++ usr.sbin/ldapd/auth.c
@@ -218,12 +218,12 @@ check_password(struct request *req, const char *stored
int sz;
if (stored_passwd == NULL)
- return -1;
+ return 0;
if (strncmp(stored_passwd, "{SHA}", 5) == 0) {
sz = b64_pton(stored_passwd + 5, tmp, sizeof(tmp));
if (sz != SHA_DIGEST_LENGTH)
- return (-1);
+ return (0);
SHA1_Init(&ctx);
SHA1_Update(&ctx, passwd, strlen(passwd));
SHA1_Final(md, &ctx);
@@ -231,7 +231,7 @@ check_password(struct request *req, const char *stored
} else if (strncmp(stored_passwd, "{SSHA}", 6) == 0) {
sz = b64_pton(stored_passwd + 6, tmp, sizeof(tmp));
if (sz <= SHA_DIGEST_LENGTH)
- return (-1);
+ return (0);
salt = tmp + SHA_DIGEST_LENGTH;
SHA1_Init(&ctx);
SHA1_Update(&ctx, passwd, strlen(passwd));
@@ -241,11 +241,11 @@ check_password(struct request *req, const char *stored
} else if (strncmp(stored_passwd, "{CRYPT}", 7) == 0) {
encpw = crypt(passwd, stored_passwd + 7);
if (encpw == NULL)
- return (-1);
+ return (0);
return (strcmp(encpw, stored_passwd + 7) == 0 ? 1 : 0);
} else if (strncmp(stored_passwd, "{BSDAUTH}", 9) == 0) {
if (send_auth_request(req, stored_passwd + 9, passwd) == -1)
- return (-1);
+ return (0);
return 2; /* Operation in progress. */
} else
return (strcmp(stored_passwd, passwd) == 0 ? 1 : 0);