X-Git-Url: http://git.samba.org/samba.git/?p=ira%2Fwip.git;a=blobdiff_plain;f=source3%2Frpc_server%2Fsrv_samr_nt.c;h=0d87ad84ae71ca6cfc49f587dabdabf4d455b768;hp=c60d904b18293684f851665e9cfe7f0878c418ff;hb=b7925cb3f219b0502bb7d5ffff2dbda7bb4c2bda;hpb=7f113904eba5361d963075bcea7e36fd98ca34aa diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index c60d904b182..0d87ad84ae7 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -32,6 +32,7 @@ */ #include "includes.h" +#include "../libcli/auth/libcli_auth.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV @@ -48,9 +49,29 @@ #define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */ #define MAX_SAM_ENTRIES_W95 50 +struct samr_connect_info { + uint8_t dummy; +}; + +struct samr_domain_info { + struct dom_sid sid; + struct disp_info *disp_info; +}; + +struct samr_user_info { + struct dom_sid sid; +}; + +struct samr_group_info { + struct dom_sid sid; +}; + +struct samr_alias_info { + struct dom_sid sid; +}; + typedef struct disp_info { DOM_SID sid; /* identify which domain this is. */ - bool builtin_domain; /* Quick flag to check if this is the builtin domain. */ struct pdb_search *users; /* querydispinfo 1 and 4 */ struct pdb_search *machines; /* querydispinfo 2 */ struct pdb_search *groups; /* querydispinfo 3 and 5, enumgroups */ @@ -63,18 +84,6 @@ typedef struct disp_info { * handler. */ } DISP_INFO; -/* We keep a static list of these by SID as modern clients close down - all resources between each request in a complete enumeration. */ - -struct samr_info { - /* for use by the \PIPE\samr policy */ - DOM_SID sid; - bool builtin_domain; /* Quick flag to check if this is the builtin domain. */ - uint32 status; /* some sort of flag. best to record it. comes from opnum 0x39 */ - uint32 acc_granted; - DISP_INFO *disp_info; -}; - static const struct generic_mapping sam_generic_mapping = { GENERIC_RIGHTS_SAM_READ, GENERIC_RIGHTS_SAM_WRITE, @@ -220,36 +229,6 @@ done: return status; } -/******************************************************************* - Checks if access to a function can be granted -********************************************************************/ - -static NTSTATUS access_check_samr_function(uint32 acc_granted, uint32 acc_required, const char *debug) -{ - DEBUG(5,("%s: access check ((granted: %#010x; required: %#010x)\n", - debug, acc_granted, acc_required)); - - /* check the security descriptor first */ - - if ( (acc_granted&acc_required) == acc_required ) - return NT_STATUS_OK; - - /* give root a free pass */ - - if (geteuid() == sec_initial_uid()) { - - DEBUG(4,("%s: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n", - debug, acc_granted, acc_required)); - DEBUGADD(4,("but overwritten by euid == 0\n")); - - return NT_STATUS_OK; - } - - DEBUG(2,("%s: ACCESS DENIED (granted: %#010x; required: %#010x)\n", - debug, acc_granted, acc_required)); - - return NT_STATUS_ACCESS_DENIED; -} /******************************************************************* Map any MAXIMUM_ALLOWED_ACCESS request to a valid access set. @@ -297,7 +276,7 @@ static void map_max_allowed_access(const NT_USER_TOKEN *token, Fetch or create a dispinfo struct. ********************************************************************/ -static DISP_INFO *get_samr_dispinfo_by_sid(DOM_SID *psid) +static DISP_INFO *get_samr_dispinfo_by_sid(const struct dom_sid *psid) { /* * We do a static cache for DISP_INFO's here. Explanation can be found @@ -366,43 +345,6 @@ static DISP_INFO *get_samr_dispinfo_by_sid(DOM_SID *psid) return NULL; } -/******************************************************************* - Create a samr_info struct. -********************************************************************/ - -static int samr_info_destructor(struct samr_info *info); - -static struct samr_info *get_samr_info_by_sid(TALLOC_CTX *mem_ctx, - DOM_SID *psid) -{ - struct samr_info *info; - fstring sid_str; - - if (psid) { - sid_to_fstring(sid_str, psid); - } else { - fstrcpy(sid_str,"(NULL)"); - } - - if ((info = TALLOC_ZERO_P(mem_ctx, struct samr_info)) == NULL) { - return NULL; - } - talloc_set_destructor(info, samr_info_destructor); - - DEBUG(10,("get_samr_info_by_sid: created new info for sid %s\n", sid_str)); - if (psid) { - sid_copy( &info->sid, psid); - info->builtin_domain = sid_check_is_builtin(psid); - } else { - DEBUG(10,("get_samr_info_by_sid: created new info for NULL sid.\n")); - info->builtin_domain = False; - } - - info->disp_info = get_samr_dispinfo_by_sid(psid); - - return info; -} - /******************************************************************* Function to free the per SID data. ********************************************************************/ @@ -426,17 +368,6 @@ static void free_samr_cache(DISP_INFO *disp_info) unbecome_root(); } -static int samr_info_destructor(struct samr_info *info) -{ - /* Only free the dispinfo cache if no one bothered to set up - a timeout. */ - - if (info->disp_info && info->disp_info->cache_timeout_event == NULL) { - free_samr_cache(info->disp_info); - } - return 0; -} - /******************************************************************* Idle event handler. Throw away the disp info cache. ********************************************************************/ @@ -480,8 +411,10 @@ static void set_disp_info_cache_timeout(DISP_INFO *disp_info, time_t secs_fromno We must also remove the timeout handler. ********************************************************************/ -static void force_flush_samr_cache(DISP_INFO *disp_info) +static void force_flush_samr_cache(const struct dom_sid *sid) { + struct disp_info *disp_info = get_samr_dispinfo_by_sid(sid); + if ((disp_info == NULL) || (disp_info->cache_timeout_event == NULL)) { return; } @@ -511,7 +444,7 @@ static uint32 count_sam_users(struct disp_info *info, uint32 acct_flags) { struct samr_displayentry *entry; - if (info->builtin_domain) { + if (sid_check_is_builtin(&info->sid)) { /* No users in builtin. */ return 0; } @@ -535,7 +468,7 @@ static uint32 count_sam_groups(struct disp_info *info) { struct samr_displayentry *entry; - if (info->builtin_domain) { + if (sid_check_is_builtin(&info->sid)) { /* No groups in builtin. */ return 0; } @@ -596,7 +529,8 @@ NTSTATUS _samr_Close(pipes_struct *p, struct samr_Close *r) NTSTATUS _samr_OpenDomain(pipes_struct *p, struct samr_OpenDomain *r) { - struct samr_info *info; + struct samr_connect_info *cinfo; + struct samr_domain_info *dinfo; SEC_DESC *psd = NULL; uint32 acc_granted; uint32 des_access = r->in.access_mask; @@ -606,15 +540,11 @@ NTSTATUS _samr_OpenDomain(pipes_struct *p, /* find the connection policy handle. */ - if ( !find_policy_by_hnd(p, r->in.connect_handle, (void**)(void *)&info) ) - return NT_STATUS_INVALID_HANDLE; - - status = access_check_samr_function(info->acc_granted, - SAMR_ACCESS_OPEN_DOMAIN, - "_samr_OpenDomain" ); - - if ( !NT_STATUS_IS_OK(status) ) + cinfo = policy_handle_find(p, r->in.connect_handle, 0, NULL, + struct samr_connect_info, &status); + if (!NT_STATUS_IS_OK(status)) { return status; + } /*check if access can be granted as requested by client. */ map_max_allowed_access(p->server_info->ptok, &des_access); @@ -637,14 +567,13 @@ NTSTATUS _samr_OpenDomain(pipes_struct *p, return NT_STATUS_NO_SUCH_DOMAIN; } - /* associate the domain SID with the (unique) handle. */ - if ((info = get_samr_info_by_sid(p->mem_ctx, r->in.sid))==NULL) - return NT_STATUS_NO_MEMORY; - info->acc_granted = acc_granted; - - /* get a (unique) handle. open a policy on it. */ - if (!create_policy_hnd(p, r->out.domain_handle, info)) - return NT_STATUS_OBJECT_NAME_NOT_FOUND; + dinfo = policy_handle_create(p, r->out.domain_handle, acc_granted, + struct samr_domain_info, &status); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + dinfo->sid = *r->in.sid; + dinfo->disp_info = get_samr_dispinfo_by_sid(r->in.sid); DEBUG(5,("_samr_OpenDomain: %d\n", __LINE__)); @@ -658,7 +587,7 @@ NTSTATUS _samr_OpenDomain(pipes_struct *p, NTSTATUS _samr_GetUserPwInfo(pipes_struct *p, struct samr_GetUserPwInfo *r) { - struct samr_info *info = NULL; + struct samr_user_info *uinfo; enum lsa_SidType sid_type; uint32_t min_password_length = 0; uint32_t password_properties = 0; @@ -667,24 +596,19 @@ NTSTATUS _samr_GetUserPwInfo(pipes_struct *p, DEBUG(5,("_samr_GetUserPwInfo: %d\n", __LINE__)); - /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, r->in.user_handle, (void **)(void *)&info)) { - return NT_STATUS_INVALID_HANDLE; - } - - status = access_check_samr_function(info->acc_granted, - SAMR_USER_ACCESS_GET_ATTRIBUTES, - "_samr_GetUserPwInfo" ); + uinfo = policy_handle_find(p, r->in.user_handle, + SAMR_USER_ACCESS_GET_ATTRIBUTES, NULL, + struct samr_user_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } - if (!sid_check_is_in_our_domain(&info->sid)) { + if (!sid_check_is_in_our_domain(&uinfo->sid)) { return NT_STATUS_OBJECT_TYPE_MISMATCH; } become_root(); - ret = lookup_sid(p->mem_ctx, &info->sid, NULL, NULL, &sid_type); + ret = lookup_sid(p->mem_ctx, &uinfo->sid, NULL, NULL, &sid_type); unbecome_root(); if (ret == false) { return NT_STATUS_NO_SUCH_USER; @@ -716,31 +640,6 @@ NTSTATUS _samr_GetUserPwInfo(pipes_struct *p, return NT_STATUS_OK; } -/******************************************************************* -********************************************************************/ - -static bool get_lsa_policy_samr_sid( pipes_struct *p, struct policy_handle *pol, - DOM_SID *sid, uint32 *acc_granted, - DISP_INFO **ppdisp_info) -{ - struct samr_info *info = NULL; - - /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, pol, (void **)(void *)&info)) - return False; - - if (!info) - return False; - - *sid = info->sid; - *acc_granted = info->acc_granted; - if (ppdisp_info) { - *ppdisp_info = info->disp_info; - } - - return True; -} - /******************************************************************* _samr_SetSecurity ********************************************************************/ @@ -748,15 +647,19 @@ static bool get_lsa_policy_samr_sid( pipes_struct *p, struct policy_handle *pol, NTSTATUS _samr_SetSecurity(pipes_struct *p, struct samr_SetSecurity *r) { - DOM_SID pol_sid; - uint32 acc_granted, i; + struct samr_user_info *uinfo; + uint32 i; SEC_ACL *dacl; bool ret; struct samu *sampass=NULL; NTSTATUS status; - if (!get_lsa_policy_samr_sid(p, r->in.handle, &pol_sid, &acc_granted, NULL)) - return NT_STATUS_INVALID_HANDLE; + uinfo = policy_handle_find(p, r->in.handle, + SAMR_USER_ACCESS_SET_ATTRIBUTES, NULL, + struct samr_user_info, &status); + if (!NT_STATUS_IS_OK(status)) { + return status; + } if (!(sampass = samu_new( p->mem_ctx))) { DEBUG(0,("No memory!\n")); @@ -765,18 +668,19 @@ NTSTATUS _samr_SetSecurity(pipes_struct *p, /* get the user record */ become_root(); - ret = pdb_getsampwsid(sampass, &pol_sid); + ret = pdb_getsampwsid(sampass, &uinfo->sid); unbecome_root(); if (!ret) { - DEBUG(4, ("User %s not found\n", sid_string_dbg(&pol_sid))); + DEBUG(4, ("User %s not found\n", + sid_string_dbg(&uinfo->sid))); TALLOC_FREE(sampass); return NT_STATUS_INVALID_HANDLE; } dacl = r->in.sdbuf->sd->dacl; for (i=0; i < dacl->num_aces; i++) { - if (sid_equal(&pol_sid, &dacl->aces[i].trustee)) { + if (sid_equal(&uinfo->sid, &dacl->aces[i].trustee)) { ret = pdb_set_pass_can_change(sampass, (dacl->aces[i].access_mask & SAMR_USER_ACCESS_CHANGE_PASSWORD) ? @@ -790,14 +694,9 @@ NTSTATUS _samr_SetSecurity(pipes_struct *p, return NT_STATUS_ACCESS_DENIED; } - status = access_check_samr_function(acc_granted, - SAMR_USER_ACCESS_SET_ATTRIBUTES, - "_samr_SetSecurity"); - if (NT_STATUS_IS_OK(status)) { - become_root(); - status = pdb_update_sam_account(sampass); - unbecome_root(); - } + become_root(); + status = pdb_update_sam_account(sampass); + unbecome_root(); TALLOC_FREE(sampass); @@ -845,60 +744,99 @@ static bool check_change_pw_access(TALLOC_CTX *mem_ctx, DOM_SID *user_sid) NTSTATUS _samr_QuerySecurity(pipes_struct *p, struct samr_QuerySecurity *r) { + struct samr_connect_info *cinfo; + struct samr_domain_info *dinfo; + struct samr_user_info *uinfo; + struct samr_group_info *ginfo; + struct samr_alias_info *ainfo; NTSTATUS status; - DOM_SID pol_sid; SEC_DESC * psd = NULL; - uint32 acc_granted; size_t sd_size; - /* Get the SID. */ - if (!get_lsa_policy_samr_sid(p, r->in.handle, &pol_sid, &acc_granted, NULL)) - return NT_STATUS_INVALID_HANDLE; - - DEBUG(10,("_samr_QuerySecurity: querying security on SID: %s\n", - sid_string_dbg(&pol_sid))); - - status = access_check_samr_function(acc_granted, - STD_RIGHT_READ_CONTROL_ACCESS, - "_samr_QuerySecurity"); - if (!NT_STATUS_IS_OK(status)) { - return status; + cinfo = policy_handle_find(p, r->in.handle, + STD_RIGHT_READ_CONTROL_ACCESS, NULL, + struct samr_connect_info, &status); + if (NT_STATUS_IS_OK(status)) { + DEBUG(5,("_samr_QuerySecurity: querying security on SAM\n")); + status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, + &sam_generic_mapping, NULL, 0); + goto done; } - /* Check what typ of SID is beeing queried (e.g Domain SID, User SID, Group SID) */ - - /* To query the security of the SAM it self an invalid SID with S-0-0 is passed to this function */ - if (pol_sid.sid_rev_num == 0) { - DEBUG(5,("_samr_QuerySecurity: querying security on SAM\n")); - status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &sam_generic_mapping, NULL, 0); - } else if (sid_equal(&pol_sid,get_global_sam_sid())) { - /* check if it is our domain SID */ + dinfo = policy_handle_find(p, r->in.handle, + STD_RIGHT_READ_CONTROL_ACCESS, NULL, + struct samr_domain_info, &status); + if (NT_STATUS_IS_OK(status)) { DEBUG(5,("_samr_QuerySecurity: querying security on Domain " - "with SID: %s\n", sid_string_dbg(&pol_sid))); - status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &dom_generic_mapping, NULL, 0); - } else if (sid_equal(&pol_sid,&global_sid_Builtin)) { - /* check if it is the Builtin Domain */ - /* TODO: Builtin probably needs a different SD with restricted write access*/ - DEBUG(5,("_samr_QuerySecurity: querying security on Builtin " - "Domain with SID: %s\n", sid_string_dbg(&pol_sid))); - status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &dom_generic_mapping, NULL, 0); - } else if (sid_check_is_in_our_domain(&pol_sid) || - sid_check_is_in_builtin(&pol_sid)) { - /* TODO: different SDs have to be generated for aliases groups and users. - Currently all three get a default user SD */ - DEBUG(10,("_samr_QuerySecurity: querying security on Object " - "with SID: %s\n", sid_string_dbg(&pol_sid))); - if (check_change_pw_access(p->mem_ctx, &pol_sid)) { - status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_generic_mapping, - &pol_sid, SAMR_USR_RIGHTS_WRITE_PW); + "with SID: %s\n", sid_string_dbg(&dinfo->sid))); + /* + * TODO: Builtin probably needs a different SD with restricted + * write access + */ + status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, + &dom_generic_mapping, NULL, 0); + goto done; + } + + uinfo = policy_handle_find(p, r->in.handle, + STD_RIGHT_READ_CONTROL_ACCESS, NULL, + struct samr_user_info, &status); + if (NT_STATUS_IS_OK(status)) { + DEBUG(10,("_samr_QuerySecurity: querying security on user " + "Object with SID: %s\n", + sid_string_dbg(&uinfo->sid))); + if (check_change_pw_access(p->mem_ctx, &uinfo->sid)) { + status = make_samr_object_sd( + p->mem_ctx, &psd, &sd_size, + &usr_generic_mapping, + &uinfo->sid, SAMR_USR_RIGHTS_WRITE_PW); } else { - status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_nopwchange_generic_mapping, - &pol_sid, SAMR_USR_RIGHTS_CANT_WRITE_PW); + status = make_samr_object_sd( + p->mem_ctx, &psd, &sd_size, + &usr_nopwchange_generic_mapping, + &uinfo->sid, SAMR_USR_RIGHTS_CANT_WRITE_PW); } - } else { - return NT_STATUS_OBJECT_TYPE_MISMATCH; + goto done; + } + + ginfo = policy_handle_find(p, r->in.handle, + STD_RIGHT_READ_CONTROL_ACCESS, NULL, + struct samr_group_info, &status); + if (NT_STATUS_IS_OK(status)) { + /* + * TODO: different SDs have to be generated for aliases groups + * and users. Currently all three get a default user SD + */ + DEBUG(10,("_samr_QuerySecurity: querying security on group " + "Object with SID: %s\n", + sid_string_dbg(&ginfo->sid))); + status = make_samr_object_sd( + p->mem_ctx, &psd, &sd_size, + &usr_nopwchange_generic_mapping, + &ginfo->sid, SAMR_USR_RIGHTS_CANT_WRITE_PW); + goto done; + } + + ainfo = policy_handle_find(p, r->in.handle, + STD_RIGHT_READ_CONTROL_ACCESS, NULL, + struct samr_alias_info, &status); + if (NT_STATUS_IS_OK(status)) { + /* + * TODO: different SDs have to be generated for aliases groups + * and users. Currently all three get a default user SD + */ + DEBUG(10,("_samr_QuerySecurity: querying security on alias " + "Object with SID: %s\n", + sid_string_dbg(&ainfo->sid))); + status = make_samr_object_sd( + p->mem_ctx, &psd, &sd_size, + &usr_nopwchange_generic_mapping, + &ainfo->sid, SAMR_USR_RIGHTS_CANT_WRITE_PW); + goto done; } + return NT_STATUS_OBJECT_TYPE_MISMATCH; +done: if ((*r->out.sdbuf = make_sec_desc_buf(p->mem_ctx, sd_size, psd)) == NULL) return NT_STATUS_NO_MEMORY; @@ -963,7 +901,7 @@ NTSTATUS _samr_EnumDomainUsers(pipes_struct *p, struct samr_EnumDomainUsers *r) { NTSTATUS status; - struct samr_info *info = NULL; + struct samr_domain_info *dinfo; int num_account; uint32 enum_context = *r->in.resume_handle; enum remote_arch_types ra_type = get_remote_arch(); @@ -973,20 +911,16 @@ NTSTATUS _samr_EnumDomainUsers(pipes_struct *p, struct samr_SamArray *samr_array = NULL; struct samr_SamEntry *samr_entries = NULL; - /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, r->in.domain_handle, (void **)(void *)&info)) - return NT_STATUS_INVALID_HANDLE; + DEBUG(5,("_samr_EnumDomainUsers: %d\n", __LINE__)); - status = access_check_samr_function(info->acc_granted, - SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, - "_samr_EnumDomainUsers"); + dinfo = policy_handle_find(p, r->in.domain_handle, + SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, NULL, + struct samr_domain_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } - DEBUG(5,("_samr_EnumDomainUsers: %d\n", __LINE__)); - - if (info->builtin_domain) { + if (sid_check_is_builtin(&dinfo->sid)) { /* No users in builtin. */ *r->out.resume_handle = *r->in.resume_handle; DEBUG(5,("_samr_EnumDomainUsers: No users in BUILTIN\n")); @@ -1003,24 +937,24 @@ NTSTATUS _samr_EnumDomainUsers(pipes_struct *p, /* AS ROOT !!!! */ - if ((info->disp_info->enum_users != NULL) && - (info->disp_info->enum_acb_mask != r->in.acct_flags)) { - TALLOC_FREE(info->disp_info->enum_users); + if ((dinfo->disp_info->enum_users != NULL) && + (dinfo->disp_info->enum_acb_mask != r->in.acct_flags)) { + TALLOC_FREE(dinfo->disp_info->enum_users); } - if (info->disp_info->enum_users == NULL) { - info->disp_info->enum_users = pdb_search_users( - info->disp_info, r->in.acct_flags); - info->disp_info->enum_acb_mask = r->in.acct_flags; + if (dinfo->disp_info->enum_users == NULL) { + dinfo->disp_info->enum_users = pdb_search_users( + dinfo->disp_info, r->in.acct_flags); + dinfo->disp_info->enum_acb_mask = r->in.acct_flags; } - if (info->disp_info->enum_users == NULL) { + if (dinfo->disp_info->enum_users == NULL) { /* END AS ROOT !!!! */ unbecome_root(); return NT_STATUS_ACCESS_DENIED; } - num_account = pdb_search_entries(info->disp_info->enum_users, + num_account = pdb_search_entries(dinfo->disp_info->enum_users, enum_context, max_entries, &entries); @@ -1049,7 +983,7 @@ NTSTATUS _samr_EnumDomainUsers(pipes_struct *p, } /* Ensure we cache this enumeration. */ - set_disp_info_cache_timeout(info->disp_info, DISP_INFO_CACHE_TIMEOUT); + set_disp_info_cache_timeout(dinfo->disp_info, DISP_INFO_CACHE_TIMEOUT); DEBUG(5, ("_samr_EnumDomainUsers: %d\n", __LINE__)); @@ -1106,26 +1040,22 @@ NTSTATUS _samr_EnumDomainGroups(pipes_struct *p, struct samr_EnumDomainGroups *r) { NTSTATUS status; - struct samr_info *info = NULL; + struct samr_domain_info *dinfo; struct samr_displayentry *groups; uint32 num_groups; struct samr_SamArray *samr_array = NULL; struct samr_SamEntry *samr_entries = NULL; - /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, r->in.domain_handle, (void **)(void *)&info)) - return NT_STATUS_INVALID_HANDLE; - - status = access_check_samr_function(info->acc_granted, - SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, - "_samr_EnumDomainGroups"); + dinfo = policy_handle_find(p, r->in.domain_handle, + SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, NULL, + struct samr_domain_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } DEBUG(5,("_samr_EnumDomainGroups: %d\n", __LINE__)); - if (info->builtin_domain) { + if (sid_check_is_builtin(&dinfo->sid)) { /* No groups in builtin. */ *r->out.resume_handle = *r->in.resume_handle; DEBUG(5,("_samr_EnumDomainGroups: No groups in BUILTIN\n")); @@ -1141,22 +1071,22 @@ NTSTATUS _samr_EnumDomainGroups(pipes_struct *p, become_root(); - if (info->disp_info->groups == NULL) { - info->disp_info->groups = pdb_search_groups(info->disp_info); + if (dinfo->disp_info->groups == NULL) { + dinfo->disp_info->groups = pdb_search_groups(dinfo->disp_info); - if (info->disp_info->groups == NULL) { + if (dinfo->disp_info->groups == NULL) { unbecome_root(); return NT_STATUS_ACCESS_DENIED; } } - num_groups = pdb_search_entries(info->disp_info->groups, + num_groups = pdb_search_entries(dinfo->disp_info->groups, *r->in.resume_handle, MAX_SAM_ENTRIES, &groups); unbecome_root(); /* Ensure we cache this enumeration. */ - set_disp_info_cache_timeout(info->disp_info, DISP_INFO_CACHE_TIMEOUT); + set_disp_info_cache_timeout(dinfo->disp_info, DISP_INFO_CACHE_TIMEOUT); make_group_sam_entry_list(p->mem_ctx, &samr_entries, num_groups, groups); @@ -1181,26 +1111,22 @@ NTSTATUS _samr_EnumDomainAliases(pipes_struct *p, struct samr_EnumDomainAliases *r) { NTSTATUS status; - struct samr_info *info; + struct samr_domain_info *dinfo; struct samr_displayentry *aliases; uint32 num_aliases = 0; struct samr_SamArray *samr_array = NULL; struct samr_SamEntry *samr_entries = NULL; - /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, r->in.domain_handle, (void **)(void *)&info)) - return NT_STATUS_INVALID_HANDLE; - - DEBUG(5,("_samr_EnumDomainAliases: sid %s\n", - sid_string_dbg(&info->sid))); - - status = access_check_samr_function(info->acc_granted, - SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, - "_samr_EnumDomainAliases"); + dinfo = policy_handle_find(p, r->in.domain_handle, + SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, NULL, + struct samr_domain_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + DEBUG(5,("_samr_EnumDomainAliases: sid %s\n", + sid_string_dbg(&dinfo->sid))); + samr_array = TALLOC_ZERO_P(p->mem_ctx, struct samr_SamArray); if (!samr_array) { return NT_STATUS_NO_MEMORY; @@ -1208,22 +1134,22 @@ NTSTATUS _samr_EnumDomainAliases(pipes_struct *p, become_root(); - if (info->disp_info->aliases == NULL) { - info->disp_info->aliases = pdb_search_aliases( - info->disp_info, &info->sid); - if (info->disp_info->aliases == NULL) { + if (dinfo->disp_info->aliases == NULL) { + dinfo->disp_info->aliases = pdb_search_aliases( + dinfo->disp_info, &dinfo->sid); + if (dinfo->disp_info->aliases == NULL) { unbecome_root(); return NT_STATUS_ACCESS_DENIED; } } - num_aliases = pdb_search_entries(info->disp_info->aliases, + num_aliases = pdb_search_entries(dinfo->disp_info->aliases, *r->in.resume_handle, MAX_SAM_ENTRIES, &aliases); unbecome_root(); /* Ensure we cache this enumeration. */ - set_disp_info_cache_timeout(info->disp_info, DISP_INFO_CACHE_TIMEOUT); + set_disp_info_cache_timeout(dinfo->disp_info, DISP_INFO_CACHE_TIMEOUT); make_group_sam_entry_list(p->mem_ctx, &samr_entries, num_aliases, aliases); @@ -1446,7 +1372,7 @@ NTSTATUS _samr_QueryDisplayInfo(pipes_struct *p, struct samr_QueryDisplayInfo *r) { NTSTATUS status; - struct samr_info *info = NULL; + struct samr_domain_info *dinfo; uint32 struct_size=0x20; /* W2K always reply that, client doesn't care */ uint32 max_entries = r->in.max_entries; @@ -1464,22 +1390,18 @@ NTSTATUS _samr_QueryDisplayInfo(pipes_struct *p, DEBUG(5,("_samr_QueryDisplayInfo: %d\n", __LINE__)); - /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, r->in.domain_handle, (void **)(void *)&info)) - return NT_STATUS_INVALID_HANDLE; - - if (info->builtin_domain) { - DEBUG(5,("_samr_QueryDisplayInfo: Nothing in BUILTIN\n")); - return NT_STATUS_OK; - } - - status = access_check_samr_function(info->acc_granted, - SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, - "_samr_QueryDisplayInfo"); + dinfo = policy_handle_find(p, r->in.domain_handle, + SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, NULL, + struct samr_domain_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + if (sid_check_is_builtin(&dinfo->sid)) { + DEBUG(5,("_samr_QueryDisplayInfo: no users in BUILTIN\n")); + return NT_STATUS_OK; + } + /* * calculate how many entries we will return. * based on @@ -1540,10 +1462,10 @@ NTSTATUS _samr_QueryDisplayInfo(pipes_struct *p, switch (r->in.level) { case 0x1: case 0x4: - if (info->disp_info->users == NULL) { - info->disp_info->users = pdb_search_users( - info->disp_info, ACB_NORMAL); - if (info->disp_info->users == NULL) { + if (dinfo->disp_info->users == NULL) { + dinfo->disp_info->users = pdb_search_users( + dinfo->disp_info, ACB_NORMAL); + if (dinfo->disp_info->users == NULL) { unbecome_root(); return NT_STATUS_ACCESS_DENIED; } @@ -1554,15 +1476,15 @@ NTSTATUS _samr_QueryDisplayInfo(pipes_struct *p, (unsigned int)enum_context )); } - num_account = pdb_search_entries(info->disp_info->users, + num_account = pdb_search_entries(dinfo->disp_info->users, enum_context, max_entries, &entries); break; case 0x2: - if (info->disp_info->machines == NULL) { - info->disp_info->machines = pdb_search_users( - info->disp_info, ACB_WSTRUST|ACB_SVRTRUST); - if (info->disp_info->machines == NULL) { + if (dinfo->disp_info->machines == NULL) { + dinfo->disp_info->machines = pdb_search_users( + dinfo->disp_info, ACB_WSTRUST|ACB_SVRTRUST); + if (dinfo->disp_info->machines == NULL) { unbecome_root(); return NT_STATUS_ACCESS_DENIED; } @@ -1573,16 +1495,16 @@ NTSTATUS _samr_QueryDisplayInfo(pipes_struct *p, (unsigned int)enum_context )); } - num_account = pdb_search_entries(info->disp_info->machines, + num_account = pdb_search_entries(dinfo->disp_info->machines, enum_context, max_entries, &entries); break; case 0x3: case 0x5: - if (info->disp_info->groups == NULL) { - info->disp_info->groups = pdb_search_groups( - info->disp_info); - if (info->disp_info->groups == NULL) { + if (dinfo->disp_info->groups == NULL) { + dinfo->disp_info->groups = pdb_search_groups( + dinfo->disp_info); + if (dinfo->disp_info->groups == NULL) { unbecome_root(); return NT_STATUS_ACCESS_DENIED; } @@ -1593,7 +1515,7 @@ NTSTATUS _samr_QueryDisplayInfo(pipes_struct *p, (unsigned int)enum_context )); } - num_account = pdb_search_entries(info->disp_info->groups, + num_account = pdb_search_entries(dinfo->disp_info->groups, enum_context, max_entries, &entries); break; @@ -1650,7 +1572,7 @@ NTSTATUS _samr_QueryDisplayInfo(pipes_struct *p, } /* Ensure we cache this enumeration. */ - set_disp_info_cache_timeout(info->disp_info, DISP_INFO_CACHE_TIMEOUT); + set_disp_info_cache_timeout(dinfo->disp_info, DISP_INFO_CACHE_TIMEOUT); DEBUG(5, ("_samr_QueryDisplayInfo: %d\n", __LINE__)); @@ -1711,9 +1633,8 @@ NTSTATUS _samr_QueryDisplayInfo3(pipes_struct *p, NTSTATUS _samr_QueryAliasInfo(pipes_struct *p, struct samr_QueryAliasInfo *r) { - DOM_SID sid; + struct samr_alias_info *ainfo; struct acct_info info; - uint32 acc_granted; NTSTATUS status; union samr_AliasInfo *alias_info = NULL; const char *alias_name = NULL; @@ -1721,24 +1642,20 @@ NTSTATUS _samr_QueryAliasInfo(pipes_struct *p, DEBUG(5,("_samr_QueryAliasInfo: %d\n", __LINE__)); + ainfo = policy_handle_find(p, r->in.alias_handle, + SAMR_ALIAS_ACCESS_LOOKUP_INFO, NULL, + struct samr_alias_info, &status); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + alias_info = TALLOC_ZERO_P(p->mem_ctx, union samr_AliasInfo); if (!alias_info) { return NT_STATUS_NO_MEMORY; } - /* find the policy handle. open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, r->in.alias_handle, &sid, &acc_granted, NULL)) - return NT_STATUS_INVALID_HANDLE; - - status = access_check_samr_function(acc_granted, - SAMR_ALIAS_ACCESS_LOOKUP_INFO, - "_samr_QueryAliasInfo"); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - become_root(); - status = pdb_get_aliasinfo(&sid, &info); + status = pdb_get_aliasinfo(&ainfo->sid, &info); unbecome_root(); if ( !NT_STATUS_IS_OK(status)) @@ -1754,6 +1671,9 @@ NTSTATUS _samr_QueryAliasInfo(pipes_struct *p, alias_info->all.num_members = 1; /* ??? */ alias_info->all.description.string = alias_description; break; + case ALIASINFONAME: + alias_info->name.string = alias_name; + break; case ALIASINFODESCRIPTION: alias_info->description.string = alias_description; break; @@ -1775,25 +1695,20 @@ NTSTATUS _samr_QueryAliasInfo(pipes_struct *p, NTSTATUS _samr_LookupNames(pipes_struct *p, struct samr_LookupNames *r) { + struct samr_domain_info *dinfo; NTSTATUS status; uint32 *rid; enum lsa_SidType *type; int i; int num_rids = r->in.num_names; - DOM_SID pol_sid; - uint32 acc_granted; struct samr_Ids rids, types; uint32_t num_mapped = 0; DEBUG(5,("_samr_LookupNames: %d\n", __LINE__)); - if (!get_lsa_policy_samr_sid(p, r->in.domain_handle, &pol_sid, &acc_granted, NULL)) { - return NT_STATUS_OBJECT_TYPE_MISMATCH; - } - - status = access_check_samr_function(acc_granted, - 0, /* Don't know the acc_bits yet */ - "_samr_LookupNames"); + dinfo = policy_handle_find(p, r->in.domain_handle, + 0 /* Don't know the acc_bits yet */, NULL, + struct samr_domain_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -1810,7 +1725,7 @@ NTSTATUS _samr_LookupNames(pipes_struct *p, NT_STATUS_HAVE_NO_MEMORY(type); DEBUG(5,("_samr_LookupNames: looking name on SID %s\n", - sid_string_dbg(&pol_sid))); + sid_string_dbg(&dinfo->sid))); for (i = 0; i < num_rids; i++) { @@ -1819,7 +1734,7 @@ NTSTATUS _samr_LookupNames(pipes_struct *p, rid[i] = 0xffffffff; - if (sid_check_is_builtin(&pol_sid)) { + if (sid_check_is_builtin(&dinfo->sid)) { if (lookup_builtin_name(r->in.names[i].string, &rid[i])) { @@ -1857,6 +1772,117 @@ NTSTATUS _samr_LookupNames(pipes_struct *p, return status; } +/**************************************************************** + _samr_ChangePasswordUser +****************************************************************/ + +NTSTATUS _samr_ChangePasswordUser(pipes_struct *p, + struct samr_ChangePasswordUser *r) +{ + NTSTATUS status; + bool ret = false; + struct samr_user_info *uinfo; + struct samu *pwd; + struct samr_Password new_lmPwdHash, new_ntPwdHash, checkHash; + struct samr_Password lm_pwd, nt_pwd; + + 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))); + + 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; + } + + { + 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 out; + } + + memcpy(&lm_pwd.hash, lm_pass, sizeof(lm_pwd.hash)); + memcpy(&nt_pwd.hash, nt_pass, sizeof(nt_pwd.hash)); + } + + /* 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 */ + status = NT_STATUS_INVALID_PARAMETER_MIX; + goto out; + } + + /* 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 out; + } + + /* 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 out; + } + + /* 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 out; + } + } + + /* 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 out; + } + } + + 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); + out: + TALLOC_FREE(pwd); + + return status; +} + /******************************************************************* _samr_ChangePasswordUser2 ********************************************************************/ @@ -1896,32 +1922,32 @@ NTSTATUS _samr_ChangePasswordUser2(pipes_struct *p, DEBUG(5,("_samr_ChangePasswordUser2: %d\n", __LINE__)); + if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) { + return NT_STATUS_WRONG_PASSWORD; + } + return status; } -/******************************************************************* - _samr_ChangePasswordUser3 - ********************************************************************/ +/**************************************************************** + _samr_OemChangePasswordUser2 +****************************************************************/ -NTSTATUS _samr_ChangePasswordUser3(pipes_struct *p, - struct samr_ChangePasswordUser3 *r) +NTSTATUS _samr_OemChangePasswordUser2(pipes_struct *p, + struct samr_OemChangePasswordUser2 *r) { NTSTATUS status; fstring user_name; const char *wks = NULL; - uint32 reject_reason; - struct samr_DomInfo1 *dominfo = NULL; - struct samr_ChangeReject *reject = NULL; - uint32_t tmp; - DEBUG(5,("_samr_ChangePasswordUser3: %d\n", __LINE__)); + DEBUG(5,("_samr_OemChangePasswordUser2: %d\n", __LINE__)); fstrcpy(user_name, r->in.account->string); if (r->in.server && r->in.server->string) { wks = r->in.server->string; } - DEBUG(5,("_samr_ChangePasswordUser3: user: %s wks: %s\n", user_name, wks)); + DEBUG(5,("_samr_OemChangePasswordUser2: user: %s wks: %s\n", user_name, wks)); /* * Pass the user through the NT -> unix user mapping @@ -1935,23 +1961,82 @@ NTSTATUS _samr_ChangePasswordUser3(pipes_struct *p, * is case insensitive. */ - status = pass_oem_change(user_name, - r->in.lm_password->data, - r->in.lm_verifier->hash, - r->in.nt_password->data, - r->in.nt_verifier->hash, - &reject_reason); + if (!r->in.hash || !r->in.password) { + return NT_STATUS_INVALID_PARAMETER; + } - if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) || - NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_RESTRICTION)) { + status = pass_oem_change(user_name, + r->in.password->data, + r->in.hash->hash, + 0, + 0, + NULL); - time_t u_expire, u_min_age; - uint32 account_policy_temp; + if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) { + return NT_STATUS_WRONG_PASSWORD; + } - dominfo = TALLOC_ZERO_P(p->mem_ctx, struct samr_DomInfo1); - if (!dominfo) { - return NT_STATUS_NO_MEMORY; - } + DEBUG(5,("_samr_OemChangePasswordUser2: %d\n", __LINE__)); + + return status; +} + +/******************************************************************* + _samr_ChangePasswordUser3 + ********************************************************************/ + +NTSTATUS _samr_ChangePasswordUser3(pipes_struct *p, + struct samr_ChangePasswordUser3 *r) +{ + NTSTATUS status; + fstring user_name; + const char *wks = NULL; + uint32 reject_reason; + struct samr_DomInfo1 *dominfo = NULL; + struct samr_ChangeReject *reject = NULL; + uint32_t tmp; + + DEBUG(5,("_samr_ChangePasswordUser3: %d\n", __LINE__)); + + fstrcpy(user_name, r->in.account->string); + if (r->in.server && r->in.server->string) { + wks = r->in.server->string; + } + + DEBUG(5,("_samr_ChangePasswordUser3: user: %s wks: %s\n", user_name, wks)); + + /* + * Pass the user through the NT -> unix user mapping + * function. + */ + + (void)map_username(user_name); + + /* + * UNIX username case mangling not required, pass_oem_change + * is case insensitive. + */ + + status = pass_oem_change(user_name, + r->in.lm_password->data, + r->in.lm_verifier->hash, + r->in.nt_password->data, + r->in.nt_verifier->hash, + &reject_reason); + if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) { + return NT_STATUS_WRONG_PASSWORD; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) || + NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_RESTRICTION)) { + + time_t u_expire, u_min_age; + uint32 account_policy_temp; + + dominfo = TALLOC_ZERO_P(p->mem_ctx, struct samr_DomInfo1); + if (!dominfo) { + return NT_STATUS_NO_MEMORY; + } reject = TALLOC_ZERO_P(p->mem_ctx, struct samr_ChangeReject); if (!reject) { @@ -2036,13 +2121,12 @@ static bool make_samr_lookup_rids(TALLOC_CTX *ctx, uint32 num_names, NTSTATUS _samr_LookupRids(pipes_struct *p, struct samr_LookupRids *r) { + struct samr_domain_info *dinfo; NTSTATUS status; const char **names; enum lsa_SidType *attrs = NULL; uint32 *wire_attrs = NULL; - DOM_SID pol_sid; int num_rids = (int)r->in.num_rids; - uint32 acc_granted; int i; struct lsa_Strings names_array; struct samr_Ids types_array; @@ -2050,13 +2134,9 @@ NTSTATUS _samr_LookupRids(pipes_struct *p, DEBUG(5,("_samr_LookupRids: %d\n", __LINE__)); - /* find the policy handle. open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, r->in.domain_handle, &pol_sid, &acc_granted, NULL)) - return NT_STATUS_INVALID_HANDLE; - - status = access_check_samr_function(acc_granted, - 0, /* Don't know the acc_bits yet */ - "_samr_LookupRids"); + dinfo = policy_handle_find(p, r->in.domain_handle, + 0 /* Don't know the acc_bits yet */, NULL, + struct samr_domain_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -2081,7 +2161,7 @@ NTSTATUS _samr_LookupRids(pipes_struct *p, } become_root(); /* lookup_sid can require root privs */ - status = pdb_lookup_rids(&pol_sid, num_rids, r->in.rids, + status = pdb_lookup_rids(&dinfo->sid, num_rids, r->in.rids, names, attrs); unbecome_root(); @@ -2122,7 +2202,8 @@ NTSTATUS _samr_OpenUser(pipes_struct *p, { struct samu *sampass=NULL; DOM_SID sid; - struct samr_info *info = NULL; + struct samr_domain_info *dinfo; + struct samr_user_info *uinfo; SEC_DESC *psd = NULL; uint32 acc_granted; uint32 des_access = r->in.access_mask; @@ -2130,18 +2211,14 @@ NTSTATUS _samr_OpenUser(pipes_struct *p, bool ret; NTSTATUS nt_status; SE_PRIV se_rights; + NTSTATUS status; - /* find the domain policy handle and get domain SID / access bits in the domain policy. */ - - if ( !get_lsa_policy_samr_sid(p, r->in.domain_handle, &sid, &acc_granted, NULL) ) - return NT_STATUS_INVALID_HANDLE; - - nt_status = access_check_samr_function(acc_granted, - SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, - "_samr_OpenUser" ); - - if ( !NT_STATUS_IS_OK(nt_status) ) - return nt_status; + dinfo = policy_handle_find(p, r->in.domain_handle, + SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, NULL, + struct samr_domain_info, &status); + if (!NT_STATUS_IS_OK(status)) { + return status; + } if ( !(sampass = samu_new( p->mem_ctx )) ) { return NT_STATUS_NO_MEMORY; @@ -2149,7 +2226,7 @@ NTSTATUS _samr_OpenUser(pipes_struct *p, /* append the user's RID to it */ - if (!sid_append_rid(&sid, r->in.rid)) + if (!sid_compose(&sid, &dinfo->sid, r->in.rid)) return NT_STATUS_NO_SUCH_USER; /* check if access can be granted as requested by client. */ @@ -2180,14 +2257,12 @@ NTSTATUS _samr_OpenUser(pipes_struct *p, TALLOC_FREE(sampass); - /* associate the user's SID and access bits with the new handle. */ - if ((info = get_samr_info_by_sid(p->mem_ctx, &sid)) == NULL) - return NT_STATUS_NO_MEMORY; - info->acc_granted = acc_granted; - - /* get a (unique) handle. open a policy on it. */ - if (!create_policy_hnd(p, r->out.user_handle, info)) - return NT_STATUS_OBJECT_NAME_NOT_FOUND; + uinfo = policy_handle_create(p, r->out.user_handle, acc_granted, + struct samr_user_info, &nt_status); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + uinfo->sid = sid; return NT_STATUS_OK; } @@ -2227,6 +2302,130 @@ static NTSTATUS init_samr_parameters_string(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } +/************************************************************************* + get_user_info_1. + *************************************************************************/ + +static NTSTATUS get_user_info_1(TALLOC_CTX *mem_ctx, + struct samr_UserInfo1 *r, + struct samu *pw, + DOM_SID *domain_sid) +{ + const DOM_SID *sid_group; + uint32_t primary_gid; + + become_root(); + sid_group = pdb_get_group_sid(pw); + unbecome_root(); + + if (!sid_peek_check_rid(domain_sid, sid_group, &primary_gid)) { + DEBUG(0, ("get_user_info_1: User %s has Primary Group SID %s, \n" + "which conflicts with the domain sid %s. Failing operation.\n", + pdb_get_username(pw), sid_string_dbg(sid_group), + sid_string_dbg(domain_sid))); + return NT_STATUS_UNSUCCESSFUL; + } + + r->account_name.string = talloc_strdup(mem_ctx, pdb_get_username(pw)); + r->full_name.string = talloc_strdup(mem_ctx, pdb_get_fullname(pw)); + r->primary_gid = primary_gid; + r->description.string = talloc_strdup(mem_ctx, pdb_get_acct_desc(pw)); + r->comment.string = talloc_strdup(mem_ctx, pdb_get_comment(pw)); + + return NT_STATUS_OK; +} + +/************************************************************************* + get_user_info_2. + *************************************************************************/ + +static NTSTATUS get_user_info_2(TALLOC_CTX *mem_ctx, + struct samr_UserInfo2 *r, + struct samu *pw) +{ + r->comment.string = talloc_strdup(mem_ctx, pdb_get_comment(pw)); + r->unknown.string = NULL; + r->country_code = 0; + r->code_page = 0; + + return NT_STATUS_OK; +} + +/************************************************************************* + get_user_info_3. + *************************************************************************/ + +static NTSTATUS get_user_info_3(TALLOC_CTX *mem_ctx, + struct samr_UserInfo3 *r, + struct samu *pw, + DOM_SID *domain_sid) +{ + const DOM_SID *sid_user, *sid_group; + uint32_t rid, primary_gid; + + sid_user = pdb_get_user_sid(pw); + + if (!sid_peek_check_rid(domain_sid, sid_user, &rid)) { + DEBUG(0, ("get_user_info_3: User %s has SID %s, \nwhich conflicts with " + "the domain sid %s. Failing operation.\n", + pdb_get_username(pw), sid_string_dbg(sid_user), + sid_string_dbg(domain_sid))); + return NT_STATUS_UNSUCCESSFUL; + } + + become_root(); + sid_group = pdb_get_group_sid(pw); + unbecome_root(); + + if (!sid_peek_check_rid(domain_sid, sid_group, &primary_gid)) { + DEBUG(0, ("get_user_info_3: User %s has Primary Group SID %s, \n" + "which conflicts with the domain sid %s. Failing operation.\n", + pdb_get_username(pw), sid_string_dbg(sid_group), + sid_string_dbg(domain_sid))); + return NT_STATUS_UNSUCCESSFUL; + } + + unix_to_nt_time(&r->last_logon, pdb_get_logon_time(pw)); + unix_to_nt_time(&r->last_logoff, pdb_get_logoff_time(pw)); + unix_to_nt_time(&r->last_password_change, pdb_get_pass_last_set_time(pw)); + unix_to_nt_time(&r->allow_password_change, pdb_get_pass_can_change_time(pw)); + unix_to_nt_time(&r->force_password_change, pdb_get_pass_must_change_time(pw)); + + r->account_name.string = talloc_strdup(mem_ctx, pdb_get_username(pw)); + r->full_name.string = talloc_strdup(mem_ctx, pdb_get_fullname(pw)); + r->home_directory.string= talloc_strdup(mem_ctx, pdb_get_homedir(pw)); + r->home_drive.string = talloc_strdup(mem_ctx, pdb_get_dir_drive(pw)); + r->logon_script.string = talloc_strdup(mem_ctx, pdb_get_logon_script(pw)); + r->profile_path.string = talloc_strdup(mem_ctx, pdb_get_profile_path(pw)); + r->workstations.string = talloc_strdup(mem_ctx, pdb_get_workstations(pw)); + + r->logon_hours = get_logon_hours_from_pdb(mem_ctx, pw); + r->rid = rid; + r->primary_gid = primary_gid; + r->acct_flags = pdb_get_acct_ctrl(pw); + r->bad_password_count = pdb_get_bad_password_count(pw); + r->logon_count = pdb_get_logon_count(pw); + + return NT_STATUS_OK; +} + +/************************************************************************* + get_user_info_4. + *************************************************************************/ + +static NTSTATUS get_user_info_4(TALLOC_CTX *mem_ctx, + struct samr_UserInfo4 *r, + struct samu *pw) +{ + r->logon_hours = get_logon_hours_from_pdb(mem_ctx, pw); + + return NT_STATUS_OK; +} + +/************************************************************************* + get_user_info_5. + *************************************************************************/ + static NTSTATUS get_user_info_5(TALLOC_CTX *mem_ctx, struct samr_UserInfo5 *r, struct samu *pw, @@ -2281,6 +2480,20 @@ static NTSTATUS get_user_info_5(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } +/************************************************************************* + get_user_info_6. + *************************************************************************/ + +static NTSTATUS get_user_info_6(TALLOC_CTX *mem_ctx, + struct samr_UserInfo6 *r, + struct samu *pw) +{ + r->account_name.string = talloc_strdup(mem_ctx, pdb_get_username(pw)); + r->full_name.string = talloc_strdup(mem_ctx, pdb_get_fullname(pw)); + + return NT_STATUS_OK; +} + /************************************************************************* get_user_info_7. Safe. Only gives out account_name. *************************************************************************/ @@ -2297,6 +2510,19 @@ static NTSTATUS get_user_info_7(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } +/************************************************************************* + get_user_info_8. + *************************************************************************/ + +static NTSTATUS get_user_info_8(TALLOC_CTX *mem_ctx, + struct samr_UserInfo8 *r, + struct samu *pw) +{ + r->full_name.string = talloc_strdup(mem_ctx, pdb_get_fullname(pw)); + + return NT_STATUS_OK; +} + /************************************************************************* get_user_info_9. Only gives out primary group SID. *************************************************************************/ @@ -2310,6 +2536,72 @@ static NTSTATUS get_user_info_9(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } +/************************************************************************* + get_user_info_10. + *************************************************************************/ + +static NTSTATUS get_user_info_10(TALLOC_CTX *mem_ctx, + struct samr_UserInfo10 *r, + struct samu *pw) +{ + r->home_directory.string= talloc_strdup(mem_ctx, pdb_get_homedir(pw)); + r->home_drive.string = talloc_strdup(mem_ctx, pdb_get_dir_drive(pw)); + + return NT_STATUS_OK; +} + +/************************************************************************* + get_user_info_11. + *************************************************************************/ + +static NTSTATUS get_user_info_11(TALLOC_CTX *mem_ctx, + struct samr_UserInfo11 *r, + struct samu *pw) +{ + r->logon_script.string = talloc_strdup(mem_ctx, pdb_get_logon_script(pw)); + + return NT_STATUS_OK; +} + +/************************************************************************* + get_user_info_12. + *************************************************************************/ + +static NTSTATUS get_user_info_12(TALLOC_CTX *mem_ctx, + struct samr_UserInfo12 *r, + struct samu *pw) +{ + r->profile_path.string = talloc_strdup(mem_ctx, pdb_get_profile_path(pw)); + + return NT_STATUS_OK; +} + +/************************************************************************* + get_user_info_13. + *************************************************************************/ + +static NTSTATUS get_user_info_13(TALLOC_CTX *mem_ctx, + struct samr_UserInfo13 *r, + struct samu *pw) +{ + r->description.string = talloc_strdup(mem_ctx, pdb_get_acct_desc(pw)); + + return NT_STATUS_OK; +} + +/************************************************************************* + get_user_info_14. + *************************************************************************/ + +static NTSTATUS get_user_info_14(TALLOC_CTX *mem_ctx, + struct samr_UserInfo14 *r, + struct samu *pw) +{ + r->workstations.string = talloc_strdup(mem_ctx, pdb_get_workstations(pw)); + + return NT_STATUS_OK; +} + /************************************************************************* get_user_info_16. Safe. Only gives out acb bits. *************************************************************************/ @@ -2323,6 +2615,19 @@ static NTSTATUS get_user_info_16(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } +/************************************************************************* + get_user_info_17. + *************************************************************************/ + +static NTSTATUS get_user_info_17(TALLOC_CTX *mem_ctx, + struct samr_UserInfo17 *r, + struct samu *pw) +{ + unix_to_nt_time(&r->acct_expiry, pdb_get_kickoff_time(pw)); + + return NT_STATUS_OK; +} + /************************************************************************* get_user_info_18. OK - this is the killer as it gives out password info. Ensure that this is only allowed on an encrypted connection with a root @@ -2541,32 +2846,28 @@ NTSTATUS _samr_QueryUserInfo(pipes_struct *p, { NTSTATUS status; union samr_UserInfo *user_info = NULL; - struct samr_info *info = NULL; + struct samr_user_info *uinfo; DOM_SID domain_sid; uint32 rid; bool ret = false; struct samu *pwd = NULL; - /* search for the handle */ - if (!find_policy_by_hnd(p, r->in.user_handle, (void **)(void *)&info)) - return NT_STATUS_INVALID_HANDLE; - - status = access_check_samr_function(info->acc_granted, - SAMR_USER_ACCESS_GET_ATTRIBUTES, - "_samr_QueryUserInfo"); + uinfo = policy_handle_find(p, r->in.user_handle, + SAMR_USER_ACCESS_GET_ATTRIBUTES, NULL, + struct samr_user_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } - domain_sid = info->sid; + domain_sid = uinfo->sid; sid_split_rid(&domain_sid, &rid); - if (!sid_check_is_in_our_domain(&info->sid)) + if (!sid_check_is_in_our_domain(&uinfo->sid)) return NT_STATUS_OBJECT_TYPE_MISMATCH; DEBUG(5,("_samr_QueryUserInfo: sid:%s\n", - sid_string_dbg(&info->sid))); + sid_string_dbg(&uinfo->sid))); user_info = TALLOC_ZERO_P(p->mem_ctx, union samr_UserInfo); if (!user_info) { @@ -2580,11 +2881,11 @@ NTSTATUS _samr_QueryUserInfo(pipes_struct *p, } become_root(); - ret = pdb_getsampwsid(pwd, &info->sid); + ret = pdb_getsampwsid(pwd, &uinfo->sid); unbecome_root(); if (ret == false) { - DEBUG(4,("User %s not found\n", sid_string_dbg(&info->sid))); + DEBUG(4,("User %s not found\n", sid_string_dbg(&uinfo->sid))); TALLOC_FREE(pwd); return NT_STATUS_NO_SUCH_USER; } @@ -2594,21 +2895,58 @@ NTSTATUS _samr_QueryUserInfo(pipes_struct *p, samr_clear_sam_passwd(pwd); switch (r->in.level) { + case 1: + status = get_user_info_1(p->mem_ctx, &user_info->info1, pwd, &domain_sid); + break; + case 2: + status = get_user_info_2(p->mem_ctx, &user_info->info2, pwd); + break; + case 3: + status = get_user_info_3(p->mem_ctx, &user_info->info3, pwd, &domain_sid); + break; + case 4: + status = get_user_info_4(p->mem_ctx, &user_info->info4, pwd); + break; case 5: status = get_user_info_5(p->mem_ctx, &user_info->info5, pwd, &domain_sid); break; - case 7: - status = get_user_info_7(p->mem_ctx, &user_info->info7, pwd); + case 6: + status = get_user_info_6(p->mem_ctx, &user_info->info6, pwd); + break; + case 7: + status = get_user_info_7(p->mem_ctx, &user_info->info7, pwd); + break; + case 8: + status = get_user_info_8(p->mem_ctx, &user_info->info8, pwd); + break; + case 9: + status = get_user_info_9(p->mem_ctx, &user_info->info9, pwd); + break; + case 10: + status = get_user_info_10(p->mem_ctx, &user_info->info10, pwd); + break; + case 11: + status = get_user_info_11(p->mem_ctx, &user_info->info11, pwd); + break; + case 12: + status = get_user_info_12(p->mem_ctx, &user_info->info12, pwd); + break; + case 13: + status = get_user_info_13(p->mem_ctx, &user_info->info13, pwd); break; - case 9: - status = get_user_info_9(p->mem_ctx, &user_info->info9, pwd); + case 14: + status = get_user_info_14(p->mem_ctx, &user_info->info14, pwd); break; case 16: status = get_user_info_16(p->mem_ctx, &user_info->info16, pwd); break; + case 17: + status = get_user_info_17(p->mem_ctx, &user_info->info17, pwd); + break; case 18: /* level 18 is special */ - status = get_user_info_18(p, p->mem_ctx, &user_info->info18, &info->sid); + status = get_user_info_18(p, p->mem_ctx, &user_info->info18, + &uinfo->sid); break; case 20: status = get_user_info_20(p->mem_ctx, &user_info->info20, pwd); @@ -2652,8 +2990,8 @@ NTSTATUS _samr_QueryUserInfo2(pipes_struct *p, NTSTATUS _samr_GetGroupsForUser(pipes_struct *p, struct samr_GetGroupsForUser *r) { + struct samr_user_info *uinfo; struct samu *sam_pass=NULL; - DOM_SID sid; DOM_SID *sids; struct samr_RidWithAttribute dom_gid; struct samr_RidWithAttribute *gids = NULL; @@ -2661,7 +2999,6 @@ NTSTATUS _samr_GetGroupsForUser(pipes_struct *p, size_t num_groups = 0; gid_t *unix_gids; size_t i, num_gids; - uint32 acc_granted; bool ret; NTSTATUS result; bool success = False; @@ -2682,23 +3019,19 @@ NTSTATUS _samr_GetGroupsForUser(pipes_struct *p, DEBUG(5,("_samr_GetGroupsForUser: %d\n", __LINE__)); + uinfo = policy_handle_find(p, r->in.user_handle, + SAMR_USER_ACCESS_GET_GROUPS, NULL, + struct samr_user_info, &result); + if (!NT_STATUS_IS_OK(result)) { + return result; + } + rids = TALLOC_ZERO_P(p->mem_ctx, struct samr_RidWithAttributeArray); if (!rids) { return NT_STATUS_NO_MEMORY; } - /* find the policy handle. open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, r->in.user_handle, &sid, &acc_granted, NULL)) - return NT_STATUS_INVALID_HANDLE; - - result = access_check_samr_function(acc_granted, - SAMR_USER_ACCESS_GET_GROUPS, - "_samr_GetGroupsForUser"); - if (!NT_STATUS_IS_OK(result)) { - return result; - } - - if (!sid_check_is_in_our_domain(&sid)) + if (!sid_check_is_in_our_domain(&uinfo->sid)) return NT_STATUS_OBJECT_TYPE_MISMATCH; if ( !(sam_pass = samu_new( p->mem_ctx )) ) { @@ -2706,12 +3039,12 @@ NTSTATUS _samr_GetGroupsForUser(pipes_struct *p, } become_root(); - ret = pdb_getsampwsid(sam_pass, &sid); + ret = pdb_getsampwsid(sam_pass, &uinfo->sid); unbecome_root(); if (!ret) { DEBUG(10, ("pdb_getsampwsid failed for %s\n", - sid_string_dbg(&sid))); + sid_string_dbg(&uinfo->sid))); return NT_STATUS_NO_SUCH_USER; } @@ -2730,7 +3063,7 @@ NTSTATUS _samr_GetGroupsForUser(pipes_struct *p, if (!NT_STATUS_IS_OK(result)) { DEBUG(10, ("pdb_enum_group_memberships failed for %s\n", - sid_string_dbg(&sid))); + sid_string_dbg(&uinfo->sid))); return result; } @@ -2787,7 +3120,7 @@ NTSTATUS _samr_QueryDomainInfo(pipes_struct *p, struct samr_QueryDomainInfo *r) { NTSTATUS status = NT_STATUS_OK; - struct samr_info *info = NULL; + struct samr_domain_info *dinfo; union samr_DomainInfo *dom_info; time_t u_expire, u_min_age; @@ -2801,23 +3134,18 @@ NTSTATUS _samr_QueryDomainInfo(pipes_struct *p, DEBUG(5,("_samr_QueryDomainInfo: %d\n", __LINE__)); + dinfo = policy_handle_find(p, r->in.domain_handle, + SAMR_ACCESS_LOOKUP_DOMAIN, NULL, + struct samr_domain_info, &status); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + dom_info = TALLOC_ZERO_P(p->mem_ctx, union samr_DomainInfo); if (!dom_info) { return NT_STATUS_NO_MEMORY; } - /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, r->in.domain_handle, (void **)(void *)&info)) { - return NT_STATUS_INVALID_HANDLE; - } - - status = access_check_samr_function(info->acc_granted, - SAMR_ACCESS_OPEN_DOMAIN, - "_samr_QueryDomainInfo" ); - - if ( !NT_STATUS_IS_OK(status) ) - return status; - switch (r->in.level) { case 0x01: @@ -2859,9 +3187,12 @@ NTSTATUS _samr_QueryDomainInfo(pipes_struct *p, /* AS ROOT !!! */ - dom_info->general.num_users = count_sam_users(info->disp_info, ACB_NORMAL); - dom_info->general.num_groups = count_sam_groups(info->disp_info); - dom_info->general.num_aliases = count_sam_aliases(info->disp_info); + dom_info->general.num_users = count_sam_users( + dinfo->disp_info, ACB_NORMAL); + dom_info->general.num_groups = count_sam_groups( + dinfo->disp_info); + dom_info->general.num_aliases = count_sam_aliases( + dinfo->disp_info); pdb_get_account_policy(AP_TIME_TO_LOGOUT, &u_logout); @@ -2942,6 +3273,66 @@ NTSTATUS _samr_QueryDomainInfo(pipes_struct *p, dom_info->info8.sequence_num = seq_num; dom_info->info8.domain_create_time = 0; + break; + case 0x09: + + dom_info->info9.domain_server_state = DOMAIN_SERVER_ENABLED; + + break; + case 0x0b: + + /* AS ROOT !!! */ + + become_root(); + + dom_info->general2.general.num_users = count_sam_users( + dinfo->disp_info, ACB_NORMAL); + dom_info->general2.general.num_groups = count_sam_groups( + dinfo->disp_info); + dom_info->general2.general.num_aliases = count_sam_aliases( + dinfo->disp_info); + + pdb_get_account_policy(AP_TIME_TO_LOGOUT, &u_logout); + + unix_to_nt_time_abs(&dom_info->general2.general.force_logoff_time, u_logout); + + if (!pdb_get_seq_num(&seq_num)) + seq_num = time(NULL); + + pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &account_policy_temp); + u_lock_duration = account_policy_temp; + if (u_lock_duration != -1) { + u_lock_duration *= 60; + } + + pdb_get_account_policy(AP_RESET_COUNT_TIME, &account_policy_temp); + u_reset_time = account_policy_temp * 60; + + pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, + &account_policy_temp); + dom_info->general2.lockout_threshold = account_policy_temp; + + /* !AS ROOT */ + + unbecome_root(); + + server_role = ROLE_DOMAIN_PDC; + if (lp_server_role() == ROLE_DOMAIN_BDC) + server_role = ROLE_DOMAIN_BDC; + + dom_info->general2.general.oem_information.string = lp_serverstring(); + dom_info->general2.general.domain_name.string = lp_workgroup(); + dom_info->general2.general.primary.string = global_myname(); + dom_info->general2.general.sequence_num = seq_num; + dom_info->general2.general.domain_server_state = DOMAIN_SERVER_ENABLED; + dom_info->general2.general.role = server_role; + dom_info->general2.general.unknown3 = 1; + + unix_to_nt_time_abs(&dom_info->general2.lockout_duration, + u_lock_duration); + unix_to_nt_time_abs(&dom_info->general2.lockout_window, + u_reset_time); + break; case 0x0c: @@ -2971,6 +3362,25 @@ NTSTATUS _samr_QueryDomainInfo(pipes_struct *p, unix_to_nt_time_abs(&dom_info->info12.lockout_window, u_reset_time); + break; + case 0x0d: + + become_root(); + + /* AS ROOT !!! */ + + if (!pdb_get_seq_num(&seq_num)) { + seq_num = time(NULL); + } + + /* !AS ROOT */ + + unbecome_root(); + + dom_info->info13.sequence_num = seq_num; + dom_info->info13.domain_create_time = 0; + dom_info->info13.modified_count_at_last_promotion = 0; + break; default: return NT_STATUS_INVALID_INFO_CLASS; @@ -3031,7 +3441,8 @@ NTSTATUS _samr_CreateUser2(pipes_struct *p, const char *account = NULL; DOM_SID sid; uint32_t acb_info = r->in.acct_flags; - struct samr_info *info = NULL; + struct samr_domain_info *dinfo; + struct samr_user_info *uinfo; NTSTATUS nt_status; uint32 acc_granted; SEC_DESC *psd; @@ -3040,25 +3451,19 @@ NTSTATUS _samr_CreateUser2(pipes_struct *p, uint32 des_access = GENERIC_RIGHTS_USER_ALL_ACCESS; bool can_add_account = False; SE_PRIV se_rights; - DISP_INFO *disp_info = NULL; - /* Get the domain SID stored in the domain policy */ - if (!get_lsa_policy_samr_sid(p, r->in.domain_handle, &sid, &acc_granted, - &disp_info)) - return NT_STATUS_INVALID_HANDLE; + dinfo = policy_handle_find(p, r->in.domain_handle, + SAMR_DOMAIN_ACCESS_CREATE_USER, NULL, + struct samr_domain_info, &nt_status); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } - if (disp_info->builtin_domain) { + if (sid_check_is_builtin(&dinfo->sid)) { DEBUG(5,("_samr_CreateUser2: Refusing user create in BUILTIN\n")); return NT_STATUS_ACCESS_DENIED; } - nt_status = access_check_samr_function(acc_granted, - SAMR_DOMAIN_ACCESS_CREATE_USER, - "_samr_CreateUser2"); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } - if (!(acb_info == ACB_NORMAL || acb_info == ACB_DOMTRUST || acb_info == ACB_WSTRUST || acb_info == ACB_SVRTRUST)) { /* Match Win2k, and return NT_STATUS_INVALID_PARAMETER if @@ -3145,22 +3550,15 @@ NTSTATUS _samr_CreateUser2(pipes_struct *p, return nt_status; } - /* associate the user's SID with the new handle. */ - if ((info = get_samr_info_by_sid(p->mem_ctx, &sid)) == NULL) { - return NT_STATUS_NO_MEMORY; - } - - ZERO_STRUCTP(info); - info->sid = sid; - info->acc_granted = acc_granted; - - /* get a (unique) handle. open a policy on it. */ - if (!create_policy_hnd(p, r->out.user_handle, info)) { - return NT_STATUS_OBJECT_NAME_NOT_FOUND; + uinfo = policy_handle_create(p, r->out.user_handle, acc_granted, + struct samr_user_info, &nt_status); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; } + uinfo->sid = sid; /* After a "set" ensure we have no cached display info. */ - force_flush_samr_cache(info->disp_info); + force_flush_samr_cache(&sid); *r->out.access_granted = acc_granted; @@ -3194,8 +3592,11 @@ NTSTATUS _samr_CreateUser(pipes_struct *p, NTSTATUS _samr_Connect(pipes_struct *p, struct samr_Connect *r) { - struct samr_info *info = NULL; + struct samr_connect_info *info; + uint32_t acc_granted; + struct policy_handle hnd; uint32 des_access = r->in.access_mask; + NTSTATUS status; /* Access check */ @@ -3204,12 +3605,6 @@ NTSTATUS _samr_Connect(pipes_struct *p, return NT_STATUS_ACCESS_DENIED; } - /* set up the SAMR connect_anon response */ - - /* associate the user's SID with the new handle. */ - if ((info = get_samr_info_by_sid(p->mem_ctx, NULL)) == NULL) - return NT_STATUS_NO_MEMORY; - /* don't give away the farm but this is probably ok. The SAMR_ACCESS_ENUM_DOMAINS was observed from a win98 client trying to enumerate users (when configured user level access control on shares) --jerry */ @@ -3217,12 +3612,20 @@ NTSTATUS _samr_Connect(pipes_struct *p, map_max_allowed_access(p->server_info->ptok, &des_access); se_map_generic( &des_access, &sam_generic_mapping ); - info->acc_granted = des_access & (SAMR_ACCESS_ENUM_DOMAINS|SAMR_ACCESS_OPEN_DOMAIN); - /* get a (unique) handle. open a policy on it. */ - if (!create_policy_hnd(p, r->out.connect_handle, info)) - return NT_STATUS_OBJECT_NAME_NOT_FOUND; + acc_granted = des_access & (SAMR_ACCESS_ENUM_DOMAINS + |SAMR_ACCESS_LOOKUP_DOMAIN); + + /* set up the SAMR connect_anon response */ + + info = policy_handle_create(p, &hnd, acc_granted, + struct samr_connect_info, + &status); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + *r->out.connect_handle = hnd; return NT_STATUS_OK; } @@ -3233,7 +3636,8 @@ NTSTATUS _samr_Connect(pipes_struct *p, NTSTATUS _samr_Connect2(pipes_struct *p, struct samr_Connect2 *r) { - struct samr_info *info = NULL; + struct samr_connect_info *info = NULL; + struct policy_handle hnd; SEC_DESC *psd = NULL; uint32 acc_granted; uint32 des_access = r->in.access_mask; @@ -3245,6 +3649,9 @@ NTSTATUS _samr_Connect2(pipes_struct *p, case NDR_SAMR_CONNECT2: fn = "_samr_Connect2"; break; + case NDR_SAMR_CONNECT3: + fn = "_samr_Connect3"; + break; case NDR_SAMR_CONNECT4: fn = "_samr_Connect4"; break; @@ -3273,20 +3680,32 @@ NTSTATUS _samr_Connect2(pipes_struct *p, if ( !NT_STATUS_IS_OK(nt_status) ) return nt_status; - /* associate the user's SID and access granted with the new handle. */ - if ((info = get_samr_info_by_sid(p->mem_ctx, NULL)) == NULL) - return NT_STATUS_NO_MEMORY; + info = policy_handle_create(p, &hnd, acc_granted, + struct samr_connect_info, &nt_status); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + + DEBUG(5,("%s: %d\n", fn, __LINE__)); - info->acc_granted = acc_granted; - info->status = r->in.access_mask; /* this looks so wrong... - gd */ + *r->out.connect_handle = hnd; + return NT_STATUS_OK; +} - /* get a (unique) handle. open a policy on it. */ - if (!create_policy_hnd(p, r->out.connect_handle, info)) - return NT_STATUS_OBJECT_NAME_NOT_FOUND; +/**************************************************************** + _samr_Connect3 +****************************************************************/ - DEBUG(5,("%s: %d\n", fn, __LINE__)); +NTSTATUS _samr_Connect3(pipes_struct *p, + struct samr_Connect3 *r) +{ + struct samr_Connect2 c; + + c.in.system_name = r->in.system_name; + c.in.access_mask = r->in.access_mask; + c.out.connect_handle = r->out.connect_handle; - return nt_status; + return _samr_Connect2(p, &c); } /******************************************************************* @@ -3323,12 +3742,13 @@ NTSTATUS _samr_Connect5(pipes_struct *p, c.in.access_mask = r->in.access_mask; c.out.connect_handle = r->out.connect_handle; + *r->out.level_out = 1; + status = _samr_Connect2(p, &c); if (!NT_STATUS_IS_OK(status)) { return status; } - *r->out.level_out = 1; r->out.info_out->info1 = info1; return NT_STATUS_OK; @@ -3341,20 +3761,18 @@ NTSTATUS _samr_Connect5(pipes_struct *p, NTSTATUS _samr_LookupDomain(pipes_struct *p, struct samr_LookupDomain *r) { - NTSTATUS status = NT_STATUS_OK; - struct samr_info *info; + NTSTATUS status; + struct samr_connect_info *info; const char *domain_name; DOM_SID *sid = NULL; - if (!find_policy_by_hnd(p, r->in.connect_handle, (void**)(void *)&info)) - return NT_STATUS_INVALID_HANDLE; - /* win9x user manager likes to use SAMR_ACCESS_ENUM_DOMAINS here. Reverted that change so we will work with RAS servers again */ - status = access_check_samr_function(info->acc_granted, - SAMR_ACCESS_OPEN_DOMAIN, - "_samr_LookupDomain"); + info = policy_handle_find(p, r->in.connect_handle, + SAMR_ACCESS_LOOKUP_DOMAIN, NULL, + struct samr_connect_info, + &status); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -3393,17 +3811,14 @@ NTSTATUS _samr_EnumDomains(pipes_struct *p, struct samr_EnumDomains *r) { NTSTATUS status; - struct samr_info *info; + struct samr_connect_info *info; uint32_t num_entries = 2; struct samr_SamEntry *entry_array = NULL; struct samr_SamArray *sam; - if (!find_policy_by_hnd(p, r->in.connect_handle, (void**)(void *)&info)) - return NT_STATUS_INVALID_HANDLE; - - status = access_check_samr_function(info->acc_granted, - SAMR_ACCESS_ENUM_DOMAINS, - "_samr_EnumDomains"); + info = policy_handle_find(p, r->in.connect_handle, + SAMR_ACCESS_ENUM_DOMAINS, NULL, + struct samr_connect_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -3444,7 +3859,8 @@ NTSTATUS _samr_OpenAlias(pipes_struct *p, { DOM_SID sid; uint32 alias_rid = r->in.rid; - struct samr_info *info = NULL; + struct samr_alias_info *ainfo; + struct samr_domain_info *dinfo; SEC_DESC *psd = NULL; uint32 acc_granted; uint32 des_access = r->in.access_mask; @@ -3452,21 +3868,16 @@ NTSTATUS _samr_OpenAlias(pipes_struct *p, NTSTATUS status; SE_PRIV se_rights; - /* find the domain policy and get the SID / access bits stored in the domain policy */ - - if ( !get_lsa_policy_samr_sid(p, r->in.domain_handle, &sid, &acc_granted, NULL) ) - return NT_STATUS_INVALID_HANDLE; - - status = access_check_samr_function(acc_granted, - SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, - "_samr_OpenAlias"); - - if ( !NT_STATUS_IS_OK(status) ) + dinfo = policy_handle_find(p, r->in.domain_handle, + SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, NULL, + struct samr_domain_info, &status); + if (!NT_STATUS_IS_OK(status)) { return status; + } /* append the alias' RID to it */ - if (!sid_append_rid(&sid, alias_rid)) + if (!sid_compose(&sid, &dinfo->sid, alias_rid)) return NT_STATUS_NO_SUCH_ALIAS; /*check if access can be granted as requested by client. */ @@ -3508,17 +3919,68 @@ NTSTATUS _samr_OpenAlias(pipes_struct *p, } - /* associate the alias SID with the new handle. */ - if ((info = get_samr_info_by_sid(p->mem_ctx, &sid)) == NULL) - return NT_STATUS_NO_MEMORY; + ainfo = policy_handle_create(p, r->out.alias_handle, acc_granted, + struct samr_alias_info, &status); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + ainfo->sid = sid; - info->acc_granted = acc_granted; + return NT_STATUS_OK; +} - /* get a (unique) handle. open a policy on it. */ - if (!create_policy_hnd(p, r->out.alias_handle, info)) - return NT_STATUS_OBJECT_NAME_NOT_FOUND; +/******************************************************************* + set_user_info_2 + ********************************************************************/ - return NT_STATUS_OK; +static NTSTATUS set_user_info_2(TALLOC_CTX *mem_ctx, + struct samr_UserInfo2 *id2, + struct samu *pwd) +{ + if (id2 == NULL) { + DEBUG(5,("set_user_info_2: NULL id2\n")); + return NT_STATUS_ACCESS_DENIED; + } + + copy_id2_to_sam_passwd(pwd, id2); + + return pdb_update_sam_account(pwd); +} + +/******************************************************************* + set_user_info_4 + ********************************************************************/ + +static NTSTATUS set_user_info_4(TALLOC_CTX *mem_ctx, + struct samr_UserInfo4 *id4, + struct samu *pwd) +{ + if (id4 == NULL) { + DEBUG(5,("set_user_info_2: NULL id4\n")); + return NT_STATUS_ACCESS_DENIED; + } + + copy_id4_to_sam_passwd(pwd, id4); + + return pdb_update_sam_account(pwd); +} + +/******************************************************************* + set_user_info_6 + ********************************************************************/ + +static NTSTATUS set_user_info_6(TALLOC_CTX *mem_ctx, + struct samr_UserInfo6 *id6, + struct samu *pwd) +{ + if (id6 == NULL) { + DEBUG(5,("set_user_info_6: NULL id6\n")); + return NT_STATUS_ACCESS_DENIED; + } + + copy_id6_to_sam_passwd(pwd, id6); + + return pdb_update_sam_account(pwd); } /******************************************************************* @@ -3536,52 +3998,172 @@ static NTSTATUS set_user_info_7(TALLOC_CTX *mem_ctx, return NT_STATUS_ACCESS_DENIED; } - if (!id7->account_name.string) { - DEBUG(5, ("set_user_info_7: failed to get new username\n")); + if (!id7->account_name.string) { + DEBUG(5, ("set_user_info_7: failed to get new username\n")); + return NT_STATUS_ACCESS_DENIED; + } + + /* check to see if the new username already exists. Note: we can't + reliably lock all backends, so there is potentially the + possibility that a user can be created in between this check and + the rename. The rename should fail, but may not get the + exact same failure status code. I think this is small enough + of a window for this type of operation and the results are + simply that the rename fails with a slightly different status + code (like UNSUCCESSFUL instead of ALREADY_EXISTS). */ + + rc = can_create(mem_ctx, id7->account_name.string); + if (!NT_STATUS_IS_OK(rc)) { + return rc; + } + + rc = pdb_rename_sam_account(pwd, id7->account_name.string); + + return rc; +} + +/******************************************************************* + set_user_info_8 + ********************************************************************/ + +static NTSTATUS set_user_info_8(TALLOC_CTX *mem_ctx, + struct samr_UserInfo8 *id8, + struct samu *pwd) +{ + if (id8 == NULL) { + DEBUG(5,("set_user_info_8: NULL id8\n")); + return NT_STATUS_ACCESS_DENIED; + } + + copy_id8_to_sam_passwd(pwd, id8); + + return pdb_update_sam_account(pwd); +} + +/******************************************************************* + set_user_info_10 + ********************************************************************/ + +static NTSTATUS set_user_info_10(TALLOC_CTX *mem_ctx, + struct samr_UserInfo10 *id10, + struct samu *pwd) +{ + if (id10 == NULL) { + DEBUG(5,("set_user_info_8: NULL id10\n")); + return NT_STATUS_ACCESS_DENIED; + } + + copy_id10_to_sam_passwd(pwd, id10); + + return pdb_update_sam_account(pwd); +} + +/******************************************************************* + set_user_info_11 + ********************************************************************/ + +static NTSTATUS set_user_info_11(TALLOC_CTX *mem_ctx, + struct samr_UserInfo11 *id11, + struct samu *pwd) +{ + if (id11 == NULL) { + DEBUG(5,("set_user_info_11: NULL id11\n")); + return NT_STATUS_ACCESS_DENIED; + } + + copy_id11_to_sam_passwd(pwd, id11); + + return pdb_update_sam_account(pwd); +} + +/******************************************************************* + set_user_info_12 + ********************************************************************/ + +static NTSTATUS set_user_info_12(TALLOC_CTX *mem_ctx, + struct samr_UserInfo12 *id12, + struct samu *pwd) +{ + if (id12 == NULL) { + DEBUG(5,("set_user_info_12: NULL id12\n")); + return NT_STATUS_ACCESS_DENIED; + } + + copy_id12_to_sam_passwd(pwd, id12); + + return pdb_update_sam_account(pwd); +} + +/******************************************************************* + set_user_info_13 + ********************************************************************/ + +static NTSTATUS set_user_info_13(TALLOC_CTX *mem_ctx, + struct samr_UserInfo13 *id13, + struct samu *pwd) +{ + if (id13 == NULL) { + DEBUG(5,("set_user_info_13: NULL id13\n")); return NT_STATUS_ACCESS_DENIED; } - /* check to see if the new username already exists. Note: we can't - reliably lock all backends, so there is potentially the - possibility that a user can be created in between this check and - the rename. The rename should fail, but may not get the - exact same failure status code. I think this is small enough - of a window for this type of operation and the results are - simply that the rename fails with a slightly different status - code (like UNSUCCESSFUL instead of ALREADY_EXISTS). */ + copy_id13_to_sam_passwd(pwd, id13); - rc = can_create(mem_ctx, id7->account_name.string); - if (!NT_STATUS_IS_OK(rc)) { - return rc; + return pdb_update_sam_account(pwd); +} + +/******************************************************************* + set_user_info_14 + ********************************************************************/ + +static NTSTATUS set_user_info_14(TALLOC_CTX *mem_ctx, + struct samr_UserInfo14 *id14, + struct samu *pwd) +{ + if (id14 == NULL) { + DEBUG(5,("set_user_info_14: NULL id14\n")); + return NT_STATUS_ACCESS_DENIED; } - rc = pdb_rename_sam_account(pwd, id7->account_name.string); + copy_id14_to_sam_passwd(pwd, id14); - return rc; + return pdb_update_sam_account(pwd); } /******************************************************************* set_user_info_16 ********************************************************************/ -static bool set_user_info_16(struct samr_UserInfo16 *id16, - struct samu *pwd) +static NTSTATUS set_user_info_16(TALLOC_CTX *mem_ctx, + struct samr_UserInfo16 *id16, + struct samu *pwd) { if (id16 == NULL) { - DEBUG(5, ("set_user_info_16: NULL id16\n")); - return False; + DEBUG(5,("set_user_info_16: NULL id16\n")); + return NT_STATUS_ACCESS_DENIED; } - /* FIX ME: check if the value is really changed --metze */ - if (!pdb_set_acct_ctrl(pwd, id16->acct_flags, PDB_CHANGED)) { - return False; - } + copy_id16_to_sam_passwd(pwd, id16); - if(!NT_STATUS_IS_OK(pdb_update_sam_account(pwd))) { - return False; + return pdb_update_sam_account(pwd); +} + +/******************************************************************* + set_user_info_17 + ********************************************************************/ + +static NTSTATUS set_user_info_17(TALLOC_CTX *mem_ctx, + struct samr_UserInfo17 *id17, + struct samu *pwd) +{ + if (id17 == NULL) { + DEBUG(5,("set_user_info_17: NULL id17\n")); + return NT_STATUS_ACCESS_DENIED; } - return True; + copy_id17_to_sam_passwd(pwd, id17); + + return pdb_update_sam_account(pwd); } /******************************************************************* @@ -3645,30 +4227,27 @@ static NTSTATUS set_user_info_18(struct samr_UserInfo18 *id18, set_user_info_20 ********************************************************************/ -static bool set_user_info_20(struct samr_UserInfo20 *id20, - struct samu *pwd) +static NTSTATUS set_user_info_20(TALLOC_CTX *mem_ctx, + struct samr_UserInfo20 *id20, + struct samu *pwd) { if (id20 == NULL) { - DEBUG(5, ("set_user_info_20: NULL id20\n")); - return False; + DEBUG(5,("set_user_info_20: NULL id20\n")); + return NT_STATUS_ACCESS_DENIED; } copy_id20_to_sam_passwd(pwd, id20); - /* write the change out */ - if(!NT_STATUS_IS_OK(pdb_update_sam_account(pwd))) { - return False; - } - - return True; + return pdb_update_sam_account(pwd); } /******************************************************************* set_user_info_21 ********************************************************************/ -static NTSTATUS set_user_info_21(TALLOC_CTX *mem_ctx, - struct samr_UserInfo21 *id21, +static NTSTATUS set_user_info_21(struct samr_UserInfo21 *id21, + TALLOC_CTX *mem_ctx, + DATA_BLOB *session_key, struct samu *pwd) { NTSTATUS status; @@ -3686,6 +4265,52 @@ static NTSTATUS set_user_info_21(TALLOC_CTX *mem_ctx, return NT_STATUS_ACCESS_DENIED; } + if (id21->fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) { + if (id21->nt_password_set) { + DATA_BLOB in, out; + + if ((id21->nt_owf_password.length != 16) || + (id21->nt_owf_password.size != 16)) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (!session_key->length) { + return NT_STATUS_NO_USER_SESSION_KEY; + } + + in = data_blob_const(id21->nt_owf_password.array, 16); + out = data_blob_talloc_zero(mem_ctx, 16); + + sess_crypt_blob(&out, &in, session_key, false); + + pdb_set_nt_passwd(pwd, out.data, PDB_CHANGED); + pdb_set_pass_last_set_time(pwd, time(NULL), PDB_CHANGED); + } + } + + if (id21->fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) { + if (id21->lm_password_set) { + DATA_BLOB in, out; + + if ((id21->lm_owf_password.length != 16) || + (id21->lm_owf_password.size != 16)) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (!session_key->length) { + return NT_STATUS_NO_USER_SESSION_KEY; + } + + in = data_blob_const(id21->lm_owf_password.array, 16); + out = data_blob_talloc_zero(mem_ctx, 16); + + sess_crypt_blob(&out, &in, session_key, false); + + pdb_set_lanman_passwd(pwd, out.data, PDB_CHANGED); + pdb_set_pass_last_set_time(pwd, time(NULL), PDB_CHANGED); + } + } + /* we need to separately check for an account rename first */ if (id21->account_name.string && @@ -3756,7 +4381,7 @@ static NTSTATUS set_user_info_23(TALLOC_CTX *mem_ctx, struct samu *pwd) { char *plaintext_buf = NULL; - uint32 len = 0; + size_t len = 0; uint32_t acct_ctrl; NTSTATUS status; @@ -3783,7 +4408,7 @@ static NTSTATUS set_user_info_23(TALLOC_CTX *mem_ctx, id23->password.data, &plaintext_buf, &len, - STR_UNICODE)) { + CH_UTF16)) { return NT_STATUS_WRONG_PASSWORD; } @@ -3845,7 +4470,7 @@ static NTSTATUS set_user_info_23(TALLOC_CTX *mem_ctx, static bool set_user_info_pw(uint8 *pass, struct samu *pwd) { - uint32 len = 0; + size_t len = 0; char *plaintext_buf = NULL; uint32 acct_ctrl; @@ -3858,7 +4483,7 @@ static bool set_user_info_pw(uint8 *pass, struct samu *pwd) pass, &plaintext_buf, &len, - STR_UNICODE)) { + CH_UTF16)) { return False; } @@ -4022,25 +4647,18 @@ static NTSTATUS set_user_info_26(TALLOC_CTX *mem_ctx, NTSTATUS _samr_SetUserInfo(pipes_struct *p, struct samr_SetUserInfo *r) { + struct samr_user_info *uinfo; NTSTATUS status; struct samu *pwd = NULL; - DOM_SID sid; union samr_UserInfo *info = r->in.info; uint16_t switch_value = r->in.level; - uint32_t acc_granted; uint32_t acc_required; bool ret; bool has_enough_rights = False; uint32_t acb_info; - DISP_INFO *disp_info = NULL; DEBUG(5,("_samr_SetUserInfo: %d\n", __LINE__)); - /* find the policy handle. open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, r->in.user_handle, &sid, &acc_granted, &disp_info)) { - return NT_STATUS_INVALID_HANDLE; - } - /* This is tricky. A WinXP domain join sets (SAMR_USER_ACCESS_SET_PASSWORD|SAMR_USER_ACCESS_SET_ATTRIBUTES|SAMR_USER_ACCESS_GET_ATTRIBUTES) The MMC lusrmgr plugin includes these perms and more in the SamrOpenUser(). But the @@ -4062,15 +4680,14 @@ NTSTATUS _samr_SetUserInfo(pipes_struct *p, break; } - status = access_check_samr_function(acc_granted, - acc_required, - "_samr_SetUserInfo"); + uinfo = policy_handle_find(p, r->in.user_handle, acc_required, NULL, + struct samr_user_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } DEBUG(5, ("_samr_SetUserInfo: sid:%s, level:%d\n", - sid_string_dbg(&sid), switch_value)); + sid_string_dbg(&uinfo->sid), switch_value)); if (info == NULL) { DEBUG(5, ("_samr_SetUserInfo: NULL info level\n")); @@ -4082,7 +4699,7 @@ NTSTATUS _samr_SetUserInfo(pipes_struct *p, } become_root(); - ret = pdb_getsampwsid(pwd, &sid); + ret = pdb_getsampwsid(pwd, &uinfo->sid); unbecome_root(); if (!ret) { @@ -4121,15 +4738,64 @@ NTSTATUS _samr_SetUserInfo(pipes_struct *p, switch (switch_value) { + case 2: + status = set_user_info_2(p->mem_ctx, + &info->info2, pwd); + break; + + case 4: + status = set_user_info_4(p->mem_ctx, + &info->info4, pwd); + break; + + case 6: + status = set_user_info_6(p->mem_ctx, + &info->info6, pwd); + break; + case 7: status = set_user_info_7(p->mem_ctx, &info->info7, pwd); break; + case 8: + status = set_user_info_8(p->mem_ctx, + &info->info8, pwd); + break; + + case 10: + status = set_user_info_10(p->mem_ctx, + &info->info10, pwd); + break; + + case 11: + status = set_user_info_11(p->mem_ctx, + &info->info11, pwd); + break; + + case 12: + status = set_user_info_12(p->mem_ctx, + &info->info12, pwd); + break; + + case 13: + status = set_user_info_13(p->mem_ctx, + &info->info13, pwd); + break; + + case 14: + status = set_user_info_14(p->mem_ctx, + &info->info14, pwd); + break; + case 16: - if (!set_user_info_16(&info->info16, pwd)) { - status = NT_STATUS_ACCESS_DENIED; - } + status = set_user_info_16(p->mem_ctx, + &info->info16, pwd); + break; + + case 17: + status = set_user_info_17(p->mem_ctx, + &info->info17, pwd); break; case 18: @@ -4141,22 +4807,23 @@ NTSTATUS _samr_SetUserInfo(pipes_struct *p, break; case 20: - if (!set_user_info_20(&info->info20, pwd)) { - status = NT_STATUS_ACCESS_DENIED; - } + status = set_user_info_20(p->mem_ctx, + &info->info20, pwd); break; case 21: - status = set_user_info_21(p->mem_ctx, - &info->info21, pwd); + status = set_user_info_21(&info->info21, + p->mem_ctx, + &p->server_info->user_session_key, + pwd); break; case 23: if (!p->server_info->user_session_key.length) { status = NT_STATUS_NO_USER_SESSION_KEY; } - SamOEMhashBlob(info->info23.password.data, 516, - &p->server_info->user_session_key); + arcfour_crypt_blob(info->info23.password.data, 516, + &p->server_info->user_session_key); dump_data(100, info->info23.password.data, 516); @@ -4168,9 +4835,9 @@ NTSTATUS _samr_SetUserInfo(pipes_struct *p, if (!p->server_info->user_session_key.length) { status = NT_STATUS_NO_USER_SESSION_KEY; } - SamOEMhashBlob(info->info24.password.data, - 516, - &p->server_info->user_session_key); + arcfour_crypt_blob(info->info24.password.data, + 516, + &p->server_info->user_session_key); dump_data(100, info->info24.password.data, 516); @@ -4219,7 +4886,7 @@ NTSTATUS _samr_SetUserInfo(pipes_struct *p, /* ================ END SeMachineAccountPrivilege BLOCK ================ */ if (NT_STATUS_IS_OK(status)) { - force_flush_samr_cache(disp_info); + force_flush_samr_cache(&uinfo->sid); } return status; @@ -4250,36 +4917,25 @@ NTSTATUS _samr_GetAliasMembership(pipes_struct *p, { size_t num_alias_rids; uint32 *alias_rids; - struct samr_info *info = NULL; + struct samr_domain_info *dinfo; size_t i; - NTSTATUS ntstatus1; - NTSTATUS ntstatus2; + NTSTATUS status; DOM_SID *members; DEBUG(5,("_samr_GetAliasMembership: %d\n", __LINE__)); - /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, r->in.domain_handle, (void **)(void *)&info)) - return NT_STATUS_INVALID_HANDLE; - - ntstatus1 = access_check_samr_function(info->acc_granted, - SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS, - "_samr_GetAliasMembership"); - ntstatus2 = access_check_samr_function(info->acc_granted, - SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, - "_samr_GetAliasMembership"); - - if (!NT_STATUS_IS_OK(ntstatus1) || !NT_STATUS_IS_OK(ntstatus2)) { - if (!(NT_STATUS_EQUAL(ntstatus1,NT_STATUS_ACCESS_DENIED) && NT_STATUS_IS_OK(ntstatus2)) && - !(NT_STATUS_EQUAL(ntstatus1,NT_STATUS_ACCESS_DENIED) && NT_STATUS_IS_OK(ntstatus1))) { - return (NT_STATUS_IS_OK(ntstatus1)) ? ntstatus2 : ntstatus1; - } + dinfo = policy_handle_find(p, r->in.domain_handle, + SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS + | SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, NULL, + struct samr_domain_info, &status); + if (!NT_STATUS_IS_OK(status)) { + return status; } - if (!sid_check_is_domain(&info->sid) && - !sid_check_is_builtin(&info->sid)) + if (!sid_check_is_domain(&dinfo->sid) && + !sid_check_is_builtin(&dinfo->sid)) return NT_STATUS_OBJECT_TYPE_MISMATCH; if (r->in.sids->num_sids) { @@ -4298,13 +4954,13 @@ NTSTATUS _samr_GetAliasMembership(pipes_struct *p, num_alias_rids = 0; become_root(); - ntstatus1 = pdb_enum_alias_memberships(p->mem_ctx, &info->sid, members, - r->in.sids->num_sids, - &alias_rids, &num_alias_rids); + status = pdb_enum_alias_memberships(p->mem_ctx, &dinfo->sid, members, + r->in.sids->num_sids, + &alias_rids, &num_alias_rids); unbecome_root(); - if (!NT_STATUS_IS_OK(ntstatus1)) { - return ntstatus1; + if (!NT_STATUS_IS_OK(status)) { + return status; } r->out.rids->count = num_alias_rids; @@ -4320,31 +4976,24 @@ NTSTATUS _samr_GetAliasMembership(pipes_struct *p, NTSTATUS _samr_GetMembersInAlias(pipes_struct *p, struct samr_GetMembersInAlias *r) { + struct samr_alias_info *ainfo; NTSTATUS status; size_t i; size_t num_sids = 0; struct lsa_SidPtr *sids = NULL; DOM_SID *pdb_sids = NULL; - DOM_SID alias_sid; - - uint32 acc_granted; - - /* find the policy handle. open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, r->in.alias_handle, &alias_sid, &acc_granted, NULL)) - return NT_STATUS_INVALID_HANDLE; - - status = access_check_samr_function(acc_granted, - SAMR_ALIAS_ACCESS_GET_MEMBERS, - "_samr_GetMembersInAlias"); + ainfo = policy_handle_find(p, r->in.alias_handle, + SAMR_ALIAS_ACCESS_GET_MEMBERS, NULL, + struct samr_alias_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } - DEBUG(10, ("sid is %s\n", sid_string_dbg(&alias_sid))); + DEBUG(10, ("sid is %s\n", sid_string_dbg(&ainfo->sid))); become_root(); - status = pdb_enum_aliasmem(&alias_sid, &pdb_sids, &num_sids); + status = pdb_enum_aliasmem(&ainfo->sid, &pdb_sids, &num_sids); unbecome_root(); if (!NT_STATUS_IS_OK(status)) { @@ -4382,45 +5031,39 @@ NTSTATUS _samr_GetMembersInAlias(pipes_struct *p, NTSTATUS _samr_QueryGroupMember(pipes_struct *p, struct samr_QueryGroupMember *r) { - DOM_SID group_sid; + struct samr_group_info *ginfo; size_t i, num_members; uint32 *rid=NULL; uint32 *attr=NULL; - uint32 acc_granted; - NTSTATUS status; struct samr_RidTypeArray *rids = NULL; + ginfo = policy_handle_find(p, r->in.group_handle, + SAMR_GROUP_ACCESS_GET_MEMBERS, NULL, + struct samr_group_info, &status); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + rids = TALLOC_ZERO_P(p->mem_ctx, struct samr_RidTypeArray); if (!rids) { return NT_STATUS_NO_MEMORY; } - /* find the policy handle. open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, r->in.group_handle, &group_sid, &acc_granted, NULL)) - return NT_STATUS_INVALID_HANDLE; - - status = access_check_samr_function(acc_granted, - SAMR_GROUP_ACCESS_GET_MEMBERS, - "_samr_QueryGroupMember"); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - DEBUG(10, ("sid is %s\n", sid_string_dbg(&group_sid))); + DEBUG(10, ("sid is %s\n", sid_string_dbg(&ginfo->sid))); - if (!sid_check_is_in_our_domain(&group_sid)) { + if (!sid_check_is_in_our_domain(&ginfo->sid)) { DEBUG(3, ("sid %s is not in our domain\n", - sid_string_dbg(&group_sid))); + sid_string_dbg(&ginfo->sid))); return NT_STATUS_NO_SUCH_GROUP; } DEBUG(10, ("lookup on Domain SID\n")); become_root(); - status = pdb_enum_group_members(p->mem_ctx, &group_sid, + status = pdb_enum_group_members(p->mem_ctx, &ginfo->sid, &rid, &num_members); unbecome_root(); @@ -4455,25 +5098,19 @@ NTSTATUS _samr_QueryGroupMember(pipes_struct *p, NTSTATUS _samr_AddAliasMember(pipes_struct *p, struct samr_AddAliasMember *r) { - DOM_SID alias_sid; - uint32 acc_granted; + struct samr_alias_info *ainfo; SE_PRIV se_rights; bool can_add_accounts; NTSTATUS status; - DISP_INFO *disp_info = NULL; - - /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, r->in.alias_handle, &alias_sid, &acc_granted, &disp_info)) - return NT_STATUS_INVALID_HANDLE; - status = access_check_samr_function(acc_granted, - SAMR_ALIAS_ACCESS_ADD_MEMBER, - "_samr_AddAliasMember"); + ainfo = policy_handle_find(p, r->in.alias_handle, + SAMR_ALIAS_ACCESS_ADD_MEMBER, NULL, + struct samr_alias_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } - DEBUG(10, ("sid is %s\n", sid_string_dbg(&alias_sid))); + DEBUG(10, ("sid is %s\n", sid_string_dbg(&ainfo->sid))); se_priv_copy( &se_rights, &se_add_users ); can_add_accounts = user_has_privileges( p->server_info->ptok, &se_rights ); @@ -4483,7 +5120,7 @@ NTSTATUS _samr_AddAliasMember(pipes_struct *p, if ( can_add_accounts ) become_root(); - status = pdb_add_aliasmem(&alias_sid, r->in.sid); + status = pdb_add_aliasmem(&ainfo->sid, r->in.sid); if ( can_add_accounts ) unbecome_root(); @@ -4491,7 +5128,7 @@ NTSTATUS _samr_AddAliasMember(pipes_struct *p, /******** END SeAddUsers BLOCK *********/ if (NT_STATUS_IS_OK(status)) { - force_flush_samr_cache(disp_info); + force_flush_samr_cache(&ainfo->sid); } return status; @@ -4504,26 +5141,20 @@ NTSTATUS _samr_AddAliasMember(pipes_struct *p, NTSTATUS _samr_DeleteAliasMember(pipes_struct *p, struct samr_DeleteAliasMember *r) { - DOM_SID alias_sid; - uint32 acc_granted; + struct samr_alias_info *ainfo; SE_PRIV se_rights; bool can_add_accounts; NTSTATUS status; - DISP_INFO *disp_info = NULL; - - /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, r->in.alias_handle, &alias_sid, &acc_granted, &disp_info)) - return NT_STATUS_INVALID_HANDLE; - status = access_check_samr_function(acc_granted, - SAMR_ALIAS_ACCESS_REMOVE_MEMBER, - "_samr_DeleteAliasMember"); + ainfo = policy_handle_find(p, r->in.alias_handle, + SAMR_ALIAS_ACCESS_REMOVE_MEMBER, NULL, + struct samr_alias_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } DEBUG(10, ("_samr_del_aliasmem:sid is %s\n", - sid_string_dbg(&alias_sid))); + sid_string_dbg(&ainfo->sid))); se_priv_copy( &se_rights, &se_add_users ); can_add_accounts = user_has_privileges( p->server_info->ptok, &se_rights ); @@ -4533,7 +5164,7 @@ NTSTATUS _samr_DeleteAliasMember(pipes_struct *p, if ( can_add_accounts ) become_root(); - status = pdb_del_aliasmem(&alias_sid, r->in.sid); + status = pdb_del_aliasmem(&ainfo->sid, r->in.sid); if ( can_add_accounts ) unbecome_root(); @@ -4541,7 +5172,7 @@ NTSTATUS _samr_DeleteAliasMember(pipes_struct *p, /******** END SeAddUsers BLOCK *********/ if (NT_STATUS_IS_OK(status)) { - force_flush_samr_cache(disp_info); + force_flush_samr_cache(&ainfo->sid); } return status; @@ -4554,28 +5185,22 @@ NTSTATUS _samr_DeleteAliasMember(pipes_struct *p, NTSTATUS _samr_AddGroupMember(pipes_struct *p, struct samr_AddGroupMember *r) { + struct samr_group_info *ginfo; NTSTATUS status; - DOM_SID group_sid; uint32 group_rid; - uint32 acc_granted; SE_PRIV se_rights; bool can_add_accounts; - DISP_INFO *disp_info = NULL; - - /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, r->in.group_handle, &group_sid, &acc_granted, &disp_info)) - return NT_STATUS_INVALID_HANDLE; - status = access_check_samr_function(acc_granted, - SAMR_GROUP_ACCESS_ADD_MEMBER, - "_samr_AddGroupMember"); + ginfo = policy_handle_find(p, r->in.group_handle, + SAMR_GROUP_ACCESS_ADD_MEMBER, NULL, + struct samr_group_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } - DEBUG(10, ("sid is %s\n", sid_string_dbg(&group_sid))); + DEBUG(10, ("sid is %s\n", sid_string_dbg(&ginfo->sid))); - if (!sid_peek_check_rid(get_global_sam_sid(), &group_sid, + if (!sid_peek_check_rid(get_global_sam_sid(), &ginfo->sid, &group_rid)) { return NT_STATUS_INVALID_HANDLE; } @@ -4595,7 +5220,7 @@ NTSTATUS _samr_AddGroupMember(pipes_struct *p, /******** END SeAddUsers BLOCK *********/ - force_flush_samr_cache(disp_info); + force_flush_samr_cache(&ginfo->sid); return status; } @@ -4608,13 +5233,11 @@ NTSTATUS _samr_DeleteGroupMember(pipes_struct *p, struct samr_DeleteGroupMember *r) { + struct samr_group_info *ginfo; NTSTATUS status; - DOM_SID group_sid; uint32 group_rid; - uint32 acc_granted; SE_PRIV se_rights; bool can_add_accounts; - DISP_INFO *disp_info = NULL; /* * delete the group member named r->in.rid @@ -4622,18 +5245,14 @@ NTSTATUS _samr_DeleteGroupMember(pipes_struct *p, * the rid is a user's rid as the group is a domain group. */ - /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, r->in.group_handle, &group_sid, &acc_granted, &disp_info)) - return NT_STATUS_INVALID_HANDLE; - - status = access_check_samr_function(acc_granted, - SAMR_GROUP_ACCESS_REMOVE_MEMBER, - "_samr_DeleteGroupMember"); + ginfo = policy_handle_find(p, r->in.group_handle, + SAMR_GROUP_ACCESS_REMOVE_MEMBER, NULL, + struct samr_group_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } - if (!sid_peek_check_rid(get_global_sam_sid(), &group_sid, + if (!sid_peek_check_rid(get_global_sam_sid(), &ginfo->sid, &group_rid)) { return NT_STATUS_INVALID_HANDLE; } @@ -4653,7 +5272,7 @@ NTSTATUS _samr_DeleteGroupMember(pipes_struct *p, /******** END SeAddUsers BLOCK *********/ - force_flush_samr_cache(disp_info); + force_flush_samr_cache(&ginfo->sid); return status; } @@ -4665,29 +5284,23 @@ NTSTATUS _samr_DeleteGroupMember(pipes_struct *p, NTSTATUS _samr_DeleteUser(pipes_struct *p, struct samr_DeleteUser *r) { + struct samr_user_info *uinfo; NTSTATUS status; - DOM_SID user_sid; struct samu *sam_pass=NULL; - uint32 acc_granted; bool can_add_accounts; uint32 acb_info; - DISP_INFO *disp_info = NULL; bool ret; DEBUG(5, ("_samr_DeleteUser: %d\n", __LINE__)); - /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, r->in.user_handle, &user_sid, &acc_granted, &disp_info)) - return NT_STATUS_INVALID_HANDLE; - - status = access_check_samr_function(acc_granted, - STD_RIGHT_DELETE_ACCESS, - "_samr_DeleteUser"); + uinfo = policy_handle_find(p, r->in.user_handle, + STD_RIGHT_DELETE_ACCESS, NULL, + struct samr_user_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } - if (!sid_check_is_in_our_domain(&user_sid)) + if (!sid_check_is_in_our_domain(&uinfo->sid)) return NT_STATUS_CANNOT_DELETE; /* check if the user exists before trying to delete */ @@ -4696,12 +5309,12 @@ NTSTATUS _samr_DeleteUser(pipes_struct *p, } become_root(); - ret = pdb_getsampwsid(sam_pass, &user_sid); + ret = pdb_getsampwsid(sam_pass, &uinfo->sid); unbecome_root(); if( !ret ) { DEBUG(5,("_samr_DeleteUser: User %s doesn't exist.\n", - sid_string_dbg(&user_sid))); + sid_string_dbg(&uinfo->sid))); TALLOC_FREE(sam_pass); return NT_STATUS_NO_SUCH_USER; } @@ -4743,7 +5356,7 @@ NTSTATUS _samr_DeleteUser(pipes_struct *p, ZERO_STRUCTP(r->out.user_handle); - force_flush_samr_cache(disp_info); + force_flush_samr_cache(&uinfo->sid); return NT_STATUS_OK; } @@ -4755,30 +5368,24 @@ NTSTATUS _samr_DeleteUser(pipes_struct *p, NTSTATUS _samr_DeleteDomainGroup(pipes_struct *p, struct samr_DeleteDomainGroup *r) { + struct samr_group_info *ginfo; NTSTATUS status; - DOM_SID group_sid; uint32 group_rid; - uint32 acc_granted; SE_PRIV se_rights; bool can_add_accounts; - DISP_INFO *disp_info = NULL; DEBUG(5, ("samr_DeleteDomainGroup: %d\n", __LINE__)); - /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, r->in.group_handle, &group_sid, &acc_granted, &disp_info)) - return NT_STATUS_INVALID_HANDLE; - - status = access_check_samr_function(acc_granted, - STD_RIGHT_DELETE_ACCESS, - "_samr_DeleteDomainGroup"); + ginfo = policy_handle_find(p, r->in.group_handle, + STD_RIGHT_DELETE_ACCESS, NULL, + struct samr_group_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } - DEBUG(10, ("sid is %s\n", sid_string_dbg(&group_sid))); + DEBUG(10, ("sid is %s\n", sid_string_dbg(&ginfo->sid))); - if (!sid_peek_check_rid(get_global_sam_sid(), &group_sid, + if (!sid_peek_check_rid(get_global_sam_sid(), &ginfo->sid, &group_rid)) { return NT_STATUS_NO_SUCH_GROUP; } @@ -4801,7 +5408,7 @@ NTSTATUS _samr_DeleteDomainGroup(pipes_struct *p, if ( !NT_STATUS_IS_OK(status) ) { DEBUG(5,("_samr_DeleteDomainGroup: Failed to delete mapping " "entry for group %s: %s\n", - sid_string_dbg(&group_sid), + sid_string_dbg(&ginfo->sid), nt_errstr(status))); return status; } @@ -4809,7 +5416,7 @@ NTSTATUS _samr_DeleteDomainGroup(pipes_struct *p, if (!close_policy_hnd(p, r->in.group_handle)) return NT_STATUS_OBJECT_NAME_INVALID; - force_flush_samr_cache(disp_info); + force_flush_samr_cache(&ginfo->sid); return NT_STATUS_OK; } @@ -4821,39 +5428,29 @@ NTSTATUS _samr_DeleteDomainGroup(pipes_struct *p, NTSTATUS _samr_DeleteDomAlias(pipes_struct *p, struct samr_DeleteDomAlias *r) { - DOM_SID alias_sid; - uint32 acc_granted; + struct samr_alias_info *ainfo; SE_PRIV se_rights; bool can_add_accounts; NTSTATUS status; - DISP_INFO *disp_info = NULL; DEBUG(5, ("_samr_DeleteDomAlias: %d\n", __LINE__)); - /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, r->in.alias_handle, &alias_sid, &acc_granted, &disp_info)) - return NT_STATUS_INVALID_HANDLE; - - /* copy the handle to the outgoing reply */ - - memcpy(r->out.alias_handle, r->in.alias_handle, sizeof(r->out.alias_handle)); - - status = access_check_samr_function(acc_granted, - STD_RIGHT_DELETE_ACCESS, - "_samr_DeleteDomAlias"); + ainfo = policy_handle_find(p, r->in.alias_handle, + STD_RIGHT_DELETE_ACCESS, NULL, + struct samr_alias_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } - DEBUG(10, ("sid is %s\n", sid_string_dbg(&alias_sid))); + DEBUG(10, ("sid is %s\n", sid_string_dbg(&ainfo->sid))); /* Don't let Windows delete builtin groups */ - if ( sid_check_is_in_builtin( &alias_sid ) ) { + if ( sid_check_is_in_builtin( &ainfo->sid ) ) { return NT_STATUS_SPECIAL_ACCOUNT; } - if (!sid_check_is_in_our_domain(&alias_sid)) + if (!sid_check_is_in_our_domain(&ainfo->sid)) return NT_STATUS_NO_SUCH_ALIAS; DEBUG(10, ("lookup on Local SID\n")); @@ -4867,7 +5464,7 @@ NTSTATUS _samr_DeleteDomAlias(pipes_struct *p, become_root(); /* Have passdb delete the alias */ - status = pdb_delete_alias(&alias_sid); + status = pdb_delete_alias(&ainfo->sid); if ( can_add_accounts ) unbecome_root(); @@ -4880,7 +5477,7 @@ NTSTATUS _samr_DeleteDomAlias(pipes_struct *p, if (!close_policy_hnd(p, r->in.alias_handle)) return NT_STATUS_OBJECT_NAME_INVALID; - force_flush_samr_cache(disp_info); + force_flush_samr_cache(&ainfo->sid); return NT_STATUS_OK; } @@ -4894,27 +5491,20 @@ NTSTATUS _samr_CreateDomainGroup(pipes_struct *p, { NTSTATUS status; - DOM_SID dom_sid; - DOM_SID info_sid; const char *name; - struct samr_info *info; - uint32 acc_granted; + struct samr_domain_info *dinfo; + struct samr_group_info *ginfo; SE_PRIV se_rights; bool can_add_accounts; - DISP_INFO *disp_info = NULL; - - /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, r->in.domain_handle, &dom_sid, &acc_granted, &disp_info)) - return NT_STATUS_INVALID_HANDLE; - status = access_check_samr_function(acc_granted, - SAMR_DOMAIN_ACCESS_CREATE_GROUP, - "_samr_CreateDomainGroup"); + dinfo = policy_handle_find(p, r->in.domain_handle, + SAMR_DOMAIN_ACCESS_CREATE_GROUP, NULL, + struct samr_domain_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } - if (!sid_equal(&dom_sid, get_global_sam_sid())) + if (!sid_equal(&dinfo->sid, get_global_sam_sid())) return NT_STATUS_ACCESS_DENIED; name = r->in.name->string; @@ -4949,20 +5539,15 @@ NTSTATUS _samr_CreateDomainGroup(pipes_struct *p, if ( !NT_STATUS_IS_OK(status) ) return status; - sid_compose(&info_sid, get_global_sam_sid(), *r->out.rid); - - if ((info = get_samr_info_by_sid(p->mem_ctx, &info_sid)) == NULL) - return NT_STATUS_NO_MEMORY; - - /* they created it; let the user do what he wants with it */ - - info->acc_granted = GENERIC_RIGHTS_GROUP_ALL_ACCESS; - - /* get a (unique) handle. open a policy on it. */ - if (!create_policy_hnd(p, r->out.group_handle, info)) - return NT_STATUS_OBJECT_NAME_NOT_FOUND; + ginfo = policy_handle_create(p, r->out.group_handle, + GENERIC_RIGHTS_GROUP_ALL_ACCESS, + struct samr_group_info, &status); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + sid_compose(&ginfo->sid, &dinfo->sid, *r->out.rid); - force_flush_samr_cache(disp_info); + force_flush_samr_cache(&dinfo->sid); return NT_STATUS_OK; } @@ -4974,29 +5559,23 @@ NTSTATUS _samr_CreateDomainGroup(pipes_struct *p, NTSTATUS _samr_CreateDomAlias(pipes_struct *p, struct samr_CreateDomAlias *r) { - DOM_SID dom_sid; DOM_SID info_sid; const char *name = NULL; - struct samr_info *info; - uint32 acc_granted; + struct samr_domain_info *dinfo; + struct samr_alias_info *ainfo; gid_t gid; NTSTATUS result; SE_PRIV se_rights; bool can_add_accounts; - DISP_INFO *disp_info = NULL; - - /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, r->in.domain_handle, &dom_sid, &acc_granted, &disp_info)) - return NT_STATUS_INVALID_HANDLE; - result = access_check_samr_function(acc_granted, - SAMR_DOMAIN_ACCESS_CREATE_ALIAS, - "_samr_CreateDomAlias"); + dinfo = policy_handle_find(p, r->in.domain_handle, + SAMR_DOMAIN_ACCESS_CREATE_ALIAS, NULL, + struct samr_domain_info, &result); if (!NT_STATUS_IS_OK(result)) { return result; } - if (!sid_equal(&dom_sid, get_global_sam_sid())) + if (!sid_equal(&dinfo->sid, get_global_sam_sid())) return NT_STATUS_ACCESS_DENIED; name = r->in.alias_name->string; @@ -5028,8 +5607,7 @@ NTSTATUS _samr_CreateDomAlias(pipes_struct *p, return result; } - sid_copy(&info_sid, get_global_sam_sid()); - sid_append_rid(&info_sid, *r->out.rid); + sid_compose(&info_sid, &dinfo->sid, *r->out.rid); if (!sid_to_gid(&info_sid, &gid)) { DEBUG(10, ("Could not find alias just created\n")); @@ -5043,18 +5621,15 @@ NTSTATUS _samr_CreateDomAlias(pipes_struct *p, return NT_STATUS_ACCESS_DENIED; } - if ((info = get_samr_info_by_sid(p->mem_ctx, &info_sid)) == NULL) - return NT_STATUS_NO_MEMORY; - - /* they created it; let the user do what he wants with it */ - - info->acc_granted = GENERIC_RIGHTS_ALIAS_ALL_ACCESS; - - /* get a (unique) handle. open a policy on it. */ - if (!create_policy_hnd(p, r->out.alias_handle, info)) - return NT_STATUS_OBJECT_NAME_NOT_FOUND; + ainfo = policy_handle_create(p, r->out.alias_handle, + GENERIC_RIGHTS_ALIAS_ALL_ACCESS, + struct samr_alias_info, &result); + if (!NT_STATUS_IS_OK(result)) { + return result; + } + ainfo->sid = info_sid; - force_flush_samr_cache(disp_info); + force_flush_samr_cache(&info_sid); return NT_STATUS_OK; } @@ -5066,11 +5641,10 @@ NTSTATUS _samr_CreateDomAlias(pipes_struct *p, NTSTATUS _samr_QueryGroupInfo(pipes_struct *p, struct samr_QueryGroupInfo *r) { + struct samr_group_info *ginfo; NTSTATUS status; - DOM_SID group_sid; GROUP_MAP map; union samr_GroupInfo *info = NULL; - uint32 acc_granted; bool ret; uint32_t attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | @@ -5078,18 +5652,15 @@ NTSTATUS _samr_QueryGroupInfo(pipes_struct *p, const char *group_name = NULL; const char *group_description = NULL; - if (!get_lsa_policy_samr_sid(p, r->in.group_handle, &group_sid, &acc_granted, NULL)) - return NT_STATUS_INVALID_HANDLE; - - status = access_check_samr_function(acc_granted, - SAMR_GROUP_ACCESS_LOOKUP_INFO, - "_samr_QueryGroupInfo"); + ginfo = policy_handle_find(p, r->in.group_handle, + SAMR_GROUP_ACCESS_LOOKUP_INFO, NULL, + struct samr_group_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } become_root(); - ret = get_domain_group_from_sid(group_sid, &map); + ret = get_domain_group_from_sid(ginfo->sid, &map); unbecome_root(); if (!ret) return NT_STATUS_INVALID_HANDLE; @@ -5110,7 +5681,8 @@ NTSTATUS _samr_QueryGroupInfo(pipes_struct *p, become_root(); status = pdb_enum_group_members( - p->mem_ctx, &group_sid, &members, &num_members); + p->mem_ctx, &ginfo->sid, &members, + &num_members); unbecome_root(); if (!NT_STATUS_IS_OK(status)) { @@ -5141,7 +5713,8 @@ NTSTATUS _samr_QueryGroupInfo(pipes_struct *p, /* become_root(); status = pdb_enum_group_members( - p->mem_ctx, &group_sid, &members, &num_members); + p->mem_ctx, &ginfo->sid, &members, + &num_members); unbecome_root(); if (!NT_STATUS_IS_OK(status)) { @@ -5171,26 +5744,21 @@ NTSTATUS _samr_QueryGroupInfo(pipes_struct *p, NTSTATUS _samr_SetGroupInfo(pipes_struct *p, struct samr_SetGroupInfo *r) { - DOM_SID group_sid; + struct samr_group_info *ginfo; GROUP_MAP map; - uint32 acc_granted; NTSTATUS status; bool ret; bool can_mod_accounts; - DISP_INFO *disp_info = NULL; - - if (!get_lsa_policy_samr_sid(p, r->in.group_handle, &group_sid, &acc_granted, &disp_info)) - return NT_STATUS_INVALID_HANDLE; - status = access_check_samr_function(acc_granted, - SAMR_GROUP_ACCESS_SET_INFO, - "_samr_SetGroupInfo"); + ginfo = policy_handle_find(p, r->in.group_handle, + SAMR_GROUP_ACCESS_SET_INFO, NULL, + struct samr_group_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } become_root(); - ret = get_domain_group_from_sid(group_sid, &map); + ret = get_domain_group_from_sid(ginfo->sid, &map); unbecome_root(); if (!ret) return NT_STATUS_NO_SUCH_GROUP; @@ -5224,7 +5792,7 @@ NTSTATUS _samr_SetGroupInfo(pipes_struct *p, /******** End SeAddUsers BLOCK *********/ if (NT_STATUS_IS_OK(status)) { - force_flush_samr_cache(disp_info); + force_flush_samr_cache(&ginfo->sid); } return status; @@ -5237,19 +5805,14 @@ NTSTATUS _samr_SetGroupInfo(pipes_struct *p, NTSTATUS _samr_SetAliasInfo(pipes_struct *p, struct samr_SetAliasInfo *r) { - DOM_SID group_sid; + struct samr_alias_info *ainfo; struct acct_info info; - uint32 acc_granted; bool can_mod_accounts; NTSTATUS status; - DISP_INFO *disp_info = NULL; - - if (!get_lsa_policy_samr_sid(p, r->in.alias_handle, &group_sid, &acc_granted, &disp_info)) - return NT_STATUS_INVALID_HANDLE; - status = access_check_samr_function(acc_granted, - SAMR_ALIAS_ACCESS_SET_INFO, - "_samr_SetAliasInfo"); + ainfo = policy_handle_find(p, r->in.alias_handle, + SAMR_ALIAS_ACCESS_SET_INFO, NULL, + struct samr_alias_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -5257,7 +5820,7 @@ NTSTATUS _samr_SetAliasInfo(pipes_struct *p, /* get the current group information */ become_root(); - status = pdb_get_aliasinfo( &group_sid, &info ); + status = pdb_get_aliasinfo( &ainfo->sid, &info ); unbecome_root(); if ( !NT_STATUS_IS_OK(status)) @@ -5273,7 +5836,7 @@ NTSTATUS _samr_SetAliasInfo(pipes_struct *p, why. The eventually needs to be fixed to be like Windows where you can rename builtin groups, just not delete them */ - if ( sid_check_is_in_builtin( &group_sid ) ) { + if ( sid_check_is_in_builtin( &ainfo->sid ) ) { return NT_STATUS_SPECIAL_ACCOUNT; } @@ -5318,7 +5881,7 @@ NTSTATUS _samr_SetAliasInfo(pipes_struct *p, if ( can_mod_accounts ) become_root(); - status = pdb_set_aliasinfo( &group_sid, &info ); + status = pdb_set_aliasinfo( &ainfo->sid, &info ); if ( can_mod_accounts ) unbecome_root(); @@ -5326,7 +5889,7 @@ NTSTATUS _samr_SetAliasInfo(pipes_struct *p, /******** End SeAddUsers BLOCK *********/ if (NT_STATUS_IS_OK(status)) - force_flush_samr_cache(disp_info); + force_flush_samr_cache(&ainfo->sid); return status; } @@ -5375,28 +5938,24 @@ NTSTATUS _samr_OpenGroup(pipes_struct *p, struct samr_OpenGroup *r) { - DOM_SID sid; DOM_SID info_sid; GROUP_MAP map; - struct samr_info *info; + struct samr_domain_info *dinfo; + struct samr_group_info *ginfo; SEC_DESC *psd = NULL; uint32 acc_granted; uint32 des_access = r->in.access_mask; size_t sd_size; NTSTATUS status; - fstring sid_string; bool ret; SE_PRIV se_rights; - if (!get_lsa_policy_samr_sid(p, r->in.domain_handle, &sid, &acc_granted, NULL)) - return NT_STATUS_INVALID_HANDLE; - - status = access_check_samr_function(acc_granted, - SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, - "_samr_OpenGroup"); - - if ( !NT_STATUS_IS_OK(status) ) + dinfo = policy_handle_find(p, r->in.domain_handle, + SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, NULL, + struct samr_domain_info, &status); + if (!NT_STATUS_IS_OK(status)) { return status; + } /*check if access can be granted as requested by client. */ map_max_allowed_access(p->server_info->ptok, &des_access); @@ -5415,30 +5974,28 @@ NTSTATUS _samr_OpenGroup(pipes_struct *p, /* this should not be hard-coded like this */ - if (!sid_equal(&sid, get_global_sam_sid())) + if (!sid_equal(&dinfo->sid, get_global_sam_sid())) return NT_STATUS_ACCESS_DENIED; - sid_copy(&info_sid, get_global_sam_sid()); - sid_append_rid(&info_sid, r->in.rid); - sid_to_fstring(sid_string, &info_sid); - - if ((info = get_samr_info_by_sid(p->mem_ctx, &info_sid)) == NULL) - return NT_STATUS_NO_MEMORY; - - info->acc_granted = acc_granted; + sid_compose(&info_sid, &dinfo->sid, r->in.rid); - DEBUG(10, ("_samr_OpenGroup:Opening SID: %s\n", sid_string)); + DEBUG(10, ("_samr_OpenGroup:Opening SID: %s\n", + sid_string_dbg(&info_sid))); /* check if that group really exists */ become_root(); - ret = get_domain_group_from_sid(info->sid, &map); + ret = get_domain_group_from_sid(info_sid, &map); unbecome_root(); if (!ret) return NT_STATUS_NO_SUCH_GROUP; - /* get a (unique) handle. open a policy on it. */ - if (!create_policy_hnd(p, r->out.group_handle, info)) - return NT_STATUS_OBJECT_NAME_NOT_FOUND; + ginfo = policy_handle_create(p, r->out.group_handle, + GENERIC_RIGHTS_GROUP_ALL_ACCESS, + struct samr_group_info, &status); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + ginfo->sid = info_sid; return NT_STATUS_OK; } @@ -5450,31 +6007,23 @@ NTSTATUS _samr_OpenGroup(pipes_struct *p, NTSTATUS _samr_RemoveMemberFromForeignDomain(pipes_struct *p, struct samr_RemoveMemberFromForeignDomain *r) { - DOM_SID delete_sid, domain_sid; - uint32 acc_granted; + struct samr_domain_info *dinfo; NTSTATUS result; - DISP_INFO *disp_info = NULL; - - sid_copy( &delete_sid, r->in.sid ); DEBUG(5,("_samr_RemoveMemberFromForeignDomain: removing SID [%s]\n", - sid_string_dbg(&delete_sid))); + sid_string_dbg(r->in.sid))); /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, r->in.domain_handle, &domain_sid, - &acc_granted, &disp_info)) - return NT_STATUS_INVALID_HANDLE; - - result = access_check_samr_function(acc_granted, - STD_RIGHT_DELETE_ACCESS, - "_samr_RemoveMemberFromForeignDomain"); - - if (!NT_STATUS_IS_OK(result)) + dinfo = policy_handle_find(p, r->in.domain_handle, + STD_RIGHT_DELETE_ACCESS, NULL, + struct samr_domain_info, &result); + if (!NT_STATUS_IS_OK(result)) { return result; + } DEBUG(8, ("_samr_RemoveMemberFromForeignDomain: sid is %s\n", - sid_string_dbg(&domain_sid))); + sid_string_dbg(&dinfo->sid))); /* we can only delete a user from a group since we don't have nested groups anyways. So in the latter case, just say OK */ @@ -5490,16 +6039,16 @@ NTSTATUS _samr_RemoveMemberFromForeignDomain(pipes_struct *p, * only application of this call. To verify this, let people report * other cases. */ - if (!sid_check_is_builtin(&domain_sid)) { + if (!sid_check_is_builtin(&dinfo->sid)) { DEBUG(1,("_samr_RemoveMemberFromForeignDomain: domain_sid = %s, " "global_sam_sid() = %s\n", - sid_string_dbg(&domain_sid), + sid_string_dbg(&dinfo->sid), sid_string_dbg(get_global_sam_sid()))); DEBUGADD(1,("please report to samba-technical@samba.org!\n")); return NT_STATUS_OK; } - force_flush_samr_cache(disp_info); + force_flush_samr_cache(&dinfo->sid); result = NT_STATUS_OK; @@ -5530,7 +6079,7 @@ NTSTATUS _samr_QueryDomainInfo2(pipes_struct *p, NTSTATUS _samr_SetDomainInfo(pipes_struct *p, struct samr_SetDomainInfo *r) { - struct samr_info *info = NULL; + struct samr_domain_info *dinfo; time_t u_expire, u_min_age; time_t u_logout; time_t u_lock_duration, u_reset_time; @@ -5538,10 +6087,6 @@ NTSTATUS _samr_SetDomainInfo(pipes_struct *p, DEBUG(5,("_samr_SetDomainInfo: %d\n", __LINE__)); - /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, r->in.domain_handle, (void **)(void *)&info)) - return NT_STATUS_INVALID_HANDLE; - /* We do have different access bits for info * levels here, but we're really just looking for * GENERIC_RIGHTS_DOMAIN_WRITE access. Unfortunately @@ -5549,12 +6094,12 @@ NTSTATUS _samr_SetDomainInfo(pipes_struct *p, * assume if we have SAMR_DOMAIN_ACCESS_SET_INFO_1 * set we are ok. */ - result = access_check_samr_function(info->acc_granted, - SAMR_DOMAIN_ACCESS_SET_INFO_1, - "_samr_SetDomainInfo"); - - if (!NT_STATUS_IS_OK(result)) + dinfo = policy_handle_find(p, r->in.domain_handle, + SAMR_DOMAIN_ACCESS_SET_INFO_1, NULL, + struct samr_domain_info, &result); + if (!NT_STATUS_IS_OK(result)) { return result; + } DEBUG(5,("_samr_SetDomainInfo: level: %d\n", r->in.level)); @@ -5568,18 +6113,18 @@ NTSTATUS _samr_SetDomainInfo(pipes_struct *p, pdb_set_account_policy(AP_MAX_PASSWORD_AGE, (int)u_expire); pdb_set_account_policy(AP_MIN_PASSWORD_AGE, (int)u_min_age); break; - case 0x02: - break; case 0x03: u_logout=nt_time_to_unix_abs((NTTIME *)&r->in.info->info3.force_logoff_time); pdb_set_account_policy(AP_TIME_TO_LOGOUT, (int)u_logout); break; - case 0x05: + case 0x04: break; case 0x06: break; case 0x07: break; + case 0x09: + break; case 0x0c: u_lock_duration=nt_time_to_unix_abs((NTTIME *)&r->in.info->info12.lockout_duration); if (u_lock_duration != -1) @@ -5607,7 +6152,7 @@ NTSTATUS _samr_SetDomainInfo(pipes_struct *p, NTSTATUS _samr_GetDisplayEnumerationIndex(pipes_struct *p, struct samr_GetDisplayEnumerationIndex *r) { - struct samr_info *info = NULL; + struct samr_domain_info *dinfo; uint32_t max_entries = (uint32_t) -1; uint32_t enum_context = 0; int i; @@ -5617,14 +6162,9 @@ NTSTATUS _samr_GetDisplayEnumerationIndex(pipes_struct *p, DEBUG(5,("_samr_GetDisplayEnumerationIndex: %d\n", __LINE__)); - /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, r->in.domain_handle, (void **)(void *)&info)) { - return NT_STATUS_INVALID_HANDLE; - } - - status = access_check_samr_function(info->acc_granted, - SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, - "_samr_GetDisplayEnumerationIndex"); + dinfo = policy_handle_find(p, r->in.domain_handle, + SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, NULL, + struct samr_domain_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -5642,10 +6182,10 @@ NTSTATUS _samr_GetDisplayEnumerationIndex(pipes_struct *p, switch (r->in.level) { case 1: - if (info->disp_info->users == NULL) { - info->disp_info->users = pdb_search_users( - info->disp_info, ACB_NORMAL); - if (info->disp_info->users == NULL) { + if (dinfo->disp_info->users == NULL) { + dinfo->disp_info->users = pdb_search_users( + dinfo->disp_info, ACB_NORMAL); + if (dinfo->disp_info->users == NULL) { unbecome_root(); return NT_STATUS_ACCESS_DENIED; } @@ -5657,15 +6197,15 @@ NTSTATUS _samr_GetDisplayEnumerationIndex(pipes_struct *p, "using cached user enumeration at index %u\n", (unsigned int)enum_context)); } - num_account = pdb_search_entries(info->disp_info->users, + num_account = pdb_search_entries(dinfo->disp_info->users, enum_context, max_entries, &entries); break; case 2: - if (info->disp_info->machines == NULL) { - info->disp_info->machines = pdb_search_users( - info->disp_info, ACB_WSTRUST|ACB_SVRTRUST); - if (info->disp_info->machines == NULL) { + if (dinfo->disp_info->machines == NULL) { + dinfo->disp_info->machines = pdb_search_users( + dinfo->disp_info, ACB_WSTRUST|ACB_SVRTRUST); + if (dinfo->disp_info->machines == NULL) { unbecome_root(); return NT_STATUS_ACCESS_DENIED; } @@ -5677,15 +6217,15 @@ NTSTATUS _samr_GetDisplayEnumerationIndex(pipes_struct *p, "using cached machine enumeration at index %u\n", (unsigned int)enum_context)); } - num_account = pdb_search_entries(info->disp_info->machines, + num_account = pdb_search_entries(dinfo->disp_info->machines, enum_context, max_entries, &entries); break; case 3: - if (info->disp_info->groups == NULL) { - info->disp_info->groups = pdb_search_groups( - info->disp_info); - if (info->disp_info->groups == NULL) { + if (dinfo->disp_info->groups == NULL) { + dinfo->disp_info->groups = pdb_search_groups( + dinfo->disp_info); + if (dinfo->disp_info->groups == NULL) { unbecome_root(); return NT_STATUS_ACCESS_DENIED; } @@ -5697,7 +6237,7 @@ NTSTATUS _samr_GetDisplayEnumerationIndex(pipes_struct *p, "using cached group enumeration at index %u\n", (unsigned int)enum_context)); } - num_account = pdb_search_entries(info->disp_info->groups, + num_account = pdb_search_entries(dinfo->disp_info->groups, enum_context, max_entries, &entries); break; @@ -5710,7 +6250,7 @@ NTSTATUS _samr_GetDisplayEnumerationIndex(pipes_struct *p, unbecome_root(); /* Ensure we cache this enumeration. */ - set_disp_info_cache_timeout(info->disp_info, DISP_INFO_CACHE_TIMEOUT); + set_disp_info_cache_timeout(dinfo->disp_info, DISP_INFO_CACHE_TIMEOUT); DEBUG(10,("_samr_GetDisplayEnumerationIndex: looking for :%s\n", r->in.name->string)); @@ -5772,16 +6312,6 @@ NTSTATUS _samr_SetMemberAttributesOfGroup(pipes_struct *p, /**************************************************************** ****************************************************************/ -NTSTATUS _samr_ChangePasswordUser(pipes_struct *p, - struct samr_ChangePasswordUser *r) -{ - p->rng_fault_state = true; - return NT_STATUS_NOT_IMPLEMENTED; -} - -/**************************************************************** -****************************************************************/ - NTSTATUS _samr_TestPrivateFunctionsDomain(pipes_struct *p, struct samr_TestPrivateFunctionsDomain *r) { @@ -5795,7 +6325,6 @@ NTSTATUS _samr_TestPrivateFunctionsDomain(pipes_struct *p, NTSTATUS _samr_TestPrivateFunctionsUser(pipes_struct *p, struct samr_TestPrivateFunctionsUser *r) { - p->rng_fault_state = true; return NT_STATUS_NOT_IMPLEMENTED; } @@ -5822,16 +6351,6 @@ NTSTATUS _samr_RemoveMultipleMembersFromAlias(pipes_struct *p, /**************************************************************** ****************************************************************/ -NTSTATUS _samr_OemChangePasswordUser2(pipes_struct *p, - struct samr_OemChangePasswordUser2 *r) -{ - p->rng_fault_state = true; - return NT_STATUS_NOT_IMPLEMENTED; -} - -/**************************************************************** -****************************************************************/ - NTSTATUS _samr_SetBootKeyInformation(pipes_struct *p, struct samr_SetBootKeyInformation *r) { @@ -5852,16 +6371,6 @@ NTSTATUS _samr_GetBootKeyInformation(pipes_struct *p, /**************************************************************** ****************************************************************/ -NTSTATUS _samr_Connect3(pipes_struct *p, - struct samr_Connect3 *r) -{ - p->rng_fault_state = true; - return NT_STATUS_NOT_IMPLEMENTED; -} - -/**************************************************************** -****************************************************************/ - NTSTATUS _samr_RidToSid(pipes_struct *p, struct samr_RidToSid *r) {