diff options
-rw-r--r-- | source3/rpc_server/samr/srv_samr_nt.c | 169 | ||||
-rw-r--r-- | source3/smbd/lanman.c | 254 | ||||
-rw-r--r-- | source4/rpc_server/samr/samr_password.c | 145 | ||||
-rw-r--r-- | source4/torture/rpc/samr.c | 6 |
4 files changed, 20 insertions, 554 deletions
diff --git a/source3/rpc_server/samr/srv_samr_nt.c b/source3/rpc_server/samr/srv_samr_nt.c index a7700c6bd6..48cfc7e12d 100644 --- a/source3/rpc_server/samr/srv_samr_nt.c +++ b/source3/rpc_server/samr/srv_samr_nt.c @@ -1713,172 +1713,19 @@ NTSTATUS _samr_LookupNames(struct pipes_struct *p, } /**************************************************************** - _samr_ChangePasswordUser + _samr_ChangePasswordUser. + + So old it is just not worth implementing + because it does not supply a plaintext and so we can't do password + complexity checking and cannot update other services that use a + plaintext password via passwd chat/pam password change/ldap password + sync. ****************************************************************/ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p, struct samr_ChangePasswordUser *r) { - NTSTATUS status; - bool ret = false; - struct samr_user_info *uinfo; - struct samu *pwd = NULL; - struct samr_Password new_lmPwdHash, new_ntPwdHash, checkHash; - struct samr_Password lm_pwd, nt_pwd; - bool updated_badpw = false; - NTSTATUS update_login_attempts_status; - - uinfo = policy_handle_find(p, r->in.user_handle, - SAMR_USER_ACCESS_SET_PASSWORD, NULL, - struct samr_user_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - DEBUG(5,("_samr_ChangePasswordUser: sid:%s\n", - sid_string_dbg(&uinfo->sid))); - - /* basic sanity checking on parameters. Do this before any database ops */ - if (!r->in.lm_present || !r->in.nt_present || - !r->in.old_lm_crypted || !r->in.new_lm_crypted || - !r->in.old_nt_crypted || !r->in.new_nt_crypted) { - /* we should really handle a change with lm not - present */ - return NT_STATUS_INVALID_PARAMETER_MIX; - } - - if (!(pwd = samu_new(NULL))) { - return NT_STATUS_NO_MEMORY; - } - - become_root(); - ret = pdb_getsampwsid(pwd, &uinfo->sid); - unbecome_root(); - - if (!ret) { - TALLOC_FREE(pwd); - return NT_STATUS_WRONG_PASSWORD; - } - - /* Quit if the account was locked out. */ - if (pdb_get_acct_ctrl(pwd) & ACB_AUTOLOCK) { - DEBUG(3, ("Account for user %s was locked out.\n", - pdb_get_username(pwd))); - status = NT_STATUS_ACCOUNT_LOCKED_OUT; - goto out; - } - - { - const uint8_t *lm_pass, *nt_pass; - - lm_pass = pdb_get_lanman_passwd(pwd); - nt_pass = pdb_get_nt_passwd(pwd); - - if (!lm_pass || !nt_pass) { - status = NT_STATUS_WRONG_PASSWORD; - goto update_login; - } - - memcpy(&lm_pwd.hash, lm_pass, sizeof(lm_pwd.hash)); - memcpy(&nt_pwd.hash, nt_pass, sizeof(nt_pwd.hash)); - } - - /* decrypt and check the new lm hash */ - D_P16(lm_pwd.hash, r->in.new_lm_crypted->hash, new_lmPwdHash.hash); - D_P16(new_lmPwdHash.hash, r->in.old_lm_crypted->hash, checkHash.hash); - if (memcmp(checkHash.hash, lm_pwd.hash, 16) != 0) { - status = NT_STATUS_WRONG_PASSWORD; - goto update_login; - } - - /* decrypt and check the new nt hash */ - D_P16(nt_pwd.hash, r->in.new_nt_crypted->hash, new_ntPwdHash.hash); - D_P16(new_ntPwdHash.hash, r->in.old_nt_crypted->hash, checkHash.hash); - if (memcmp(checkHash.hash, nt_pwd.hash, 16) != 0) { - status = NT_STATUS_WRONG_PASSWORD; - goto update_login; - } - - /* The NT Cross is not required by Win2k3 R2, but if present - check the nt cross hash */ - if (r->in.cross1_present && r->in.nt_cross) { - D_P16(lm_pwd.hash, r->in.nt_cross->hash, checkHash.hash); - if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) { - status = NT_STATUS_WRONG_PASSWORD; - goto update_login; - } - } - - /* The LM Cross is not required by Win2k3 R2, but if present - check the lm cross hash */ - if (r->in.cross2_present && r->in.lm_cross) { - D_P16(nt_pwd.hash, r->in.lm_cross->hash, checkHash.hash); - if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) { - status = NT_STATUS_WRONG_PASSWORD; - goto update_login; - } - } - - if (!pdb_set_nt_passwd(pwd, new_ntPwdHash.hash, PDB_CHANGED) || - !pdb_set_lanman_passwd(pwd, new_lmPwdHash.hash, PDB_CHANGED)) { - status = NT_STATUS_ACCESS_DENIED; - goto out; - } - - status = pdb_update_sam_account(pwd); - -update_login: - - /* - * Notify passdb backend of login success/failure. If not - * NT_STATUS_OK the backend doesn't like the login - */ - update_login_attempts_status = pdb_update_login_attempts(pwd, - NT_STATUS_IS_OK(status)); - - if (!NT_STATUS_IS_OK(status)) { - bool increment_bad_pw_count = false; - - if (NT_STATUS_EQUAL(status,NT_STATUS_WRONG_PASSWORD) && - (pdb_get_acct_ctrl(pwd) & ACB_NORMAL) && - NT_STATUS_IS_OK(update_login_attempts_status)) - { - increment_bad_pw_count = true; - } - - if (increment_bad_pw_count) { - pdb_increment_bad_password_count(pwd); - updated_badpw = true; - } else { - pdb_update_bad_password_count(pwd, - &updated_badpw); - } - } else { - - if ((pdb_get_acct_ctrl(pwd) & ACB_NORMAL) && - (pdb_get_bad_password_count(pwd) > 0)){ - pdb_set_bad_password_count(pwd, 0, PDB_CHANGED); - pdb_set_bad_password_time(pwd, 0, PDB_CHANGED); - updated_badpw = true; - } - } - - if (updated_badpw) { - NTSTATUS update_status; - become_root(); - update_status = pdb_update_sam_account(pwd); - unbecome_root(); - - if (!NT_STATUS_IS_OK(update_status)) { - DEBUG(1, ("Failed to modify entry: %s\n", - nt_errstr(update_status))); - } - } - - out: - TALLOC_FREE(pwd); - - return status; + return NT_STATUS_NOT_IMPLEMENTED; } /******************************************************************* diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index f7f77534ee..63c2ad7cae 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2948,259 +2948,6 @@ static bool api_NetRemoteTOD(struct smbd_server_connection *sconn, } /**************************************************************************** - Set the user password. -*****************************************************************************/ - -static bool api_SetUserPassword(struct smbd_server_connection *sconn, - connection_struct *conn,uint64_t vuid, - char *param, int tpscnt, - char *data, int tdscnt, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *np = get_safe_str_ptr(param,tpscnt,param,2); - char *p = NULL; - fstring user; - fstring pass1,pass2; - TALLOC_CTX *mem_ctx = talloc_tos(); - NTSTATUS status, result; - struct rpc_pipe_client *cli = NULL; - struct policy_handle connect_handle, domain_handle, user_handle; - struct lsa_String domain_name; - struct dom_sid2 *domain_sid; - struct lsa_String names; - struct samr_Ids rids; - struct samr_Ids types; - struct samr_Password old_lm_hash; - struct samr_Password new_lm_hash; - int errcode = NERR_badpass; - uint32_t rid; - int encrypted; - int min_pwd_length; - struct dcerpc_binding_handle *b = NULL; - - /* Skip 2 strings. */ - p = skip_string(param,tpscnt,np); - p = skip_string(param,tpscnt,p); - - if (!np || !p) { - return False; - } - - /* Do we have a string ? */ - if (skip_string(param,tpscnt,p) == NULL) { - return False; - } - pull_ascii_fstring(user,p); - - p = skip_string(param,tpscnt,p); - if (!p) { - return False; - } - - memset(pass1,'\0',sizeof(pass1)); - memset(pass2,'\0',sizeof(pass2)); - /* - * We use 31 here not 32 as we're checking - * the last byte we want to access is safe. - */ - if (!is_offset_safe(param,tpscnt,p,31)) { - return False; - } - memcpy(pass1,p,16); - memcpy(pass2,p+16,16); - - encrypted = get_safe_SVAL(param,tpscnt,p+32,0,-1); - if (encrypted == -1) { - errcode = W_ERROR_V(WERR_INVALID_PARAM); - goto out; - } - - min_pwd_length = get_safe_SVAL(param,tpscnt,p+34,0,-1); - if (min_pwd_length == -1) { - errcode = W_ERROR_V(WERR_INVALID_PARAM); - goto out; - } - - *rparam_len = 4; - *rparam = smb_realloc_limit(*rparam,*rparam_len); - if (!*rparam) { - return False; - } - - *rdata_len = 0; - - DEBUG(3,("Set password for <%s> (encrypted: %d, min_pwd_length: %d)\n", - user, encrypted, min_pwd_length)); - - ZERO_STRUCT(connect_handle); - ZERO_STRUCT(domain_handle); - ZERO_STRUCT(user_handle); - - status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr, - conn->session_info, - conn->sconn->remote_address, - conn->sconn->msg_ctx, - &cli); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("api_SetUserPassword: could not connect to samr: %s\n", - nt_errstr(status))); - errcode = W_ERROR_V(ntstatus_to_werror(status)); - goto out; - } - - b = cli->binding_handle; - - status = dcerpc_samr_Connect2(b, mem_ctx, - lp_netbios_name(), - SAMR_ACCESS_CONNECT_TO_SERVER | - SAMR_ACCESS_ENUM_DOMAINS | - SAMR_ACCESS_LOOKUP_DOMAIN, - &connect_handle, - &result); - if (!NT_STATUS_IS_OK(status)) { - errcode = W_ERROR_V(ntstatus_to_werror(status)); - goto out; - } - if (!NT_STATUS_IS_OK(result)) { - errcode = W_ERROR_V(ntstatus_to_werror(result)); - goto out; - } - - init_lsa_String(&domain_name, get_global_sam_name()); - - status = dcerpc_samr_LookupDomain(b, mem_ctx, - &connect_handle, - &domain_name, - &domain_sid, - &result); - if (!NT_STATUS_IS_OK(status)) { - errcode = W_ERROR_V(ntstatus_to_werror(status)); - goto out; - } - if (!NT_STATUS_IS_OK(result)) { - errcode = W_ERROR_V(ntstatus_to_werror(result)); - goto out; - } - - status = dcerpc_samr_OpenDomain(b, mem_ctx, - &connect_handle, - SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, - domain_sid, - &domain_handle, - &result); - if (!NT_STATUS_IS_OK(status)) { - errcode = W_ERROR_V(ntstatus_to_werror(status)); - goto out; - } - if (!NT_STATUS_IS_OK(result)) { - errcode = W_ERROR_V(ntstatus_to_werror(result)); - goto out; - } - - init_lsa_String(&names, user); - - status = dcerpc_samr_LookupNames(b, mem_ctx, - &domain_handle, - 1, - &names, - &rids, - &types, - &result); - if (!NT_STATUS_IS_OK(status)) { - errcode = W_ERROR_V(ntstatus_to_werror(status)); - goto out; - } - if (!NT_STATUS_IS_OK(result)) { - errcode = W_ERROR_V(ntstatus_to_werror(result)); - goto out; - } - - if (rids.count != 1) { - errcode = W_ERROR_V(WERR_NO_SUCH_USER); - goto out; - } - if (rids.count != types.count) { - errcode = W_ERROR_V(WERR_INVALID_PARAM); - goto out; - } - if (types.ids[0] != SID_NAME_USER) { - errcode = W_ERROR_V(WERR_INVALID_PARAM); - goto out; - } - - rid = rids.ids[0]; - - status = dcerpc_samr_OpenUser(b, mem_ctx, - &domain_handle, - SAMR_USER_ACCESS_CHANGE_PASSWORD, - rid, - &user_handle, - &result); - if (!NT_STATUS_IS_OK(status)) { - errcode = W_ERROR_V(ntstatus_to_werror(status)); - goto out; - } - if (!NT_STATUS_IS_OK(result)) { - errcode = W_ERROR_V(ntstatus_to_werror(result)); - goto out; - } - - if (encrypted == 0) { - E_deshash(pass1, old_lm_hash.hash); - E_deshash(pass2, new_lm_hash.hash); - } else { - ZERO_STRUCT(old_lm_hash); - ZERO_STRUCT(new_lm_hash); - memcpy(old_lm_hash.hash, pass1, MIN(strlen(pass1), 16)); - memcpy(new_lm_hash.hash, pass2, MIN(strlen(pass2), 16)); - } - - status = dcerpc_samr_ChangePasswordUser(b, mem_ctx, - &user_handle, - true, /* lm_present */ - &old_lm_hash, - &new_lm_hash, - false, /* nt_present */ - NULL, /* old_nt_crypted */ - NULL, /* new_nt_crypted */ - false, /* cross1_present */ - NULL, /* nt_cross */ - false, /* cross2_present */ - NULL, /* lm_cross */ - &result); - if (!NT_STATUS_IS_OK(status)) { - errcode = W_ERROR_V(ntstatus_to_werror(status)); - goto out; - } - if (!NT_STATUS_IS_OK(result)) { - errcode = W_ERROR_V(ntstatus_to_werror(result)); - goto out; - } - - errcode = NERR_Success; - out: - - if (b && is_valid_policy_hnd(&user_handle)) { - dcerpc_samr_Close(b, mem_ctx, &user_handle, &result); - } - if (b && is_valid_policy_hnd(&domain_handle)) { - dcerpc_samr_Close(b, mem_ctx, &domain_handle, &result); - } - if (b && is_valid_policy_hnd(&connect_handle)) { - dcerpc_samr_Close(b, mem_ctx, &connect_handle, &result); - } - - memset((char *)pass1,'\0',sizeof(fstring)); - memset((char *)pass2,'\0',sizeof(fstring)); - - SSVAL(*rparam,0,errcode); - SSVAL(*rparam,2,0); /* converter word */ - return(True); -} - -/**************************************************************************** Set the user password (SamOEM version - gets plaintext). ****************************************************************************/ @@ -5797,7 +5544,6 @@ static const struct { {"NetServerEnum2", RAP_NetServerEnum2, api_RNetServerEnum2}, /* anon OK */ {"NetServerEnum3", RAP_NetServerEnum3, api_RNetServerEnum3}, /* anon OK */ {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms}, - {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword}, {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon}, {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo}, {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum}, diff --git a/source4/rpc_server/samr/samr_password.c b/source4/rpc_server/samr/samr_password.c index 2d9c48abd7..9d6c9212f4 100644 --- a/source4/rpc_server/samr/samr_password.c +++ b/source4/rpc_server/samr/samr_password.c @@ -33,150 +33,17 @@ /* samr_ChangePasswordUser + + So old it is just not worth implementing + because it does not supply a plaintext and so we can't do password + complexity checking and cannot update all the other password hashes. + */ NTSTATUS dcesrv_samr_ChangePasswordUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct samr_ChangePasswordUser *r) { - struct dcesrv_handle *h; - struct samr_account_state *a_state; - struct ldb_context *sam_ctx; - struct ldb_message **res; - int ret; - struct samr_Password new_lmPwdHash, new_ntPwdHash, checkHash; - struct samr_Password *lm_pwd, *nt_pwd; - NTSTATUS status = NT_STATUS_OK; - const char * const attrs[] = { "dBCSPwd", "unicodePwd" , NULL }; - - DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER); - - a_state = h->data; - - /* basic sanity checking on parameters. Do this before any database ops */ - if (!r->in.lm_present || !r->in.nt_present || - !r->in.old_lm_crypted || !r->in.new_lm_crypted || - !r->in.old_nt_crypted || !r->in.new_nt_crypted) { - /* we should really handle a change with lm not - present */ - return NT_STATUS_INVALID_PARAMETER_MIX; - } - - /* Connect to a SAMDB with system privileges for fetching the old pw - * hashes. */ - sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, - dce_call->conn->dce_ctx->lp_ctx, - system_session(dce_call->conn->dce_ctx->lp_ctx), 0); - if (sam_ctx == NULL) { - return NT_STATUS_INVALID_SYSTEM_SERVICE; - } - - /* fetch the old hashes */ - ret = gendb_search_dn(sam_ctx, mem_ctx, - a_state->account_dn, &res, attrs); - if (ret != 1) { - return NT_STATUS_WRONG_PASSWORD; - } - - status = samdb_result_passwords(mem_ctx, - dce_call->conn->dce_ctx->lp_ctx, - res[0], &lm_pwd, &nt_pwd); - if (!NT_STATUS_IS_OK(status) || !nt_pwd) { - return NT_STATUS_WRONG_PASSWORD; - } - - /* decrypt and check the new lm hash */ - if (lm_pwd) { - D_P16(lm_pwd->hash, r->in.new_lm_crypted->hash, new_lmPwdHash.hash); - D_P16(new_lmPwdHash.hash, r->in.old_lm_crypted->hash, checkHash.hash); - } - - /* decrypt and check the new nt hash */ - D_P16(nt_pwd->hash, r->in.new_nt_crypted->hash, new_ntPwdHash.hash); - D_P16(new_ntPwdHash.hash, r->in.old_nt_crypted->hash, checkHash.hash); - - /* The NT Cross is not required by Win2k3 R2, but if present - check the nt cross hash */ - if (r->in.cross1_present && r->in.nt_cross && lm_pwd) { - D_P16(lm_pwd->hash, r->in.nt_cross->hash, checkHash.hash); - } - - /* The LM Cross is not required by Win2k3 R2, but if present - check the lm cross hash */ - if (r->in.cross2_present && r->in.lm_cross && lm_pwd) { - D_P16(nt_pwd->hash, r->in.lm_cross->hash, checkHash.hash); - } - - /* Start a SAM with user privileges for the password change */ - sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, - dce_call->conn->dce_ctx->lp_ctx, - dce_call->conn->auth_state.session_info, 0); - if (sam_ctx == NULL) { - return NT_STATUS_INVALID_SYSTEM_SERVICE; - } - - /* Start transaction */ - ret = ldb_transaction_start(sam_ctx); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx))); - return NT_STATUS_TRANSACTION_ABORTED; - } - - /* Performs the password modification. We pass the old hashes read out - * from the database since they were already checked against the user- - * provided ones. */ - status = samdb_set_password(sam_ctx, mem_ctx, - a_state->account_dn, - a_state->domain_state->domain_dn, - NULL, &new_lmPwdHash, &new_ntPwdHash, - lm_pwd, nt_pwd, /* this is a user password change */ - NULL, - NULL); - if (!NT_STATUS_IS_OK(status)) { - ldb_transaction_cancel(sam_ctx); - return status; - } - - /* decrypt and check the new lm hash */ - if (lm_pwd) { - if (memcmp(checkHash.hash, lm_pwd, 16) != 0) { - ldb_transaction_cancel(sam_ctx); - return NT_STATUS_WRONG_PASSWORD; - } - } - - if (memcmp(checkHash.hash, nt_pwd, 16) != 0) { - ldb_transaction_cancel(sam_ctx); - return NT_STATUS_WRONG_PASSWORD; - } - - /* The NT Cross is not required by Win2k3 R2, but if present - check the nt cross hash */ - if (r->in.cross1_present && r->in.nt_cross && lm_pwd) { - if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) { - ldb_transaction_cancel(sam_ctx); - return NT_STATUS_WRONG_PASSWORD; - } - } - - /* The LM Cross is not required by Win2k3 R2, but if present - check the lm cross hash */ - if (r->in.cross2_present && r->in.lm_cross && lm_pwd) { - if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) { - ldb_transaction_cancel(sam_ctx); - return NT_STATUS_WRONG_PASSWORD; - } - } - - /* And this confirms it in a transaction commit */ - ret = ldb_transaction_commit(sam_ctx); - if (ret != LDB_SUCCESS) { - DEBUG(1,("Failed to commit transaction to change password on %s: %s\n", - ldb_dn_get_linearized(a_state->account_dn), - ldb_errstring(sam_ctx))); - return NT_STATUS_TRANSACTION_ABORTED; - } - - return NT_STATUS_OK; + return NT_STATUS_NOT_IMPLEMENTED; } /* diff --git a/source4/torture/rpc/samr.c b/source4/torture/rpc/samr.c index 6b6ffc30f1..c0d8039331 100644 --- a/source4/torture/rpc/samr.c +++ b/source4/torture/rpc/samr.c @@ -1758,6 +1758,12 @@ static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b, torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n", __location__, __FUNCTION__, oldpass, newpass, nt_errstr(r.out.result)); + + /* Do not proceed if this call has been removed */ + if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_NOT_IMPLEMENTED)) { + torture_skip(tctx, "ValidatePassword not supported by server\n"); + } + if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) { torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash"); |