On Fri, 6 Mar 2020 21:50:34 +0100 Robert Klein <rokl...@roklein.de> wrote:
> Hi, > > > sorry, I simply forgot ldap_auth_sasl. > > LDAP_OTHER is a good return code for imsg failure and I really like > the idea of using the LDAP return codes right away instead of the > extra mapping. > > Your patch however doesn't work for SASL authentication (and > ldapsearch gives some strange messages), because > sent_auth_request *never* returns LDAP_SUCCESS (this happens via imsg) > but LDAP_SASL_BIND_IN_PROGRESS. See comment inline. > > After changing the one line bind with SASL works, too. Additional note: if the rest of ldap_auth_sasl succeeds it returns LDAP_SUCCESS. This could also be turned into LDAP_SASL_BIND_IN_PROGRESS if and only if the corresponding line(s) in ldap_bind() below are also changes. In the end it doesn't matter what value gets there as long as it is handled consistently. Its only purpose is that ldap_respond() is not called from ldap_bind. The value itself gets returned to the caller which discards is (request_dispatch() in conn.c). Best regards Robert > > All tests using ldap_auth_simple worked ok. > > Best regards > Robert > > > On Tue, 3 Mar 2020 20:33:41 +0100 > Martijn van Duren <openbsd+t...@list.imperialat.at> wrote: > > > I agree that returning Operations Error is the wrong return value. > > I don't agree that we should *always* return invalidCredentials, > > however, acting like the other LDAP servers on an invalid entry > > seems reasonable to me. One option I do see is if we can't create > > an imsg to the parent process handling a BSDAUTH request, this > > clearly is an internal error. > > > > Also, you missed the case for ldap_auth_sasl. > > > > Diff below should change this, but it's compile tested only. > > > > martijn@ > > > > On 3/1/20 5:24 PM, Robert Klein wrote: > > > 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 > > > > > > > > Index: auth.c > > =================================================================== > > RCS file: /cvs/src/usr.sbin/ldapd/auth.c,v > > retrieving revision 1.14 > > diff -u -p -r1.14 auth.c > > --- auth.c 24 Oct 2019 12:39:26 -0000 1.14 > > +++ auth.c 3 Mar 2020 19:31:41 -0000 > > @@ -179,33 +179,34 @@ send_auth_request(struct request *req, c > > const char *password) > > { > > struct auth_req auth_req; > > + int ret = LDAP_SASL_BIND_IN_PROGRESS; > > > > memset(&auth_req, 0, sizeof(auth_req)); > > if (strlcpy(auth_req.name, username, > > - sizeof(auth_req.name)) >= sizeof(auth_req.name)) > > + sizeof(auth_req.name)) >= sizeof(auth_req.name)) { > > + ret = LDAP_INVALID_CREDENTIALS; > > goto fail; > > + } > > if (strlcpy(auth_req.password, password, > > - sizeof(auth_req.password)) >= > > sizeof(auth_req.password)) > > + sizeof(auth_req.password)) >= > > sizeof(auth_req.password)) { > > + ret = LDAP_INVALID_CREDENTIALS; > > goto fail; > > + } > > auth_req.fd = req->conn->fd; > > auth_req.msgid = req->msgid; > > > > if (imsgev_compose(iev_ldapd, IMSG_LDAPD_AUTH, 0, 0, -1, > > &auth_req, > > - sizeof(auth_req)) == -1) > > + sizeof(auth_req)) == -1) { > > + ret = LDAP_OTHER; > > goto fail; > > + } > > > > req->conn->bind_req = req; > > - return 0; > > - > > fail: > > memset(&auth_req, 0, sizeof(auth_req)); > > - return -1; > > + return ret; > > } > > > > -/* > > - * Check password. Returns 1 if password matches, 2 if password > > matching > > - * is in progress, 0 on mismatch and -1 on error. > > - */ > > static int > > check_password(struct request *req, const char *stored_passwd, > > const char *passwd) > > @@ -218,37 +219,39 @@ check_password(struct request *req, cons > > int sz; > > > > if (stored_passwd == NULL) > > - return -1; > > + return LDAP_INVALID_CREDENTIALS; > > > > if (strncmp(stored_passwd, "{SHA}", 5) == 0) { > > sz = b64_pton(stored_passwd + 5, tmp, sizeof(tmp)); > > if (sz != SHA_DIGEST_LENGTH) > > - return (-1); > > + return (LDAP_INVALID_CREDENTIALS); > > SHA1_Init(&ctx); > > SHA1_Update(&ctx, passwd, strlen(passwd)); > > SHA1_Final(md, &ctx); > > - return (bcmp(md, tmp, SHA_DIGEST_LENGTH) == 0 ? 1 : > > 0); > > + return (bcmp(md, tmp, SHA_DIGEST_LENGTH) == 0 ? > > + LDAP_SUCCESS : LDAP_INVALID_CREDENTIALS); > > } 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 (LDAP_INVALID_CREDENTIALS); > > salt = tmp + SHA_DIGEST_LENGTH; > > SHA1_Init(&ctx); > > SHA1_Update(&ctx, passwd, strlen(passwd)); > > SHA1_Update(&ctx, salt, sz - SHA_DIGEST_LENGTH); > > SHA1_Final(md, &ctx); > > - return (bcmp(md, tmp, SHA_DIGEST_LENGTH) == 0 ? 1 : > > 0); > > + return (bcmp(md, tmp, SHA_DIGEST_LENGTH) == 0 ? > > + LDAP_SUCCESS : LDAP_INVALID_CREDENTIALS); > > } else if (strncmp(stored_passwd, "{CRYPT}", 7) == 0) { > > encpw = crypt(passwd, stored_passwd + 7); > > if (encpw == NULL) > > - return (-1); > > - return (strcmp(encpw, stored_passwd + 7) == 0 ? 1 : > > 0); > > + return (LDAP_INVALID_CREDENTIALS); > > + return (strcmp(encpw, stored_passwd + 7) == 0 ? > > + LDAP_SUCCESS : LDAP_INVALID_CREDENTIALS); > > } else if (strncmp(stored_passwd, "{BSDAUTH}", 9) == 0) { > > - if (send_auth_request(req, stored_passwd + 9, > > passwd) == -1) > > - return (-1); > > - return 2; /* Operation in progress. */ > > + return send_auth_request(req, stored_passwd + 9, > > passwd); } else > > - return (strcmp(stored_passwd, passwd) == 0 ? 1 : > > 0); > > + return (strcmp(stored_passwd, passwd) == 0 ? > > + LDAP_SUCCESS : LDAP_INVALID_CREDENTIALS); > > } > > > > static int > > @@ -258,6 +261,7 @@ ldap_auth_sasl(struct request *req, char > > char *authzid, *authcid, *password; > > char *creds; > > size_t len; > > + int ret; > > > > if (ober_scanf_elements(params, "{sx", &method, &creds, > > &len) != 0) return LDAP_PROTOCOL_ERROR; > > @@ -283,8 +287,8 @@ ldap_auth_sasl(struct request *req, char > > log_debug("sasl authorization id = [%s]", authzid); > > log_debug("sasl authentication id = [%s]", authcid); > > > > - if (send_auth_request(req, authcid, password) != 0) > > - return LDAP_OPERATIONS_ERROR; > > + if ((ret = send_auth_request(req, authcid, password)) != > > LDAP_SUCCESS) > > ---^^^ this should be LDAP_SASL_BIND_IN_PROGRESS. > > > + return ret; > > > > free(req->conn->binddn); > > req->conn->binddn = NULL; > > @@ -352,7 +356,8 @@ ldap_auth_simple(struct request *req, ch > > if (ober_get_string(elm, > > &user_password) != 0) continue; > > pwret = check_password(req, > > user_password, password); > > - if (pwret >= 1) > > + if (pwret == LDAP_SUCCESS || > > + pwret == > > LDAP_SASL_BIND_IN_PROGRESS) break; > > } > > } > > @@ -361,20 +366,18 @@ ldap_auth_simple(struct request *req, ch > > free(req->conn->binddn); > > req->conn->binddn = NULL; > > > > - if (pwret == 1) { > > + if (pwret == LDAP_SUCCESS) { > > if ((req->conn->binddn = strdup(binddn)) == NULL) > > return LDAP_OTHER; > > log_debug("successfully authenticated as %s", > > req->conn->binddn); > > return LDAP_SUCCESS; > > - } else if (pwret == 2) { > > + } else if (pwret == LDAP_SASL_BIND_IN_PROGRESS) { > > if ((req->conn->pending_binddn = strdup(binddn)) == > > NULL) return LDAP_OTHER; > > return -LDAP_SASL_BIND_IN_PROGRESS; > > - } else if (pwret == 0) > > - return LDAP_INVALID_CREDENTIALS; > > - else > > - return LDAP_OPERATIONS_ERROR; > > + } else > > + return pwret; > > } > > > > void >