From bff1df678a8948d382f4555e83a1df23146a4b12 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 17 Nov 2005 22:40:10 +0000 Subject: [PATCH] r11769: Looking at a performance problem enumerating accounts, wondered if changing to support samr_connect5 might help so quickly coded it up. No it doesn't :-(. Don't merge this for 3.0.21 please. Jeremy. --- source/include/rpc_samr.h | 28 +++++++- source/rpc_parse/parse_samr.c | 112 +++++++++++++++++++++++++++++++- source/rpc_server/srv_samr.c | 34 +++++++++- source/rpc_server/srv_samr_nt.c | 54 +++++++++++++++ 4 files changed, 225 insertions(+), 3 deletions(-) diff --git a/source/include/rpc_samr.h b/source/include/rpc_samr.h index 6067587654e..2c125253b3d 100644 --- a/source/include/rpc_samr.h +++ b/source/include/rpc_samr.h @@ -143,6 +143,7 @@ SamrTestPrivateFunctionsUser #define SAMR_CONNECT 0x39 #define SAMR_SET_USERINFO 0x3A #define SAMR_CONNECT4 0x3E +#define SAMR_CONNECT5 0x40 typedef struct logon_hours_info { @@ -1697,7 +1698,7 @@ typedef struct q_samr_connect_info /* SAMR_R_CONNECT - probably an open */ typedef struct r_samr_connect_info { - POLICY_HND connect_pol; /* policy handle */ + POLICY_HND connect_pol; /* policy handle */ NTSTATUS status; /* return status */ } SAMR_R_CONNECT; @@ -1715,6 +1716,31 @@ typedef struct q_samr_connect4_info /* SAMR_R_CONNECT4 - same format as connect */ typedef struct r_samr_connect_info SAMR_R_CONNECT4; +/* SAMR_Q_CONNECT5 */ +typedef struct q_samr_connect5_info +{ + uint32 ptr_srv_name; /* pointer to server name */ + UNISTR2 uni_srv_name; + uint32 access_mask; + uint32 level; + /* These following are acutally a level dependent + value. Fudge it for now. JRA */ + uint32 info1_unk1; + uint32 info1_unk2; +} SAMR_Q_CONNECT5; + +/* SAMR_R_CONNECT5 */ +typedef struct r_samr_connect_info5 +{ + uint32 level; + uint32 info1_unk1; + uint32 info1_unk2; + POLICY_HND connect_pol; /* policy handle */ + NTSTATUS status; /* return status */ + +} SAMR_R_CONNECT5; + + /* SAMR_Q_GET_DOM_PWINFO */ typedef struct q_samr_get_dom_pwinfo { diff --git a/source/rpc_parse/parse_samr.c b/source/rpc_parse/parse_samr.c index dfe80a65e27..7e39b44fe66 100644 --- a/source/rpc_parse/parse_samr.c +++ b/source/rpc_parse/parse_samr.c @@ -6734,7 +6734,7 @@ inits a SAMR_Q_CONNECT4 structure. void init_samr_q_connect4(SAMR_Q_CONNECT4 * q_u, char *srv_name, uint32 access_mask) { - DEBUG(5, ("init_samr_q_connect\n")); + DEBUG(5, ("init_samr_q_connect4\n")); /* make PDC server name \\server */ q_u->ptr_srv_name = (srv_name != NULL && *srv_name) ? 1 : 0; @@ -6803,6 +6803,116 @@ BOOL samr_io_r_connect4(const char *desc, SAMR_R_CONNECT4 * r_u, return True; } +/******************************************************************* +inits a SAMR_Q_CONNECT5 structure. +********************************************************************/ + +void init_samr_q_connect5(SAMR_Q_CONNECT5 * q_u, + char *srv_name, uint32 access_mask) +{ + DEBUG(5, ("init_samr_q_connect5\n")); + + /* make PDC server name \\server */ + q_u->ptr_srv_name = (srv_name != NULL && *srv_name) ? 1 : 0; + init_unistr2(&q_u->uni_srv_name, srv_name, UNI_STR_TERMINATE); + + /* example values: 0x0000 0002 */ + q_u->access_mask = access_mask; + + q_u->level = 1; + q_u->info1_unk1 = 3; + q_u->info1_unk2 = 0; +} + +/******************************************************************* +inits a SAMR_R_CONNECT5 structure. +********************************************************************/ + +void init_samr_r_connect5(SAMR_R_CONNECT5 * r_u, POLICY_HND *pol, NTSTATUS status) +{ + DEBUG(5, ("init_samr_q_connect5\n")); + + r_u->level = 1; + r_u->info1_unk1 = 3; + r_u->info1_unk2 = 0; + + r_u->connect_pol = *pol; + r_u->status = status; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ + +BOOL samr_io_q_connect5(const char *desc, SAMR_Q_CONNECT5 * q_u, + prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "samr_io_q_connect5"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_uint32("ptr_srv_name", ps, depth, &q_u->ptr_srv_name)) + return False; + if(!smb_io_unistr2("", &q_u->uni_srv_name, q_u->ptr_srv_name, ps, depth)) + return False; + + if(!prs_align(ps)) + return False; + if(!prs_uint32("access_mask", ps, depth, &q_u->access_mask)) + return False; + + if(!prs_uint32("level", ps, depth, &q_u->level)) + return False; + if(!prs_uint32("level", ps, depth, &q_u->level)) + return False; + + if(!prs_uint32("info1_unk1", ps, depth, &q_u->info1_unk1)) + return False; + if(!prs_uint32("info1_unk2", ps, depth, &q_u->info1_unk2)) + return False; + + return True; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ + +BOOL samr_io_r_connect5(const char *desc, SAMR_R_CONNECT5 * r_u, + prs_struct *ps, int depth) +{ + if (r_u == NULL) + return False; + + prs_debug(ps, depth, desc, "samr_io_r_connect5"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_uint32("level", ps, depth, &r_u->level)) + return False; + if(!prs_uint32("level", ps, depth, &r_u->level)) + return False; + if(!prs_uint32("info1_unk1", ps, depth, &r_u->info1_unk1)) + return False; + if(!prs_uint32("info1_unk2", ps, depth, &r_u->info1_unk2)) + return False; + + if(!smb_io_pol_hnd("connect_pol", &r_u->connect_pol, ps, depth)) + return False; + + if(!prs_ntstatus("status", ps, depth, &r_u->status)) + return False; + + return True; +} + /******************************************************************* inits a SAMR_Q_CONNECT_ANON structure. ********************************************************************/ diff --git a/source/rpc_server/srv_samr.c b/source/rpc_server/srv_samr.c index ffb7882e110..520bf47a315 100644 --- a/source/rpc_server/srv_samr.c +++ b/source/rpc_server/srv_samr.c @@ -679,6 +679,37 @@ static BOOL api_samr_connect4(pipes_struct *p) return True; } +/******************************************************************* + api_samr_connect5 + ********************************************************************/ + +static BOOL api_samr_connect5(pipes_struct *p) +{ + SAMR_Q_CONNECT5 q_u; + SAMR_R_CONNECT5 r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + /* grab the samr open policy */ + if(!samr_io_q_connect5("", &q_u, data, 0)) { + DEBUG(0,("api_samr_connect5: unable to unmarshall SAMR_Q_CONNECT5.\n")); + return False; + } + + r_u.status = _samr_connect5(p, &q_u, &r_u); + + /* store the response in the SMB stream */ + if(!samr_io_r_connect5("", &r_u, rdata, 0)) { + DEBUG(0,("api_samr_connect5: unable to marshall SAMR_R_CONNECT5.\n")); + return False; + } + + return True; +} + /********************************************************************** api_samr_lookup_domain **********************************************************************/ @@ -1492,7 +1523,8 @@ static struct api_struct api_samr_cmds [] = {"SAMR_GET_USRDOM_PWINFO" , SAMR_GET_USRDOM_PWINFO, api_samr_get_usrdom_pwinfo}, {"SAMR_UNKNOWN_2E" , SAMR_UNKNOWN_2E , api_samr_unknown_2e }, {"SAMR_SET_DOMAIN_INFO" , SAMR_SET_DOMAIN_INFO , api_samr_set_dom_info }, - {"SAMR_CONNECT4" , SAMR_CONNECT4 , api_samr_connect4 } + {"SAMR_CONNECT4" , SAMR_CONNECT4 , api_samr_connect4 }, + {"SAMR_CONNECT5" , SAMR_CONNECT5 , api_samr_connect5 } }; void samr_get_pipe_fns( struct api_struct **fns, int *n_fns ) diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c index 71272a9a98b..bfc96ea0f60 100644 --- a/source/rpc_server/srv_samr_nt.c +++ b/source/rpc_server/srv_samr_nt.c @@ -2293,6 +2293,60 @@ NTSTATUS _samr_connect4(pipes_struct *p, SAMR_Q_CONNECT4 *q_u, SAMR_R_CONNECT4 * return r_u->status; } +/******************************************************************* + samr_connect5 + ********************************************************************/ + +NTSTATUS _samr_connect5(pipes_struct *p, SAMR_Q_CONNECT5 *q_u, SAMR_R_CONNECT5 *r_u) +{ + struct samr_info *info = NULL; + SEC_DESC *psd = NULL; + uint32 acc_granted; + uint32 des_access = q_u->access_mask; + NTSTATUS nt_status; + POLICY_HND pol; + size_t sd_size; + + + DEBUG(5,("_samr_connect5: %d\n", __LINE__)); + + ZERO_STRUCTP(r_u); + + /* 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; + } + + 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) ) + 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; + + /* get a (unique) handle. open a policy on it. */ + if (!create_policy_hnd(p, &pol, free_samr_info, (void *)info)) + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + + DEBUG(5,("_samr_connect: %d\n", __LINE__)); + + init_samr_r_connect5(r_u, &pol, NT_STATUS_OK); + + return r_u->status; +} + /********************************************************************** api_samr_lookup_domain **********************************************************************/ -- 2.34.1