diff options
Diffstat (limited to 'source3/rpc_server/srv_samr_nt.c')
-rw-r--r-- | source3/rpc_server/srv_samr_nt.c | 3508 |
1 files changed, 2092 insertions, 1416 deletions
diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index 01ce932afa..f38a8fcfc0 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -11,6 +11,7 @@ * Copyright (C) Gerald (Jerry) Carter 2003-2004, * Copyright (C) Simo Sorce 2003. * Copyright (C) Volker Lendecke 2005. + * Copyright (C) Guenther Deschner 2008. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -125,12 +126,12 @@ static NTSTATUS make_samr_object_sd( TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd /* add Full Access 'BUILTIN\Administrators' and 'BUILTIN\Account Operators */ init_sec_access(&mask, map->generic_all); - + init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); init_sec_ace(&ace[i++], &global_sid_Builtin_Account_Operators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); /* Add Full Access for Domain Admins if we are a DC */ - + if ( IS_DC ) { sid_copy( &domadmin_sid, get_global_sam_sid() ); sid_append_rid( &domadmin_sid, DOMAIN_GROUP_RID_ADMINS ); @@ -162,57 +163,57 @@ static NTSTATUS make_samr_object_sd( TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd level of access for further checks. ********************************************************************/ -static NTSTATUS access_check_samr_object( SEC_DESC *psd, NT_USER_TOKEN *token, +static NTSTATUS access_check_samr_object( SEC_DESC *psd, NT_USER_TOKEN *token, SE_PRIV *rights, uint32 rights_mask, - uint32 des_access, uint32 *acc_granted, + uint32 des_access, uint32 *acc_granted, const char *debug ) { NTSTATUS status = NT_STATUS_ACCESS_DENIED; uint32 saved_mask = 0; - /* check privileges; certain SAM access bits should be overridden - by privileges (mostly having to do with creating/modifying/deleting + /* check privileges; certain SAM access bits should be overridden + by privileges (mostly having to do with creating/modifying/deleting users and groups) */ - + if ( rights && user_has_any_privilege( token, rights ) ) { - + saved_mask = (des_access & rights_mask); des_access &= ~saved_mask; - + DEBUG(4,("access_check_samr_object: user rights access mask [0x%x]\n", rights_mask)); } - - + + /* check the security descriptor first */ - + if ( se_access_check(psd, token, des_access, acc_granted, &status) ) goto done; - + /* give root a free pass */ - + if ( geteuid() == sec_initial_uid() ) { - + DEBUG(4,("%s: ACCESS should be DENIED (requested: %#010x)\n", debug, des_access)); DEBUGADD(4,("but overritten by euid == sec_initial_uid()\n")); - + *acc_granted = des_access; - + status = NT_STATUS_OK; goto done; } - - + + done: - /* add in any bits saved during the privilege check (only + /* add in any bits saved during the privilege check (only matters is status is ok) */ - + *acc_granted |= rights_mask; - DEBUG(4,("%s: access %s (requested: 0x%08x, granted: 0x%08x)\n", - debug, NT_STATUS_IS_OK(status) ? "GRANTED" : "DENIED", + DEBUG(4,("%s: access %s (requested: 0x%08x, granted: 0x%08x)\n", + debug, NT_STATUS_IS_OK(status) ? "GRANTED" : "DENIED", des_access, *acc_granted)); - + return status; } @@ -222,28 +223,28 @@ done: 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(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(2,("%s: ACCESS DENIED (granted: %#010x; required: %#010x)\n", debug, acc_granted, acc_required)); - + return NT_STATUS_ACCESS_DENIED; } @@ -278,7 +279,7 @@ static DISP_INFO *get_samr_dispinfo_by_sid(DOM_SID *psid) /* There are two cases to consider here: 1) The SID is a domain SID and we look for an equality match, or - 2) This is an account SID and so we return the DISP_INFO* for our + 2) This is an account SID and so we return the DISP_INFO* for our domain */ if (psid == NULL) { @@ -293,7 +294,7 @@ static DISP_INFO *get_samr_dispinfo_by_sid(DOM_SID *psid) return &builtin_dispinfo; } - + if (sid_check_is_domain(psid) || sid_check_is_in_our_domain(psid)) { /* * Necessary only once, but it does not really hurt. @@ -315,7 +316,7 @@ static struct samr_info *get_samr_info_by_sid(DOM_SID *psid) struct samr_info *info; fstring sid_str; TALLOC_CTX *mem_ctx; - + if (psid) { sid_to_fstring(sid_str, psid); } else { @@ -465,7 +466,7 @@ static void force_flush_samr_cache(DISP_INFO *disp_info) static void samr_clear_sam_passwd(struct samu *sam_pass) { - + if (!sam_pass) return; @@ -543,116 +544,113 @@ static uint32 count_sam_aliases(struct disp_info *info) } /******************************************************************* - _samr_close_hnd + _samr_Close ********************************************************************/ -NTSTATUS _samr_close_hnd(pipes_struct *p, SAMR_Q_CLOSE_HND *q_u, SAMR_R_CLOSE_HND *r_u) +NTSTATUS _samr_Close(pipes_struct *p, struct samr_Close *r) { - r_u->status = NT_STATUS_OK; - - /* close the policy handle */ - if (!close_policy_hnd(p, &q_u->pol)) - return NT_STATUS_OBJECT_NAME_INVALID; + if (!close_policy_hnd(p, r->in.handle)) { + return NT_STATUS_INVALID_HANDLE; + } - DEBUG(5,("samr_reply_close_hnd: %d\n", __LINE__)); + ZERO_STRUCTP(r->out.handle); - return r_u->status; + return NT_STATUS_OK; } /******************************************************************* - samr_reply_open_domain + _samr_OpenDomain ********************************************************************/ -NTSTATUS _samr_open_domain(pipes_struct *p, SAMR_Q_OPEN_DOMAIN *q_u, SAMR_R_OPEN_DOMAIN *r_u) +NTSTATUS _samr_OpenDomain(pipes_struct *p, + struct samr_OpenDomain *r) { struct samr_info *info; SEC_DESC *psd = NULL; uint32 acc_granted; - uint32 des_access = q_u->flags; + uint32 des_access = r->in.access_mask; NTSTATUS status; size_t sd_size; SE_PRIV se_rights; - r_u->status = NT_STATUS_OK; - /* find the connection policy handle. */ - - if ( !find_policy_by_hnd(p, &q_u->pol, (void**)(void *)&info) ) + + 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, - SA_RIGHT_SAM_OPEN_DOMAIN, "_samr_open_domain" ); - + status = access_check_samr_function(info->acc_granted, + SA_RIGHT_SAM_OPEN_DOMAIN, + "_samr_OpenDomain" ); + if ( !NT_STATUS_IS_OK(status) ) return status; /*check if access can be granted as requested by client. */ - + make_samr_object_sd( p->mem_ctx, &psd, &sd_size, &dom_generic_mapping, NULL, 0 ); se_map_generic( &des_access, &dom_generic_mapping ); - + se_priv_copy( &se_rights, &se_machine_account ); se_priv_add( &se_rights, &se_add_users ); - status = access_check_samr_object( psd, p->pipe_user.nt_user_token, - &se_rights, GENERIC_RIGHTS_DOMAIN_WRITE, des_access, - &acc_granted, "_samr_open_domain" ); - + status = access_check_samr_object( psd, p->pipe_user.nt_user_token, + &se_rights, GENERIC_RIGHTS_DOMAIN_WRITE, des_access, + &acc_granted, "_samr_OpenDomain" ); + if ( !NT_STATUS_IS_OK(status) ) return status; - if (!sid_check_is_domain(&q_u->dom_sid.sid) && - !sid_check_is_builtin(&q_u->dom_sid.sid)) { + if (!sid_check_is_domain(r->in.sid) && + !sid_check_is_builtin(r->in.sid)) { return NT_STATUS_NO_SUCH_DOMAIN; } /* associate the domain SID with the (unique) handle. */ - if ((info = get_samr_info_by_sid(&q_u->dom_sid.sid))==NULL) + if ((info = get_samr_info_by_sid(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_u->domain_pol, free_samr_info, (void *)info)) + if (!create_policy_hnd(p, r->out.domain_handle, free_samr_info, (void *)info)) return NT_STATUS_OBJECT_NAME_NOT_FOUND; - DEBUG(5,("samr_open_domain: %d\n", __LINE__)); + DEBUG(5,("_samr_OpenDomain: %d\n", __LINE__)); - return r_u->status; + return NT_STATUS_OK; } /******************************************************************* - _samr_get_usrdom_pwinfo + _samr_GetUserPwInfo ********************************************************************/ -NTSTATUS _samr_get_usrdom_pwinfo(pipes_struct *p, SAMR_Q_GET_USRDOM_PWINFO *q_u, SAMR_R_GET_USRDOM_PWINFO *r_u) +NTSTATUS _samr_GetUserPwInfo(pipes_struct *p, + struct samr_GetUserPwInfo *r) { struct samr_info *info = NULL; - r_u->status = NT_STATUS_OK; - /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, &q_u->user_pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, r->in.user_handle, (void **)(void *)&info)) return NT_STATUS_INVALID_HANDLE; if (!sid_check_is_in_our_domain(&info->sid)) return NT_STATUS_OBJECT_TYPE_MISMATCH; - init_samr_r_get_usrdom_pwinfo(r_u, NT_STATUS_OK); + ZERO_STRUCTP(r->out.info); - DEBUG(5,("_samr_get_usrdom_pwinfo: %d\n", __LINE__)); + DEBUG(5,("_samr_GetUserPwInfo: %d\n", __LINE__)); - /* + /* * NT sometimes return NT_STATUS_ACCESS_DENIED * I don't know yet why. */ - return r_u->status; + return NT_STATUS_OK; } /******************************************************************* ********************************************************************/ -static bool get_lsa_policy_samr_sid( pipes_struct *p, POLICY_HND *pol, +static bool get_lsa_policy_samr_sid( pipes_struct *p, POLICY_HND *pol, DOM_SID *sid, uint32 *acc_granted, DISP_INFO **ppdisp_info) { @@ -675,10 +673,11 @@ static bool get_lsa_policy_samr_sid( pipes_struct *p, POLICY_HND *pol, } /******************************************************************* - _samr_set_sec_obj + _samr_SetSecurity ********************************************************************/ -NTSTATUS _samr_set_sec_obj(pipes_struct *p, SAMR_Q_SET_SEC_OBJ *q_u, SAMR_R_SET_SEC_OBJ *r_u) +NTSTATUS _samr_SetSecurity(pipes_struct *p, + struct samr_SetSecurity *r) { DOM_SID pol_sid; uint32 acc_granted, i; @@ -687,9 +686,7 @@ NTSTATUS _samr_set_sec_obj(pipes_struct *p, SAMR_Q_SET_SEC_OBJ *q_u, SAMR_R_SET_ struct samu *sampass=NULL; NTSTATUS status; - r_u->status = NT_STATUS_OK; - - if (!get_lsa_policy_samr_sid(p, &q_u->pol, &pol_sid, &acc_granted, NULL)) + if (!get_lsa_policy_samr_sid(p, r->in.handle, &pol_sid, &acc_granted, NULL)) return NT_STATUS_INVALID_HANDLE; if (!(sampass = samu_new( p->mem_ctx))) { @@ -708,12 +705,12 @@ NTSTATUS _samr_set_sec_obj(pipes_struct *p, SAMR_Q_SET_SEC_OBJ *q_u, SAMR_R_SET_ return NT_STATUS_INVALID_HANDLE; } - dacl = q_u->buf->sd->dacl; + dacl = r->in.sdbuf->sd->dacl; for (i=0; i < dacl->num_aces; i++) { if (sid_equal(&pol_sid, &dacl->aces[i].trustee)) { - ret = pdb_set_pass_can_change(sampass, - (dacl->aces[i].access_mask & - SA_RIGHT_USER_CHANGE_PASSWORD) ? + ret = pdb_set_pass_can_change(sampass, + (dacl->aces[i].access_mask & + SA_RIGHT_USER_CHANGE_PASSWORD) ? True: False); break; } @@ -724,7 +721,9 @@ NTSTATUS _samr_set_sec_obj(pipes_struct *p, SAMR_Q_SET_SEC_OBJ *q_u, SAMR_R_SET_ return NT_STATUS_ACCESS_DENIED; } - status = access_check_samr_function(acc_granted, SA_RIGHT_USER_SET_ATTRIBUTES, "_samr_set_sec_obj"); + status = access_check_samr_function(acc_granted, + SA_RIGHT_USER_SET_ATTRIBUTES, + "_samr_SetSecurity"); if (NT_STATUS_IS_OK(status)) { become_root(); status = pdb_update_sam_account(sampass); @@ -771,98 +770,92 @@ static bool check_change_pw_access(TALLOC_CTX *mem_ctx, DOM_SID *user_sid) /******************************************************************* - _samr_query_sec_obj + _samr_QuerySecurity ********************************************************************/ -NTSTATUS _samr_query_sec_obj(pipes_struct *p, SAMR_Q_QUERY_SEC_OBJ *q_u, SAMR_R_QUERY_SEC_OBJ *r_u) +NTSTATUS _samr_QuerySecurity(pipes_struct *p, + struct samr_QuerySecurity *r) { + NTSTATUS status; DOM_SID pol_sid; SEC_DESC * psd = NULL; uint32 acc_granted; size_t sd_size; - r_u->status = NT_STATUS_OK; - /* Get the SID. */ - if (!get_lsa_policy_samr_sid(p, &q_u->user_pol, &pol_sid, &acc_granted, NULL)) + if (!get_lsa_policy_samr_sid(p, r->in.handle, &pol_sid, &acc_granted, NULL)) return NT_STATUS_INVALID_HANDLE; - DEBUG(10,("_samr_query_sec_obj: querying security on SID: %s\n", + DEBUG(10,("_samr_QuerySecurity: querying security on SID: %s\n", sid_string_dbg(&pol_sid))); /* 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_query_sec_obj: querying security on SAM\n")); - r_u->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())) { + 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 */ - DEBUG(5,("_samr_query_sec_obj: querying security on Domain " + DEBUG(5,("_samr_QuerySecurity: querying security on Domain " "with SID: %s\n", sid_string_dbg(&pol_sid))); - r_u->status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &dom_generic_mapping, NULL, 0); + 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_query_sec_obj: querying security on Builtin " + DEBUG(5,("_samr_QuerySecurity: querying security on Builtin " "Domain with SID: %s\n", sid_string_dbg(&pol_sid))); - r_u->status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &dom_generic_mapping, NULL, 0); + 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_query_sec_obj: querying security on Object " + 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)) { - r_u->status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_generic_mapping, + status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_generic_mapping, &pol_sid, SAMR_USR_RIGHTS_WRITE_PW); } else { - r_u->status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_nopwchange_generic_mapping, + status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_nopwchange_generic_mapping, &pol_sid, SAMR_USR_RIGHTS_CANT_WRITE_PW); } } else { return NT_STATUS_OBJECT_TYPE_MISMATCH; } - if ((r_u->buf = make_sec_desc_buf(p->mem_ctx, sd_size, psd)) == NULL) + if ((*r->out.sdbuf = make_sec_desc_buf(p->mem_ctx, sd_size, psd)) == NULL) return NT_STATUS_NO_MEMORY; - if (NT_STATUS_IS_OK(r_u->status)) - r_u->ptr = 1; - - return r_u->status; + return status; } /******************************************************************* makes a SAM_ENTRY / UNISTR2* structure from a user list. ********************************************************************/ -static NTSTATUS make_user_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, - UNISTR2 **uni_name_pp, - uint32 num_entries, uint32 start_idx, +static NTSTATUS make_user_sam_entry_list(TALLOC_CTX *ctx, + struct samr_SamEntry **sam_pp, + uint32_t num_entries, + uint32_t start_idx, struct samr_displayentry *entries) { - uint32 i; - SAM_ENTRY *sam; - UNISTR2 *uni_name; - + uint32_t i; + struct samr_SamEntry *sam; + *sam_pp = NULL; - *uni_name_pp = NULL; - if (num_entries == 0) + if (num_entries == 0) { return NT_STATUS_OK; + } - sam = TALLOC_ZERO_ARRAY(ctx, SAM_ENTRY, num_entries); - - uni_name = TALLOC_ZERO_ARRAY(ctx, UNISTR2, num_entries); - - if (sam == NULL || uni_name == NULL) { + sam = TALLOC_ZERO_ARRAY(ctx, struct samr_SamEntry, num_entries); + if (sam == NULL) { DEBUG(0, ("make_user_sam_entry_list: TALLOC_ZERO failed!\n")); return NT_STATUS_NO_MEMORY; } for (i = 0; i < num_entries; i++) { - UNISTR2 uni_temp_name; +#if 0 /* * usrmgr expects a non-NULL terminated string with * trust relationships @@ -874,50 +867,59 @@ static NTSTATUS make_user_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, init_unistr2(&uni_temp_name, entries[i].account_name, UNI_STR_TERMINATE); } - - init_sam_entry(&sam[i], &uni_temp_name, entries[i].rid); - copy_unistr2(&uni_name[i], &uni_temp_name); +#endif + init_lsa_String(&sam[i].name, entries[i].account_name); + sam[i].idx = entries[i].rid; } *sam_pp = sam; - *uni_name_pp = uni_name; + return NT_STATUS_OK; } +#define MAX_SAM_ENTRIES MAX_SAM_ENTRIES_W2K + /******************************************************************* - samr_reply_enum_dom_users + _samr_EnumDomainUsers ********************************************************************/ -NTSTATUS _samr_enum_dom_users(pipes_struct *p, SAMR_Q_ENUM_DOM_USERS *q_u, - SAMR_R_ENUM_DOM_USERS *r_u) +NTSTATUS _samr_EnumDomainUsers(pipes_struct *p, + struct samr_EnumDomainUsers *r) { + NTSTATUS status; struct samr_info *info = NULL; int num_account; - uint32 enum_context=q_u->start_idx; + uint32 enum_context = *r->in.resume_handle; enum remote_arch_types ra_type = get_remote_arch(); int max_sam_entries = (ra_type == RA_WIN95) ? MAX_SAM_ENTRIES_W95 : MAX_SAM_ENTRIES_W2K; uint32 max_entries = max_sam_entries; struct samr_displayentry *entries = NULL; - - r_u->status = NT_STATUS_OK; + 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, &q_u->pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, r->in.domain_handle, (void **)(void *)&info)) return NT_STATUS_INVALID_HANDLE; - if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(info->acc_granted, - SA_RIGHT_DOMAIN_ENUM_ACCOUNTS, - "_samr_enum_dom_users"))) { - return r_u->status; + status = access_check_samr_function(info->acc_granted, + SA_RIGHT_DOMAIN_ENUM_ACCOUNTS, + "_samr_EnumDomainUsers"); + if (!NT_STATUS_IS_OK(status)) { + return status; } - - DEBUG(5,("_samr_enum_dom_users: %d\n", __LINE__)); + + DEBUG(5,("_samr_EnumDomainUsers: %d\n", __LINE__)); if (info->builtin_domain) { /* No users in builtin. */ - init_samr_r_enum_dom_users(r_u, q_u->start_idx, 0); - DEBUG(5,("_samr_enum_dom_users: No users in BUILTIN\n")); - return r_u->status; + *r->out.resume_handle = *r->in.resume_handle; + DEBUG(5,("_samr_EnumDomainUsers: No users in BUILTIN\n")); + return status; + } + + samr_array = TALLOC_ZERO_P(p->mem_ctx, struct samr_SamArray); + if (!samr_array) { + return NT_STATUS_NO_MEMORY; } become_root(); @@ -925,14 +927,14 @@ NTSTATUS _samr_enum_dom_users(pipes_struct *p, SAMR_Q_ENUM_DOM_USERS *q_u, /* AS ROOT !!!! */ if ((info->disp_info->enum_users != NULL) && - (info->disp_info->enum_acb_mask != q_u->acb_mask)) { + (info->disp_info->enum_acb_mask != r->in.acct_flags)) { pdb_search_destroy(info->disp_info->enum_users); info->disp_info->enum_users = NULL; } if (info->disp_info->enum_users == NULL) { - info->disp_info->enum_users = pdb_search_users(q_u->acb_mask); - info->disp_info->enum_acb_mask = q_u->acb_mask; + info->disp_info->enum_users = pdb_search_users(r->in.acct_flags); + info->disp_info->enum_acb_mask = r->in.acct_flags; } if (info->disp_info->enum_users == NULL) { @@ -950,63 +952,62 @@ NTSTATUS _samr_enum_dom_users(pipes_struct *p, SAMR_Q_ENUM_DOM_USERS *q_u, unbecome_root(); if (num_account == 0) { - DEBUG(5, ("_samr_enum_dom_users: enumeration handle over " + DEBUG(5, ("_samr_EnumDomainUsers: enumeration handle over " "total entries\n")); - init_samr_r_enum_dom_users(r_u, q_u->start_idx, 0); + *r->out.resume_handle = *r->in.resume_handle; return NT_STATUS_OK; } - r_u->status = make_user_sam_entry_list(p->mem_ctx, &r_u->sam, - &r_u->uni_acct_name, - num_account, enum_context, - entries); - - if (!NT_STATUS_IS_OK(r_u->status)) - return r_u->status; + status = make_user_sam_entry_list(p->mem_ctx, &samr_entries, + num_account, enum_context, + entries); + if (!NT_STATUS_IS_OK(status)) { + return status; + } if (max_entries <= num_account) { - r_u->status = STATUS_MORE_ENTRIES; + status = STATUS_MORE_ENTRIES; } else { - r_u->status = NT_STATUS_OK; + status = NT_STATUS_OK; } /* Ensure we cache this enumeration. */ set_disp_info_cache_timeout(info->disp_info, DISP_INFO_CACHE_TIMEOUT); - DEBUG(5, ("_samr_enum_dom_users: %d\n", __LINE__)); + DEBUG(5, ("_samr_EnumDomainUsers: %d\n", __LINE__)); - init_samr_r_enum_dom_users(r_u, q_u->start_idx + num_account, - num_account); + samr_array->count = num_account; + samr_array->entries = samr_entries; - DEBUG(5,("_samr_enum_dom_users: %d\n", __LINE__)); + *r->out.resume_handle = *r->in.resume_handle + num_account; + *r->out.sam = samr_array; + *r->out.num_entries = num_account; - return r_u->status; + DEBUG(5,("_samr_EnumDomainUsers: %d\n", __LINE__)); + + return status; } /******************************************************************* makes a SAM_ENTRY / UNISTR2* structure from a group list. ********************************************************************/ -static void make_group_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, - UNISTR2 **uni_name_pp, - uint32 num_sam_entries, +static void make_group_sam_entry_list(TALLOC_CTX *ctx, + struct samr_SamEntry **sam_pp, + uint32_t num_sam_entries, struct samr_displayentry *entries) { - uint32 i; - SAM_ENTRY *sam; - UNISTR2 *uni_name; + struct samr_SamEntry *sam; + uint32_t i; *sam_pp = NULL; - *uni_name_pp = NULL; - if (num_sam_entries == 0) + if (num_sam_entries == 0) { return; + } - sam = TALLOC_ZERO_ARRAY(ctx, SAM_ENTRY, num_sam_entries); - uni_name = TALLOC_ZERO_ARRAY(ctx, UNISTR2, num_sam_entries); - - if (sam == NULL || uni_name == NULL) { - DEBUG(0, ("NULL pointers in SAMR_R_QUERY_DISPINFO\n")); + sam = TALLOC_ZERO_ARRAY(ctx, struct samr_SamEntry, num_sam_entries); + if (sam == NULL) { return; } @@ -1014,44 +1015,50 @@ static void make_group_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, /* * JRA. I think this should include the null. TNG does not. */ - init_unistr2(&uni_name[i], entries[i].account_name, - UNI_STR_TERMINATE); - init_sam_entry(&sam[i], &uni_name[i], entries[i].rid); + init_lsa_String(&sam[i].name, entries[i].account_name); + sam[i].idx = entries[i].rid; } *sam_pp = sam; - *uni_name_pp = uni_name; } /******************************************************************* - samr_reply_enum_dom_groups + _samr_EnumDomainGroups ********************************************************************/ -NTSTATUS _samr_enum_dom_groups(pipes_struct *p, SAMR_Q_ENUM_DOM_GROUPS *q_u, SAMR_R_ENUM_DOM_GROUPS *r_u) +NTSTATUS _samr_EnumDomainGroups(pipes_struct *p, + struct samr_EnumDomainGroups *r) { + NTSTATUS status; struct samr_info *info = NULL; struct samr_displayentry *groups; uint32 num_groups; - - r_u->status = NT_STATUS_OK; + 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, &q_u->pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, r->in.domain_handle, (void **)(void *)&info)) return NT_STATUS_INVALID_HANDLE; - r_u->status = access_check_samr_function(info->acc_granted, - SA_RIGHT_DOMAIN_ENUM_ACCOUNTS, - "_samr_enum_dom_groups"); - if (!NT_STATUS_IS_OK(r_u->status)) - return r_u->status; + status = access_check_samr_function(info->acc_granted, + SA_RIGHT_DOMAIN_ENUM_ACCOUNTS, + "_samr_EnumDomainGroups"); + if (!NT_STATUS_IS_OK(status)) { + return status; + } - DEBUG(5,("samr_reply_enum_dom_groups: %d\n", __LINE__)); + DEBUG(5,("_samr_EnumDomainGroups: %d\n", __LINE__)); if (info->builtin_domain) { /* No groups in builtin. */ - init_samr_r_enum_dom_groups(r_u, q_u->start_idx, 0); - DEBUG(5,("_samr_enum_dom_users: No groups in BUILTIN\n")); - return r_u->status; + *r->out.resume_handle = *r->in.resume_handle; + DEBUG(5,("_samr_EnumDomainGroups: No groups in BUILTIN\n")); + return status; + } + + samr_array = TALLOC_ZERO_P(p->mem_ctx, struct samr_SamArray); + if (!samr_array) { + return NT_STATUS_NO_MEMORY; } /* the domain group array is being allocated in the function below */ @@ -1067,46 +1074,64 @@ NTSTATUS _samr_enum_dom_groups(pipes_struct *p, SAMR_Q_ENUM_DOM_GROUPS *q_u, SAM } } - num_groups = pdb_search_entries(info->disp_info->groups, q_u->start_idx, + num_groups = pdb_search_entries(info->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); - make_group_sam_entry_list(p->mem_ctx, &r_u->sam, &r_u->uni_grp_name, + make_group_sam_entry_list(p->mem_ctx, &samr_entries, num_groups, groups); - init_samr_r_enum_dom_groups(r_u, q_u->start_idx, num_groups); + samr_array->count = num_groups; + samr_array->entries = samr_entries; + + *r->out.sam = samr_array; + *r->out.num_entries = num_groups; + /* this was missing, IMHO: + *r->out.resume_handle = num_groups + *r->in.resume_handle; + */ - DEBUG(5,("samr_enum_dom_groups: %d\n", __LINE__)); + DEBUG(5,("_samr_EnumDomainGroups: %d\n", __LINE__)); - return r_u->status; + return status; } /******************************************************************* - samr_reply_enum_dom_aliases + _samr_EnumDomainAliases ********************************************************************/ -NTSTATUS _samr_enum_dom_aliases(pipes_struct *p, SAMR_Q_ENUM_DOM_ALIASES *q_u, SAMR_R_ENUM_DOM_ALIASES *r_u) +NTSTATUS _samr_EnumDomainAliases(pipes_struct *p, + struct samr_EnumDomainAliases *r) { + NTSTATUS status; struct samr_info *info; 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, &q_u->pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, r->in.domain_handle, (void **)(void *)&info)) return NT_STATUS_INVALID_HANDLE; - r_u->status = access_check_samr_function(info->acc_granted, - SA_RIGHT_DOMAIN_ENUM_ACCOUNTS, - "_samr_enum_dom_aliases"); - if (!NT_STATUS_IS_OK(r_u->status)) - return r_u->status; + status = access_check_samr_function(info->acc_granted, + SA_RIGHT_DOMAIN_ENUM_ACCOUNTS, + "_samr_EnumDomainAliases"); + if (!NT_STATUS_IS_OK(status)) { + return status; + } - DEBUG(5,("samr_reply_enum_dom_aliases: sid %s\n", + DEBUG(5,("_samr_EnumDomainAliases: sid %s\n", sid_string_dbg(&info->sid))); + samr_array = TALLOC_ZERO_P(p->mem_ctx, struct samr_SamArray); + if (!samr_array) { + return NT_STATUS_NO_MEMORY; + } + become_root(); if (info->disp_info->aliases == NULL) { @@ -1117,39 +1142,244 @@ NTSTATUS _samr_enum_dom_aliases(pipes_struct *p, SAMR_Q_ENUM_DOM_ALIASES *q_u, S } } - num_aliases = pdb_search_entries(info->disp_info->aliases, q_u->start_idx, + num_aliases = pdb_search_entries(info->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); - make_group_sam_entry_list(p->mem_ctx, &r_u->sam, &r_u->uni_grp_name, + make_group_sam_entry_list(p->mem_ctx, &samr_entries, num_aliases, aliases); - init_samr_r_enum_dom_aliases(r_u, q_u->start_idx + num_aliases, - num_aliases); + DEBUG(5,("_samr_EnumDomainAliases: %d\n", __LINE__)); + + samr_array->count = num_aliases; + samr_array->entries = samr_entries; + + *r->out.sam = samr_array; + *r->out.num_entries = num_aliases; + *r->out.resume_handle = num_aliases + *r->in.resume_handle; + + return status; +} + +/******************************************************************* + inits a samr_DispInfoGeneral structure. +********************************************************************/ + +static NTSTATUS init_samr_dispinfo_1(TALLOC_CTX *ctx, + struct samr_DispInfoGeneral *r, + uint32_t num_entries, + uint32_t start_idx, + struct samr_displayentry *entries) +{ + uint32 i; + + DEBUG(10, ("init_samr_dispinfo_1: num_entries: %d\n", num_entries)); + + if (num_entries == 0) { + return NT_STATUS_OK; + } + + r->count = num_entries; + + r->entries = TALLOC_ZERO_ARRAY(ctx, struct samr_DispEntryGeneral, num_entries); + if (!r->entries) { + return NT_STATUS_NO_MEMORY; + } + + for (i = 0; i < num_entries ; i++) { - DEBUG(5,("samr_enum_dom_aliases: %d\n", __LINE__)); + init_lsa_String(&r->entries[i].account_name, + entries[i].account_name); - return r_u->status; + init_lsa_String(&r->entries[i].description, + entries[i].description); + + init_lsa_String(&r->entries[i].full_name, + entries[i].fullname); + + r->entries[i].rid = entries[i].rid; + r->entries[i].acct_flags = entries[i].acct_flags; + r->entries[i].idx = start_idx+i+1; + } + + return NT_STATUS_OK; +} + +/******************************************************************* + inits a samr_DispInfoFull structure. +********************************************************************/ + +static NTSTATUS init_samr_dispinfo_2(TALLOC_CTX *ctx, + struct samr_DispInfoFull *r, + uint32_t num_entries, + uint32_t start_idx, + struct samr_displayentry *entries) +{ + uint32_t i; + + DEBUG(10, ("init_samr_dispinfo_2: num_entries: %d\n", num_entries)); + + if (num_entries == 0) { + return NT_STATUS_OK; + } + + r->count = num_entries; + + r->entries = TALLOC_ZERO_ARRAY(ctx, struct samr_DispEntryFull, num_entries); + if (!r->entries) { + return NT_STATUS_NO_MEMORY; + } + + for (i = 0; i < num_entries ; i++) { + + init_lsa_String(&r->entries[i].account_name, + entries[i].account_name); + + init_lsa_String(&r->entries[i].description, + entries[i].description); + + r->entries[i].rid = entries[i].rid; + r->entries[i].acct_flags = entries[i].acct_flags; + r->entries[i].idx = start_idx+i+1; + } + + return NT_STATUS_OK; +} + +/******************************************************************* + inits a samr_DispInfoFullGroups structure. +********************************************************************/ + +static NTSTATUS init_samr_dispinfo_3(TALLOC_CTX *ctx, + struct samr_DispInfoFullGroups *r, + uint32_t num_entries, + uint32_t start_idx, + struct samr_displayentry *entries) +{ + uint32_t i; + + DEBUG(5, ("init_samr_dispinfo_3: num_entries: %d\n", num_entries)); + + if (num_entries == 0) { + return NT_STATUS_OK; + } + + r->count = num_entries; + + r->entries = TALLOC_ZERO_ARRAY(ctx, struct samr_DispEntryFullGroup, num_entries); + if (!r->entries) { + return NT_STATUS_NO_MEMORY; + } + + for (i = 0; i < num_entries ; i++) { + + init_lsa_String(&r->entries[i].account_name, + entries[i].account_name); + + init_lsa_String(&r->entries[i].description, + entries[i].description); + + r->entries[i].rid = entries[i].rid; + r->entries[i].acct_flags = entries[i].acct_flags; + r->entries[i].idx = start_idx+i+1; + } + + return NT_STATUS_OK; +} + +/******************************************************************* + inits a samr_DispInfoAscii structure. +********************************************************************/ + +static NTSTATUS init_samr_dispinfo_4(TALLOC_CTX *ctx, + struct samr_DispInfoAscii *r, + uint32_t num_entries, + uint32_t start_idx, + struct samr_displayentry *entries) +{ + uint32_t i; + + DEBUG(5, ("init_samr_dispinfo_4: num_entries: %d\n", num_entries)); + + if (num_entries == 0) { + return NT_STATUS_OK; + } + + r->count = num_entries; + + r->entries = TALLOC_ZERO_ARRAY(ctx, struct samr_DispEntryAscii, num_entries); + if (!r->entries) { + return NT_STATUS_NO_MEMORY; + } + + for (i = 0; i < num_entries ; i++) { + + init_lsa_AsciiStringLarge(&r->entries[i].account_name, + entries[i].account_name); + + r->entries[i].idx = start_idx+i+1; + } + + return NT_STATUS_OK; } /******************************************************************* - samr_reply_query_dispinfo + inits a samr_DispInfoAscii structure. +********************************************************************/ + +static NTSTATUS init_samr_dispinfo_5(TALLOC_CTX *ctx, + struct samr_DispInfoAscii *r, + uint32_t num_entries, + uint32_t start_idx, + struct samr_displayentry *entries) +{ + uint32_t i; + + DEBUG(5, ("init_samr_dispinfo_5: num_entries: %d\n", num_entries)); + + if (num_entries == 0) { + return NT_STATUS_OK; + } + + r->count = num_entries; + + r->entries = TALLOC_ZERO_ARRAY(ctx, struct samr_DispEntryAscii, num_entries); + if (!r->entries) { + return NT_STATUS_NO_MEMORY; + } + + for (i = 0; i < num_entries ; i++) { + + init_lsa_AsciiStringLarge(&r->entries[i].account_name, + entries[i].account_name); + + r->entries[i].idx = start_idx+i+1; + } + + return NT_STATUS_OK; +} + +/******************************************************************* + _samr_QueryDisplayInfo ********************************************************************/ -NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, - SAMR_R_QUERY_DISPINFO *r_u) +NTSTATUS _samr_QueryDisplayInfo(pipes_struct *p, + struct samr_QueryDisplayInfo *r) { + NTSTATUS status; struct samr_info *info = NULL; uint32 struct_size=0x20; /* W2K always reply that, client doesn't care */ - - uint32 max_entries=q_u->max_entries; - uint32 enum_context=q_u->start_idx; - uint32 max_size=q_u->max_size; - SAM_DISPINFO_CTR *ctr; + uint32 max_entries = r->in.max_entries; + uint32 enum_context = r->in.start_idx; + uint32 max_size = r->in.buf_size; + + union samr_DispInfo *disp_info = r->out.info; + uint32 temp_size=0, total_data_size=0; NTSTATUS disp_ret = NT_STATUS_UNSUCCESSFUL; uint32 num_account = 0; @@ -1157,16 +1387,15 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, int max_sam_entries = (ra_type == RA_WIN95) ? MAX_SAM_ENTRIES_W95 : MAX_SAM_ENTRIES_W2K; struct samr_displayentry *entries = NULL; - DEBUG(5, ("samr_reply_query_dispinfo: %d\n", __LINE__)); - r_u->status = NT_STATUS_UNSUCCESSFUL; + DEBUG(5,("_samr_QueryDisplayInfo: %d\n", __LINE__)); /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, &q_u->domain_pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, r->in.domain_handle, (void **)(void *)&info)) return NT_STATUS_INVALID_HANDLE; /* * calculate how many entries we will return. - * based on + * based on * - the number of entries the client asked * - our limit on that * - the starting point (enumeration context) @@ -1192,15 +1421,15 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, * JFM, 12/20/2001 */ - if ((q_u->switch_level < 1) || (q_u->switch_level > 5)) { - DEBUG(0,("_samr_query_dispinfo: Unknown info level (%u)\n", - (unsigned int)q_u->switch_level )); + if ((r->in.level < 1) || (r->in.level > 5)) { + DEBUG(0,("_samr_QueryDisplayInfo: Unknown info level (%u)\n", + (unsigned int)r->in.level )); return NT_STATUS_INVALID_INFO_CLASS; } /* first limit the number of entries we will return */ if(max_entries > max_sam_entries) { - DEBUG(5, ("samr_reply_query_dispinfo: client requested %d " + DEBUG(5, ("_samr_QueryDisplayInfo: client requested %d " "entries, limiting to %d\n", max_entries, max_sam_entries)); max_entries = max_sam_entries; @@ -1210,23 +1439,18 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, * return */ temp_size=max_entries*struct_size; - + if (temp_size>max_size) { max_entries=MIN((max_size/struct_size),max_entries);; - DEBUG(5, ("samr_reply_query_dispinfo: buffer size limits to " + DEBUG(5, ("_samr_QueryDisplayInfo: buffer size limits to " "only %d entries\n", max_entries)); } - if (!(ctr = TALLOC_ZERO_P(p->mem_ctx,SAM_DISPINFO_CTR))) - return NT_STATUS_NO_MEMORY; - - ZERO_STRUCTP(ctr); - become_root(); /* THe following done as ROOT. Don't return without unbecome_root(). */ - switch (q_u->switch_level) { + switch (r->in.level) { case 0x1: case 0x4: if (info->disp_info->users == NULL) { @@ -1235,10 +1459,10 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, unbecome_root(); return NT_STATUS_ACCESS_DENIED; } - DEBUG(10,("samr_reply_query_dispinfo: starting user enumeration at index %u\n", + DEBUG(10,("_samr_QueryDisplayInfo: starting user enumeration at index %u\n", (unsigned int)enum_context )); } else { - DEBUG(10,("samr_reply_query_dispinfo: using cached user enumeration at index %u\n", + DEBUG(10,("_samr_QueryDisplayInfo: using cached user enumeration at index %u\n", (unsigned int)enum_context )); } @@ -1254,10 +1478,10 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, unbecome_root(); return NT_STATUS_ACCESS_DENIED; } - DEBUG(10,("samr_reply_query_dispinfo: starting machine enumeration at index %u\n", + DEBUG(10,("_samr_QueryDisplayInfo: starting machine enumeration at index %u\n", (unsigned int)enum_context )); } else { - DEBUG(10,("samr_reply_query_dispinfo: using cached machine enumeration at index %u\n", + DEBUG(10,("_samr_QueryDisplayInfo: using cached machine enumeration at index %u\n", (unsigned int)enum_context )); } @@ -1273,10 +1497,10 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, unbecome_root(); return NT_STATUS_ACCESS_DENIED; } - DEBUG(10,("samr_reply_query_dispinfo: starting group enumeration at index %u\n", + DEBUG(10,("_samr_QueryDisplayInfo: starting group enumeration at index %u\n", (unsigned int)enum_context )); } else { - DEBUG(10,("samr_reply_query_dispinfo: using cached group enumeration at index %u\n", + DEBUG(10,("_samr_QueryDisplayInfo: using cached group enumeration at index %u\n", (unsigned int)enum_context )); } @@ -1291,32 +1515,33 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, } unbecome_root(); + /* Now create reply structure */ - switch (q_u->switch_level) { + switch (r->in.level) { case 0x1: - disp_ret = init_sam_dispinfo_1(p->mem_ctx, &ctr->sam.info1, - num_account, enum_context, - entries); + disp_ret = init_samr_dispinfo_1(p->mem_ctx, &disp_info->info1, + num_account, enum_context, + entries); break; case 0x2: - disp_ret = init_sam_dispinfo_2(p->mem_ctx, &ctr->sam.info2, - num_account, enum_context, - entries); + disp_ret = init_samr_dispinfo_2(p->mem_ctx, &disp_info->info2, + num_account, enum_context, + entries); break; case 0x3: - disp_ret = init_sam_dispinfo_3(p->mem_ctx, &ctr->sam.info3, - num_account, enum_context, - entries); + disp_ret = init_samr_dispinfo_3(p->mem_ctx, &disp_info->info3, + num_account, enum_context, + entries); break; case 0x4: - disp_ret = init_sam_dispinfo_4(p->mem_ctx, &ctr->sam.info4, - num_account, enum_context, - entries); + disp_ret = init_samr_dispinfo_4(p->mem_ctx, &disp_info->info4, + num_account, enum_context, + entries); break; case 0x5: - disp_ret = init_sam_dispinfo_5(p->mem_ctx, &ctr->sam.info5, - num_account, enum_context, - entries); + disp_ret = init_samr_dispinfo_5(p->mem_ctx, &disp_info->info5, + num_account, enum_context, + entries); break; default: smb_panic("info class changed"); @@ -1330,73 +1555,130 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, total_data_size=num_account*struct_size; if (num_account) { - r_u->status = STATUS_MORE_ENTRIES; + status = STATUS_MORE_ENTRIES; } else { - r_u->status = NT_STATUS_OK; + status = NT_STATUS_OK; } /* Ensure we cache this enumeration. */ set_disp_info_cache_timeout(info->disp_info, DISP_INFO_CACHE_TIMEOUT); - DEBUG(5, ("_samr_query_dispinfo: %d\n", __LINE__)); + DEBUG(5, ("_samr_QueryDisplayInfo: %d\n", __LINE__)); + + *r->out.total_size = total_data_size; + *r->out.returned_size = temp_size; + + return status; +} + +/**************************************************************** + _samr_QueryDisplayInfo2 +****************************************************************/ + +NTSTATUS _samr_QueryDisplayInfo2(pipes_struct *p, + struct samr_QueryDisplayInfo2 *r) +{ + struct samr_QueryDisplayInfo q; + + q.in.domain_handle = r->in.domain_handle; + q.in.level = r->in.level; + q.in.start_idx = r->in.start_idx; + q.in.max_entries = r->in.max_entries; + q.in.buf_size = r->in.buf_size; + + q.out.total_size = r->out.total_size; + q.out.returned_size = r->out.returned_size; + q.out.info = r->out.info; + + return _samr_QueryDisplayInfo(p, &q); +} + +/**************************************************************** + _samr_QueryDisplayInfo3 +****************************************************************/ + +NTSTATUS _samr_QueryDisplayInfo3(pipes_struct *p, + struct samr_QueryDisplayInfo3 *r) +{ + struct samr_QueryDisplayInfo q; - init_samr_r_query_dispinfo(r_u, num_account, total_data_size, - temp_size, q_u->switch_level, ctr, - r_u->status); + q.in.domain_handle = r->in.domain_handle; + q.in.level = r->in.level; + q.in.start_idx = r->in.start_idx; + q.in.max_entries = r->in.max_entries; + q.in.buf_size = r->in.buf_size; - return r_u->status; + q.out.total_size = r->out.total_size; + q.out.returned_size = r->out.returned_size; + q.out.info = r->out.info; + return _samr_QueryDisplayInfo(p, &q); } /******************************************************************* - samr_reply_query_aliasinfo + _samr_QueryAliasInfo ********************************************************************/ -NTSTATUS _samr_query_aliasinfo(pipes_struct *p, SAMR_Q_QUERY_ALIASINFO *q_u, SAMR_R_QUERY_ALIASINFO *r_u) +NTSTATUS _samr_QueryAliasInfo(pipes_struct *p, + struct samr_QueryAliasInfo *r) { DOM_SID sid; struct acct_info info; uint32 acc_granted; NTSTATUS status; + union samr_AliasInfo *alias_info = NULL; + const char *alias_name = NULL; + const char *alias_description = NULL; - r_u->status = NT_STATUS_OK; + DEBUG(5,("_samr_QueryAliasInfo: %d\n", __LINE__)); - DEBUG(5,("_samr_query_aliasinfo: %d\n", __LINE__)); + 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, &q_u->pol, &sid, &acc_granted, NULL)) + if (!get_lsa_policy_samr_sid(p, r->in.alias_handle, &sid, &acc_granted, NULL)) return NT_STATUS_INVALID_HANDLE; - if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_ALIAS_LOOKUP_INFO, "_samr_query_aliasinfo"))) { - return r_u->status; + + status = access_check_samr_function(acc_granted, + SA_RIGHT_ALIAS_LOOKUP_INFO, + "_samr_QueryAliasInfo"); + if (!NT_STATUS_IS_OK(status)) { + return status; } become_root(); status = pdb_get_aliasinfo(&sid, &info); unbecome_root(); - + if ( !NT_STATUS_IS_OK(status)) return status; - if ( !(r_u->ctr = TALLOC_ZERO_P( p->mem_ctx, ALIAS_INFO_CTR )) ) - return NT_STATUS_NO_MEMORY; - + /* FIXME: info contains fstrings */ + alias_name = talloc_strdup(r, info.acct_name); + alias_description = talloc_strdup(r, info.acct_desc); - switch (q_u->level ) { - case 1: - r_u->ctr->level = 1; - init_samr_alias_info1(&r_u->ctr->alias.info1, info.acct_name, 1, info.acct_desc); + switch (r->in.level) { + case ALIASINFOALL: + init_samr_alias_info1(&alias_info->all, + alias_name, + 1, + alias_description); break; - case 3: - r_u->ctr->level = 3; - init_samr_alias_info3(&r_u->ctr->alias.info3, info.acct_desc); + case ALIASINFODESCRIPTION: + init_samr_alias_info3(&alias_info->description, + alias_description); break; default: return NT_STATUS_INVALID_INFO_CLASS; } - DEBUG(5,("_samr_query_aliasinfo: %d\n", __LINE__)); + *r->out.info = alias_info; - return r_u->status; + DEBUG(5,("_samr_QueryAliasInfo: %d\n", __LINE__)); + + return NT_STATUS_OK; } #if 0 @@ -1460,170 +1742,184 @@ NTSTATUS _samr_query_aliasinfo(pipes_struct *p, SAMR_Q_QUERY_ALIASINFO *q_u, SAM #endif /******************************************************************* - _samr_lookup_names + _samr_LookupNames ********************************************************************/ -NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LOOKUP_NAMES *r_u) +NTSTATUS _samr_LookupNames(pipes_struct *p, + struct samr_LookupNames *r) { + NTSTATUS status; uint32 rid[MAX_SAM_ENTRIES]; enum lsa_SidType type[MAX_SAM_ENTRIES]; int i; - int num_rids = q_u->num_names2; + int num_rids = r->in.num_names; DOM_SID pol_sid; uint32 acc_granted; + struct samr_Ids rids, types; - r_u->status = NT_STATUS_OK; - - DEBUG(5,("_samr_lookup_names: %d\n", __LINE__)); + DEBUG(5,("_samr_LookupNames: %d\n", __LINE__)); ZERO_ARRAY(rid); ZERO_ARRAY(type); - if (!get_lsa_policy_samr_sid(p, &q_u->pol, &pol_sid, &acc_granted, NULL)) { - init_samr_r_lookup_names(p->mem_ctx, r_u, 0, NULL, NULL, NT_STATUS_OBJECT_TYPE_MISMATCH); - return r_u->status; + if (!get_lsa_policy_samr_sid(p, r->in.domain_handle, &pol_sid, &acc_granted, NULL)) { + return NT_STATUS_OBJECT_TYPE_MISMATCH; } - - if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, 0, "_samr_lookup_names"))) { /* Don't know the acc_bits yet */ - return r_u->status; + + status = access_check_samr_function(acc_granted, + 0, /* Don't know the acc_bits yet */ + "_samr_LookupNames"); + if (!NT_STATUS_IS_OK(status)) { + return status; } if (num_rids > MAX_SAM_ENTRIES) { num_rids = MAX_SAM_ENTRIES; - DEBUG(5,("_samr_lookup_names: truncating entries to %d\n", num_rids)); + DEBUG(5,("_samr_LookupNames: truncating entries to %d\n", num_rids)); } - DEBUG(5,("_samr_lookup_names: looking name on SID %s\n", + DEBUG(5,("_samr_LookupNames: looking name on SID %s\n", sid_string_dbg(&pol_sid))); - + for (i = 0; i < num_rids; i++) { - fstring name; - int ret; - r_u->status = NT_STATUS_NONE_MAPPED; + status = NT_STATUS_NONE_MAPPED; type[i] = SID_NAME_UNKNOWN; - rid [i] = 0xffffffff; - - ret = rpcstr_pull(name, q_u->uni_name[i].buffer, sizeof(name), q_u->uni_name[i].uni_str_len*2, 0); - - if (ret <= 0) { - continue; - } + rid[i] = 0xffffffff; if (sid_check_is_builtin(&pol_sid)) { - if (lookup_builtin_name(name, &rid[i])) { + if (lookup_builtin_name(r->in.names[i].string, + &rid[i])) + { type[i] = SID_NAME_ALIAS; } } else { - lookup_global_sam_name(name, 0, &rid[i], &type[i]); + lookup_global_sam_name(r->in.names[i].string, 0, + &rid[i], &type[i]); } if (type[i] != SID_NAME_UNKNOWN) { - r_u->status = NT_STATUS_OK; + status = NT_STATUS_OK; } } - init_samr_r_lookup_names(p->mem_ctx, r_u, num_rids, rid, type, r_u->status); + rids.count = num_rids; + rids.ids = rid; + + types.count = num_rids; + types.ids = type; - DEBUG(5,("_samr_lookup_names: %d\n", __LINE__)); + *r->out.rids = rids; + *r->out.types = types; - return r_u->status; + DEBUG(5,("_samr_LookupNames: %d\n", __LINE__)); + + return status; } /******************************************************************* - _samr_chgpasswd_user + _samr_ChangePasswordUser2 ********************************************************************/ -NTSTATUS _samr_chgpasswd_user(pipes_struct *p, SAMR_Q_CHGPASSWD_USER *q_u, SAMR_R_CHGPASSWD_USER *r_u) +NTSTATUS _samr_ChangePasswordUser2(pipes_struct *p, + struct samr_ChangePasswordUser2 *r) { + NTSTATUS status; fstring user_name; fstring wks; - DEBUG(5,("_samr_chgpasswd_user: %d\n", __LINE__)); + DEBUG(5,("_samr_ChangePasswordUser2: %d\n", __LINE__)); - r_u->status = NT_STATUS_OK; + fstrcpy(user_name, r->in.account->string); + fstrcpy(wks, r->in.server->string); - rpcstr_pull(user_name, q_u->uni_user_name.buffer, sizeof(user_name), q_u->uni_user_name.uni_str_len*2, 0); - rpcstr_pull(wks, q_u->uni_dest_host.buffer, sizeof(wks), q_u->uni_dest_host.uni_str_len*2,0); - - DEBUG(5,("samr_chgpasswd_user: user: %s wks: %s\n", user_name, wks)); + DEBUG(5,("_samr_ChangePasswordUser2: 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 + * UNIX username case mangling not required, pass_oem_change * is case insensitive. */ - r_u->status = pass_oem_change(user_name, q_u->lm_newpass.pass, q_u->lm_oldhash.hash, - q_u->nt_newpass.pass, q_u->nt_oldhash.hash, NULL); - - init_samr_r_chgpasswd_user(r_u, r_u->status); + 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, + NULL); - DEBUG(5,("_samr_chgpasswd_user: %d\n", __LINE__)); + DEBUG(5,("_samr_ChangePasswordUser2: %d\n", __LINE__)); - return r_u->status; + return status; } /******************************************************************* - _samr_chgpasswd_user3 + _samr_ChangePasswordUser3 ********************************************************************/ -NTSTATUS _samr_chgpasswd_user3(pipes_struct *p, SAMR_Q_CHGPASSWD_USER3 *q_u, SAMR_R_CHGPASSWD_USER3 *r_u) +NTSTATUS _samr_ChangePasswordUser3(pipes_struct *p, + struct samr_ChangePasswordUser3 *r) { + NTSTATUS status; fstring user_name; - fstring wks; + const char *wks = NULL; uint32 reject_reason; - SAM_UNK_INFO_1 *info = NULL; - SAMR_CHANGE_REJECT *reject = NULL; + struct samr_DomInfo1 *dominfo = NULL; + struct samr_ChangeReject *reject = NULL; - DEBUG(5,("_samr_chgpasswd_user3: %d\n", __LINE__)); + DEBUG(5,("_samr_ChangePasswordUser3: %d\n", __LINE__)); - rpcstr_pull(user_name, q_u->uni_user_name.buffer, sizeof(user_name), q_u->uni_user_name.uni_str_len*2, 0); - rpcstr_pull(wks, q_u->uni_dest_host.buffer, sizeof(wks), q_u->uni_dest_host.uni_str_len*2,0); + fstrcpy(user_name, r->in.account->string); + if (r->in.server && r->in.server->string) { + wks = r->in.server->string; + } - DEBUG(5,("_samr_chgpasswd_user3: user: %s wks: %s\n", user_name, wks)); + 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 + * UNIX username case mangling not required, pass_oem_change * is case insensitive. */ - r_u->status = pass_oem_change(user_name, q_u->lm_newpass.pass, q_u->lm_oldhash.hash, - q_u->nt_newpass.pass, q_u->nt_oldhash.hash, &reject_reason); + 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(r_u->status, NT_STATUS_PASSWORD_RESTRICTION) || - NT_STATUS_EQUAL(r_u->status, NT_STATUS_ACCOUNT_RESTRICTION)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) || + NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_RESTRICTION)) { uint32 min_pass_len,pass_hist,password_properties; time_t u_expire, u_min_age; NTTIME nt_expire, nt_min_age; uint32 account_policy_temp; - if ((info = TALLOC_ZERO_P(p->mem_ctx, SAM_UNK_INFO_1)) == NULL) { + dominfo = TALLOC_ZERO_P(p->mem_ctx, struct samr_DomInfo1); + if (!dominfo) { return NT_STATUS_NO_MEMORY; } - if ((reject = TALLOC_ZERO_P(p->mem_ctx, SAMR_CHANGE_REJECT)) == NULL) { + reject = TALLOC_ZERO_P(p->mem_ctx, struct samr_ChangeReject); + if (!reject) { return NT_STATUS_NO_MEMORY; } - ZERO_STRUCTP(info); - ZERO_STRUCTP(reject); - become_root(); /* AS ROOT !!! */ @@ -1644,23 +1940,32 @@ NTSTATUS _samr_chgpasswd_user3(pipes_struct *p, SAMR_Q_CHGPASSWD_USER3 *q_u, SAM u_min_age = account_policy_temp; /* !AS ROOT */ - + unbecome_root(); unix_to_nt_time_abs(&nt_expire, u_expire); unix_to_nt_time_abs(&nt_min_age, u_min_age); - init_unk_info1(info, (uint16)min_pass_len, (uint16)pass_hist, - password_properties, nt_expire, nt_min_age); + if (lp_check_password_script() && *lp_check_password_script()) { + password_properties |= DOMAIN_PASSWORD_COMPLEX; + } + + init_samr_DomInfo1(dominfo, + min_pass_len, + pass_hist, + password_properties, + u_expire, + u_min_age); - reject->reject_reason = reject_reason; + reject->reason = reject_reason; + + *r->out.dominfo = dominfo; + *r->out.reject = reject; } - - init_samr_r_chgpasswd_user3(r_u, r_u->status, reject, info); - DEBUG(5,("_samr_chgpasswd_user3: %d\n", __LINE__)); + DEBUG(5,("_samr_ChangePasswordUser3: %d\n", __LINE__)); - return r_u->status; + return status; } /******************************************************************* @@ -1668,60 +1973,54 @@ makes a SAMR_R_LOOKUP_RIDS structure. ********************************************************************/ static bool make_samr_lookup_rids(TALLOC_CTX *ctx, uint32 num_names, - const char **names, UNIHDR **pp_hdr_name, - UNISTR2 **pp_uni_name) + const char **names, + struct lsa_String **lsa_name_array_p) { - uint32 i; - UNIHDR *hdr_name=NULL; - UNISTR2 *uni_name=NULL; + struct lsa_String *lsa_name_array = NULL; + uint32_t i; - *pp_uni_name = NULL; - *pp_hdr_name = NULL; + *lsa_name_array_p = NULL; if (num_names != 0) { - hdr_name = TALLOC_ZERO_ARRAY(ctx, UNIHDR, num_names); - if (hdr_name == NULL) - return False; - - uni_name = TALLOC_ZERO_ARRAY(ctx,UNISTR2, num_names); - if (uni_name == NULL) - return False; + lsa_name_array = TALLOC_ZERO_ARRAY(ctx, struct lsa_String, num_names); + if (!lsa_name_array) { + return false; + } } for (i = 0; i < num_names; i++) { DEBUG(10, ("names[%d]:%s\n", i, names[i] && *names[i] ? names[i] : "")); - init_unistr2(&uni_name[i], names[i], UNI_FLAGS_NONE); - init_uni_hdr(&hdr_name[i], &uni_name[i]); + init_lsa_String(&lsa_name_array[i], names[i]); } - *pp_uni_name = uni_name; - *pp_hdr_name = hdr_name; + *lsa_name_array_p = lsa_name_array; - return True; + return true; } /******************************************************************* - _samr_lookup_rids + _samr_LookupRids ********************************************************************/ -NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOKUP_RIDS *r_u) +NTSTATUS _samr_LookupRids(pipes_struct *p, + struct samr_LookupRids *r) { + NTSTATUS status; const char **names; enum lsa_SidType *attrs = NULL; uint32 *wire_attrs = NULL; - UNIHDR *hdr_name = NULL; - UNISTR2 *uni_name = NULL; DOM_SID pol_sid; - int num_rids = (int)q_u->num_rids1; + int num_rids = (int)r->in.num_rids; uint32 acc_granted; int i; + struct lsa_Strings names_array; + struct samr_Ids types_array; + struct lsa_String *lsa_names = NULL; - r_u->status = NT_STATUS_OK; - - DEBUG(5,("_samr_lookup_rids: %d\n", __LINE__)); + DEBUG(5,("_samr_LookupRids: %d\n", __LINE__)); /* find the policy handle. open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, &q_u->pol, &pol_sid, &acc_granted, NULL)) + if (!get_lsa_policy_samr_sid(p, r->in.domain_handle, &pol_sid, &acc_granted, NULL)) return NT_STATUS_INVALID_HANDLE; if (num_rids > 1000) { @@ -1744,59 +2043,67 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK } become_root(); /* lookup_sid can require root privs */ - r_u->status = pdb_lookup_rids(&pol_sid, num_rids, q_u->rid, - names, attrs); + status = pdb_lookup_rids(&pol_sid, num_rids, r->in.rids, + names, attrs); unbecome_root(); - if ( NT_STATUS_EQUAL(r_u->status, NT_STATUS_NONE_MAPPED) && (num_rids == 0) ) { - r_u->status = NT_STATUS_OK; + if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED) && (num_rids == 0)) { + status = NT_STATUS_OK; } - if(!make_samr_lookup_rids(p->mem_ctx, num_rids, names, - &hdr_name, &uni_name)) + if (!make_samr_lookup_rids(p->mem_ctx, num_rids, names, + &lsa_names)) { return NT_STATUS_NO_MEMORY; + } /* Convert from enum lsa_SidType to uint32 for wire format. */ for (i = 0; i < num_rids; i++) { wire_attrs[i] = (uint32)attrs[i]; } - init_samr_r_lookup_rids(r_u, num_rids, hdr_name, uni_name, wire_attrs); + names_array.count = num_rids; + names_array.names = lsa_names; + + types_array.count = num_rids; + types_array.ids = wire_attrs; - DEBUG(5,("_samr_lookup_rids: %d\n", __LINE__)); + *r->out.names = names_array; + *r->out.types = types_array; - return r_u->status; + DEBUG(5,("_samr_LookupRids: %d\n", __LINE__)); + + return status; } /******************************************************************* - _samr_open_user. Safe - gives out no passwd info. - ********************************************************************/ + _samr_OpenUser +********************************************************************/ -NTSTATUS _samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN_USER *r_u) +NTSTATUS _samr_OpenUser(pipes_struct *p, + struct samr_OpenUser *r) { struct samu *sampass=NULL; DOM_SID sid; - POLICY_HND domain_pol = q_u->domain_pol; - POLICY_HND *user_pol = &r_u->user_pol; + POLICY_HND domain_pol = *r->in.domain_handle; + POLICY_HND *user_pol = r->out.user_handle; struct samr_info *info = NULL; SEC_DESC *psd = NULL; uint32 acc_granted; - uint32 des_access = q_u->access_mask; + uint32 des_access = r->in.access_mask; size_t sd_size; bool ret; NTSTATUS nt_status; SE_PRIV se_rights; - r_u->status = NT_STATUS_OK; - /* find the domain policy handle and get domain SID / access bits in the domain policy. */ - + if ( !get_lsa_policy_samr_sid(p, &domain_pol, &sid, &acc_granted, NULL) ) return NT_STATUS_INVALID_HANDLE; - - nt_status = access_check_samr_function( acc_granted, - SA_RIGHT_DOMAIN_OPEN_ACCOUNT, "_samr_open_user" ); - + + nt_status = access_check_samr_function(acc_granted, + SA_RIGHT_DOMAIN_OPEN_ACCOUNT, + "_samr_OpenUser" ); + if ( !NT_STATUS_IS_OK(nt_status) ) return nt_status; @@ -1805,22 +2112,22 @@ NTSTATUS _samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN_USE } /* append the user's RID to it */ - - if (!sid_append_rid(&sid, q_u->user_rid)) + + if (!sid_append_rid(&sid, r->in.rid)) return NT_STATUS_NO_SUCH_USER; - + /* check if access can be granted as requested by client. */ - + make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_generic_mapping, &sid, SAMR_USR_RIGHTS_WRITE_PW); se_map_generic(&des_access, &usr_generic_mapping); - + se_priv_copy( &se_rights, &se_machine_account ); se_priv_add( &se_rights, &se_add_users ); - - nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token, - &se_rights, GENERIC_RIGHTS_USER_WRITE, des_access, - &acc_granted, "_samr_open_user"); - + + nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token, + &se_rights, GENERIC_RIGHTS_USER_WRITE, des_access, + &acc_granted, "_samr_OpenUser"); + if ( !NT_STATUS_IS_OK(nt_status) ) return nt_status; @@ -1844,22 +2151,27 @@ NTSTATUS _samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN_USE if (!create_policy_hnd(p, user_pol, free_samr_info, (void *)info)) return NT_STATUS_OBJECT_NAME_NOT_FOUND; - return r_u->status; + return NT_STATUS_OK; } /************************************************************************* get_user_info_7. Safe. Only gives out account_name. *************************************************************************/ -static NTSTATUS get_user_info_7(TALLOC_CTX *mem_ctx, SAM_USER_INFO_7 *id7, DOM_SID *user_sid) +static NTSTATUS get_user_info_7(TALLOC_CTX *mem_ctx, + struct samr_UserInfo7 *r, + DOM_SID *user_sid) { struct samu *smbpass=NULL; bool ret; + const char *account_name = NULL; + + ZERO_STRUCTP(r); if ( !(smbpass = samu_new( mem_ctx )) ) { return NT_STATUS_NO_MEMORY; } - + become_root(); ret = pdb_getsampwsid(smbpass, user_sid); unbecome_root(); @@ -1869,12 +2181,16 @@ static NTSTATUS get_user_info_7(TALLOC_CTX *mem_ctx, SAM_USER_INFO_7 *id7, DOM_S return NT_STATUS_NO_SUCH_USER; } - DEBUG(3,("User:[%s]\n", pdb_get_username(smbpass) )); + account_name = talloc_strdup(mem_ctx, pdb_get_username(smbpass)); + if (!account_name) { + TALLOC_FREE(smbpass); + return NT_STATUS_NO_MEMORY; + } + TALLOC_FREE(smbpass); - ZERO_STRUCTP(id7); - init_sam_user_info7(id7, pdb_get_username(smbpass) ); + DEBUG(3,("User:[%s]\n", account_name)); - TALLOC_FREE(smbpass); + init_samr_user_info7(r, account_name); return NT_STATUS_OK; } @@ -1882,11 +2198,16 @@ static NTSTATUS get_user_info_7(TALLOC_CTX *mem_ctx, SAM_USER_INFO_7 *id7, DOM_S /************************************************************************* get_user_info_9. Only gives out primary group SID. *************************************************************************/ -static NTSTATUS get_user_info_9(TALLOC_CTX *mem_ctx, SAM_USER_INFO_9 * id9, DOM_SID *user_sid) + +static NTSTATUS get_user_info_9(TALLOC_CTX *mem_ctx, + struct samr_UserInfo9 *r, + DOM_SID *user_sid) { struct samu *smbpass=NULL; bool ret; + ZERO_STRUCTP(r); + if ( !(smbpass = samu_new( mem_ctx )) ) { return NT_STATUS_NO_MEMORY; } @@ -1897,13 +2218,13 @@ static NTSTATUS get_user_info_9(TALLOC_CTX *mem_ctx, SAM_USER_INFO_9 * id9, DOM_ if (ret==False) { DEBUG(4,("User %s not found\n", sid_string_dbg(user_sid))); + TALLOC_FREE(smbpass); return NT_STATUS_NO_SUCH_USER; } DEBUG(3,("User:[%s]\n", pdb_get_username(smbpass) )); - ZERO_STRUCTP(id9); - init_sam_user_info9(id9, pdb_get_group_rid(smbpass) ); + init_samr_user_info9(r, pdb_get_group_rid(smbpass)); TALLOC_FREE(smbpass); @@ -1914,11 +2235,15 @@ static NTSTATUS get_user_info_9(TALLOC_CTX *mem_ctx, SAM_USER_INFO_9 * id9, DOM_ get_user_info_16. Safe. Only gives out acb bits. *************************************************************************/ -static NTSTATUS get_user_info_16(TALLOC_CTX *mem_ctx, SAM_USER_INFO_16 *id16, DOM_SID *user_sid) +static NTSTATUS get_user_info_16(TALLOC_CTX *mem_ctx, + struct samr_UserInfo16 *r, + DOM_SID *user_sid) { struct samu *smbpass=NULL; bool ret; + ZERO_STRUCTP(r); + if ( !(smbpass = samu_new( mem_ctx )) ) { return NT_STATUS_NO_MEMORY; } @@ -1929,13 +2254,13 @@ static NTSTATUS get_user_info_16(TALLOC_CTX *mem_ctx, SAM_USER_INFO_16 *id16, DO if (ret==False) { DEBUG(4,("User %s not found\n", sid_string_dbg(user_sid))); + TALLOC_FREE(smbpass); return NT_STATUS_NO_SUCH_USER; } DEBUG(3,("User:[%s]\n", pdb_get_username(smbpass) )); - ZERO_STRUCTP(id16); - init_sam_user_info16(id16, pdb_get_acct_ctrl(smbpass) ); + init_samr_user_info16(r, pdb_get_acct_ctrl(smbpass)); TALLOC_FREE(smbpass); @@ -1945,14 +2270,19 @@ static NTSTATUS get_user_info_16(TALLOC_CTX *mem_ctx, SAM_USER_INFO_16 *id16, DO /************************************************************************* 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 - user. JRA. + user. JRA. *************************************************************************/ -static NTSTATUS get_user_info_18(pipes_struct *p, TALLOC_CTX *mem_ctx, SAM_USER_INFO_18 * id18, DOM_SID *user_sid) +static NTSTATUS get_user_info_18(pipes_struct *p, + TALLOC_CTX *mem_ctx, + struct samr_UserInfo18 *r, + DOM_SID *user_sid) { struct samu *smbpass=NULL; bool ret; + ZERO_STRUCTP(r); + if (p->auth.auth_type != PIPE_AUTH_TYPE_NTLMSSP || p->auth.auth_type != PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) { return NT_STATUS_ACCESS_DENIED; } @@ -1984,9 +2314,9 @@ static NTSTATUS get_user_info_18(pipes_struct *p, TALLOC_CTX *mem_ctx, SAM_USER_ return NT_STATUS_ACCOUNT_DISABLED; } - ZERO_STRUCTP(id18); - init_sam_user_info18(id18, pdb_get_lanman_passwd(smbpass), pdb_get_nt_passwd(smbpass)); - + init_samr_user_info18(r, pdb_get_lanman_passwd(smbpass), + pdb_get_nt_passwd(smbpass)); + TALLOC_FREE(smbpass); return NT_STATUS_OK; @@ -1996,10 +2326,17 @@ static NTSTATUS get_user_info_18(pipes_struct *p, TALLOC_CTX *mem_ctx, SAM_USER_ get_user_info_20 *************************************************************************/ -static NTSTATUS get_user_info_20(TALLOC_CTX *mem_ctx, SAM_USER_INFO_20 *id20, DOM_SID *user_sid) +static NTSTATUS get_user_info_20(TALLOC_CTX *mem_ctx, + struct samr_UserInfo20 *r, + DOM_SID *user_sid) { struct samu *sampass=NULL; bool ret; + const char *munged_dial = NULL; + const char *munged_dial_decoded = NULL; + DATA_BLOB blob; + + ZERO_STRUCTP(r); if ( !(sampass = samu_new( mem_ctx )) ) { return NT_STATUS_NO_MEMORY; @@ -2011,72 +2348,221 @@ static NTSTATUS get_user_info_20(TALLOC_CTX *mem_ctx, SAM_USER_INFO_20 *id20, DO if (ret == False) { DEBUG(4,("User %s not found\n", sid_string_dbg(user_sid))); + TALLOC_FREE(sampass); return NT_STATUS_NO_SUCH_USER; } + munged_dial = pdb_get_munged_dial(sampass); + samr_clear_sam_passwd(sampass); DEBUG(3,("User:[%s]\n", pdb_get_username(sampass) )); - ZERO_STRUCTP(id20); - init_sam_user_info20A(id20, sampass); - + if (munged_dial) { + blob = base64_decode_data_blob(munged_dial); + munged_dial_decoded = talloc_strndup(mem_ctx, + (const char *)blob.data, + blob.length); + data_blob_free(&blob); + if (!munged_dial_decoded) { + TALLOC_FREE(sampass); + return NT_STATUS_NO_MEMORY; + } + } + +#if 0 + init_unistr2_from_datablob(&usr->uni_munged_dial, &blob); + init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial); + data_blob_free(&blob); +#endif + init_samr_user_info20(r, munged_dial_decoded); + TALLOC_FREE(sampass); return NT_STATUS_OK; } + /************************************************************************* get_user_info_21 *************************************************************************/ -static NTSTATUS get_user_info_21(TALLOC_CTX *mem_ctx, SAM_USER_INFO_21 *id21, - DOM_SID *user_sid, DOM_SID *domain_sid) +static NTSTATUS get_user_info_21(TALLOC_CTX *mem_ctx, + struct samr_UserInfo21 *r, + DOM_SID *user_sid, + DOM_SID *domain_sid) { - struct samu *sampass=NULL; + struct samu *pw = NULL; bool ret; - NTSTATUS nt_status; - - if ( !(sampass = samu_new( mem_ctx )) ) { + const DOM_SID *sid_user, *sid_group; + uint32_t rid, primary_gid; + NTTIME last_logon, last_logoff, last_password_change, + acct_expiry, allow_password_change, force_password_change; + time_t must_change_time; + uint8_t password_expired; + const char *account_name, *full_name, *home_directory, *home_drive, + *logon_script, *profile_path, *description, + *workstations, *comment, *parameters; + struct samr_LogonHours logon_hours; + const char *munged_dial = NULL; + DATA_BLOB blob; + + ZERO_STRUCTP(r); + + if (!(pw = samu_new(mem_ctx))) { return NT_STATUS_NO_MEMORY; } become_root(); - ret = pdb_getsampwsid(sampass, user_sid); + ret = pdb_getsampwsid(pw, user_sid); unbecome_root(); if (ret == False) { DEBUG(4,("User %s not found\n", sid_string_dbg(user_sid))); + TALLOC_FREE(pw); return NT_STATUS_NO_SUCH_USER; } - samr_clear_sam_passwd(sampass); + samr_clear_sam_passwd(pw); - DEBUG(3,("User:[%s]\n", pdb_get_username(sampass) )); + DEBUG(3,("User:[%s]\n", pdb_get_username(pw))); - ZERO_STRUCTP(id21); - nt_status = init_sam_user_info21A(id21, sampass, domain_sid); - - TALLOC_FREE(sampass); + sid_user = pdb_get_user_sid(pw); - return nt_status; + if (!sid_peek_check_rid(domain_sid, sid_user, &rid)) { + DEBUG(0, ("get_user_info_21: 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))); + TALLOC_FREE(pw); + 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_21: 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))); + TALLOC_FREE(pw); + return NT_STATUS_UNSUCCESSFUL; + } + + unix_to_nt_time(&last_logon, pdb_get_logon_time(pw)); + unix_to_nt_time(&last_logoff, pdb_get_logoff_time(pw)); + unix_to_nt_time(&acct_expiry, pdb_get_kickoff_time(pw)); + unix_to_nt_time(&last_password_change, pdb_get_pass_last_set_time(pw)); + unix_to_nt_time(&allow_password_change, pdb_get_pass_can_change_time(pw)); + + must_change_time = pdb_get_pass_must_change_time(pw); + if (must_change_time == get_time_t_max()) { + unix_to_nt_time_abs(&force_password_change, must_change_time); + } else { + unix_to_nt_time(&force_password_change, must_change_time); + } + + if (pdb_get_pass_must_change_time(pw) == 0) { + password_expired = PASS_MUST_CHANGE_AT_NEXT_LOGON; + } else { + password_expired = 0; + } + + munged_dial = pdb_get_munged_dial(pw); + if (munged_dial) { + blob = base64_decode_data_blob(munged_dial); + parameters = talloc_strndup(mem_ctx, (const char *)blob.data, blob.length); + data_blob_free(&blob); + if (!parameters) { + TALLOC_FREE(pw); + return NT_STATUS_NO_MEMORY; + } + } else { + parameters = NULL; + } + + + account_name = talloc_strdup(mem_ctx, pdb_get_username(pw)); + full_name = talloc_strdup(mem_ctx, pdb_get_fullname(pw)); + home_directory = talloc_strdup(mem_ctx, pdb_get_homedir(pw)); + home_drive = talloc_strdup(mem_ctx, pdb_get_dir_drive(pw)); + logon_script = talloc_strdup(mem_ctx, pdb_get_logon_script(pw)); + profile_path = talloc_strdup(mem_ctx, pdb_get_profile_path(pw)); + description = talloc_strdup(mem_ctx, pdb_get_acct_desc(pw)); + workstations = talloc_strdup(mem_ctx, pdb_get_workstations(pw)); + comment = talloc_strdup(mem_ctx, pdb_get_comment(pw)); + + logon_hours = get_logon_hours_from_pdb(mem_ctx, pw); +#if 0 + + /* + Look at a user on a real NT4 PDC with usrmgr, press + 'ok'. Then you will see that fields_present is set to + 0x08f827fa. Look at the user immediately after that again, + and you will see that 0x00fffff is returned. This solves + the problem that you get access denied after having looked + at the user. + -- Volker + */ + +#if 0 + init_unistr2_from_datablob(&usr->uni_munged_dial, &munged_dial_blob); + init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial); + data_blob_free(&munged_dial_blob); +#endif +#endif + + init_samr_user_info21(r, + last_logon, + last_logoff, + last_password_change, + acct_expiry, + allow_password_change, + force_password_change, + account_name, + full_name, + home_directory, + home_drive, + logon_script, + profile_path, + description, + workstations, + comment, + parameters, + rid, + primary_gid, + pdb_get_acct_ctrl(pw), + pdb_build_fields_present(pw), + logon_hours, + pdb_get_bad_password_count(pw), + pdb_get_logon_count(pw), + 0, /* country_code */ + 0, /* code_page */ + 0, /* nt_password_set */ + 0, /* lm_password_set */ + password_expired); + TALLOC_FREE(pw); + + return NT_STATUS_OK; } /******************************************************************* - _samr_query_userinfo + _samr_QueryUserInfo ********************************************************************/ -NTSTATUS _samr_query_userinfo(pipes_struct *p, SAMR_Q_QUERY_USERINFO *q_u, SAMR_R_QUERY_USERINFO *r_u) +NTSTATUS _samr_QueryUserInfo(pipes_struct *p, + struct samr_QueryUserInfo *r) { - SAM_USERINFO_CTR *ctr; + NTSTATUS status; + union samr_UserInfo *user_info = NULL; struct samr_info *info = NULL; DOM_SID domain_sid; uint32 rid; - - r_u->status=NT_STATUS_OK; /* search for the handle */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, r->in.user_handle, (void **)(void *)&info)) return NT_STATUS_INVALID_HANDLE; domain_sid = info->sid; @@ -2086,94 +2572,81 @@ NTSTATUS _samr_query_userinfo(pipes_struct *p, SAMR_Q_QUERY_USERINFO *q_u, SAMR_ if (!sid_check_is_in_our_domain(&info->sid)) return NT_STATUS_OBJECT_TYPE_MISMATCH; - DEBUG(5,("_samr_query_userinfo: sid:%s\n", + DEBUG(5,("_samr_QueryUserInfo: sid:%s\n", sid_string_dbg(&info->sid))); - ctr = TALLOC_ZERO_P(p->mem_ctx, SAM_USERINFO_CTR); - if (!ctr) + user_info = TALLOC_ZERO_P(p->mem_ctx, union samr_UserInfo); + if (!user_info) { return NT_STATUS_NO_MEMORY; + } - ZERO_STRUCTP(ctr); - - /* ok! user info levels (lots: see MSDEV help), off we go... */ - ctr->switch_value = q_u->switch_value; - - DEBUG(5,("_samr_query_userinfo: user info level: %d\n", q_u->switch_value)); + DEBUG(5,("_samr_QueryUserInfo: user info level: %d\n", r->in.level)); - switch (q_u->switch_value) { + switch (r->in.level) { case 7: - ctr->info.id7 = TALLOC_ZERO_P(p->mem_ctx, SAM_USER_INFO_7); - if (ctr->info.id7 == NULL) - return NT_STATUS_NO_MEMORY; - - if (!NT_STATUS_IS_OK(r_u->status = get_user_info_7(p->mem_ctx, ctr->info.id7, &info->sid))) - return r_u->status; + status = get_user_info_7(p->mem_ctx, &user_info->info7, &info->sid); + if (!NT_STATUS_IS_OK(status)) { + return status; + } break; case 9: - ctr->info.id9 = TALLOC_ZERO_P(p->mem_ctx, SAM_USER_INFO_9); - if (ctr->info.id9 == NULL) - return NT_STATUS_NO_MEMORY; - - if (!NT_STATUS_IS_OK(r_u->status = get_user_info_9(p->mem_ctx, ctr->info.id9, &info->sid))) - return r_u->status; + status = get_user_info_9(p->mem_ctx, &user_info->info9, &info->sid); + if (!NT_STATUS_IS_OK(status)) { + return status; + } break; case 16: - ctr->info.id16 = TALLOC_ZERO_P(p->mem_ctx, SAM_USER_INFO_16); - if (ctr->info.id16 == NULL) - return NT_STATUS_NO_MEMORY; - - if (!NT_STATUS_IS_OK(r_u->status = get_user_info_16(p->mem_ctx, ctr->info.id16, &info->sid))) - return r_u->status; + status = get_user_info_16(p->mem_ctx, &user_info->info16, &info->sid); + if (!NT_STATUS_IS_OK(status)) { + return status; + } break; case 18: - ctr->info.id18 = TALLOC_ZERO_P(p->mem_ctx, SAM_USER_INFO_18); - if (ctr->info.id18 == NULL) - return NT_STATUS_NO_MEMORY; - - if (!NT_STATUS_IS_OK(r_u->status = get_user_info_18(p, p->mem_ctx, ctr->info.id18, &info->sid))) - return r_u->status; + status = get_user_info_18(p, p->mem_ctx, &user_info->info18, &info->sid); + if (!NT_STATUS_IS_OK(status)) { + return status; + } break; - + case 20: - ctr->info.id20 = TALLOC_ZERO_P(p->mem_ctx,SAM_USER_INFO_20); - if (ctr->info.id20 == NULL) - return NT_STATUS_NO_MEMORY; - if (!NT_STATUS_IS_OK(r_u->status = get_user_info_20(p->mem_ctx, ctr->info.id20, &info->sid))) - return r_u->status; + status = get_user_info_20(p->mem_ctx, &user_info->info20, &info->sid); + if (!NT_STATUS_IS_OK(status)) { + return status; + } break; case 21: - ctr->info.id21 = TALLOC_ZERO_P(p->mem_ctx,SAM_USER_INFO_21); - if (ctr->info.id21 == NULL) - return NT_STATUS_NO_MEMORY; - if (!NT_STATUS_IS_OK(r_u->status = get_user_info_21(p->mem_ctx, ctr->info.id21, - &info->sid, &domain_sid))) - return r_u->status; + status = get_user_info_21(p->mem_ctx, &user_info->info21, + &info->sid, &domain_sid); + if (!NT_STATUS_IS_OK(status)) { + return status; + } break; default: return NT_STATUS_INVALID_INFO_CLASS; } - init_samr_r_query_userinfo(r_u, ctr, r_u->status); + *r->out.info = user_info; + + DEBUG(5,("_samr_QueryUserInfo: %d\n", __LINE__)); - DEBUG(5,("_samr_query_userinfo: %d\n", __LINE__)); - - return r_u->status; + return status; } /******************************************************************* - samr_reply_query_usergroups + _samr_GetGroupsForUser ********************************************************************/ -NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, SAMR_R_QUERY_USERGROUPS *r_u) +NTSTATUS _samr_GetGroupsForUser(pipes_struct *p, + struct samr_GetGroupsForUser *r) { struct samu *sam_pass=NULL; DOM_SID sid; DOM_SID *sids; - DOM_GID dom_gid; - DOM_GID *gids = NULL; + struct samr_RidWithAttribute dom_gid; + struct samr_RidWithAttribute *gids = NULL; uint32 primary_group_rid; size_t num_groups = 0; gid_t *unix_gids; @@ -2183,6 +2656,8 @@ NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, S NTSTATUS result; bool success = False; + struct samr_RidWithAttributeArray *rids = NULL; + /* * from the SID in the request: * we should send back the list of DOMAIN GROUPS @@ -2195,16 +2670,22 @@ NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, S * JFM, 12/2/2001 */ - r_u->status = NT_STATUS_OK; + DEBUG(5,("_samr_GetGroupsForUser: %d\n", __LINE__)); - DEBUG(5,("_samr_query_usergroups: %d\n", __LINE__)); + 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, &q_u->pol, &sid, &acc_granted, NULL)) + if (!get_lsa_policy_samr_sid(p, r->in.user_handle, &sid, &acc_granted, NULL)) return NT_STATUS_INVALID_HANDLE; - - if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_USER_GET_GROUPS, "_samr_query_usergroups"))) { - return r_u->status; + + result = access_check_samr_function(acc_granted, + SA_RIGHT_USER_GET_GROUPS, + "_samr_GetGroupsForUser"); + if (!NT_STATUS_IS_OK(result)) { + return result; } if (!sid_check_is_in_our_domain(&sid)) @@ -2231,7 +2712,7 @@ NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, S result = pdb_enum_group_memberships(p->mem_ctx, sam_pass, &sids, &unix_gids, &num_groups); if ( NT_STATUS_IS_OK(result) ) { - success = sid_peek_check_rid(get_global_sam_sid(), + success = sid_peek_check_rid(get_global_sam_sid(), pdb_get_group_sid(sam_pass), &primary_group_rid); } @@ -2254,48 +2735,53 @@ NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, S gids = NULL; num_gids = 0; - dom_gid.attr = (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT| - SE_GROUP_ENABLED); - dom_gid.g_rid = primary_group_rid; - ADD_TO_ARRAY(p->mem_ctx, DOM_GID, dom_gid, &gids, &num_gids); + dom_gid.attributes = (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT| + SE_GROUP_ENABLED); + dom_gid.rid = primary_group_rid; + ADD_TO_ARRAY(p->mem_ctx, struct samr_RidWithAttribute, dom_gid, &gids, &num_gids); for (i=0; i<num_groups; i++) { if (!sid_peek_check_rid(get_global_sam_sid(), - &(sids[i]), &dom_gid.g_rid)) { + &(sids[i]), &dom_gid.rid)) { DEBUG(10, ("Found sid %s not in our domain\n", sid_string_dbg(&sids[i]))); continue; } - if (dom_gid.g_rid == primary_group_rid) { + if (dom_gid.rid == primary_group_rid) { /* We added the primary group directly from the * sam_account. The other SIDs are unique from * enum_group_memberships */ continue; } - ADD_TO_ARRAY(p->mem_ctx, DOM_GID, dom_gid, &gids, &num_gids); + ADD_TO_ARRAY(p->mem_ctx, struct samr_RidWithAttribute, dom_gid, &gids, &num_gids); } - - /* construct the response. lkclXXXX: gids are not copied! */ - init_samr_r_query_usergroups(r_u, num_gids, gids, r_u->status); - - DEBUG(5,("_samr_query_usergroups: %d\n", __LINE__)); - - return r_u->status; + + rids->count = num_gids; + rids->rids = gids; + + *r->out.rids = rids; + + DEBUG(5,("_samr_GetGroupsForUser: %d\n", __LINE__)); + + return result; } /******************************************************************* - _samr_query_domain_info + samr_QueryDomainInfo_internal ********************************************************************/ -NTSTATUS _samr_query_domain_info(pipes_struct *p, - SAMR_Q_QUERY_DOMAIN_INFO *q_u, - SAMR_R_QUERY_DOMAIN_INFO *r_u) +static NTSTATUS samr_QueryDomainInfo_internal(const char *fn_name, + pipes_struct *p, + struct policy_handle *handle, + uint32_t level, + union samr_DomainInfo **dom_info_ptr) { + NTSTATUS status = NT_STATUS_OK; struct samr_info *info = NULL; - SAM_UNK_CTR *ctr; + union samr_DomainInfo *dom_info; uint32 min_pass_len,pass_hist,password_properties; time_t u_expire, u_min_age; NTTIME nt_expire, nt_min_age; @@ -2313,24 +2799,23 @@ NTSTATUS _samr_query_domain_info(pipes_struct *p, uint32 num_users=0, num_groups=0, num_aliases=0; - if ((ctr = TALLOC_ZERO_P(p->mem_ctx, SAM_UNK_CTR)) == NULL) { + DEBUG(5,("%s: %d\n", fn_name, __LINE__)); + + dom_info = TALLOC_ZERO_P(p->mem_ctx, union samr_DomainInfo); + if (!dom_info) { return NT_STATUS_NO_MEMORY; } - ZERO_STRUCTP(ctr); + *dom_info_ptr = dom_info; - r_u->status = NT_STATUS_OK; - - DEBUG(5,("_samr_query_domain_info: %d\n", __LINE__)); - /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, &q_u->domain_pol, (void **)(void *)&info)) { + if (!find_policy_by_hnd(p, handle, (void **)(void *)&info)) { return NT_STATUS_INVALID_HANDLE; } - - switch (q_u->switch_value) { + + switch (level) { case 0x01: - + become_root(); /* AS ROOT !!! */ @@ -2351,14 +2836,18 @@ NTSTATUS _samr_query_domain_info(pipes_struct *p, u_min_age = account_policy_temp; /* !AS ROOT */ - + unbecome_root(); unix_to_nt_time_abs(&nt_expire, u_expire); unix_to_nt_time_abs(&nt_min_age, u_min_age); - init_unk_info1(&ctr->info.inf1, (uint16)min_pass_len, (uint16)pass_hist, - password_properties, nt_expire, nt_min_age); + init_samr_DomInfo1(&dom_info->info1, + (uint16)min_pass_len, + (uint16)pass_hist, + password_properties, + nt_expire, + nt_min_age); break; case 0x02: @@ -2379,15 +2868,25 @@ NTSTATUS _samr_query_domain_info(pipes_struct *p, seq_num = time(NULL); /* !AS ROOT */ - + unbecome_root(); server_role = ROLE_DOMAIN_PDC; if (lp_server_role() == ROLE_DOMAIN_BDC) server_role = ROLE_DOMAIN_BDC; - init_unk_info2(&ctr->info.inf2, lp_serverstring(), lp_workgroup(), global_myname(), seq_num, - num_users, num_groups, num_aliases, nt_logout, server_role); + init_samr_DomInfo2(&dom_info->info2, + nt_logout, + lp_serverstring(), + lp_workgroup(), + global_myname(), + seq_num, + 1, + server_role, + 1, + num_users, + num_groups, + num_aliases); break; case 0x03: @@ -2402,31 +2901,37 @@ NTSTATUS _samr_query_domain_info(pipes_struct *p, } /* !AS ROOT */ - + unbecome_root(); unix_to_nt_time_abs(&nt_logout, u_logout); - - init_unk_info3(&ctr->info.inf3, nt_logout); + + init_samr_DomInfo3(&dom_info->info3, + nt_logout); + break; case 0x04: - init_unk_info4(&ctr->info.inf4, lp_serverstring()); + init_samr_DomInfo4(&dom_info->info4, + lp_serverstring()); break; case 0x05: - init_unk_info5(&ctr->info.inf5, get_global_sam_name()); + init_samr_DomInfo5(&dom_info->info5, + get_global_sam_name()); break; case 0x06: /* NT returns its own name when a PDC. win2k and later * only the name of the PDC if itself is a BDC (samba4 * idl) */ - init_unk_info6(&ctr->info.inf6, global_myname()); + init_samr_DomInfo6(&dom_info->info6, + global_myname()); break; case 0x07: server_role = ROLE_DOMAIN_PDC; if (lp_server_role() == ROLE_DOMAIN_BDC) server_role = ROLE_DOMAIN_BDC; - init_unk_info7(&ctr->info.inf7, server_role); + init_samr_DomInfo7(&dom_info->info7, + server_role); break; case 0x08: @@ -2439,10 +2944,12 @@ NTSTATUS _samr_query_domain_info(pipes_struct *p, } /* !AS ROOT */ - + unbecome_root(); - init_unk_info8(&ctr->info.inf8, (uint32) seq_num); + init_samr_DomInfo8(&dom_info->info8, + seq_num, + 0); break; case 0x0c: @@ -2463,24 +2970,38 @@ NTSTATUS _samr_query_domain_info(pipes_struct *p, lockout = account_policy_temp; /* !AS ROOT */ - + unbecome_root(); unix_to_nt_time_abs(&nt_lock_duration, u_lock_duration); unix_to_nt_time_abs(&nt_reset_time, u_reset_time); - - init_unk_info12(&ctr->info.inf12, nt_lock_duration, nt_reset_time, (uint16)lockout); + + init_samr_DomInfo12(&dom_info->info12, + nt_lock_duration, + nt_reset_time, + (uint16)lockout); break; default: return NT_STATUS_INVALID_INFO_CLASS; - } - + } + + DEBUG(5,("%s: %d\n", fn_name, __LINE__)); + + return status; +} - init_samr_r_query_domain_info(r_u, q_u->switch_value, ctr, NT_STATUS_OK); - - DEBUG(5,("_samr_query_domain_info: %d\n", __LINE__)); - - return r_u->status; +/******************************************************************* + _samr_QueryDomainInfo + ********************************************************************/ + +NTSTATUS _samr_QueryDomainInfo(pipes_struct *p, + struct samr_QueryDomainInfo *r) +{ + return samr_QueryDomainInfo_internal("_samr_QueryDomainInfo", + p, + r->in.domain_handle, + r->in.level, + r->out.info); } /* W2k3 seems to use the same check for all 3 objects that can be created via @@ -2522,19 +3043,17 @@ static NTSTATUS can_create(TALLOC_CTX *mem_ctx, const char *new_name) } /******************************************************************* - _samr_create_user - Create an account, can be either a normal user or a machine. - This funcion will need to be updated for bdc/domain trusts. + _samr_CreateUser2 ********************************************************************/ -NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, - SAMR_R_CREATE_USER *r_u) +NTSTATUS _samr_CreateUser2(pipes_struct *p, + struct samr_CreateUser2 *r) { - char *account; + const char *account = NULL; DOM_SID sid; - POLICY_HND dom_pol = q_u->domain_pol; - uint16 acb_info = q_u->acb_info; - POLICY_HND *user_pol = &r_u->user_pol; + POLICY_HND dom_pol = *r->in.domain_handle; + uint32_t acb_info = r->in.acct_flags; + POLICY_HND *user_pol = r->out.user_handle; struct samr_info *info = NULL; NTSTATUS nt_status; uint32 acc_granted; @@ -2553,19 +3072,19 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, nt_status = access_check_samr_function(acc_granted, SA_RIGHT_DOMAIN_CREATE_USER, - "_samr_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 + acb_info == ACB_WSTRUST || acb_info == ACB_SVRTRUST)) { + /* Match Win2k, and return NT_STATUS_INVALID_PARAMETER if this parameter is not an account type */ return NT_STATUS_INVALID_PARAMETER; } - account = rpcstr_pull_unistr2_talloc(p->mem_ctx, &q_u->uni_name); + account = r->in.account_name->string; if (account == NULL) { return NT_STATUS_NO_MEMORY; } @@ -2576,14 +3095,14 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, } /* determine which user right we need to check based on the acb_info */ - + if ( acb_info & ACB_WSTRUST ) { se_priv_copy( &se_rights, &se_machine_account ); can_add_account = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); - } - /* usrmgr.exe (and net rpc trustdom grant) creates a normal user + } + /* usrmgr.exe (and net rpc trustdom grant) creates a normal user account for domain trusts and changes the ACB flags later */ else if ( acb_info & ACB_NORMAL && (account[strlen(account)-1] != '$') ) @@ -2591,7 +3110,7 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, se_priv_copy( &se_rights, &se_add_users ); can_add_account = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); - } + } else /* implicit assumption of a BDC or domain trust account here * (we already check the flags earlier) */ { @@ -2603,41 +3122,41 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, DOMAIN_GROUP_RID_ADMINS ); } } - - DEBUG(5, ("_samr_create_user: %s can add this account : %s\n", + + DEBUG(5, ("_samr_CreateUser2: %s can add this account : %s\n", uidtoname(p->pipe_user.ut.uid), can_add_account ? "True":"False" )); - + /********** BEGIN Admin BLOCK **********/ if ( can_add_account ) become_root(); nt_status = pdb_create_user(p->mem_ctx, account, acb_info, - &r_u->user_rid); + r->out.rid); if ( can_add_account ) unbecome_root(); /********** END Admin BLOCK **********/ - + /* now check for failure */ - + if ( !NT_STATUS_IS_OK(nt_status) ) return nt_status; - + /* Get the user's SID */ - sid_compose(&sid, get_global_sam_sid(), r_u->user_rid); - + sid_compose(&sid, get_global_sam_sid(), *r->out.rid); + make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_generic_mapping, &sid, SAMR_USR_RIGHTS_WRITE_PW); se_map_generic(&des_access, &usr_generic_mapping); - - nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token, - &se_rights, GENERIC_RIGHTS_USER_WRITE, des_access, - &acc_granted, "_samr_create_user"); - + + nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token, + &se_rights, GENERIC_RIGHTS_USER_WRITE, des_access, + &acc_granted, "_samr_CreateUser2"); + if ( !NT_STATUS_IS_OK(nt_status) ) { return nt_status; } @@ -2659,40 +3178,38 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, /* After a "set" ensure we have no cached display info. */ force_flush_samr_cache(info->disp_info); - r_u->access_granted = acc_granted; + *r->out.access_granted = acc_granted; return NT_STATUS_OK; } /******************************************************************* - samr_reply_connect_anon + _samr_Connect ********************************************************************/ -NTSTATUS _samr_connect_anon(pipes_struct *p, SAMR_Q_CONNECT_ANON *q_u, SAMR_R_CONNECT_ANON *r_u) +NTSTATUS _samr_Connect(pipes_struct *p, + struct samr_Connect *r) { struct samr_info *info = NULL; - uint32 des_access = q_u->access_mask; + uint32 des_access = r->in.access_mask; /* Access check */ if (!pipe_access_check(p)) { - DEBUG(3, ("access denied to samr_connect_anon\n")); - r_u->status = NT_STATUS_ACCESS_DENIED; - return r_u->status; + DEBUG(3, ("access denied to _samr_Connect\n")); + return NT_STATUS_ACCESS_DENIED; } /* set up the SAMR connect_anon response */ - r_u->status = NT_STATUS_OK; - /* associate the user's SID with the new handle. */ if ((info = get_samr_info_by_sid(NULL)) == NULL) return NT_STATUS_NO_MEMORY; /* don't give away the farm but this is probably ok. The SA_RIGHT_SAM_ENUM_DOMAINS - was observed from a win98 client trying to enumerate users (when configured + was observed from a win98 client trying to enumerate users (when configured user level access control on shares) --jerry */ - + if (des_access == MAXIMUM_ALLOWED_ACCESS) { /* Map to max possible knowing we're filtered below. */ des_access = GENERIC_ALL_ACCESS; @@ -2700,152 +3217,143 @@ NTSTATUS _samr_connect_anon(pipes_struct *p, SAMR_Q_CONNECT_ANON *q_u, SAMR_R_CO se_map_generic( &des_access, &sam_generic_mapping ); info->acc_granted = des_access & (SA_RIGHT_SAM_ENUM_DOMAINS|SA_RIGHT_SAM_OPEN_DOMAIN); - - info->status = q_u->unknown_0; /* get a (unique) handle. open a policy on it. */ - if (!create_policy_hnd(p, &r_u->connect_pol, free_samr_info, (void *)info)) + if (!create_policy_hnd(p, r->out.connect_handle, free_samr_info, (void *)info)) return NT_STATUS_OBJECT_NAME_NOT_FOUND; - return r_u->status; + return NT_STATUS_OK; } /******************************************************************* - samr_reply_connect + _samr_Connect2 ********************************************************************/ -NTSTATUS _samr_connect(pipes_struct *p, SAMR_Q_CONNECT *q_u, SAMR_R_CONNECT *r_u) +NTSTATUS _samr_Connect2(pipes_struct *p, + struct samr_Connect2 *r) { struct samr_info *info = NULL; SEC_DESC *psd = NULL; uint32 acc_granted; - uint32 des_access = q_u->access_mask; + uint32 des_access = r->in.access_mask; NTSTATUS nt_status; size_t sd_size; - DEBUG(5,("_samr_connect: %d\n", __LINE__)); + DEBUG(5,("_samr_Connect2: %d\n", __LINE__)); /* Access check */ if (!pipe_access_check(p)) { - DEBUG(3, ("access denied to samr_connect\n")); - r_u->status = NT_STATUS_ACCESS_DENIED; - return r_u->status; + DEBUG(3, ("access denied to _samr_Connect2\n")); + return NT_STATUS_ACCESS_DENIED; } make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &sam_generic_mapping, NULL, 0); se_map_generic(&des_access, &sam_generic_mapping); - - nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token, - NULL, 0, des_access, &acc_granted, "_samr_connect"); - - if ( !NT_STATUS_IS_OK(nt_status) ) - return nt_status; - r_u->status = NT_STATUS_OK; + nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token, + NULL, 0, des_access, &acc_granted, "_samr_Connect2"); + + 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(NULL)) == NULL) return NT_STATUS_NO_MEMORY; info->acc_granted = acc_granted; - info->status = q_u->access_mask; + info->status = r->in.access_mask; /* this looks so wrong... - gd */ /* get a (unique) handle. open a policy on it. */ - if (!create_policy_hnd(p, &r_u->connect_pol, free_samr_info, (void *)info)) + if (!create_policy_hnd(p, r->out.connect_handle, free_samr_info, (void *)info)) return NT_STATUS_OBJECT_NAME_NOT_FOUND; - DEBUG(5,("_samr_connect: %d\n", __LINE__)); + DEBUG(5,("_samr_Connect2: %d\n", __LINE__)); - return r_u->status; + return nt_status; } /******************************************************************* - samr_connect4 + _samr_Connect4 ********************************************************************/ -NTSTATUS _samr_connect4(pipes_struct *p, SAMR_Q_CONNECT4 *q_u, SAMR_R_CONNECT4 *r_u) +NTSTATUS _samr_Connect4(pipes_struct *p, + struct samr_Connect4 *r) { struct samr_info *info = NULL; SEC_DESC *psd = NULL; uint32 acc_granted; - uint32 des_access = q_u->access_mask; + uint32 des_access = r->in.access_mask; NTSTATUS nt_status; size_t sd_size; - DEBUG(5,("_samr_connect4: %d\n", __LINE__)); + DEBUG(5,("_samr_Connect4: %d\n", __LINE__)); /* Access check */ if (!pipe_access_check(p)) { - DEBUG(3, ("access denied to samr_connect4\n")); - r_u->status = NT_STATUS_ACCESS_DENIED; - return r_u->status; + DEBUG(3, ("access denied to samr_Connect4\n")); + return NT_STATUS_ACCESS_DENIED; } make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &sam_generic_mapping, NULL, 0); se_map_generic(&des_access, &sam_generic_mapping); - - nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token, - NULL, 0, des_access, &acc_granted, "_samr_connect4"); - - if ( !NT_STATUS_IS_OK(nt_status) ) - return nt_status; - r_u->status = NT_STATUS_OK; + nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token, + NULL, 0, des_access, &acc_granted, "_samr_Connect4"); + + 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(NULL)) == NULL) return NT_STATUS_NO_MEMORY; info->acc_granted = acc_granted; - info->status = q_u->access_mask; + info->status = r->in.access_mask; /* ??? */ /* get a (unique) handle. open a policy on it. */ - if (!create_policy_hnd(p, &r_u->connect_pol, free_samr_info, (void *)info)) + if (!create_policy_hnd(p, r->out.connect_handle, free_samr_info, (void *)info)) return NT_STATUS_OBJECT_NAME_NOT_FOUND; - DEBUG(5,("_samr_connect: %d\n", __LINE__)); + DEBUG(5,("_samr_Connect4: %d\n", __LINE__)); - return r_u->status; + return NT_STATUS_OK; } /******************************************************************* - samr_connect5 + _samr_Connect5 ********************************************************************/ -NTSTATUS _samr_connect5(pipes_struct *p, SAMR_Q_CONNECT5 *q_u, SAMR_R_CONNECT5 *r_u) +NTSTATUS _samr_Connect5(pipes_struct *p, + struct samr_Connect5 *r) { struct samr_info *info = NULL; SEC_DESC *psd = NULL; uint32 acc_granted; - uint32 des_access = q_u->access_mask; + uint32 des_access = r->in.access_mask; NTSTATUS nt_status; - POLICY_HND pol; size_t sd_size; + struct samr_ConnectInfo1 info1; - - DEBUG(5,("_samr_connect5: %d\n", __LINE__)); - - ZERO_STRUCTP(r_u); + DEBUG(5,("_samr_Connect5: %d\n", __LINE__)); /* Access check */ if (!pipe_access_check(p)) { - DEBUG(3, ("access denied to samr_connect5\n")); - r_u->status = NT_STATUS_ACCESS_DENIED; - return r_u->status; + DEBUG(3, ("access denied to samr_Connect5\n")); + return NT_STATUS_ACCESS_DENIED; } make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &sam_generic_mapping, NULL, 0); se_map_generic(&des_access, &sam_generic_mapping); - - nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token, - NULL, 0, des_access, &acc_granted, "_samr_connect5"); - - if ( !NT_STATUS_IS_OK(nt_status) ) + + nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token, + NULL, 0, des_access, &acc_granted, "_samr_Connect5"); + + if ( !NT_STATUS_IS_OK(nt_status) ) return nt_status; /* associate the user's SID and access granted with the new handle. */ @@ -2853,181 +3361,169 @@ NTSTATUS _samr_connect5(pipes_struct *p, SAMR_Q_CONNECT5 *q_u, SAMR_R_CONNECT5 * return NT_STATUS_NO_MEMORY; info->acc_granted = acc_granted; - info->status = q_u->access_mask; + info->status = r->in.access_mask; /* ??? */ /* get a (unique) handle. open a policy on it. */ - if (!create_policy_hnd(p, &pol, free_samr_info, (void *)info)) + if (!create_policy_hnd(p, r->out.connect_handle, free_samr_info, (void *)info)) return NT_STATUS_OBJECT_NAME_NOT_FOUND; - DEBUG(5,("_samr_connect: %d\n", __LINE__)); + DEBUG(5,("_samr_Connect5: %d\n", __LINE__)); - init_samr_r_connect5(r_u, &pol, NT_STATUS_OK); + info1.client_version = SAMR_CONNECT_AFTER_W2K; + info1.unknown2 = 0; - return r_u->status; + *r->out.level_out = 1; + r->out.info_out->info1 = info1; + + return NT_STATUS_OK; } /********************************************************************** - api_samr_lookup_domain + _samr_LookupDomain **********************************************************************/ -NTSTATUS _samr_lookup_domain(pipes_struct *p, SAMR_Q_LOOKUP_DOMAIN *q_u, SAMR_R_LOOKUP_DOMAIN *r_u) +NTSTATUS _samr_LookupDomain(pipes_struct *p, + struct samr_LookupDomain *r) { + NTSTATUS status = NT_STATUS_OK; struct samr_info *info; - fstring domain_name; - DOM_SID sid; - - r_u->status = NT_STATUS_OK; + const char *domain_name; + DOM_SID *sid = NULL; - if (!find_policy_by_hnd(p, &q_u->connect_pol, (void**)(void *)&info)) + if (!find_policy_by_hnd(p, r->in.connect_handle, (void**)(void *)&info)) return NT_STATUS_INVALID_HANDLE; - /* win9x user manager likes to use SA_RIGHT_SAM_ENUM_DOMAINS here. + /* win9x user manager likes to use SA_RIGHT_SAM_ENUM_DOMAINS here. Reverted that change so we will work with RAS servers again */ - if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(info->acc_granted, - SA_RIGHT_SAM_OPEN_DOMAIN, "_samr_lookup_domain"))) - { - return r_u->status; + status = access_check_samr_function(info->acc_granted, + SA_RIGHT_SAM_OPEN_DOMAIN, + "_samr_LookupDomain"); + if (!NT_STATUS_IS_OK(status)) { + return status; } - rpcstr_pull(domain_name, q_u->uni_domain.buffer, sizeof(domain_name), q_u->uni_domain.uni_str_len*2, 0); + domain_name = r->in.domain_name->string; - ZERO_STRUCT(sid); + sid = TALLOC_ZERO_P(p->mem_ctx, struct dom_sid2); + if (!sid) { + return NT_STATUS_NO_MEMORY; + } if (strequal(domain_name, builtin_domain_name())) { - sid_copy(&sid, &global_sid_Builtin); + sid_copy(sid, &global_sid_Builtin); } else { - if (!secrets_fetch_domain_sid(domain_name, &sid)) { - r_u->status = NT_STATUS_NO_SUCH_DOMAIN; + if (!secrets_fetch_domain_sid(domain_name, sid)) { + status = NT_STATUS_NO_SUCH_DOMAIN; } } DEBUG(2,("Returning domain sid for domain %s -> %s\n", domain_name, - sid_string_dbg(&sid))); - - init_samr_r_lookup_domain(r_u, &sid, r_u->status); + sid_string_dbg(sid))); - return r_u->status; -} + *r->out.sid = sid; -/****************************************************************** -makes a SAMR_R_ENUM_DOMAINS structure. -********************************************************************/ - -static bool make_enum_domains(TALLOC_CTX *ctx, SAM_ENTRY **pp_sam, - UNISTR2 **pp_uni_name, uint32 num_sam_entries, fstring doms[]) -{ - uint32 i; - SAM_ENTRY *sam; - UNISTR2 *uni_name; - - DEBUG(5, ("make_enum_domains\n")); - - *pp_sam = NULL; - *pp_uni_name = NULL; - - if (num_sam_entries == 0) - return True; - - sam = TALLOC_ZERO_ARRAY(ctx, SAM_ENTRY, num_sam_entries); - uni_name = TALLOC_ZERO_ARRAY(ctx, UNISTR2, num_sam_entries); - - if (sam == NULL || uni_name == NULL) - return False; - - for (i = 0; i < num_sam_entries; i++) { - init_unistr2(&uni_name[i], doms[i], UNI_FLAGS_NONE); - init_sam_entry(&sam[i], &uni_name[i], 0); - } - - *pp_sam = sam; - *pp_uni_name = uni_name; - - return True; + return status; } /********************************************************************** - api_samr_enum_domains + _samr_EnumDomains **********************************************************************/ -NTSTATUS _samr_enum_domains(pipes_struct *p, SAMR_Q_ENUM_DOMAINS *q_u, SAMR_R_ENUM_DOMAINS *r_u) +NTSTATUS _samr_EnumDomains(pipes_struct *p, + struct samr_EnumDomains *r) { + NTSTATUS status; struct samr_info *info; - uint32 num_entries = 2; - fstring dom[2]; - const char *name; + uint32_t num_entries = 2; + struct samr_SamEntry *entry_array = NULL; + struct samr_SamArray *sam; - r_u->status = NT_STATUS_OK; - - if (!find_policy_by_hnd(p, &q_u->pol, (void**)(void *)&info)) + if (!find_policy_by_hnd(p, r->in.connect_handle, (void**)(void *)&info)) return NT_STATUS_INVALID_HANDLE; - - if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(info->acc_granted, SA_RIGHT_SAM_ENUM_DOMAINS, "_samr_enum_domains"))) { - return r_u->status; - } - name = get_global_sam_name(); + status = access_check_samr_function(info->acc_granted, + SA_RIGHT_SAM_ENUM_DOMAINS, + "_samr_EnumDomains"); + if (!NT_STATUS_IS_OK(status)) { + return status; + } - fstrcpy(dom[0],name); - strupper_m(dom[0]); - fstrcpy(dom[1],"Builtin"); + sam = TALLOC_ZERO_P(p->mem_ctx, struct samr_SamArray); + if (!sam) { + return NT_STATUS_NO_MEMORY; + } - if (!make_enum_domains(p->mem_ctx, &r_u->sam, &r_u->uni_dom_name, num_entries, dom)) + entry_array = TALLOC_ZERO_ARRAY(p->mem_ctx, + struct samr_SamEntry, + num_entries); + if (!entry_array) { return NT_STATUS_NO_MEMORY; + } + + entry_array[0].idx = 0; + init_lsa_String(&entry_array[0].name, get_global_sam_name()); - init_samr_r_enum_domains(r_u, q_u->start_idx + num_entries, num_entries); + entry_array[1].idx = 1; + init_lsa_String(&entry_array[1].name, "Builtin"); - return r_u->status; + sam->count = num_entries; + sam->entries = entry_array; + + *r->out.sam = sam; + *r->out.num_entries = num_entries; + + return status; } /******************************************************************* - api_samr_open_alias + _samr_OpenAlias ********************************************************************/ -NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_ALIAS *r_u) +NTSTATUS _samr_OpenAlias(pipes_struct *p, + struct samr_OpenAlias *r) { DOM_SID sid; - POLICY_HND domain_pol = q_u->dom_pol; - uint32 alias_rid = q_u->rid_alias; - POLICY_HND *alias_pol = &r_u->pol; + POLICY_HND domain_pol = *r->in.domain_handle; + uint32 alias_rid = r->in.rid; + POLICY_HND *alias_pol = r->out.alias_handle; struct samr_info *info = NULL; SEC_DESC *psd = NULL; uint32 acc_granted; - uint32 des_access = q_u->access_mask; + uint32 des_access = r->in.access_mask; size_t sd_size; NTSTATUS status; SE_PRIV se_rights; - r_u->status = NT_STATUS_OK; - /* find the domain policy and get the SID / access bits stored in the domain policy */ - + if ( !get_lsa_policy_samr_sid(p, &domain_pol, &sid, &acc_granted, NULL) ) return NT_STATUS_INVALID_HANDLE; - - status = access_check_samr_function(acc_granted, - SA_RIGHT_DOMAIN_OPEN_ACCOUNT, "_samr_open_alias"); - - if ( !NT_STATUS_IS_OK(status) ) + + status = access_check_samr_function(acc_granted, + SA_RIGHT_DOMAIN_OPEN_ACCOUNT, + "_samr_OpenAlias"); + + if ( !NT_STATUS_IS_OK(status) ) return status; /* append the alias' RID to it */ - + if (!sid_append_rid(&sid, alias_rid)) return NT_STATUS_NO_SUCH_ALIAS; - + /*check if access can be granted as requested by client. */ - + make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &ali_generic_mapping, NULL, 0); se_map_generic(&des_access,&ali_generic_mapping); - + se_priv_copy( &se_rights, &se_add_users ); - - - status = access_check_samr_object(psd, p->pipe_user.nt_user_token, - &se_rights, GENERIC_RIGHTS_ALIAS_WRITE, des_access, - &acc_granted, "_samr_open_alias"); - + + + status = access_check_samr_object(psd, p->pipe_user.nt_user_token, + &se_rights, GENERIC_RIGHTS_ALIAS_WRITE, des_access, + &acc_granted, "_samr_OpenAlias"); + if ( !NT_STATUS_IS_OK(status) ) return status; @@ -3046,7 +3542,7 @@ NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_A } /* make sure there is a mapping */ - + if ( !sid_to_gid( &sid, &gid ) ) { return NT_STATUS_NO_SUCH_ALIAS; } @@ -3056,23 +3552,24 @@ NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_A /* associate the alias SID with the new handle. */ if ((info = get_samr_info_by_sid(&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, alias_pol, free_samr_info, (void *)info)) return NT_STATUS_OBJECT_NAME_NOT_FOUND; - return r_u->status; + return NT_STATUS_OK; } /******************************************************************* set_user_info_7 ********************************************************************/ + static NTSTATUS set_user_info_7(TALLOC_CTX *mem_ctx, - const SAM_USER_INFO_7 *id7, struct samu *pwd) + struct samr_UserInfo7 *id7, + struct samu *pwd) { - fstring new_name; NTSTATUS rc; if (id7 == NULL) { @@ -3081,14 +3578,14 @@ static NTSTATUS set_user_info_7(TALLOC_CTX *mem_ctx, return NT_STATUS_ACCESS_DENIED; } - if(!rpcstr_pull(new_name, id7->uni_name.buffer, sizeof(new_name), id7->uni_name.uni_str_len*2, 0)) { + if (!id7->account_name.string) { DEBUG(5, ("set_user_info_7: failed to get new username\n")); TALLOC_FREE(pwd); 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 + 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 @@ -3096,12 +3593,12 @@ static NTSTATUS set_user_info_7(TALLOC_CTX *mem_ctx, simply that the rename fails with a slightly different status code (like UNSUCCESSFUL instead of ALREADY_EXISTS). */ - rc = can_create(mem_ctx, new_name); + rc = can_create(mem_ctx, id7->account_name.string); if (!NT_STATUS_IS_OK(rc)) { return rc; } - rc = pdb_rename_sam_account(pwd, new_name); + rc = pdb_rename_sam_account(pwd, id7->account_name.string); TALLOC_FREE(pwd); return rc; @@ -3111,16 +3608,17 @@ static NTSTATUS set_user_info_7(TALLOC_CTX *mem_ctx, set_user_info_16 ********************************************************************/ -static bool set_user_info_16(const SAM_USER_INFO_16 *id16, struct samu *pwd) +static bool set_user_info_16(struct samr_UserInfo16 *id16, + struct samu *pwd) { if (id16 == NULL) { DEBUG(5, ("set_user_info_16: NULL id16\n")); TALLOC_FREE(pwd); return False; } - + /* FIX ME: check if the value is really changed --metze */ - if (!pdb_set_acct_ctrl(pwd, id16->acb_info, PDB_CHANGED)) { + if (!pdb_set_acct_ctrl(pwd, id16->acct_flags, PDB_CHANGED)) { TALLOC_FREE(pwd); return False; } @@ -3139,28 +3637,28 @@ static bool set_user_info_16(const SAM_USER_INFO_16 *id16, struct samu *pwd) set_user_info_18 ********************************************************************/ -static bool set_user_info_18(SAM_USER_INFO_18 *id18, struct samu *pwd) +static bool set_user_info_18(struct samr_UserInfo18 *id18, + struct samu *pwd) { - if (id18 == NULL) { DEBUG(2, ("set_user_info_18: id18 is NULL\n")); TALLOC_FREE(pwd); return False; } - - if (!pdb_set_lanman_passwd (pwd, id18->lm_pwd, PDB_CHANGED)) { + + if (!pdb_set_lanman_passwd (pwd, id18->lm_pwd.hash, PDB_CHANGED)) { TALLOC_FREE(pwd); return False; } - if (!pdb_set_nt_passwd (pwd, id18->nt_pwd, PDB_CHANGED)) { + if (!pdb_set_nt_passwd (pwd, id18->nt_pwd.hash, PDB_CHANGED)) { TALLOC_FREE(pwd); return False; } if (!pdb_set_pass_last_set_time (pwd, time(NULL), PDB_CHANGED)) { TALLOC_FREE(pwd); - return False; + return False; } - + if(!NT_STATUS_IS_OK(pdb_update_sam_account(pwd))) { TALLOC_FREE(pwd); return False; @@ -3174,13 +3672,14 @@ static bool set_user_info_18(SAM_USER_INFO_18 *id18, struct samu *pwd) set_user_info_20 ********************************************************************/ -static bool set_user_info_20(SAM_USER_INFO_20 *id20, struct samu *pwd) +static bool set_user_info_20(struct samr_UserInfo20 *id20, + struct samu *pwd) { if (id20 == NULL) { DEBUG(5, ("set_user_info_20: NULL id20\n")); return False; } - + copy_id20_to_sam_passwd(pwd, id20); /* write the change out */ @@ -3193,30 +3692,30 @@ static bool set_user_info_20(SAM_USER_INFO_20 *id20, struct samu *pwd) return True; } + /******************************************************************* set_user_info_21 ********************************************************************/ -static NTSTATUS set_user_info_21(TALLOC_CTX *mem_ctx, SAM_USER_INFO_21 *id21, +static NTSTATUS set_user_info_21(TALLOC_CTX *mem_ctx, + struct samr_UserInfo21 *id21, struct samu *pwd) { - fstring new_name; NTSTATUS status; - + if (id21 == NULL) { DEBUG(5, ("set_user_info_21: NULL id21\n")); return NT_STATUS_INVALID_PARAMETER; } /* we need to separately check for an account rename first */ - - if (rpcstr_pull(new_name, id21->uni_user_name.buffer, - sizeof(new_name), id21->uni_user_name.uni_str_len*2, 0) - && (!strequal(new_name, pdb_get_username(pwd)))) + + if (id21->account_name.string && + (!strequal(id21->account_name.string, pdb_get_username(pwd)))) { /* check to see if the new username already exists. Note: we can't - reliably lock all backends, so there is potentially the + 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 @@ -3224,43 +3723,43 @@ static NTSTATUS set_user_info_21(TALLOC_CTX *mem_ctx, SAM_USER_INFO_21 *id21, simply that the rename fails with a slightly different status code (like UNSUCCESSFUL instead of ALREADY_EXISTS). */ - status = can_create(mem_ctx, new_name); + status = can_create(mem_ctx, id21->account_name.string); if (!NT_STATUS_IS_OK(status)) { return status; } - status = pdb_rename_sam_account(pwd, new_name); + status = pdb_rename_sam_account(pwd, id21->account_name.string); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("set_user_info_21: failed to rename account: %s\n", + DEBUG(0,("set_user_info_21: failed to rename account: %s\n", nt_errstr(status))); TALLOC_FREE(pwd); return status; } - /* set the new username so that later + /* set the new username so that later functions can work on the new account */ - pdb_set_username(pwd, new_name, PDB_SET); + pdb_set_username(pwd, id21->account_name.string, PDB_SET); } - copy_id21_to_sam_passwd(pwd, id21); - + copy_id21_to_sam_passwd("INFO_21", pwd, id21); + /* * The funny part about the previous two calls is * that pwd still has the password hashes from the * passdb entry. These have not been updated from * id21. I don't know if they need to be set. --jerry */ - + if ( IS_SAM_CHANGED(pwd, PDB_GROUPSID) ) { status = pdb_set_unix_primary_group(mem_ctx, pwd); if ( !NT_STATUS_IS_OK(status) ) { return status; } } - + /* Don't worry about writing out the user account since the - primary group SID is generated solely from the user's Unix + primary group SID is generated solely from the user's Unix primary group. */ /* write the change out */ @@ -3278,7 +3777,8 @@ static NTSTATUS set_user_info_21(TALLOC_CTX *mem_ctx, SAM_USER_INFO_21 *id21, set_user_info_23 ********************************************************************/ -static NTSTATUS set_user_info_23(TALLOC_CTX *mem_ctx, SAM_USER_INFO_23 *id23, +static NTSTATUS set_user_info_23(TALLOC_CTX *mem_ctx, + struct samr_UserInfo23 *id23, struct samu *pwd) { char *plaintext_buf = NULL; @@ -3297,7 +3797,7 @@ static NTSTATUS set_user_info_23(TALLOC_CTX *mem_ctx, SAM_USER_INFO_23 *id23, acct_ctrl = pdb_get_acct_ctrl(pwd); if (!decode_pw_buffer(mem_ctx, - id23->pass, + id23->password.data, &plaintext_buf, &len, STR_UNICODE)) { @@ -3445,18 +3945,19 @@ static bool set_user_info_pw(uint8 *pass, struct samu *pwd) set_user_info_25 ********************************************************************/ -static NTSTATUS set_user_info_25(TALLOC_CTX *mem_ctx, SAM_USER_INFO_25 *id25, +static NTSTATUS set_user_info_25(TALLOC_CTX *mem_ctx, + struct samr_UserInfo25 *id25, struct samu *pwd) { NTSTATUS status; - + if (id25 == NULL) { DEBUG(5, ("set_user_info_25: NULL id25\n")); return NT_STATUS_INVALID_PARAMETER; } copy_id25_to_sam_passwd(pwd, id25); - + /* write the change out */ if(!NT_STATUS_IS_OK(status = pdb_update_sam_account(pwd))) { TALLOC_FREE(pwd); @@ -3477,7 +3978,7 @@ static NTSTATUS set_user_info_25(TALLOC_CTX *mem_ctx, SAM_USER_INFO_25 *id25, return status; } } - + /* WARNING: No TALLOC_FREE(pwd), we are about to set the password * hereafter! */ @@ -3485,38 +3986,41 @@ static NTSTATUS set_user_info_25(TALLOC_CTX *mem_ctx, SAM_USER_INFO_25 *id25, } /******************************************************************* - samr_reply_set_userinfo + samr_SetUserInfo_internal ********************************************************************/ -NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SET_USERINFO *r_u) +static NTSTATUS samr_SetUserInfo_internal(const char *fn_name, + pipes_struct *p, + struct policy_handle *user_handle, + uint16_t level, + union samr_UserInfo *info) { + NTSTATUS status; struct samu *pwd = NULL; DOM_SID sid; - POLICY_HND *pol = &q_u->pol; - uint16 switch_value = q_u->switch_value; - SAM_USERINFO_CTR *ctr = q_u->ctr; - uint32 acc_granted; - uint32 acc_required; + POLICY_HND *pol = user_handle; + uint16_t switch_value = level; + uint32_t acc_granted; + uint32_t acc_required; bool ret; bool has_enough_rights = False; - uint32 acb_info; + uint32_t acb_info; DISP_INFO *disp_info = NULL; - DEBUG(5, ("_samr_set_userinfo: %d\n", __LINE__)); - - r_u->status = NT_STATUS_OK; + DEBUG(5,("%s: %d\n", fn_name, __LINE__)); /* find the policy handle. open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, pol, &sid, &acc_granted, &disp_info)) + if (!get_lsa_policy_samr_sid(p, pol, &sid, &acc_granted, &disp_info)) { return NT_STATUS_INVALID_HANDLE; + } - /* This is tricky. A WinXP domain join sets + /* This is tricky. A WinXP domain join sets (SA_RIGHT_USER_SET_PASSWORD|SA_RIGHT_USER_SET_ATTRIBUTES|SA_RIGHT_USER_ACCT_FLAGS_EXPIRY) - The MMC lusrmgr plugin includes these perms and more in the SamrOpenUser(). But the - standard Win32 API calls just ask for SA_RIGHT_USER_SET_PASSWORD in the SamrOpenUser(). - This should be enough for levels 18, 24, 25,& 26. Info level 23 can set more so + The MMC lusrmgr plugin includes these perms and more in the SamrOpenUser(). But the + standard Win32 API calls just ask for SA_RIGHT_USER_SET_PASSWORD in the SamrOpenUser(). + This should be enough for levels 18, 24, 25,& 26. Info level 23 can set more so we'll use the set from the WinXP join as the basis. */ - + switch (switch_value) { case 18: case 24: @@ -3525,319 +4029,252 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE acc_required = SA_RIGHT_USER_SET_PASSWORD; break; default: - acc_required = SA_RIGHT_USER_SET_PASSWORD | SA_RIGHT_USER_SET_ATTRIBUTES | SA_RIGHT_USER_ACCT_FLAGS_EXPIRY; + acc_required = SA_RIGHT_USER_SET_PASSWORD | + SA_RIGHT_USER_SET_ATTRIBUTES | + SA_RIGHT_USER_ACCT_FLAGS_EXPIRY; break; } - - if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, acc_required, "_samr_set_userinfo"))) { - return r_u->status; + + status = access_check_samr_function(acc_granted, + acc_required, + fn_name); + if (!NT_STATUS_IS_OK(status)) { + return status; } - DEBUG(5, ("_samr_set_userinfo: sid:%s, level:%d\n", - sid_string_dbg(&sid), switch_value)); + DEBUG(5, ("%s: sid:%s, level:%d\n", + fn_name, sid_string_dbg(&sid), switch_value)); - if (ctr == NULL) { - DEBUG(5, ("_samr_set_userinfo: NULL info level\n")); + if (info == NULL) { + DEBUG(5, ("%s: NULL info level\n", fn_name)); return NT_STATUS_INVALID_INFO_CLASS; } - - if ( !(pwd = samu_new( NULL )) ) { + + if (!(pwd = samu_new(NULL))) { return NT_STATUS_NO_MEMORY; } - + become_root(); ret = pdb_getsampwsid(pwd, &sid); unbecome_root(); - - if ( !ret ) { + + if (!ret) { TALLOC_FREE(pwd); return NT_STATUS_NO_SUCH_USER; } - + /* deal with machine password changes differently from userinfo changes */ /* check to see if we have the sufficient rights */ - + acb_info = pdb_get_acct_ctrl(pwd); - if ( acb_info & ACB_WSTRUST ) - has_enough_rights = user_has_privileges( p->pipe_user.nt_user_token, &se_machine_account); - else if ( acb_info & ACB_NORMAL ) - has_enough_rights = user_has_privileges( p->pipe_user.nt_user_token, &se_add_users ); - else if ( acb_info & (ACB_SVRTRUST|ACB_DOMTRUST) ) { - if ( lp_enable_privileges() ) - has_enough_rights = nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ); - } - - DEBUG(5, ("_samr_set_userinfo: %s does%s possess sufficient rights\n", + if (acb_info & ACB_WSTRUST) + has_enough_rights = user_has_privileges(p->pipe_user.nt_user_token, + &se_machine_account); + else if (acb_info & ACB_NORMAL) + has_enough_rights = user_has_privileges(p->pipe_user.nt_user_token, + &se_add_users); + else if (acb_info & (ACB_SVRTRUST|ACB_DOMTRUST)) { + if (lp_enable_privileges()) { + has_enough_rights = nt_token_check_domain_rid(p->pipe_user.nt_user_token, + DOMAIN_GROUP_RID_ADMINS); + } + } + + DEBUG(5, ("%s: %s does%s possess sufficient rights\n", + fn_name, uidtoname(p->pipe_user.ut.uid), has_enough_rights ? "" : " not")); /* ================ BEGIN SeMachineAccountPrivilege BLOCK ================ */ - - if ( has_enough_rights ) - become_root(); - + + if (has_enough_rights) { + become_root(); + } + /* ok! user info levels (lots: see MSDEV help), off we go... */ switch (switch_value) { + + case 7: + status = set_user_info_7(p->mem_ctx, + &info->info7, pwd); + break; + + case 16: + if (!set_user_info_16(&info->info16, pwd)) { + status = NT_STATUS_ACCESS_DENIED; + } + break; + case 18: - if (!set_user_info_18(ctr->info.id18, pwd)) - r_u->status = NT_STATUS_ACCESS_DENIED; + /* Used by AS/U JRA. */ + if (!set_user_info_18(&info->info18, pwd)) { + status = NT_STATUS_ACCESS_DENIED; + } break; - case 24: + case 20: + if (!set_user_info_20(&info->info20, pwd)) { + status = NT_STATUS_ACCESS_DENIED; + } + break; + + case 21: + status = set_user_info_21(p->mem_ctx, + &info->info21, pwd); + break; + + case 23: if (!p->session_key.length) { - r_u->status = NT_STATUS_NO_USER_SESSION_KEY; + status = NT_STATUS_NO_USER_SESSION_KEY; } - SamOEMhashBlob(ctr->info.id24->pass, 516, &p->session_key); + SamOEMhashBlob(info->info23.password.data, 516, + &p->session_key); - dump_data(100, ctr->info.id24->pass, 516); + dump_data(100, info->info23.password.data, 516); - if (!set_user_info_pw(ctr->info.id24->pass, pwd)) - r_u->status = NT_STATUS_ACCESS_DENIED; + status = set_user_info_23(p->mem_ctx, + &info->info23, pwd); break; - case 25: + case 24: if (!p->session_key.length) { - r_u->status = NT_STATUS_NO_USER_SESSION_KEY; + status = NT_STATUS_NO_USER_SESSION_KEY; } - encode_or_decode_arc4_passwd_buffer(ctr->info.id25->pass, &p->session_key); + SamOEMhashBlob(info->info24.password.data, + 516, + &p->session_key); - dump_data(100, ctr->info.id25->pass, 532); + dump_data(100, info->info24.password.data, 516); - r_u->status = set_user_info_25(p->mem_ctx, - ctr->info.id25, pwd); - if (!NT_STATUS_IS_OK(r_u->status)) { - goto done; + if (!set_user_info_pw(info->info24.password.data, pwd)) { + status = NT_STATUS_ACCESS_DENIED; } - if (!set_user_info_pw(ctr->info.id25->pass, pwd)) - r_u->status = NT_STATUS_ACCESS_DENIED; break; - case 26: + case 25: if (!p->session_key.length) { - r_u->status = NT_STATUS_NO_USER_SESSION_KEY; + status = NT_STATUS_NO_USER_SESSION_KEY; } - encode_or_decode_arc4_passwd_buffer(ctr->info.id26->pass, &p->session_key); + encode_or_decode_arc4_passwd_buffer(info->info25.password.data, + &p->session_key); - dump_data(100, ctr->info.id26->pass, 516); + dump_data(100, info->info25.password.data, 532); - if (!set_user_info_pw(ctr->info.id26->pass, pwd)) - r_u->status = NT_STATUS_ACCESS_DENIED; + status = set_user_info_25(p->mem_ctx, + &info->info25, pwd); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + if (!set_user_info_pw(info->info25.password.data, pwd)) { + status = NT_STATUS_ACCESS_DENIED; + } break; - case 23: + case 26: if (!p->session_key.length) { - r_u->status = NT_STATUS_NO_USER_SESSION_KEY; + status = NT_STATUS_NO_USER_SESSION_KEY; } - SamOEMhashBlob(ctr->info.id23->pass, 516, &p->session_key); + encode_or_decode_arc4_passwd_buffer(info->info26.password.data, + &p->session_key); - dump_data(100, ctr->info.id23->pass, 516); + dump_data(100, info->info26.password.data, 516); - r_u->status = set_user_info_23(p->mem_ctx, - ctr->info.id23, pwd); + if (!set_user_info_pw(info->info26.password.data, pwd)) { + status = NT_STATUS_ACCESS_DENIED; + } break; default: - r_u->status = NT_STATUS_INVALID_INFO_CLASS; + status = NT_STATUS_INVALID_INFO_CLASS; } done: - - if ( has_enough_rights ) + + if (has_enough_rights) { unbecome_root(); - + } + /* ================ END SeMachineAccountPrivilege BLOCK ================ */ - if (NT_STATUS_IS_OK(r_u->status)) { + if (NT_STATUS_IS_OK(status)) { force_flush_samr_cache(disp_info); } - return r_u->status; + return status; } /******************************************************************* - samr_reply_set_userinfo2 + _samr_SetUserInfo ********************************************************************/ -NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_SET_USERINFO2 *r_u) +NTSTATUS _samr_SetUserInfo(pipes_struct *p, + struct samr_SetUserInfo *r) { - struct samu *pwd = NULL; - DOM_SID sid; - SAM_USERINFO_CTR *ctr = q_u->ctr; - POLICY_HND *pol = &q_u->pol; - uint16 switch_value = q_u->switch_value; - uint32 acc_granted; - uint32 acc_required; - bool ret; - bool has_enough_rights = False; - uint32 acb_info; - DISP_INFO *disp_info = NULL; - - DEBUG(5, ("samr_reply_set_userinfo2: %d\n", __LINE__)); - - r_u->status = NT_STATUS_OK; - - /* find the policy handle. open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, pol, &sid, &acc_granted, &disp_info)) - return NT_STATUS_INVALID_HANDLE; - - -#if 0 /* this really should be applied on a per info level basis --jerry */ - - /* observed when joining XP client to Samba domain */ - acc_required = SA_RIGHT_USER_SET_PASSWORD | SA_RIGHT_USER_SET_ATTRIBUTES | SA_RIGHT_USER_ACCT_FLAGS_EXPIRY; -#else - acc_required = SA_RIGHT_USER_SET_ATTRIBUTES; -#endif - - if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, acc_required, "_samr_set_userinfo2"))) { - return r_u->status; - } - - DEBUG(5, ("samr_reply_set_userinfo2: sid:%s\n", - sid_string_dbg(&sid))); - - if (ctr == NULL) { - DEBUG(5, ("samr_reply_set_userinfo2: NULL info level\n")); - return NT_STATUS_INVALID_INFO_CLASS; - } - - switch_value=ctr->switch_value; - - if ( !(pwd = samu_new( NULL )) ) { - return NT_STATUS_NO_MEMORY; - } - - become_root(); - ret = pdb_getsampwsid(pwd, &sid); - unbecome_root(); - - if ( !ret ) { - TALLOC_FREE(pwd); - return NT_STATUS_NO_SUCH_USER; - } - - acb_info = pdb_get_acct_ctrl(pwd); - if ( acb_info & ACB_WSTRUST ) - has_enough_rights = user_has_privileges( p->pipe_user.nt_user_token, &se_machine_account); - else if ( acb_info & ACB_NORMAL ) - has_enough_rights = user_has_privileges( p->pipe_user.nt_user_token, &se_add_users ); - else if ( acb_info & (ACB_SVRTRUST|ACB_DOMTRUST) ) { - if ( lp_enable_privileges() ) - has_enough_rights = nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ); - } - - DEBUG(5, ("_samr_set_userinfo2: %s does%s possess sufficient rights\n", - uidtoname(p->pipe_user.ut.uid), - has_enough_rights ? "" : " not")); - - /* ================ BEGIN SeMachineAccountPrivilege BLOCK ================ */ - - if ( has_enough_rights ) - become_root(); - - /* ok! user info levels (lots: see MSDEV help), off we go... */ - - switch (switch_value) { - case 7: - r_u->status = set_user_info_7(p->mem_ctx, - ctr->info.id7, pwd); - break; - case 16: - if (!set_user_info_16(ctr->info.id16, pwd)) - r_u->status = NT_STATUS_ACCESS_DENIED; - break; - case 18: - /* Used by AS/U JRA. */ - if (!set_user_info_18(ctr->info.id18, pwd)) - r_u->status = NT_STATUS_ACCESS_DENIED; - break; - case 20: - if (!set_user_info_20(ctr->info.id20, pwd)) - r_u->status = NT_STATUS_ACCESS_DENIED; - break; - case 21: - r_u->status = set_user_info_21(p->mem_ctx, - ctr->info.id21, pwd); - break; - case 23: - if (!p->session_key.length) { - r_u->status = NT_STATUS_NO_USER_SESSION_KEY; - } - SamOEMhashBlob(ctr->info.id23->pass, 516, &p->session_key); - - dump_data(100, ctr->info.id23->pass, 516); - - r_u->status = set_user_info_23(p->mem_ctx, - ctr->info.id23, pwd); - break; - case 26: - if (!p->session_key.length) { - r_u->status = NT_STATUS_NO_USER_SESSION_KEY; - } - encode_or_decode_arc4_passwd_buffer(ctr->info.id26->pass, &p->session_key); - - dump_data(100, ctr->info.id26->pass, 516); - - if (!set_user_info_pw(ctr->info.id26->pass, pwd)) - r_u->status = NT_STATUS_ACCESS_DENIED; - break; - default: - r_u->status = NT_STATUS_INVALID_INFO_CLASS; - } - - if ( has_enough_rights ) - unbecome_root(); - - /* ================ END SeMachineAccountPrivilege BLOCK ================ */ + return samr_SetUserInfo_internal("_samr_SetUserInfo", + p, + r->in.user_handle, + r->in.level, + r->in.info); +} - if (NT_STATUS_IS_OK(r_u->status)) { - force_flush_samr_cache(disp_info); - } +/******************************************************************* + _samr_SetUserInfo2 + ********************************************************************/ - return r_u->status; +NTSTATUS _samr_SetUserInfo2(pipes_struct *p, + struct samr_SetUserInfo2 *r) +{ + return samr_SetUserInfo_internal("_samr_SetUserInfo2", + p, + r->in.user_handle, + r->in.level, + r->in.info); } /********************************************************************* - _samr_query_aliasmem + _samr_GetAliasMembership *********************************************************************/ -NTSTATUS _samr_query_useraliases(pipes_struct *p, SAMR_Q_QUERY_USERALIASES *q_u, SAMR_R_QUERY_USERALIASES *r_u) +NTSTATUS _samr_GetAliasMembership(pipes_struct *p, + struct samr_GetAliasMembership *r) { size_t num_alias_rids; uint32 *alias_rids; struct samr_info *info = NULL; size_t i; - + NTSTATUS ntstatus1; NTSTATUS ntstatus2; DOM_SID *members; - r_u->status = NT_STATUS_OK; - - DEBUG(5,("_samr_query_useraliases: %d\n", __LINE__)); + DEBUG(5,("_samr_GetAliasMembership: %d\n", __LINE__)); /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info)) + 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, SA_RIGHT_DOMAIN_LOOKUP_ALIAS_BY_MEM, "_samr_query_useraliases"); - ntstatus2 = access_check_samr_function(info->acc_granted, SA_RIGHT_DOMAIN_OPEN_ACCOUNT, "_samr_query_useraliases"); - + + ntstatus1 = access_check_samr_function(info->acc_granted, + SA_RIGHT_DOMAIN_LOOKUP_ALIAS_BY_MEM, + "_samr_GetAliasMembership"); + ntstatus2 = access_check_samr_function(info->acc_granted, + SA_RIGHT_DOMAIN_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; } - } + } if (!sid_check_is_domain(&info->sid) && !sid_check_is_builtin(&info->sid)) return NT_STATUS_OBJECT_TYPE_MISMATCH; - if (q_u->num_sids1) { - members = TALLOC_ARRAY(p->mem_ctx, DOM_SID, q_u->num_sids1); + if (r->in.sids->num_sids) { + members = TALLOC_ARRAY(p->mem_ctx, DOM_SID, r->in.sids->num_sids); if (members == NULL) return NT_STATUS_NO_MEMORY; @@ -3845,15 +4282,15 @@ NTSTATUS _samr_query_useraliases(pipes_struct *p, SAMR_Q_QUERY_USERALIASES *q_u, members = NULL; } - for (i=0; i<q_u->num_sids1; i++) - sid_copy(&members[i], &q_u->sid[i].sid); + for (i=0; i<r->in.sids->num_sids; i++) + sid_copy(&members[i], r->in.sids->sids[i].sid); alias_rids = NULL; num_alias_rids = 0; become_root(); ntstatus1 = pdb_enum_alias_memberships(p->mem_ctx, &info->sid, members, - q_u->num_sids1, + r->in.sids->num_sids, &alias_rids, &num_alias_rids); unbecome_root(); @@ -3861,40 +4298,44 @@ NTSTATUS _samr_query_useraliases(pipes_struct *p, SAMR_Q_QUERY_USERALIASES *q_u, return ntstatus1; } - init_samr_r_query_useraliases(r_u, num_alias_rids, alias_rids, - NT_STATUS_OK); + r->out.rids->count = num_alias_rids; + r->out.rids->ids = alias_rids; + return NT_STATUS_OK; } /********************************************************************* - _samr_query_aliasmem + _samr_GetMembersInAlias *********************************************************************/ -NTSTATUS _samr_query_aliasmem(pipes_struct *p, SAMR_Q_QUERY_ALIASMEM *q_u, SAMR_R_QUERY_ALIASMEM *r_u) +NTSTATUS _samr_GetMembersInAlias(pipes_struct *p, + struct samr_GetMembersInAlias *r) { NTSTATUS status; size_t i; size_t num_sids = 0; - DOM_SID2 *sid; - DOM_SID *sids=NULL; + 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, &q_u->alias_pol, &alias_sid, &acc_granted, NULL)) + if (!get_lsa_policy_samr_sid(p, r->in.alias_handle, &alias_sid, &acc_granted, NULL)) return NT_STATUS_INVALID_HANDLE; - - if (!NT_STATUS_IS_OK(r_u->status = - access_check_samr_function(acc_granted, SA_RIGHT_ALIAS_GET_MEMBERS, "_samr_query_aliasmem"))) { - return r_u->status; + + status = access_check_samr_function(acc_granted, + SA_RIGHT_ALIAS_GET_MEMBERS, + "_samr_GetMembersInAlias"); + if (!NT_STATUS_IS_OK(status)) { + return status; } DEBUG(10, ("sid is %s\n", sid_string_dbg(&alias_sid))); become_root(); - status = pdb_enum_aliasmem(&alias_sid, &sids, &num_sids); + status = pdb_enum_aliasmem(&alias_sid, &pdb_sids, &num_sids); unbecome_root(); if (!NT_STATUS_IS_OK(status)) { @@ -3902,31 +4343,35 @@ NTSTATUS _samr_query_aliasmem(pipes_struct *p, SAMR_Q_QUERY_ALIASMEM *q_u, SAMR_ } if (num_sids) { - sid = TALLOC_ZERO_ARRAY(p->mem_ctx, DOM_SID2, num_sids); - if (sid == NULL) { - SAFE_FREE(sids); + sids = TALLOC_ZERO_ARRAY(p->mem_ctx, struct lsa_SidPtr, num_sids); + if (sids == NULL) { + TALLOC_FREE(pdb_sids); return NT_STATUS_NO_MEMORY; } - } else { - sid = NULL; } for (i = 0; i < num_sids; i++) { - init_dom_sid2(&sid[i], &sids[i]); + sids[i].sid = sid_dup_talloc(p->mem_ctx, &pdb_sids[i]); + if (!sids[i].sid) { + TALLOC_FREE(pdb_sids); + return NT_STATUS_NO_MEMORY; + } } - init_samr_r_query_aliasmem(r_u, num_sids, sid, NT_STATUS_OK); + r->out.sids->num_sids = num_sids; + r->out.sids->sids = sids; - TALLOC_FREE(sids); + TALLOC_FREE(pdb_sids); return NT_STATUS_OK; } /********************************************************************* - _samr_query_groupmem + _samr_QueryGroupMember *********************************************************************/ -NTSTATUS _samr_query_groupmem(pipes_struct *p, SAMR_Q_QUERY_GROUPMEM *q_u, SAMR_R_QUERY_GROUPMEM *r_u) +NTSTATUS _samr_QueryGroupMember(pipes_struct *p, + struct samr_QueryGroupMember *r) { DOM_SID group_sid; size_t i, num_members; @@ -3936,16 +4381,25 @@ NTSTATUS _samr_query_groupmem(pipes_struct *p, SAMR_Q_QUERY_GROUPMEM *q_u, SAMR_ uint32 acc_granted; - NTSTATUS result; + NTSTATUS status; + struct samr_RidTypeArray *rids = NULL; + + 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, &q_u->group_pol, &group_sid, &acc_granted, NULL)) + if (!get_lsa_policy_samr_sid(p, r->in.group_handle, &group_sid, &acc_granted, NULL)) return NT_STATUS_INVALID_HANDLE; - - if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_GROUP_GET_MEMBERS, "_samr_query_groupmem"))) { - return r_u->status; + + status = access_check_samr_function(acc_granted, + SA_RIGHT_GROUP_GET_MEMBERS, + "_samr_QueryGroupMember"); + if (!NT_STATUS_IS_OK(status)) { + return status; } - + DEBUG(10, ("sid is %s\n", sid_string_dbg(&group_sid))); if (!sid_check_is_in_our_domain(&group_sid)) { @@ -3957,12 +4411,12 @@ NTSTATUS _samr_query_groupmem(pipes_struct *p, SAMR_Q_QUERY_GROUPMEM *q_u, SAMR_ DEBUG(10, ("lookup on Domain SID\n")); become_root(); - result = pdb_enum_group_members(p->mem_ctx, &group_sid, + status = pdb_enum_group_members(p->mem_ctx, &group_sid, &rid, &num_members); unbecome_root(); - if (!NT_STATUS_IS_OK(result)) - return result; + if (!NT_STATUS_IS_OK(status)) + return status; if (num_members) { attr=TALLOC_ZERO_ARRAY(p->mem_ctx, uint32, num_members); @@ -3972,81 +4426,93 @@ NTSTATUS _samr_query_groupmem(pipes_struct *p, SAMR_Q_QUERY_GROUPMEM *q_u, SAMR_ } else { attr = NULL; } - + for (i=0; i<num_members; i++) attr[i] = SID_NAME_USER; - init_samr_r_query_groupmem(r_u, num_members, rid, attr, NT_STATUS_OK); + rids->count = num_members; + rids->types = attr; + rids->rids = rid; + + *r->out.rids = rids; return NT_STATUS_OK; } /********************************************************************* - _samr_add_aliasmem + _samr_AddAliasMember *********************************************************************/ -NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_ADD_ALIASMEM *r_u) +NTSTATUS _samr_AddAliasMember(pipes_struct *p, + struct samr_AddAliasMember *r) { DOM_SID alias_sid; uint32 acc_granted; SE_PRIV se_rights; bool can_add_accounts; - NTSTATUS ret; + NTSTATUS status; DISP_INFO *disp_info = NULL; /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted, &disp_info)) + if (!get_lsa_policy_samr_sid(p, r->in.alias_handle, &alias_sid, &acc_granted, &disp_info)) return NT_STATUS_INVALID_HANDLE; - - if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_ALIAS_ADD_MEMBER, "_samr_add_aliasmem"))) { - return r_u->status; + + status = access_check_samr_function(acc_granted, + SA_RIGHT_ALIAS_ADD_MEMBER, + "_samr_AddAliasMember"); + if (!NT_STATUS_IS_OK(status)) { + return status; } - + DEBUG(10, ("sid is %s\n", sid_string_dbg(&alias_sid))); - + se_priv_copy( &se_rights, &se_add_users ); can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); /******** BEGIN SeAddUsers BLOCK *********/ - + if ( can_add_accounts ) become_root(); - - ret = pdb_add_aliasmem(&alias_sid, &q_u->sid.sid); - + + status = pdb_add_aliasmem(&alias_sid, r->in.sid); + if ( can_add_accounts ) unbecome_root(); - + /******** END SeAddUsers BLOCK *********/ - - if (NT_STATUS_IS_OK(ret)) { + + if (NT_STATUS_IS_OK(status)) { force_flush_samr_cache(disp_info); } - return ret; + return status; } /********************************************************************* - _samr_del_aliasmem + _samr_DeleteAliasMember *********************************************************************/ -NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DEL_ALIASMEM *r_u) +NTSTATUS _samr_DeleteAliasMember(pipes_struct *p, + struct samr_DeleteAliasMember *r) { DOM_SID alias_sid; uint32 acc_granted; SE_PRIV se_rights; bool can_add_accounts; - NTSTATUS ret; + NTSTATUS status; DISP_INFO *disp_info = NULL; /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted, &disp_info)) + if (!get_lsa_policy_samr_sid(p, r->in.alias_handle, &alias_sid, &acc_granted, &disp_info)) return NT_STATUS_INVALID_HANDLE; - - if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_ALIAS_REMOVE_MEMBER, "_samr_del_aliasmem"))) { - return r_u->status; + + status = access_check_samr_function(acc_granted, + SA_RIGHT_ALIAS_REMOVE_MEMBER, + "_samr_DeleteAliasMember"); + if (!NT_STATUS_IS_OK(status)) { + return status; } - + DEBUG(10, ("_samr_del_aliasmem:sid is %s\n", sid_string_dbg(&alias_sid))); @@ -4054,30 +4520,32 @@ NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DE can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); /******** BEGIN SeAddUsers BLOCK *********/ - + if ( can_add_accounts ) become_root(); - ret = pdb_del_aliasmem(&alias_sid, &q_u->sid.sid); - + status = pdb_del_aliasmem(&alias_sid, r->in.sid); + if ( can_add_accounts ) unbecome_root(); - + /******** END SeAddUsers BLOCK *********/ - - if (NT_STATUS_IS_OK(ret)) { + + if (NT_STATUS_IS_OK(status)) { force_flush_samr_cache(disp_info); } - return ret; + return status; } /********************************************************************* - _samr_add_groupmem + _samr_AddGroupMember *********************************************************************/ -NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_ADD_GROUPMEM *r_u) +NTSTATUS _samr_AddGroupMember(pipes_struct *p, + struct samr_AddGroupMember *r) { + NTSTATUS status; DOM_SID group_sid; uint32 group_rid; uint32 acc_granted; @@ -4086,11 +4554,14 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD DISP_INFO *disp_info = NULL; /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid, &acc_granted, &disp_info)) + if (!get_lsa_policy_samr_sid(p, r->in.group_handle, &group_sid, &acc_granted, &disp_info)) return NT_STATUS_INVALID_HANDLE; - - if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_GROUP_ADD_MEMBER, "_samr_add_groupmem"))) { - return r_u->status; + + status = access_check_samr_function(acc_granted, + SA_RIGHT_GROUP_ADD_MEMBER, + "_samr_AddGroupMember"); + if (!NT_STATUS_IS_OK(status)) { + return status; } DEBUG(10, ("sid is %s\n", sid_string_dbg(&group_sid))); @@ -4104,28 +4575,31 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); /******** BEGIN SeAddUsers BLOCK *********/ - + if ( can_add_accounts ) become_root(); - r_u->status = pdb_add_groupmem(p->mem_ctx, group_rid, q_u->rid); - + status = pdb_add_groupmem(p->mem_ctx, group_rid, r->in.rid); + if ( can_add_accounts ) unbecome_root(); - + /******** END SeAddUsers BLOCK *********/ - + force_flush_samr_cache(disp_info); - return r_u->status; + return status; } /********************************************************************* - _samr_del_groupmem + _samr_DeleteGroupMember *********************************************************************/ -NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DEL_GROUPMEM *r_u) +NTSTATUS _samr_DeleteGroupMember(pipes_struct *p, + struct samr_DeleteGroupMember *r) + { + NTSTATUS status; DOM_SID group_sid; uint32 group_rid; uint32 acc_granted; @@ -4134,17 +4608,20 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE DISP_INFO *disp_info = NULL; /* - * delete the group member named q_u->rid + * delete the group member named r->in.rid * who is a member of the sid associated with the handle * 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, &q_u->pol, &group_sid, &acc_granted, &disp_info)) + if (!get_lsa_policy_samr_sid(p, r->in.group_handle, &group_sid, &acc_granted, &disp_info)) return NT_STATUS_INVALID_HANDLE; - - if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_GROUP_REMOVE_MEMBER, "_samr_del_groupmem"))) { - return r_u->status; + + status = access_check_samr_function(acc_granted, + SA_RIGHT_GROUP_REMOVE_MEMBER, + "_samr_DeleteGroupMember"); + if (!NT_STATUS_IS_OK(status)) { + return status; } if (!sid_peek_check_rid(get_global_sam_sid(), &group_sid, @@ -4156,28 +4633,30 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); /******** BEGIN SeAddUsers BLOCK *********/ - + if ( can_add_accounts ) become_root(); - - r_u->status = pdb_del_groupmem(p->mem_ctx, group_rid, q_u->rid); + + status = pdb_del_groupmem(p->mem_ctx, group_rid, r->in.rid); if ( can_add_accounts ) unbecome_root(); - + /******** END SeAddUsers BLOCK *********/ - + force_flush_samr_cache(disp_info); - return r_u->status; + return status; } /********************************************************************* - _samr_delete_dom_user + _samr_DeleteUser *********************************************************************/ -NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAMR_R_DELETE_DOM_USER *r_u ) +NTSTATUS _samr_DeleteUser(pipes_struct *p, + struct samr_DeleteUser *r) { + NTSTATUS status; DOM_SID user_sid; struct samu *sam_pass=NULL; uint32 acc_granted; @@ -4186,16 +4665,19 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM DISP_INFO *disp_info = NULL; bool ret; - DEBUG(5, ("_samr_delete_dom_user: %d\n", __LINE__)); + DEBUG(5, ("_samr_DeleteUser: %d\n", __LINE__)); /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, &q_u->user_pol, &user_sid, &acc_granted, &disp_info)) + if (!get_lsa_policy_samr_sid(p, r->in.user_handle, &user_sid, &acc_granted, &disp_info)) return NT_STATUS_INVALID_HANDLE; - - if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, STD_RIGHT_DELETE_ACCESS, "_samr_delete_dom_user"))) { - return r_u->status; + + status = access_check_samr_function(acc_granted, + STD_RIGHT_DELETE_ACCESS, + "_samr_DeleteUser"); + if (!NT_STATUS_IS_OK(status)) { + return status; } - + if (!sid_check_is_in_our_domain(&user_sid)) return NT_STATUS_CANNOT_DELETE; @@ -4209,12 +4691,12 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM unbecome_root(); if( !ret ) { - DEBUG(5,("_samr_delete_dom_user:User %s doesn't exist.\n", + DEBUG(5,("_samr_DeleteUser: User %s doesn't exist.\n", sid_string_dbg(&user_sid))); TALLOC_FREE(sam_pass); return NT_STATUS_NO_SUCH_USER; } - + acb_info = pdb_get_acct_ctrl(sam_pass); /* For machine accounts it's the SeMachineAccountPrivilege that counts. */ @@ -4222,32 +4704,32 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_machine_account ); } else { can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_add_users ); - } + } /******** BEGIN SeAddUsers BLOCK *********/ - + if ( can_add_accounts ) become_root(); - r_u->status = pdb_delete_user(p->mem_ctx, sam_pass); + status = pdb_delete_user(p->mem_ctx, sam_pass); if ( can_add_accounts ) unbecome_root(); - + /******** END SeAddUsers BLOCK *********/ - - if ( !NT_STATUS_IS_OK(r_u->status) ) { - DEBUG(5,("_samr_delete_dom_user: Failed to delete entry for " + + if ( !NT_STATUS_IS_OK(status) ) { + DEBUG(5,("_samr_DeleteUser: Failed to delete entry for " "user %s: %s.\n", pdb_get_username(sam_pass), - nt_errstr(r_u->status))); + nt_errstr(status))); TALLOC_FREE(sam_pass); - return r_u->status; + return status; } TALLOC_FREE(sam_pass); - if (!close_policy_hnd(p, &q_u->user_pol)) + if (!close_policy_hnd(p, r->in.user_handle)) return NT_STATUS_OBJECT_NAME_INVALID; force_flush_samr_cache(disp_info); @@ -4256,11 +4738,13 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM } /********************************************************************* - _samr_delete_dom_group + _samr_DeleteDomainGroup *********************************************************************/ -NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, SAMR_R_DELETE_DOM_GROUP *r_u) +NTSTATUS _samr_DeleteDomainGroup(pipes_struct *p, + struct samr_DeleteDomainGroup *r) { + NTSTATUS status; DOM_SID group_sid; uint32 group_rid; uint32 acc_granted; @@ -4268,14 +4752,17 @@ NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, S bool can_add_accounts; DISP_INFO *disp_info = NULL; - DEBUG(5, ("samr_delete_dom_group: %d\n", __LINE__)); + DEBUG(5, ("samr_DeleteDomainGroup: %d\n", __LINE__)); /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, &q_u->group_pol, &group_sid, &acc_granted, &disp_info)) + if (!get_lsa_policy_samr_sid(p, r->in.group_handle, &group_sid, &acc_granted, &disp_info)) return NT_STATUS_INVALID_HANDLE; - - if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, STD_RIGHT_DELETE_ACCESS, "_samr_delete_dom_group"))) { - return r_u->status; + + status = access_check_samr_function(acc_granted, + STD_RIGHT_DELETE_ACCESS, + "_samr_DeleteDomainGroup"); + if (!NT_STATUS_IS_OK(status)) { + return status; } DEBUG(10, ("sid is %s\n", sid_string_dbg(&group_sid))); @@ -4289,26 +4776,26 @@ NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, S can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); /******** BEGIN SeAddUsers BLOCK *********/ - + if ( can_add_accounts ) become_root(); - r_u->status = pdb_delete_dom_group(p->mem_ctx, group_rid); + status = pdb_delete_dom_group(p->mem_ctx, group_rid); if ( can_add_accounts ) unbecome_root(); - + /******** END SeAddUsers BLOCK *********/ - - if ( !NT_STATUS_IS_OK(r_u->status) ) { - DEBUG(5,("_samr_delete_dom_group: Failed to delete mapping " + + 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), - nt_errstr(r_u->status))); - return r_u->status; + nt_errstr(status))); + return status; } - - if (!close_policy_hnd(p, &q_u->group_pol)) + + if (!close_policy_hnd(p, r->in.group_handle)) return NT_STATUS_OBJECT_NAME_INVALID; force_flush_samr_cache(disp_info); @@ -4317,10 +4804,11 @@ NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, S } /********************************************************************* - _samr_delete_dom_alias + _samr_DeleteDomAlias *********************************************************************/ -NTSTATUS _samr_delete_dom_alias(pipes_struct *p, SAMR_Q_DELETE_DOM_ALIAS *q_u, SAMR_R_DELETE_DOM_ALIAS *r_u) +NTSTATUS _samr_DeleteDomAlias(pipes_struct *p, + struct samr_DeleteDomAlias *r) { DOM_SID alias_sid; uint32 acc_granted; @@ -4329,18 +4817,21 @@ NTSTATUS _samr_delete_dom_alias(pipes_struct *p, SAMR_Q_DELETE_DOM_ALIAS *q_u, S NTSTATUS status; DISP_INFO *disp_info = NULL; - DEBUG(5, ("_samr_delete_dom_alias: %d\n", __LINE__)); + DEBUG(5, ("_samr_DeleteDomAlias: %d\n", __LINE__)); /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted, &disp_info)) + 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_u->pol, &q_u->alias_pol, sizeof(r_u->pol) ); + memcpy(r->out.alias_handle, r->in.alias_handle, sizeof(r->out.alias_handle)); - if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, STD_RIGHT_DELETE_ACCESS, "_samr_delete_dom_alias"))) { - return r_u->status; + status = access_check_samr_function(acc_granted, + STD_RIGHT_DELETE_ACCESS, + "_samr_DeleteDomAlias"); + if (!NT_STATUS_IS_OK(status)) { + return status; } DEBUG(10, ("sid is %s\n", sid_string_dbg(&alias_sid))); @@ -4353,29 +4844,29 @@ NTSTATUS _samr_delete_dom_alias(pipes_struct *p, SAMR_Q_DELETE_DOM_ALIAS *q_u, S if (!sid_check_is_in_our_domain(&alias_sid)) return NT_STATUS_NO_SUCH_ALIAS; - + DEBUG(10, ("lookup on Local SID\n")); se_priv_copy( &se_rights, &se_add_users ); can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); /******** BEGIN SeAddUsers BLOCK *********/ - + if ( can_add_accounts ) become_root(); /* Have passdb delete the alias */ status = pdb_delete_alias(&alias_sid); - + if ( can_add_accounts ) unbecome_root(); - + /******** END SeAddUsers BLOCK *********/ if ( !NT_STATUS_IS_OK(status)) return status; - if (!close_policy_hnd(p, &q_u->alias_pol)) + if (!close_policy_hnd(p, r->in.alias_handle)) return NT_STATUS_OBJECT_NAME_INVALID; force_flush_samr_cache(disp_info); @@ -4384,11 +4875,14 @@ NTSTATUS _samr_delete_dom_alias(pipes_struct *p, SAMR_Q_DELETE_DOM_ALIAS *q_u, S } /********************************************************************* - _samr_create_dom_group + _samr_CreateDomainGroup *********************************************************************/ -NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, SAMR_R_CREATE_DOM_GROUP *r_u) +NTSTATUS _samr_CreateDomainGroup(pipes_struct *p, + struct samr_CreateDomainGroup *r) + { + NTSTATUS status; DOM_SID dom_sid; DOM_SID info_sid; const char *name; @@ -4399,50 +4893,53 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S DISP_INFO *disp_info = NULL; /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, &q_u->pol, &dom_sid, &acc_granted, &disp_info)) + if (!get_lsa_policy_samr_sid(p, r->in.domain_handle, &dom_sid, &acc_granted, &disp_info)) return NT_STATUS_INVALID_HANDLE; - - if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_DOMAIN_CREATE_GROUP, "_samr_create_dom_group"))) { - return r_u->status; + + status = access_check_samr_function(acc_granted, + SA_RIGHT_DOMAIN_CREATE_GROUP, + "_samr_CreateDomainGroup"); + if (!NT_STATUS_IS_OK(status)) { + return status; } - + if (!sid_equal(&dom_sid, get_global_sam_sid())) return NT_STATUS_ACCESS_DENIED; - name = rpcstr_pull_unistr2_talloc(p->mem_ctx, &q_u->uni_acct_desc); + name = r->in.name->string; if (name == NULL) { return NT_STATUS_NO_MEMORY; } - r_u->status = can_create(p->mem_ctx, name); - if (!NT_STATUS_IS_OK(r_u->status)) { - return r_u->status; + status = can_create(p->mem_ctx, name); + if (!NT_STATUS_IS_OK(status)) { + return status; } se_priv_copy( &se_rights, &se_add_users ); can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); /******** BEGIN SeAddUsers BLOCK *********/ - + if ( can_add_accounts ) become_root(); - + /* check that we successfully create the UNIX group */ - - r_u->status = pdb_create_dom_group(p->mem_ctx, name, &r_u->rid); + + status = pdb_create_dom_group(p->mem_ctx, name, r->out.rid); if ( can_add_accounts ) unbecome_root(); - + /******** END SeAddUsers BLOCK *********/ - + /* check if we should bail out here */ - - if ( !NT_STATUS_IS_OK(r_u->status) ) - return r_u->status; - sid_compose(&info_sid, get_global_sam_sid(), r_u->rid); - + 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(&info_sid)) == NULL) return NT_STATUS_NO_MEMORY; @@ -4451,7 +4948,7 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S info->acc_granted = GENERIC_RIGHTS_GROUP_ALL_ACCESS; /* get a (unique) handle. open a policy on it. */ - if (!create_policy_hnd(p, &r_u->pol, free_samr_info, (void *)info)) + if (!create_policy_hnd(p, r->out.group_handle, free_samr_info, (void *)info)) return NT_STATUS_OBJECT_NAME_NOT_FOUND; force_flush_samr_cache(disp_info); @@ -4460,14 +4957,15 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S } /********************************************************************* - _samr_create_dom_alias + _samr_CreateDomAlias *********************************************************************/ -NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, SAMR_R_CREATE_DOM_ALIAS *r_u) +NTSTATUS _samr_CreateDomAlias(pipes_struct *p, + struct samr_CreateDomAlias *r) { DOM_SID dom_sid; DOM_SID info_sid; - fstring name; + const char *name = NULL; struct samr_info *info; uint32 acc_granted; gid_t gid; @@ -4477,17 +4975,20 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S DISP_INFO *disp_info = NULL; /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, &q_u->dom_pol, &dom_sid, &acc_granted, &disp_info)) + if (!get_lsa_policy_samr_sid(p, r->in.domain_handle, &dom_sid, &acc_granted, &disp_info)) return NT_STATUS_INVALID_HANDLE; - - if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_DOMAIN_CREATE_ALIAS, "_samr_create_alias"))) { - return r_u->status; + + result = access_check_samr_function(acc_granted, + SA_RIGHT_DOMAIN_CREATE_ALIAS, + "_samr_CreateDomAlias"); + if (!NT_STATUS_IS_OK(result)) { + return result; } - + if (!sid_equal(&dom_sid, get_global_sam_sid())) return NT_STATUS_ACCESS_DENIED; - unistr2_to_ascii(name, &q_u->uni_acct_desc, sizeof(name)); + name = r->in.alias_name->string; se_priv_copy( &se_rights, &se_add_users ); can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); @@ -4498,16 +4999,16 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S } /******** BEGIN SeAddUsers BLOCK *********/ - + if ( can_add_accounts ) become_root(); /* Have passdb create the alias */ - result = pdb_create_alias(name, &r_u->rid); + result = pdb_create_alias(name, r->out.rid); if ( can_add_accounts ) unbecome_root(); - + /******** END SeAddUsers BLOCK *********/ if (!NT_STATUS_IS_OK(result)) { @@ -4517,7 +5018,7 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S } sid_copy(&info_sid, get_global_sam_sid()); - sid_append_rid(&info_sid, r_u->rid); + sid_append_rid(&info_sid, *r->out.rid); if (!sid_to_gid(&info_sid, &gid)) { DEBUG(10, ("Could not find alias just created\n")); @@ -4539,7 +5040,7 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S info->acc_granted = GENERIC_RIGHTS_ALIAS_ALL_ACCESS; /* get a (unique) handle. open a policy on it. */ - if (!create_policy_hnd(p, &r_u->alias_pol, free_samr_info, (void *)info)) + if (!create_policy_hnd(p, r->out.alias_handle, free_samr_info, (void *)info)) return NT_STATUS_OBJECT_NAME_NOT_FOUND; force_flush_samr_cache(disp_info); @@ -4548,68 +5049,81 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S } /********************************************************************* - _samr_query_groupinfo - -sends the name/comment pair of a domain group -level 1 send also the number of users of that group + _samr_QueryGroupInfo *********************************************************************/ -NTSTATUS _samr_query_groupinfo(pipes_struct *p, SAMR_Q_QUERY_GROUPINFO *q_u, SAMR_R_QUERY_GROUPINFO *r_u) +NTSTATUS _samr_QueryGroupInfo(pipes_struct *p, + struct samr_QueryGroupInfo *r) { + NTSTATUS status; DOM_SID group_sid; GROUP_MAP map; - GROUP_INFO_CTR *ctr; + union samr_GroupInfo *info = NULL; uint32 acc_granted; bool ret; + uint32_t attributes = SE_GROUP_MANDATORY | + SE_GROUP_ENABLED_BY_DEFAULT | + SE_GROUP_ENABLED; + const char *group_name = NULL; + const char *group_description = NULL; - if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid, &acc_granted, NULL)) + if (!get_lsa_policy_samr_sid(p, r->in.group_handle, &group_sid, &acc_granted, NULL)) return NT_STATUS_INVALID_HANDLE; - - if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_GROUP_LOOKUP_INFO, "_samr_query_groupinfo"))) { - return r_u->status; + + status = access_check_samr_function(acc_granted, + SA_RIGHT_GROUP_LOOKUP_INFO, + "_samr_QueryGroupInfo"); + if (!NT_STATUS_IS_OK(status)) { + return status; } - + become_root(); ret = get_domain_group_from_sid(group_sid, &map); unbecome_root(); if (!ret) return NT_STATUS_INVALID_HANDLE; - ctr=TALLOC_ZERO_P(p->mem_ctx, GROUP_INFO_CTR); - if (ctr==NULL) + /* FIXME: map contains fstrings */ + group_name = talloc_strdup(r, map.nt_name); + group_description = talloc_strdup(r, map.comment); + + info = TALLOC_ZERO_P(p->mem_ctx, union samr_GroupInfo); + if (!info) { return NT_STATUS_NO_MEMORY; + } - switch (q_u->switch_level) { + switch (r->in.level) { case 1: { uint32 *members; size_t num_members; - ctr->switch_value1 = 1; - become_root(); - r_u->status = pdb_enum_group_members( + status = pdb_enum_group_members( p->mem_ctx, &group_sid, &members, &num_members); unbecome_root(); - - if (!NT_STATUS_IS_OK(r_u->status)) { - return r_u->status; + + if (!NT_STATUS_IS_OK(status)) { + return status; } - init_samr_group_info1(&ctr->group.info1, map.nt_name, - map.comment, num_members); + init_samr_group_info1(&info->all, + group_name, + attributes, + num_members, + group_description); break; } case 2: - ctr->switch_value1 = 2; - init_samr_group_info2(&ctr->group.info2, map.nt_name); + init_samr_group_info2(&info->name, + group_name); break; case 3: - ctr->switch_value1 = 3; - init_samr_group_info3(&ctr->group.info3); + init_samr_group_info3(&info->attributes, + attributes); break; case 4: - ctr->switch_value1 = 4; - init_samr_group_info4(&ctr->group.info4, map.comment); + init_samr_group_info4(&info->description, + group_description); break; case 5: { /* @@ -4617,69 +5131,70 @@ NTSTATUS _samr_query_groupinfo(pipes_struct *p, SAMR_Q_QUERY_GROUPINFO *q_u, SAM size_t num_members; */ - ctr->switch_value1 = 5; - /* become_root(); - r_u->status = pdb_enum_group_members( + status = pdb_enum_group_members( p->mem_ctx, &group_sid, &members, &num_members); unbecome_root(); - - if (!NT_STATUS_IS_OK(r_u->status)) { - return r_u->status; + + if (!NT_STATUS_IS_OK(status)) { + return status; } */ - init_samr_group_info5(&ctr->group.info5, map.nt_name, - map.comment, 0 /* num_members */); /* in w2k3 this is always 0 */ + init_samr_group_info5(&info->all2, + group_name, + attributes, + 0, /* num_members - in w2k3 this is always 0 */ + group_description); + break; } default: return NT_STATUS_INVALID_INFO_CLASS; } - init_samr_r_query_groupinfo(r_u, ctr, NT_STATUS_OK); + *r->out.info = info; return NT_STATUS_OK; } /********************************************************************* - _samr_set_groupinfo - - update a domain group's comment. + _samr_SetGroupInfo *********************************************************************/ -NTSTATUS _samr_set_groupinfo(pipes_struct *p, SAMR_Q_SET_GROUPINFO *q_u, SAMR_R_SET_GROUPINFO *r_u) +NTSTATUS _samr_SetGroupInfo(pipes_struct *p, + struct samr_SetGroupInfo *r) { DOM_SID group_sid; GROUP_MAP map; - GROUP_INFO_CTR *ctr; uint32 acc_granted; - NTSTATUS ret; - bool result; + NTSTATUS status; + bool ret; bool can_mod_accounts; DISP_INFO *disp_info = NULL; - if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid, &acc_granted, &disp_info)) + if (!get_lsa_policy_samr_sid(p, r->in.group_handle, &group_sid, &acc_granted, &disp_info)) return NT_STATUS_INVALID_HANDLE; - - if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_GROUP_SET_INFO, "_samr_set_groupinfo"))) { - return r_u->status; + + status = access_check_samr_function(acc_granted, + SA_RIGHT_GROUP_SET_INFO, + "_samr_SetGroupInfo"); + if (!NT_STATUS_IS_OK(status)) { + return status; } become_root(); - result = get_domain_group_from_sid(group_sid, &map); + ret = get_domain_group_from_sid(group_sid, &map); unbecome_root(); - if (!result) + if (!ret) return NT_STATUS_NO_SUCH_GROUP; - - ctr=q_u->ctr; - switch (ctr->switch_value1) { + switch (r->in.level) { case 1: - unistr2_to_ascii(map.comment, &(ctr->group.info1.uni_acct_desc), sizeof(map.comment)); + fstrcpy(map.comment, r->in.info->all.description.string); break; case 4: - unistr2_to_ascii(map.comment, &(ctr->group.info4.uni_acct_desc), sizeof(map.comment)); + fstrcpy(map.comment, r->in.info->description.string); break; default: return NT_STATUS_INVALID_INFO_CLASS; @@ -4691,45 +5206,44 @@ NTSTATUS _samr_set_groupinfo(pipes_struct *p, SAMR_Q_SET_GROUPINFO *q_u, SAMR_R_ if ( can_mod_accounts ) become_root(); - - ret = pdb_update_group_mapping_entry(&map); + + status = pdb_update_group_mapping_entry(&map); if ( can_mod_accounts ) unbecome_root(); /******** End SeAddUsers BLOCK *********/ - if (NT_STATUS_IS_OK(ret)) { + if (NT_STATUS_IS_OK(status)) { force_flush_samr_cache(disp_info); } - return ret; + return status; } /********************************************************************* - _samr_set_aliasinfo - - update an alias's comment. + _samr_SetAliasInfo *********************************************************************/ -NTSTATUS _samr_set_aliasinfo(pipes_struct *p, SAMR_Q_SET_ALIASINFO *q_u, SAMR_R_SET_ALIASINFO *r_u) +NTSTATUS _samr_SetAliasInfo(pipes_struct *p, + struct samr_SetAliasInfo *r) { DOM_SID group_sid; struct acct_info info; - ALIAS_INFO_CTR *ctr; uint32 acc_granted; bool can_mod_accounts; NTSTATUS status; DISP_INFO *disp_info = NULL; - if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &group_sid, &acc_granted, &disp_info)) + if (!get_lsa_policy_samr_sid(p, r->in.alias_handle, &group_sid, &acc_granted, &disp_info)) return NT_STATUS_INVALID_HANDLE; - - if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_ALIAS_SET_INFO, "_samr_set_aliasinfo"))) { - return r_u->status; + + status = access_check_samr_function(acc_granted, + SA_RIGHT_ALIAS_SET_INFO, + "_samr_SetAliasInfo"); + if (!NT_STATUS_IS_OK(status)) { + return status; } - - ctr=&q_u->ctr; /* get the current group information */ @@ -4740,13 +5254,13 @@ NTSTATUS _samr_set_aliasinfo(pipes_struct *p, SAMR_Q_SET_ALIASINFO *q_u, SAMR_R_ if ( !NT_STATUS_IS_OK(status)) return status; - switch (ctr->level) { - case 2: + switch (r->in.level) { + case ALIASINFONAME: { - fstring group_name, acct_name; + fstring group_name; /* We currently do not support renaming groups in the - the BUILTIN domain. Refer to util_builtin.c to understand + the BUILTIN domain. Refer to util_builtin.c to understand why. The eventually needs to be fixed to be like Windows where you can rename builtin groups, just not delete them */ @@ -4756,37 +5270,33 @@ NTSTATUS _samr_set_aliasinfo(pipes_struct *p, SAMR_Q_SET_ALIASINFO *q_u, SAMR_R_ /* There has to be a valid name (and it has to be different) */ - if ( !ctr->alias.info2.name.string ) + if ( !r->in.info->name.string ) return NT_STATUS_INVALID_PARAMETER; - unistr2_to_ascii( acct_name, ctr->alias.info2.name.string, - sizeof(acct_name)); - /* If the name is the same just reply "ok". Yes this doesn't allow you to change the case of a group name. */ - if ( strequal( acct_name, info.acct_name ) ) + if ( strequal( r->in.info->name.string, info.acct_name ) ) return NT_STATUS_OK; - fstrcpy( info.acct_name, acct_name ); + fstrcpy( info.acct_name, r->in.info->name.string); - /* make sure the name doesn't already exist as a user + /* make sure the name doesn't already exist as a user or local group */ fstr_sprintf( group_name, "%s\\%s", global_myname(), info.acct_name ); status = can_create( p->mem_ctx, group_name ); - if ( !NT_STATUS_IS_OK( status ) ) + if ( !NT_STATUS_IS_OK( status ) ) return status; break; } - case 3: - if ( ctr->alias.info3.description.string ) { - unistr2_to_ascii( info.acct_desc, - ctr->alias.info3.description.string, - sizeof(info.acct_desc)); - } - else + case ALIASINFODESCRIPTION: + if (r->in.info->description.string) { + fstrcpy(info.acct_desc, + r->in.info->description.string); + } else { fstrcpy( info.acct_desc, "" ); + } break; default: return NT_STATUS_INVALID_INFO_CLASS; @@ -4812,32 +5322,35 @@ NTSTATUS _samr_set_aliasinfo(pipes_struct *p, SAMR_Q_SET_ALIASINFO *q_u, SAMR_R_ return status; } -/********************************************************************* - _samr_get_dom_pwinfo -*********************************************************************/ +/**************************************************************** + _samr_GetDomPwInfo +****************************************************************/ -NTSTATUS _samr_get_dom_pwinfo(pipes_struct *p, SAMR_Q_GET_DOM_PWINFO *q_u, SAMR_R_GET_DOM_PWINFO *r_u) +NTSTATUS _samr_GetDomPwInfo(pipes_struct *p, + struct samr_GetDomPwInfo *r) { /* Perform access check. Since this rpc does not require a policy handle it will not be caught by the access checks on SAMR_CONNECT or SAMR_CONNECT_ANON. */ if (!pipe_access_check(p)) { - DEBUG(3, ("access denied to samr_get_dom_pwinfo\n")); - r_u->status = NT_STATUS_ACCESS_DENIED; - return r_u->status; + DEBUG(3, ("access denied to _samr_GetDomPwInfo\n")); + return NT_STATUS_ACCESS_DENIED; } /* Actually, returning zeros here works quite well :-). */ + ZERO_STRUCTP(r->out.info); return NT_STATUS_OK; } /********************************************************************* - _samr_open_group + _samr_OpenGroup *********************************************************************/ -NTSTATUS _samr_open_group(pipes_struct *p, SAMR_Q_OPEN_GROUP *q_u, SAMR_R_OPEN_GROUP *r_u) +NTSTATUS _samr_OpenGroup(pipes_struct *p, + struct samr_OpenGroup *r) + { DOM_SID sid; DOM_SID info_sid; @@ -4845,50 +5358,51 @@ NTSTATUS _samr_open_group(pipes_struct *p, SAMR_Q_OPEN_GROUP *q_u, SAMR_R_OPEN_G struct samr_info *info; SEC_DESC *psd = NULL; uint32 acc_granted; - uint32 des_access = q_u->access_mask; + 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, &q_u->domain_pol, &sid, &acc_granted, NULL)) + 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, - SA_RIGHT_DOMAIN_OPEN_ACCOUNT, "_samr_open_group"); - + + status = access_check_samr_function(acc_granted, + SA_RIGHT_DOMAIN_OPEN_ACCOUNT, + "_samr_OpenGroup"); + if ( !NT_STATUS_IS_OK(status) ) return status; - + /*check if access can be granted as requested by client. */ make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &grp_generic_mapping, NULL, 0); se_map_generic(&des_access,&grp_generic_mapping); se_priv_copy( &se_rights, &se_add_users ); - status = access_check_samr_object(psd, p->pipe_user.nt_user_token, - &se_rights, GENERIC_RIGHTS_GROUP_WRITE, des_access, - &acc_granted, "_samr_open_group"); - - if ( !NT_STATUS_IS_OK(status) ) + status = access_check_samr_object(psd, p->pipe_user.nt_user_token, + &se_rights, GENERIC_RIGHTS_GROUP_WRITE, des_access, + &acc_granted, "_samr_OpenGroup"); + + if ( !NT_STATUS_IS_OK(status) ) return status; /* this should not be hard-coded like this */ - + if (!sid_equal(&sid, get_global_sam_sid())) return NT_STATUS_ACCESS_DENIED; sid_copy(&info_sid, get_global_sam_sid()); - sid_append_rid(&info_sid, q_u->rid_group); + sid_append_rid(&info_sid, r->in.rid); sid_to_fstring(sid_string, &info_sid); if ((info = get_samr_info_by_sid(&info_sid)) == NULL) return NT_STATUS_NO_MEMORY; - + info->acc_granted = acc_granted; - DEBUG(10, ("_samr_open_group:Opening SID: %s\n", sid_string)); + DEBUG(10, ("_samr_OpenGroup:Opening SID: %s\n", sid_string)); /* check if that group really exists */ become_root(); @@ -4898,46 +5412,46 @@ NTSTATUS _samr_open_group(pipes_struct *p, SAMR_Q_OPEN_GROUP *q_u, SAMR_R_OPEN_G return NT_STATUS_NO_SUCH_GROUP; /* get a (unique) handle. open a policy on it. */ - if (!create_policy_hnd(p, &r_u->pol, free_samr_info, (void *)info)) + if (!create_policy_hnd(p, r->out.group_handle, free_samr_info, (void *)info)) return NT_STATUS_OBJECT_NAME_NOT_FOUND; return NT_STATUS_OK; } /********************************************************************* - _samr_remove_sid_foreign_domain + _samr_RemoveMemberFromForeignDomain *********************************************************************/ -NTSTATUS _samr_remove_sid_foreign_domain(pipes_struct *p, - SAMR_Q_REMOVE_SID_FOREIGN_DOMAIN *q_u, - SAMR_R_REMOVE_SID_FOREIGN_DOMAIN *r_u) +NTSTATUS _samr_RemoveMemberFromForeignDomain(pipes_struct *p, + struct samr_RemoveMemberFromForeignDomain *r) { DOM_SID delete_sid, domain_sid; uint32 acc_granted; NTSTATUS result; DISP_INFO *disp_info = NULL; - sid_copy( &delete_sid, &q_u->sid.sid ); + sid_copy( &delete_sid, r->in.sid ); - DEBUG(5,("_samr_remove_sid_foreign_domain: removing SID [%s]\n", + DEBUG(5,("_samr_RemoveMemberFromForeignDomain: removing SID [%s]\n", sid_string_dbg(&delete_sid))); /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, &q_u->dom_pol, &domain_sid, - &acc_granted, &disp_info)) + 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_remove_sid_foreign_domain"); - - if (!NT_STATUS_IS_OK(result)) + + result = access_check_samr_function(acc_granted, + STD_RIGHT_DELETE_ACCESS, + "_samr_RemoveMemberFromForeignDomain"); + + if (!NT_STATUS_IS_OK(result)) return result; - - DEBUG(8, ("_samr_remove_sid_foreign_domain:sid is %s\n", + + DEBUG(8, ("_samr_RemoveMemberFromForeignDomain: sid is %s\n", sid_string_dbg(&domain_sid))); - /* we can only delete a user from a group since we don't have + /* 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 */ /* TODO: The above comment nowadays is bogus. Since we have nested @@ -4952,7 +5466,7 @@ NTSTATUS _samr_remove_sid_foreign_domain(pipes_struct *p, * other cases. */ if (!sid_check_is_builtin(&domain_sid)) { - DEBUG(1,("_samr_remove_sid_foreign_domain: domain_sid = %s, " + DEBUG(1,("_samr_RemoveMemberFromForeignDomain: domain_sid = %s, " "global_sam_sid() = %s\n", sid_string_dbg(&domain_sid), sid_string_dbg(get_global_sam_sid()))); @@ -4968,68 +5482,52 @@ NTSTATUS _samr_remove_sid_foreign_domain(pipes_struct *p, } /******************************************************************* - _samr_query_domain_info2 + _samr_QueryDomainInfo2 ********************************************************************/ -NTSTATUS _samr_query_domain_info2(pipes_struct *p, - SAMR_Q_QUERY_DOMAIN_INFO2 *q_u, - SAMR_R_QUERY_DOMAIN_INFO2 *r_u) +NTSTATUS _samr_QueryDomainInfo2(pipes_struct *p, + struct samr_QueryDomainInfo2 *r) { - SAMR_Q_QUERY_DOMAIN_INFO q; - SAMR_R_QUERY_DOMAIN_INFO r; - - ZERO_STRUCT(q); - ZERO_STRUCT(r); - - DEBUG(5,("_samr_query_domain_info2: %d\n", __LINE__)); - - q.domain_pol = q_u->domain_pol; - q.switch_value = q_u->switch_value; - - r_u->status = _samr_query_domain_info(p, &q, &r); - - r_u->ptr_0 = r.ptr_0; - r_u->switch_value = r.switch_value; - r_u->ctr = r.ctr; - - return r_u->status; + return samr_QueryDomainInfo_internal("_samr_QueryDomainInfo2", + p, + r->in.domain_handle, + r->in.level, + r->out.info); } /******************************************************************* - _samr_set_dom_info + _samr_SetDomainInfo ********************************************************************/ -NTSTATUS _samr_set_dom_info(pipes_struct *p, SAMR_Q_SET_DOMAIN_INFO *q_u, SAMR_R_SET_DOMAIN_INFO *r_u) +NTSTATUS _samr_SetDomainInfo(pipes_struct *p, + struct samr_SetDomainInfo *r) { time_t u_expire, u_min_age; time_t u_logout; time_t u_lock_duration, u_reset_time; - r_u->status = NT_STATUS_OK; - - DEBUG(5,("_samr_set_dom_info: %d\n", __LINE__)); + DEBUG(5,("_samr_SetDomainInfo: %d\n", __LINE__)); /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, &q_u->domain_pol, NULL)) + if (!find_policy_by_hnd(p, r->in.domain_handle, NULL)) return NT_STATUS_INVALID_HANDLE; - DEBUG(5,("_samr_set_dom_info: switch_value: %d\n", q_u->switch_value)); + DEBUG(5,("_samr_SetDomainInfo: level: %d\n", r->in.level)); - switch (q_u->switch_value) { + switch (r->in.level) { case 0x01: - u_expire=nt_time_to_unix_abs(&q_u->ctr->info.inf1.expire); - u_min_age=nt_time_to_unix_abs(&q_u->ctr->info.inf1.min_passwordage); - - pdb_set_account_policy(AP_MIN_PASSWORD_LEN, (uint32)q_u->ctr->info.inf1.min_length_password); - pdb_set_account_policy(AP_PASSWORD_HISTORY, (uint32)q_u->ctr->info.inf1.password_history); - pdb_set_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, (uint32)q_u->ctr->info.inf1.password_properties); + u_expire=nt_time_to_unix_abs((NTTIME *)&r->in.info->info1.max_password_age); + u_min_age=nt_time_to_unix_abs((NTTIME *)&r->in.info->info1.min_password_age); + pdb_set_account_policy(AP_MIN_PASSWORD_LEN, (uint32)r->in.info->info1.min_password_length); + pdb_set_account_policy(AP_PASSWORD_HISTORY, (uint32)r->in.info->info1.password_history_length); + pdb_set_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, (uint32)r->in.info->info1.password_properties); 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(&q_u->ctr->info.inf3.logout); + 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: @@ -5039,23 +5537,201 @@ NTSTATUS _samr_set_dom_info(pipes_struct *p, SAMR_Q_SET_DOMAIN_INFO *q_u, SAMR_R case 0x07: break; case 0x0c: - u_lock_duration=nt_time_to_unix_abs(&q_u->ctr->info.inf12.duration); + u_lock_duration=nt_time_to_unix_abs((NTTIME *)&r->in.info->info12.lockout_duration); if (u_lock_duration != -1) u_lock_duration /= 60; - u_reset_time=nt_time_to_unix_abs(&q_u->ctr->info.inf12.reset_count)/60; - + u_reset_time=nt_time_to_unix_abs((NTTIME *)&r->in.info->info12.lockout_window)/60; + pdb_set_account_policy(AP_LOCK_ACCOUNT_DURATION, (int)u_lock_duration); pdb_set_account_policy(AP_RESET_COUNT_TIME, (int)u_reset_time); - pdb_set_account_policy(AP_BAD_ATTEMPT_LOCKOUT, (uint32)q_u->ctr->info.inf12.bad_attempt_lockout); + pdb_set_account_policy(AP_BAD_ATTEMPT_LOCKOUT, (uint32)r->in.info->info12.lockout_threshold); break; default: return NT_STATUS_INVALID_INFO_CLASS; } - init_samr_r_set_domain_info(r_u, NT_STATUS_OK); + DEBUG(5,("_samr_SetDomainInfo: %d\n", __LINE__)); + + return NT_STATUS_OK; +} + +/**************************************************************** +****************************************************************/ + +NTSTATUS _samr_Shutdown(pipes_struct *p, + struct samr_Shutdown *r) +{ + p->rng_fault_state = true; + return NT_STATUS_NOT_IMPLEMENTED; +} + +/**************************************************************** +****************************************************************/ + +NTSTATUS _samr_CreateUser(pipes_struct *p, + struct samr_CreateUser *r) +{ + p->rng_fault_state = true; + return NT_STATUS_NOT_IMPLEMENTED; +} + +/**************************************************************** +****************************************************************/ + +NTSTATUS _samr_SetMemberAttributesOfGroup(pipes_struct *p, + struct samr_SetMemberAttributesOfGroup *r) +{ + p->rng_fault_state = true; + return NT_STATUS_NOT_IMPLEMENTED; +} + +/**************************************************************** +****************************************************************/ + +NTSTATUS _samr_ChangePasswordUser(pipes_struct *p, + struct samr_ChangePasswordUser *r) +{ + p->rng_fault_state = true; + return NT_STATUS_NOT_IMPLEMENTED; +} + +/**************************************************************** +****************************************************************/ + +NTSTATUS _samr_GetDisplayEnumerationIndex(pipes_struct *p, + struct samr_GetDisplayEnumerationIndex *r) +{ + p->rng_fault_state = true; + return NT_STATUS_NOT_IMPLEMENTED; +} - DEBUG(5,("_samr_set_dom_info: %d\n", __LINE__)); +/**************************************************************** +****************************************************************/ + +NTSTATUS _samr_TestPrivateFunctionsDomain(pipes_struct *p, + struct samr_TestPrivateFunctionsDomain *r) +{ + p->rng_fault_state = true; + return NT_STATUS_NOT_IMPLEMENTED; +} + +/**************************************************************** +****************************************************************/ + +NTSTATUS _samr_TestPrivateFunctionsUser(pipes_struct *p, + struct samr_TestPrivateFunctionsUser *r) +{ + p->rng_fault_state = true; + return NT_STATUS_NOT_IMPLEMENTED; +} - return r_u->status; +/**************************************************************** +****************************************************************/ + +NTSTATUS _samr_QueryUserInfo2(pipes_struct *p, + struct samr_QueryUserInfo2 *r) +{ + p->rng_fault_state = true; + return NT_STATUS_NOT_IMPLEMENTED; +} + +/**************************************************************** +****************************************************************/ + +NTSTATUS _samr_GetDisplayEnumerationIndex2(pipes_struct *p, + struct samr_GetDisplayEnumerationIndex2 *r) +{ + p->rng_fault_state = true; + return NT_STATUS_NOT_IMPLEMENTED; +} + +/**************************************************************** +****************************************************************/ + +NTSTATUS _samr_AddMultipleMembersToAlias(pipes_struct *p, + struct samr_AddMultipleMembersToAlias *r) +{ + p->rng_fault_state = true; + return NT_STATUS_NOT_IMPLEMENTED; +} + +/**************************************************************** +****************************************************************/ + +NTSTATUS _samr_RemoveMultipleMembersFromAlias(pipes_struct *p, + struct samr_RemoveMultipleMembersFromAlias *r) +{ + p->rng_fault_state = true; + return NT_STATUS_NOT_IMPLEMENTED; +} + +/**************************************************************** +****************************************************************/ + +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) +{ + p->rng_fault_state = true; + return NT_STATUS_NOT_IMPLEMENTED; +} + +/**************************************************************** +****************************************************************/ + +NTSTATUS _samr_GetBootKeyInformation(pipes_struct *p, + struct samr_GetBootKeyInformation *r) +{ + p->rng_fault_state = true; + return NT_STATUS_NOT_IMPLEMENTED; +} + +/**************************************************************** +****************************************************************/ + +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) +{ + p->rng_fault_state = true; + return NT_STATUS_NOT_IMPLEMENTED; +} + +/**************************************************************** +****************************************************************/ + +NTSTATUS _samr_SetDsrmPassword(pipes_struct *p, + struct samr_SetDsrmPassword *r) +{ + p->rng_fault_state = true; + return NT_STATUS_NOT_IMPLEMENTED; +} + +/**************************************************************** +****************************************************************/ + +NTSTATUS _samr_ValidatePassword(pipes_struct *p, + struct samr_ValidatePassword *r) +{ + p->rng_fault_state = true; + return NT_STATUS_NOT_IMPLEMENTED; } |