The branch, master has been updated via 7fa2129... s3-lanman: parse encrypted and min_pwd_length in api_SetUserPassword(). via a17203b... s3-lanman: use samr for api_SetUserPassword(). from c1e8838... flags.h - fix comment for "GTYPE_SECURITY_UNIVERSAL_GROUP" constant
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 7fa2129db665331dcfd2f1849220ea3278252ce3 Author: Günther Deschner <g...@samba.org> Date: Tue May 11 02:24:43 2010 +0200 s3-lanman: parse encrypted and min_pwd_length in api_SetUserPassword(). Guenther commit a17203ba651eb643580e98aa67955eb23a374a3e Author: Günther Deschner <g...@samba.org> Date: Fri May 7 14:37:25 2010 +0200 s3-lanman: use samr for api_SetUserPassword(). Guenther ----------------------------------------------------------------------- Summary of changes: source3/smbd/lanman.c | 183 ++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 145 insertions(+), 38 deletions(-) Changeset truncated at 500 lines: diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 0d5cda7..8c4d60c 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -36,6 +36,7 @@ #include "../librpc/gen_ndr/srv_srvsvc.h" #include "../librpc/gen_ndr/rap.h" #include "../lib/util/binsearch.h" +#include "../libcli/auth/libcli_auth.h" #ifdef CHECK_TYPES #undef CHECK_TYPES @@ -2826,6 +2827,21 @@ static bool api_SetUserPassword(connection_struct *conn,uint16 vuid, char *p = NULL; fstring user; fstring pass1,pass2; + TALLOC_CTX *mem_ctx = talloc_tos(); + NTSTATUS status; + 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; /* Skip 2 strings. */ p = skip_string(param,tpscnt,np); @@ -2858,6 +2874,18 @@ static bool api_SetUserPassword(connection_struct *conn,uint16 vuid, 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) { @@ -2866,59 +2894,138 @@ static bool api_SetUserPassword(connection_struct *conn,uint16 vuid, *rdata_len = 0; - SSVAL(*rparam,0,NERR_badpass); - SSVAL(*rparam,2,0); /* converter word */ + DEBUG(3,("Set password for <%s> (encrypted: %d, min_pwd_length: %d)\n", + user, encrypted, min_pwd_length)); - DEBUG(3,("Set password for <%s>\n",user)); + ZERO_STRUCT(connect_handle); + ZERO_STRUCT(domain_handle); + ZERO_STRUCT(user_handle); - /* - * Attempt to verify the old password against smbpasswd entries - * Win98 clients send old and new password in plaintext for this call. - */ + status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id, + rpc_samr_dispatch, conn->server_info, + &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; + } - { - struct auth_serversupplied_info *server_info = NULL; - DATA_BLOB password = data_blob(pass1, strlen(pass1)+1); + status = rpccli_samr_Connect2(cli, mem_ctx, + global_myname(), + SAMR_ACCESS_CONNECT_TO_SERVER | + SAMR_ACCESS_ENUM_DOMAINS | + SAMR_ACCESS_LOOKUP_DOMAIN, + &connect_handle); + if (!NT_STATUS_IS_OK(status)) { + errcode = W_ERROR_V(ntstatus_to_werror(status)); + goto out; + } - if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) { + init_lsa_String(&domain_name, get_global_sam_name()); - become_root(); - if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) { - SSVAL(*rparam,0,NERR_Success); - } - unbecome_root(); + status = rpccli_samr_LookupDomain(cli, mem_ctx, + &connect_handle, + &domain_name, + &domain_sid); + if (!NT_STATUS_IS_OK(status)) { + errcode = W_ERROR_V(ntstatus_to_werror(status)); + goto out; + } - TALLOC_FREE(server_info); - } - data_blob_clear_free(&password); + status = rpccli_samr_OpenDomain(cli, mem_ctx, + &connect_handle, + SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, + domain_sid, + &domain_handle); + if (!NT_STATUS_IS_OK(status)) { + errcode = W_ERROR_V(ntstatus_to_werror(status)); + goto out; } - /* - * If the plaintext change failed, attempt - * the old encrypted method. NT will generate this - * after trying the samr method. Note that this - * method is done as a last resort as this - * password change method loses the NT password hash - * and cannot change the UNIX password as no plaintext - * is received. - */ + init_lsa_String(&names, user); - if(SVAL(*rparam,0) != NERR_Success) { - struct samu *hnd = NULL; + status = rpccli_samr_LookupNames(cli, mem_ctx, + &domain_handle, + 1, + &names, + &rids, + &types); + if (!NT_STATUS_IS_OK(status)) { + errcode = W_ERROR_V(ntstatus_to_werror(status)); + goto out; + } - if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) { - become_root(); - if (change_lanman_password(hnd,(uchar *)pass2)) { - SSVAL(*rparam,0,NERR_Success); - } - unbecome_root(); - TALLOC_FREE(hnd); - } + 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 = rpccli_samr_OpenUser(cli, mem_ctx, + &domain_handle, + SAMR_USER_ACCESS_CHANGE_PASSWORD, + rid, + &user_handle); + if (!NT_STATUS_IS_OK(status)) { + errcode = W_ERROR_V(ntstatus_to_werror(status)); + 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, pass1, MIN(strlen(pass2), 16)); + } + + status = rpccli_samr_ChangePasswordUser(cli, 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 */ + if (!NT_STATUS_IS_OK(status)) { + errcode = W_ERROR_V(ntstatus_to_werror(status)); + goto out; + } + + errcode = NERR_Success; + out: + + if (cli && is_valid_policy_hnd(&user_handle)) { + rpccli_samr_Close(cli, mem_ctx, &user_handle); + } + if (cli && is_valid_policy_hnd(&domain_handle)) { + rpccli_samr_Close(cli, mem_ctx, &domain_handle); + } + if (cli && is_valid_policy_hnd(&connect_handle)) { + rpccli_samr_Close(cli, mem_ctx, &connect_handle); } memset((char *)pass1,'\0',sizeof(fstring)); memset((char *)pass2,'\0',sizeof(fstring)); + SSVAL(*rparam,0,errcode); + SSVAL(*rparam,2,0); /* converter word */ return(True); } -- Samba Shared Repository