From: Andrew Bartlett Date: Mon, 29 Mar 2021 21:51:26 +0000 (+1300) Subject: CVE-2021-20251 s4-rpc_server: Use authsam_search_account() to find the user X-Git-Tag: talloc-2.4.0~1087 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=439f96a2cfe77f6cbf331d965a387512c2db91c6;p=thirdparty%2Fsamba.git CVE-2021-20251 s4-rpc_server: Use authsam_search_account() to find the user This helps the bad password and audit log handling code as it allows assumptions to be made about the attributes found in the variable "msg", such as that DSDB_SEARCH_SHOW_EXTENDED_DN was used. This ensures we can re-search on the DN via the embedded GUID, which in in turn rename-proof. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14611 Signed-off-by: Andrew Bartlett Reviewed-by: Joseph Sutton Reviewed-by: Andreas Schneider --- diff --git a/source4/rpc_server/samr/samr_password.c b/source4/rpc_server/samr/samr_password.c index da22ab7484b..09d7501d474 100644 --- a/source4/rpc_server/samr/samr_password.c +++ b/source4/rpc_server/samr/samr_password.c @@ -312,13 +312,7 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call, struct ldb_context *sam_ctx = NULL; struct ldb_dn *user_dn = NULL; int ret; - struct ldb_result *res = NULL; - const char * const attrs[] = { "unicodePwd", "dBCSPwd", - "userAccountControl", - "msDS-ResultantPSO", - "msDS-User-Account-Control-Computed", - "badPwdCount", "badPasswordTime", - "objectSid", NULL }; + struct ldb_message *msg = NULL; struct samr_Password *nt_pwd; struct samr_DomInfo1 *dominfo = NULL; struct userPwdChangeFailureInformation *reject = NULL; @@ -356,26 +350,26 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call, return NT_STATUS_INVALID_SYSTEM_SERVICE; } - /* we need the users dn and the domain dn (derived from the - user SID). We also need the current lm and nt password hashes - in order to decrypt the incoming passwords */ - ret = dsdb_search(sam_ctx, mem_ctx, &res, - ldb_get_default_basedn(sam_ctx), - LDB_SCOPE_SUBTREE, attrs, - DSDB_SEARCH_SHOW_EXTENDED_DN, - "(&(sAMAccountName=%s)(objectclass=user))", - ldb_binary_encode_string(mem_ctx, r->in.account->string)); - if (ret != LDB_SUCCESS || res->count != 1) { - status = NT_STATUS_NO_SUCH_USER; /* Converted to WRONG_PASSWORD below */ + /* + * We use authsam_search_account() to be consistent with the + * other callers in the bad password and audit log handling + * systems. It ensures we get DSDB_SEARCH_SHOW_EXTENDED_DN. + */ + status = authsam_search_account(mem_ctx, + sam_ctx, + r->in.account->string, + ldb_get_default_basedn(sam_ctx), + &msg); + if (!NT_STATUS_IS_OK(status)) { goto failed; } - user_dn = res->msgs[0]->dn; - user_samAccountName = ldb_msg_find_attr_as_string(res->msgs[0], "samAccountName", NULL); - user_objectSid = samdb_result_dom_sid(res, res->msgs[0], "objectSid"); + user_dn = msg->dn; + user_samAccountName = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL); + user_objectSid = samdb_result_dom_sid(mem_ctx, msg, "objectSid"); status = samdb_result_passwords(mem_ctx, lp_ctx, - res->msgs[0], &nt_pwd); + msg, &nt_pwd); if (!NT_STATUS_IS_OK(status) ) { goto failed; } @@ -491,7 +485,7 @@ failed: /* Only update the badPwdCount if we found the user */ if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) { - authsam_update_bad_pwd_count(sam_ctx, res->msgs[0], ldb_get_default_basedn(sam_ctx)); + authsam_update_bad_pwd_count(sam_ctx, msg, ldb_get_default_basedn(sam_ctx)); } else if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) { /* Don't give the game away: (don't allow anonymous users to prove the existence of usernames) */ status = NT_STATUS_WRONG_PASSWORD;