diff options
author | Jeremy Allison <jra@samba.org> | 2001-12-22 00:16:37 +0000 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2001-12-22 00:16:37 +0000 |
commit | f2ba4343e416b2e66bda087a3626be9e16368c56 (patch) | |
tree | a4f38a35b8796d6218eb9beb117f28fd96d8bf19 | |
parent | de33a4a7784f30d61545f21b5ff57b13bc037c98 (diff) | |
download | samba-f2ba4343e416b2e66bda087a3626be9e16368c56.tar.gz samba-f2ba4343e416b2e66bda087a3626be9e16368c56.tar.xz samba-f2ba4343e416b2e66bda087a3626be9e16368c56.zip |
Merged in enough of JF's fixes for enumerating users that this should
fix the Win98 bug. Did not merge the group stuff (go'on Gerald, let me.... :-).
as Jerry would kill me :-).
Jeremy.
-rw-r--r-- | source/include/proto.h | 52 | ||||
-rw-r--r-- | source/include/rpc_samr.h | 38 | ||||
-rw-r--r-- | source/lib/time.c | 126 | ||||
-rw-r--r-- | source/rpc_parse/parse_misc.c | 2 | ||||
-rw-r--r-- | source/rpc_parse/parse_samr.c | 375 | ||||
-rw-r--r-- | source/rpc_server/srv_samr_nt.c | 808 |
6 files changed, 810 insertions, 591 deletions
diff --git a/source/include/proto.h b/source/include/proto.h index 4c07348faaf..0842774c1c1 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -1015,8 +1015,10 @@ void TimeInit(void); int TimeDiff(time_t t); struct tm *LocalTime(time_t *t); time_t nt_time_to_unix(NTTIME *nt); +time_t nt_time_to_unix_abs(NTTIME *nt); time_t interpret_long_date(char *p); void unix_to_nt_time(NTTIME *nt, time_t t); +void unix_to_nt_time_abs(NTTIME *nt, time_t t); void put_long_date(char *p,time_t t); BOOL null_mtime(time_t mtime); void put_dos_date(char *buf,int offset,time_t unixdate); @@ -1787,13 +1789,14 @@ BOOL winbind_nametogid(gid_t *pgid, const char *gname); /*The following definitions come from nsswitch/wb_common.c */ +void free_response(struct winbindd_response *response); void winbind_exclude_domain(const char *domain); void init_request(struct winbindd_request *request, int request_type); void init_response(struct winbindd_response *response); void close_sock(void); +int winbind_open_pipe_sock(void); int write_sock(void *buffer, int count); int read_reply(struct winbindd_response *response); -void free_response(struct winbindd_response *response); /*The following definitions come from param/loadparm.c */ @@ -2587,7 +2590,7 @@ void init_enum_hnd(ENUM_HND *enh, uint32 hnd); BOOL smb_io_enum_hnd(char *desc, ENUM_HND *hnd, prs_struct *ps, int depth); BOOL smb_io_dom_sid(char *desc, DOM_SID *sid, prs_struct *ps, int depth); void init_dom_sid(DOM_SID *sid, char *str_sid); -void init_dom_sid2(DOM_SID2 *sid2, DOM_SID *sid); +void init_dom_sid2(DOM_SID2 *sid2, const DOM_SID *sid); BOOL smb_io_dom_sid2(char *desc, DOM_SID2 *sid, prs_struct *ps, int depth); void init_str_hdr(STRHDR *hdr, int max_len, int len, uint32 buffer); BOOL smb_io_strhdr(char *desc, STRHDR *hdr, prs_struct *ps, int depth); @@ -2955,7 +2958,7 @@ BOOL samr_io_r_unknown_2d(char *desc, SAMR_R_UNKNOWN_2D * r_u, prs_struct *ps, int depth); void init_samr_q_open_domain(SAMR_Q_OPEN_DOMAIN * q_u, POLICY_HND *pol, uint32 flags, - DOM_SID *sid); + const DOM_SID *sid); BOOL samr_io_q_open_domain(char *desc, SAMR_Q_OPEN_DOMAIN * q_u, prs_struct *ps, int depth); BOOL samr_io_r_open_domain(char *desc, SAMR_R_OPEN_DOMAIN * r_u, @@ -2975,15 +2978,16 @@ void init_samr_q_query_dom_info(SAMR_Q_QUERY_DOMAIN_INFO * q_u, POLICY_HND *domain_pol, uint16 switch_value); BOOL samr_io_q_query_dom_info(char *desc, SAMR_Q_QUERY_DOMAIN_INFO * q_u, prs_struct *ps, int depth); -void init_unk_info3(SAM_UNK_INFO_3 * u_3); +void init_unk_info3(SAM_UNK_INFO_3 *u_3, NTTIME nt_logout); void init_unk_info6(SAM_UNK_INFO_6 * u_6); void init_unk_info7(SAM_UNK_INFO_7 * u_7); -void init_unk_info12(SAM_UNK_INFO_12 * u_12); +void init_unk_info12(SAM_UNK_INFO_12 * u_12, NTTIME nt_lock_duration, NTTIME nt_reset_time, uint16 lockout); void init_unk_info5(SAM_UNK_INFO_5 * u_5,char *server); void init_unk_info2(SAM_UNK_INFO_2 * u_2, char *domain, char *server, - uint32 seq_num); -void init_unk_info1(SAM_UNK_INFO_1 * u_1); + uint32 seq_num, uint32 num_users, uint32 num_groups, uint32 num_alias); +void init_unk_info1(SAM_UNK_INFO_1 *u_1, uint16 min_pass_len, uint16 pass_hist, + uint32 flag, NTTIME nt_expire, NTTIME nt_min_age); void init_samr_r_query_dom_info(SAMR_R_QUERY_DOMAIN_INFO * r_u, uint16 switch_value, SAM_UNK_CTR * ctr, NTSTATUS status); @@ -3006,23 +3010,18 @@ void init_samr_q_query_dispinfo(SAMR_Q_QUERY_DISPINFO * q_e, POLICY_HND *pol, uint32 max_entries); BOOL samr_io_q_query_dispinfo(char *desc, SAMR_Q_QUERY_DISPINFO * q_e, prs_struct *ps, int depth); -NTSTATUS init_sam_dispinfo_1(TALLOC_CTX *ctx, SAM_DISPINFO_1 *sam, uint32 *num_entries, - uint32 *data_size, uint32 start_idx, - SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]); -NTSTATUS init_sam_dispinfo_2(TALLOC_CTX *ctx, SAM_DISPINFO_2 *sam, uint32 *num_entries, - uint32 *data_size, uint32 start_idx, - SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]); -NTSTATUS init_sam_dispinfo_3(TALLOC_CTX *ctx, SAM_DISPINFO_3 *sam, uint32 *num_entries, - uint32 *data_size, uint32 start_idx, - DOMAIN_GRP * grp); -NTSTATUS init_sam_dispinfo_4(TALLOC_CTX *ctx, SAM_DISPINFO_4 *sam, uint32 *num_entries, - uint32 *data_size, uint32 start_idx, - SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]); -NTSTATUS init_sam_dispinfo_5(TALLOC_CTX *ctx, SAM_DISPINFO_5 *sam, uint32 *num_entries, - uint32 *data_size, uint32 start_idx, - DOMAIN_GRP * grp); +NTSTATUS init_sam_dispinfo_1(TALLOC_CTX *ctx, SAM_DISPINFO_1 *sam, uint32 num_entries, + uint32 start_idx, DISP_USER_INFO *disp_user_info); +NTSTATUS init_sam_dispinfo_2(TALLOC_CTX *ctx, SAM_DISPINFO_2 *sam, uint32 num_entries, + uint32 start_idx, DISP_USER_INFO *disp_user_info); +NTSTATUS init_sam_dispinfo_3(TALLOC_CTX *ctx, SAM_DISPINFO_3 *sam, uint32 num_entries, + uint32 start_idx, DISP_GROUP_INFO *disp_group_info); +NTSTATUS init_sam_dispinfo_4(TALLOC_CTX *ctx, SAM_DISPINFO_4 *sam, uint32 num_entries, + uint32 start_idx, DISP_USER_INFO *disp_user_info); +NTSTATUS init_sam_dispinfo_5(TALLOC_CTX *ctx, SAM_DISPINFO_5 *sam, uint32 num_entries, + uint32 start_idx, DISP_GROUP_INFO *disp_group_info); void init_samr_r_query_dispinfo(SAMR_R_QUERY_DISPINFO * r_u, - uint32 num_entries, uint32 data_size, + uint32 num_entries, uint32 total_size, uint32 data_size, uint16 switch_level, SAM_DISPINFO_CTR * ctr, NTSTATUS status); BOOL samr_io_r_query_dispinfo(char *desc, SAMR_R_QUERY_DISPINFO * r_u, @@ -3039,6 +3038,8 @@ void init_samr_group_info1(GROUP_INFO1 * gr1, uint32 num_members); BOOL samr_io_group_info1(char *desc, GROUP_INFO1 * gr1, prs_struct *ps, int depth); +void init_samr_group_info3(GROUP_INFO3 *gr3); +BOOL samr_io_group_info3(char *desc, GROUP_INFO3 *gr3, prs_struct *ps, int depth); void init_samr_group_info4(GROUP_INFO4 * gr4, char *acct_desc); BOOL samr_io_group_info4(char *desc, GROUP_INFO4 * gr4, prs_struct *ps, int depth); @@ -3131,6 +3132,9 @@ BOOL samr_io_q_enum_dom_aliases(char *desc, SAMR_Q_ENUM_DOM_ALIASES * q_e, void init_samr_r_enum_dom_aliases(SAMR_R_ENUM_DOM_ALIASES *r_u, uint32 next_idx, uint32 num_sam_entries); BOOL samr_io_r_enum_dom_aliases(char *desc, SAMR_R_ENUM_DOM_ALIASES * r_u, prs_struct *ps, int depth); +void init_samr_alias_info1(ALIAS_INFO1 * al1, char *acct_name, uint32 num_member, char *acct_desc); +BOOL samr_io_alias_info1(char *desc, ALIAS_INFO1 * al1, + prs_struct *ps, int depth); void init_samr_alias_info3(ALIAS_INFO3 * al3, char *acct_desc); BOOL samr_io_alias_info3(char *desc, ALIAS_INFO3 * al3, prs_struct *ps, int depth); @@ -3245,7 +3249,7 @@ BOOL samr_io_r_open_user(char *desc, SAMR_R_OPEN_USER * r_u, prs_struct *ps, int depth); void init_samr_q_create_user(SAMR_Q_CREATE_USER * q_u, POLICY_HND *pol, - char *name, + const char *name, uint32 acb_info, uint32 access_mask); BOOL samr_io_q_create_user(char *desc, SAMR_Q_CREATE_USER * q_u, prs_struct *ps, int depth); diff --git a/source/include/rpc_samr.h b/source/include/rpc_samr.h index b3b46c6f0c6..c0b908b3486 100644 --- a/source/include/rpc_samr.h +++ b/source/include/rpc_samr.h @@ -5,6 +5,7 @@ Copyright (C) Andrew Tridgell 1992-2000 Copyright (C) Luke Kenneth Casson Leighton 1996-2000 Copyright (C) Paul Ashton 1997-2000 + Copyright (C) Jean François Micouleau 1998-2001. 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 @@ -146,6 +147,14 @@ SamrTestPrivateFunctionsUser #define SAMR_SET_USERINFO 0x3A +typedef struct _DISP_USER_INFO { + SAM_ACCOUNT *sam; +} DISP_USER_INFO; + +typedef struct _DISP_GROUP_INFO { + DOMAIN_GRP *grp; +} DISP_GROUP_INFO; + typedef struct logon_hours_info { @@ -481,14 +490,11 @@ typedef struct q_samr_query_domain_info typedef struct sam_unknown_info_3_info { - uint32 unknown_0; /* 0x0000 0000 */ - uint32 unknown_1; - + NTTIME logout; /* 0x8000 0000 */ /* DON'T forcibly disconnect remote users from server when logon hours expire*/ /* 0x0000 0000 */ /* forcibly disconnect remote users from server when logon hours expire*/ - } SAM_UNK_INFO_3; typedef struct sam_unknown_info_6_info @@ -791,7 +797,6 @@ typedef struct samr_entry_info1 uint32 rid_user; uint16 acb_info; - uint16 pad; UNIHDR hdr_acct_name; UNIHDR hdr_user_name; @@ -823,7 +828,6 @@ typedef struct samr_entry_info2 uint32 rid_user; uint16 acb_info; - uint16 pad; UNIHDR hdr_srv_name; UNIHDR hdr_srv_desc; @@ -1036,6 +1040,12 @@ typedef struct samr_group_info1 } GROUP_INFO1; +typedef struct samr_group_info3 +{ + uint32 unknown_1; /* 0x0000 0003 - number of group members? */ + +} GROUP_INFO3; + typedef struct samr_group_info4 { UNIHDR hdr_acct_desc; @@ -1047,12 +1057,12 @@ typedef struct samr_group_info4 typedef struct group_info_ctr { uint16 switch_value1; - uint16 switch_value2; union { - GROUP_INFO4 info4; GROUP_INFO1 info1; + GROUP_INFO3 info3; + GROUP_INFO4 info4; } group; @@ -1133,6 +1143,16 @@ typedef struct q_samr_query_alias_info } SAMR_Q_QUERY_ALIASINFO; +typedef struct samr_alias_info1 +{ + UNIHDR hdr_acct_name; + UNIHDR hdr_acct_desc; + uint32 num_member; + UNISTR2 uni_acct_name; + UNISTR2 uni_acct_desc; + +} ALIAS_INFO1; + typedef struct samr_alias_info3 { UNIHDR hdr_acct_desc; @@ -1148,6 +1168,7 @@ typedef struct alias_info_ctr union { + ALIAS_INFO1 info1; ALIAS_INFO3 info3; } alias; @@ -1491,7 +1512,6 @@ typedef struct r_samr_query_groupmem_info typedef struct q_samr_del_group_mem_info { POLICY_HND pol; /* policy handle */ - uint32 rid; /* rid */ } SAMR_Q_DEL_GROUPMEM; diff --git a/source/lib/time.c b/source/lib/time.c index cf088e8ee43..f0f62ca8419 100644 --- a/source/lib/time.c +++ b/source/lib/time.c @@ -27,7 +27,6 @@ */ -int serverzone=0; int extra_time_offset = 0; #ifndef CHAR_BIT @@ -105,21 +104,36 @@ static int TimeZone(time_t t) } +static BOOL done_serverzone_init; -/******************************************************************* -init the time differences -********************************************************************/ -void TimeInit(void) +/* Return the smb serverzone value */ + +static int get_serverzone(void) { - serverzone = TimeZone(time(NULL)); + static int serverzone; - if ((serverzone % 60) != 0) { - DEBUG(1,("WARNING: Your timezone is not a multiple of 1 minute.\n")); - } + if (!done_serverzone_init) { + serverzone = TimeZone(time(NULL)); + + if ((serverzone % 60) != 0) { + DEBUG(1,("WARNING: Your timezone is not a multiple of 1 minute.\n")); + } + + DEBUG(4,("Serverzone is %d\n",serverzone)); - DEBUG(4,("Serverzone is %d\n",serverzone)); + done_serverzone_init = True; + } + + return serverzone; } +/* Re-read the smb serverzone value */ + +void TimeInit(void) +{ + done_serverzone_init = False; + get_serverzone(); +} /******************************************************************* return the same value as TimeZone, but it should be more efficient. @@ -284,12 +298,56 @@ time_t nt_time_to_unix(NTTIME *nt) ret = (time_t)(d+0.5); /* this takes us from kludge-GMT to real GMT */ - ret -= serverzone; + ret -= get_serverzone(); ret += LocTimeDiff(ret); return(ret); } +/**************************************************************************** +convert a NTTIME structure to a time_t +It's originally in "100ns units" + +this is an absolute version of the one above. +By absolute I mean, it doesn't adjust from 1/1/1601 to 1/1/1970 +if the NTTIME was 5 seconds, the time_t is 5 seconds. JFM +****************************************************************************/ +time_t nt_time_to_unix_abs(NTTIME *nt) +{ + double d; + time_t ret; + /* The next two lines are a fix needed for the + broken SCO compiler. JRA. */ + time_t l_time_min = TIME_T_MIN; + time_t l_time_max = TIME_T_MAX; + + if (nt->high == 0) + return(0); + + if (nt->high==0x80000000 && nt->low==0) + return -1; + + /* reverse the time */ + /* it's a negative value, turn it to positive */ + nt->high=~nt->high; + nt->low=~nt->low; + + d = ((double)nt->high)*4.0*(double)(1<<30); + d += (nt->low&0xFFF00000); + d *= 1.0e-7; + + if (!(l_time_min <= d && d <= l_time_max)) + return(0); + + ret = (time_t)(d+0.5); + + /* this takes us from kludge-GMT to real GMT */ + ret -= get_serverzone(); + ret += LocTimeDiff(ret); + + return(ret); +} + /**************************************************************************** @@ -331,7 +389,7 @@ void unix_to_nt_time(NTTIME *nt, time_t t) } /* this converts GMT to kludge-GMT */ - t -= LocTimeDiff(t) - serverzone; + t -= LocTimeDiff(t) - get_serverzone(); d = (double)(t); d += TIME_FIXUP_CONSTANT; @@ -341,6 +399,50 @@ void unix_to_nt_time(NTTIME *nt, time_t t) nt->low = (uint32)(d - ((double)nt->high)*4.0*(double)(1<<30)); } +/**************************************************************************** +convert a time_t to a NTTIME structure + +this is an absolute version of the one above. +By absolute I mean, it doesn't adjust from 1/1/1970 to 1/1/1601 +if the nttime_t was 5 seconds, the NTTIME is 5 seconds. JFM +****************************************************************************/ +void unix_to_nt_time_abs(NTTIME *nt, time_t t) +{ + double d; + + if (t==0) { + nt->low = 0; + nt->high = 0; + return; + } + + if (t == TIME_T_MAX) { + nt->low = 0xffffffff; + nt->high = 0x7fffffff; + return; + } + + if (t == -1) { + /* that's what NT uses for infinite */ + nt->low = 0x0; + nt->high = 0x80000000; + return; + } + + /* this converts GMT to kludge-GMT */ + t -= LocTimeDiff(t) - get_serverzone(); + + d = (double)(t); + d *= 1.0e7; + + nt->high = (uint32)(d * (1.0/(4.0*(double)(1<<30)))); + nt->low = (uint32)(d - ((double)nt->high)*4.0*(double)(1<<30)); + + /* convert to a negative value */ + nt->high=~nt->high; + nt->low=~nt->low; +} + /**************************************************************************** take an NTTIME structure, containing high / low time. convert to unix time. diff --git a/source/rpc_parse/parse_misc.c b/source/rpc_parse/parse_misc.c index db325025e83..afb829637c3 100644 --- a/source/rpc_parse/parse_misc.c +++ b/source/rpc_parse/parse_misc.c @@ -294,7 +294,7 @@ void init_dom_sid(DOM_SID *sid, char *str_sid) Inits a DOM_SID2 structure. ********************************************************************/ -void init_dom_sid2(DOM_SID2 *sid2, DOM_SID *sid) +void init_dom_sid2(DOM_SID2 *sid2, const DOM_SID *sid) { sid2->sid = *sid; sid2->num_auths = sid2->sid.num_auths; diff --git a/source/rpc_parse/parse_samr.c b/source/rpc_parse/parse_samr.c index 99c0fe30bea..f207d32e55c 100644 --- a/source/rpc_parse/parse_samr.c +++ b/source/rpc_parse/parse_samr.c @@ -7,6 +7,7 @@ * Copyright (C) Paul Ashton 1997-2000, * Copyright (C) Elrond 2000, * Copyright (C) Jeremy Allison 2001 + * Copyright (C) Jean François Micouleau 1998-2001. * * 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 @@ -243,7 +244,7 @@ reads or writes a structure. void init_samr_q_open_domain(SAMR_Q_OPEN_DOMAIN * q_u, POLICY_HND *pol, uint32 flags, - DOM_SID *sid) + const DOM_SID *sid) { DEBUG(5, ("samr_init_samr_q_open_domain\n")); @@ -345,8 +346,16 @@ void init_samr_r_get_usrdom_pwinfo(SAMR_R_GET_USRDOM_PWINFO *r_u, NTSTATUS statu DEBUG(5, ("init_samr_r_get_usrdom_pwinfo\n")); r_u->unknown_0 = 0x0000; - r_u->unknown_1 = 0x0015; - r_u->unknown_2 = 0x00000000; + + /* + * used to be + * r_u->unknown_1 = 0x0015; + * but for trusts. + */ + r_u->unknown_1 = 0x01D1; + r_u->unknown_1 = 0x0015; + + r_u->unknown_2 = 0x00000000; r_u->status = status; } @@ -461,10 +470,10 @@ BOOL samr_io_q_query_dom_info(char *desc, SAMR_Q_QUERY_DOMAIN_INFO * q_u, inits a structure. ********************************************************************/ -void init_unk_info3(SAM_UNK_INFO_3 * u_3) +void init_unk_info3(SAM_UNK_INFO_3 *u_3, NTTIME nt_logout) { - u_3->unknown_0 = 0x00000000; - u_3->unknown_1 = 0x80000000; + u_3->logout.low = nt_logout.low; + u_3->logout.high = nt_logout.high; } /******************************************************************* @@ -480,9 +489,7 @@ static BOOL sam_io_unk_info3(char *desc, SAM_UNK_INFO_3 * u_3, prs_debug(ps, depth, desc, "sam_io_unk_info3"); depth++; - if(!prs_uint32("unknown_0", ps, depth, &u_3->unknown_0)) /* 0x0000 0000 */ - return False; - if(!prs_uint32("unknown_1", ps, depth, &u_3->unknown_1)) /* 0x8000 0000 */ + if(!smb_io_time("logout", &u_3->logout, ps, depth)) return False; return True; @@ -554,14 +561,14 @@ static BOOL sam_io_unk_info7(char *desc, SAM_UNK_INFO_7 * u_7, inits a structure. ********************************************************************/ -void init_unk_info12(SAM_UNK_INFO_12 * u_12) +void init_unk_info12(SAM_UNK_INFO_12 * u_12, NTTIME nt_lock_duration, NTTIME nt_reset_time, uint16 lockout) { - u_12->duration.low = 0xcf1dcc00; - u_12->duration.high = 0xfffffffb; - u_12->reset_count.low = 0xcf1dcc00; - u_12->reset_count.high = 0xfffffffb; + u_12->duration.low = nt_lock_duration.low; + u_12->duration.high = nt_lock_duration.high; + u_12->reset_count.low = nt_reset_time.low; + u_12->reset_count.high = nt_reset_time.high; - u_12->bad_attempt_lockout = 0x0000; + u_12->bad_attempt_lockout = lockout; } /******************************************************************* @@ -626,7 +633,7 @@ inits a structure. ********************************************************************/ void init_unk_info2(SAM_UNK_INFO_2 * u_2, char *domain, char *server, - uint32 seq_num) + uint32 seq_num, uint32 num_users, uint32 num_groups, uint32 num_alias) { int len_domain = strlen(domain); int len_server = strlen(server); @@ -645,9 +652,9 @@ void init_unk_info2(SAM_UNK_INFO_2 * u_2, u_2->unknown_4 = 0x00000001; u_2->unknown_5 = 0x00000003; u_2->unknown_6 = 0x00000001; - u_2->num_domain_usrs = MAX_SAM_ENTRIES; - u_2->num_domain_grps = MAX_SAM_ENTRIES; - u_2->num_local_grps = MAX_SAM_ENTRIES; + u_2->num_domain_usrs = num_users; + u_2->num_domain_grps = num_groups; + u_2->num_local_grps = num_alias; memset(u_2->padding, 0, sizeof(u_2->padding)); /* 12 bytes zeros */ @@ -719,19 +726,20 @@ static BOOL sam_io_unk_info2(char *desc, SAM_UNK_INFO_2 * u_2, inits a structure. ********************************************************************/ -void init_unk_info1(SAM_UNK_INFO_1 * u_1) +void init_unk_info1(SAM_UNK_INFO_1 *u_1, uint16 min_pass_len, uint16 pass_hist, + uint32 flag, NTTIME nt_expire, NTTIME nt_min_age) { - u_1->min_length_password = 0; - u_1->password_history = 0; - u_1->flag = 0; + u_1->min_length_password = min_pass_len; + u_1->password_history = pass_hist; + u_1->flag = flag; /* password never expire */ - u_1->expire.high = 0x80000000; - u_1->expire.low = 0; + u_1->expire.high = nt_expire.high; + u_1->expire.low = nt_expire.low; /* can change the password now */ - u_1->min_passwordage.high = 0; - u_1->min_passwordage.low = 0; + u_1->min_passwordage.high = nt_min_age.high; + u_1->min_passwordage.low = nt_min_age.low; } @@ -927,7 +935,6 @@ static void init_sam_entry1(SAM_ENTRY1 * sam, uint32 user_idx, sam->user_idx = user_idx; sam->rid_user = rid_user; sam->acb_info = acb_info; - sam->pad = 0; init_uni_hdr(&sam->hdr_acct_name, len_sam_name); init_uni_hdr(&sam->hdr_user_name, len_sam_full); @@ -957,7 +964,8 @@ static BOOL sam_io_sam_entry1(char *desc, SAM_ENTRY1 * sam, return False; if(!prs_uint16("acb_info ", ps, depth, &sam->acb_info)) return False; - if(!prs_uint16("pad ", ps, depth, &sam->pad)) + + if(!prs_align(ps)) return False; if (!smb_io_unihdr("hdr_acct_name", &sam->hdr_acct_name, ps, depth)) @@ -1006,7 +1014,6 @@ static void init_sam_entry2(SAM_ENTRY2 * sam, uint32 user_idx, sam->user_idx = user_idx; sam->rid_user = rid_user; sam->acb_info = acb_info; - sam->pad = 0; init_uni_hdr(&sam->hdr_srv_name, len_sam_name); init_uni_hdr(&sam->hdr_srv_desc, len_sam_desc); @@ -1035,7 +1042,8 @@ static BOOL sam_io_sam_entry2(char *desc, SAM_ENTRY2 * sam, return False; if(!prs_uint16("acb_info ", ps, depth, &sam->acb_info)) return False; - if(!prs_uint16("pad ", ps, depth, &sam->pad)) + + if(!prs_align(ps)) return False; if(!smb_io_unihdr("unihdr", &sam->hdr_srv_name, ps, depth)) /* account name unicode string header */ @@ -1429,62 +1437,53 @@ BOOL samr_io_q_query_dispinfo(char *desc, SAMR_Q_QUERY_DISPINFO * q_e, inits a SAM_DISPINFO_1 structure. ********************************************************************/ -NTSTATUS init_sam_dispinfo_1(TALLOC_CTX *ctx, SAM_DISPINFO_1 *sam, uint32 *num_entries, - uint32 *data_size, uint32 start_idx, - SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]) +NTSTATUS init_sam_dispinfo_1(TALLOC_CTX *ctx, SAM_DISPINFO_1 *sam, uint32 num_entries, + uint32 start_idx, DISP_USER_INFO *disp_user_info) { uint32 len_sam_name, len_sam_full, len_sam_desc; - uint32 max_entries, max_data_size; - uint32 dsize = 0; uint32 i; + SAM_ACCOUNT *pwd = NULL; ZERO_STRUCTP(sam); - max_entries = *num_entries; - max_data_size = *data_size; - - DEBUG(5, ("init_sam_dispinfo_1: max_entries: %d max_dsize: 0x%x\n", - max_entries, max_data_size)); + DEBUG(10, ("init_sam_dispinfo_1: num_entries: %d\n", num_entries)); - if (max_entries==0) + if (num_entries==0) return NT_STATUS_OK; - sam->sam=(SAM_ENTRY1 *)talloc(ctx, max_entries*sizeof(SAM_ENTRY1)); + sam->sam=(SAM_ENTRY1 *)talloc(ctx, num_entries*sizeof(SAM_ENTRY1)); if (!sam->sam) return NT_STATUS_NO_MEMORY; - sam->str=(SAM_STR1 *)talloc(ctx, max_entries*sizeof(SAM_STR1)); + sam->str=(SAM_STR1 *)talloc(ctx, num_entries*sizeof(SAM_STR1)); if (!sam->str) return NT_STATUS_NO_MEMORY; ZERO_STRUCTP(sam->sam); ZERO_STRUCTP(sam->str); - for (i = 0; (i < max_entries) && (dsize < max_data_size); i++) { - DEBUG(5, ("init_sam_dispinfo_1: entry: %d\n",i)); - len_sam_name = pass[i].uni_user_name.uni_str_len; - len_sam_full = pass[i].uni_full_name.uni_str_len; - len_sam_desc = pass[i].uni_acct_desc.uni_str_len; + for (i = 0; i < num_entries ; i++) { + DEBUG(11, ("init_sam_dispinfo_1: entry: %d\n",i)); + + pwd=disp_user_info[i+start_idx].sam; + + len_sam_name = strlen(pdb_get_username(pwd)); + len_sam_full = strlen(pdb_get_fullname(pwd)); + len_sam_desc = strlen(pdb_get_acct_desc(pwd)); init_sam_entry1(&sam->sam[i], start_idx + i + 1, len_sam_name, len_sam_full, len_sam_desc, - pass[i].user_rid, pass[i].acb_info); + pdb_get_user_rid(pwd), pdb_get_acct_ctrl(pwd)); ZERO_STRUCTP(&sam->str[i].uni_acct_name); ZERO_STRUCTP(&sam->str[i].uni_full_name); ZERO_STRUCTP(&sam->str[i].uni_acct_desc); - copy_unistr2(&sam->str[i].uni_acct_name, &pass[i].uni_user_name); - copy_unistr2(&sam->str[i].uni_full_name, &pass[i].uni_full_name); - copy_unistr2(&sam->str[i].uni_acct_desc, &pass[i].uni_acct_desc); - - dsize += sizeof(SAM_ENTRY1); - dsize += len_sam_name + len_sam_full + len_sam_desc; + init_unistr2(&sam->str[i].uni_acct_name, pdb_get_username(pwd), len_sam_name); + init_unistr2(&sam->str[i].uni_full_name, pdb_get_fullname(pwd), len_sam_full); + init_unistr2(&sam->str[i].uni_acct_desc, pdb_get_acct_desc(pwd), len_sam_desc); } - *num_entries = i; - *data_size = dsize; - return NT_STATUS_OK; } @@ -1541,55 +1540,47 @@ static BOOL sam_io_sam_dispinfo_1(char *desc, SAM_DISPINFO_1 * sam, inits a SAM_DISPINFO_2 structure. ********************************************************************/ -NTSTATUS init_sam_dispinfo_2(TALLOC_CTX *ctx, SAM_DISPINFO_2 *sam, uint32 *num_entries, - uint32 *data_size, uint32 start_idx, - SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]) +NTSTATUS init_sam_dispinfo_2(TALLOC_CTX *ctx, SAM_DISPINFO_2 *sam, uint32 num_entries, + uint32 start_idx, DISP_USER_INFO *disp_user_info) { uint32 len_sam_name, len_sam_desc; - uint32 max_entries, max_data_size; - uint32 dsize = 0; uint32 i; - DEBUG(5, ("init_sam_dispinfo_2\n")); - + SAM_ACCOUNT *pwd = NULL; ZERO_STRUCTP(sam); - max_entries = *num_entries; - max_data_size = *data_size; + DEBUG(10, ("init_sam_dispinfo_2: num_entries: %d\n", num_entries)); - if (max_entries==0) + if (num_entries==0) return NT_STATUS_OK; - if (!(sam->sam=(SAM_ENTRY2 *)talloc(ctx, max_entries*sizeof(SAM_ENTRY2)))) + if (!(sam->sam=(SAM_ENTRY2 *)talloc(ctx, num_entries*sizeof(SAM_ENTRY2)))) return NT_STATUS_NO_MEMORY; - if (!(sam->str=(SAM_STR2 *)talloc(ctx, max_entries*sizeof(SAM_STR2)))) + if (!(sam->str=(SAM_STR2 *)talloc(ctx, num_entries*sizeof(SAM_STR2)))) return NT_STATUS_NO_MEMORY; ZERO_STRUCTP(sam->sam); ZERO_STRUCTP(sam->str); - for (i = 0; (i < max_entries) && (dsize < max_data_size); i++) { - len_sam_name = pass[i].uni_user_name.uni_str_len; - len_sam_desc = pass[i].uni_acct_desc.uni_str_len; + for (i = 0; i < num_entries; i++) { + DEBUG(11, ("init_sam_dispinfo_2: entry: %d\n",i)); + pwd=disp_user_info[i+start_idx].sam; + + len_sam_name = strlen(pdb_get_username(pwd)); + len_sam_desc = strlen(pdb_get_acct_desc(pwd)); init_sam_entry2(&sam->sam[i], start_idx + i + 1, len_sam_name, len_sam_desc, - pass[i].user_rid, pass[i].acb_info); + pdb_get_user_rid(pwd), pdb_get_acct_ctrl(pwd)); ZERO_STRUCTP(&sam->str[i].uni_srv_name); ZERO_STRUCTP(&sam->str[i].uni_srv_desc); - copy_unistr2(&sam->str[i].uni_srv_name, &pass[i].uni_user_name); - copy_unistr2(&sam->str[i].uni_srv_desc, &pass[i].uni_acct_desc); - - dsize += sizeof(SAM_ENTRY2); - dsize += len_sam_name + len_sam_desc; + init_unistr2(&sam->str[i].uni_srv_name, pdb_get_username(pwd), len_sam_name); + init_unistr2(&sam->str[i].uni_srv_desc, pdb_get_acct_desc(pwd), len_sam_desc); } - *num_entries = i; - *data_size = dsize; - return NT_STATUS_OK; } @@ -1648,35 +1639,33 @@ static BOOL sam_io_sam_dispinfo_2(char *desc, SAM_DISPINFO_2 * sam, inits a SAM_DISPINFO_3 structure. ********************************************************************/ -NTSTATUS init_sam_dispinfo_3(TALLOC_CTX *ctx, SAM_DISPINFO_3 *sam, uint32 *num_entries, - uint32 *data_size, uint32 start_idx, - DOMAIN_GRP * grp) +NTSTATUS init_sam_dispinfo_3(TALLOC_CTX *ctx, SAM_DISPINFO_3 *sam, uint32 num_entries, + uint32 start_idx, DISP_GROUP_INFO *disp_group_info) { uint32 len_sam_name, len_sam_desc; - uint32 max_entries, max_data_size; - uint32 dsize = 0; uint32 i; - DEBUG(5, ("init_sam_dispinfo_3\n")); - + DOMAIN_GRP *grp; ZERO_STRUCTP(sam); - max_entries = *num_entries; - max_data_size = *data_size; + DEBUG(5, ("init_sam_dispinfo_3: num_entries: %d\n", num_entries)); - if (max_entries==0) + if (num_entries==0) return NT_STATUS_OK; - if (!(sam->sam=(SAM_ENTRY3 *)talloc(ctx, max_entries*sizeof(SAM_ENTRY3)))) + if (!(sam->sam=(SAM_ENTRY3 *)talloc(ctx, num_entries*sizeof(SAM_ENTRY3)))) return NT_STATUS_NO_MEMORY; - if (!(sam->str=(SAM_STR3 *)talloc(ctx, max_entries*sizeof(SAM_STR3)))) + if (!(sam->str=(SAM_STR3 *)talloc(ctx, num_entries*sizeof(SAM_STR3)))) return NT_STATUS_NO_MEMORY; ZERO_STRUCTP(sam->sam); ZERO_STRUCTP(sam->str); - for (i = 0; (i < max_entries) && (dsize < max_data_size); i++) { + for (i = 0; i < num_entries; i++) { + DEBUG(11, ("init_sam_dispinfo_3: entry: %d\n",i)); + grp=disp_group_info[i+start_idx].grp; + len_sam_name = strlen(grp[i].name); len_sam_desc = strlen(grp[i].comment); @@ -1684,15 +1673,8 @@ NTSTATUS init_sam_dispinfo_3(TALLOC_CTX *ctx, SAM_DISPINFO_3 *sam, uint32 *num_e init_unistr2(&sam->str[i].uni_grp_name, grp[i].name, len_sam_name); init_unistr2(&sam->str[i].uni_grp_desc, grp[i].comment, len_sam_desc); - - dsize += sizeof(SAM_ENTRY3); - dsize += (len_sam_name + len_sam_desc) * 2; - dsize += 14; } - *num_entries = i; - *data_size = dsize; - return NT_STATUS_OK; } @@ -1751,50 +1733,40 @@ static BOOL sam_io_sam_dispinfo_3(char *desc, SAM_DISPINFO_3 * sam, inits a SAM_DISPINFO_4 structure. ********************************************************************/ -NTSTATUS init_sam_dispinfo_4(TALLOC_CTX *ctx, SAM_DISPINFO_4 *sam, uint32 *num_entries, - uint32 *data_size, uint32 start_idx, - SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]) +NTSTATUS init_sam_dispinfo_4(TALLOC_CTX *ctx, SAM_DISPINFO_4 *sam, uint32 num_entries, + uint32 start_idx, DISP_USER_INFO *disp_user_info) { - fstring sam_name; uint32 len_sam_name; - uint32 max_entries, max_data_size; - uint32 dsize = 0; uint32 i; - DEBUG(5, ("init_sam_dispinfo_4\n")); - + SAM_ACCOUNT *pwd = NULL; ZERO_STRUCTP(sam); - max_entries = *num_entries; - max_data_size = *data_size; + DEBUG(5, ("init_sam_dispinfo_4: num_entries: %d\n", num_entries)); - if (max_entries==0) + if (num_entries==0) return NT_STATUS_OK; - if (!(sam->sam=(SAM_ENTRY4 *)talloc(ctx, max_entries*sizeof(SAM_ENTRY4)))) + if (!(sam->sam=(SAM_ENTRY4 *)talloc(ctx, num_entries*sizeof(SAM_ENTRY4)))) return NT_STATUS_NO_MEMORY; - if (!(sam->str=(SAM_STR4 *)talloc(ctx, max_entries*sizeof(SAM_STR4)))) + if (!(sam->str=(SAM_STR4 *)talloc(ctx, num_entries*sizeof(SAM_STR4)))) return NT_STATUS_NO_MEMORY; ZERO_STRUCTP(sam->sam); ZERO_STRUCTP(sam->str); - for (i = 0; (i < max_entries) && (dsize < max_data_size); i++) { - len_sam_name = pass[i].uni_user_name.uni_str_len; + for (i = 0; i < num_entries; i++) { + DEBUG(11, ("init_sam_dispinfo_2: entry: %d\n",i)); + pwd=disp_user_info[i+start_idx].sam; + + len_sam_name = strlen(pdb_get_username(pwd)); init_sam_entry4(&sam->sam[i], start_idx + i + 1, len_sam_name); - unistr2_to_ascii(sam_name, &pass[i].uni_user_name, sizeof(sam_name)); - init_string2(&sam->str[i].acct_name, sam_name, len_sam_name+1, len_sam_name); - - dsize += sizeof(SAM_ENTRY4); - dsize += len_sam_name; + init_string2(&sam->str[i].acct_name, pdb_get_username(pwd), len_sam_name+1, len_sam_name); } - *num_entries = i; - *data_size = dsize; - return NT_STATUS_OK; } @@ -1852,46 +1824,38 @@ static BOOL sam_io_sam_dispinfo_4(char *desc, SAM_DISPINFO_4 * sam, inits a SAM_DISPINFO_5 structure. ********************************************************************/ -NTSTATUS init_sam_dispinfo_5(TALLOC_CTX *ctx, SAM_DISPINFO_5 *sam, uint32 *num_entries, - uint32 *data_size, uint32 start_idx, - DOMAIN_GRP * grp) +NTSTATUS init_sam_dispinfo_5(TALLOC_CTX *ctx, SAM_DISPINFO_5 *sam, uint32 num_entries, + uint32 start_idx, DISP_GROUP_INFO *disp_group_info) { uint32 len_sam_name; - uint32 max_entries, max_data_size; - uint32 dsize = 0; uint32 i; - DEBUG(5, ("init_sam_dispinfo_5\n")); - + DOMAIN_GRP *grp; ZERO_STRUCTP(sam); - max_entries = *num_entries; - max_data_size = *data_size; + DEBUG(5, ("init_sam_dispinfo_5: num_entries: %d\n", num_entries)); - if (max_entries==0) + if (num_entries==0) return NT_STATUS_OK; - if (!(sam->sam=(SAM_ENTRY5 *)talloc(ctx, max_entries*sizeof(SAM_ENTRY5)))) + if (!(sam->sam=(SAM_ENTRY5 *)talloc(ctx, num_entries*sizeof(SAM_ENTRY5)))) return NT_STATUS_NO_MEMORY; - if (!(sam->str=(SAM_STR5 *)talloc(ctx, max_entries*sizeof(SAM_STR5)))) + if (!(sam->str=(SAM_STR5 *)talloc(ctx, num_entries*sizeof(SAM_STR5)))) return NT_STATUS_NO_MEMORY; ZERO_STRUCTP(sam->sam); ZERO_STRUCTP(sam->str); - for (i = 0; (i < max_entries) && (dsize < max_data_size); i++) { + for (i = 0; i < num_entries; i++) { + DEBUG(11, ("init_sam_dispinfo_5: entry: %d\n",i)); + grp=disp_group_info[i+start_idx].grp; + len_sam_name = strlen(grp[i].name); init_sam_entry5(&sam->sam[i], start_idx + i + 1, len_sam_name); init_string2(&sam->str[i].grp_name, grp[i].name, len_sam_name+1, len_sam_name); - - dsize += sizeof(SAM_ENTRY5); - dsize += len_sam_name; } - - *num_entries = i; - *data_size = dsize; return NT_STATUS_OK; } @@ -1941,8 +1905,6 @@ static BOOL sam_io_sam_dispinfo_5(char *desc, SAM_DISPINFO_5 * sam, if(!smb_io_string2("grp_name", &sam->str[i].grp_name, sam->sam[i].hdr_grp_name.buffer, ps, depth)) return False; - if(!prs_align(ps)) - return False; } return True; @@ -1953,16 +1915,13 @@ inits a SAMR_R_QUERY_DISPINFO structure. ********************************************************************/ void init_samr_r_query_dispinfo(SAMR_R_QUERY_DISPINFO * r_u, - uint32 num_entries, uint32 data_size, + uint32 num_entries, uint32 total_size, uint32 data_size, uint16 switch_level, SAM_DISPINFO_CTR * ctr, NTSTATUS status) { DEBUG(5, ("init_samr_r_query_dispinfo: level %d\n", switch_level)); - if (switch_level==4) - r_u->total_size = 0; /* not calculated */ - else - r_u->total_size = data_size; /* not calculated */ + r_u->total_size = total_size; r_u->data_size = data_size; @@ -2193,6 +2152,38 @@ BOOL samr_io_group_info1(char *desc, GROUP_INFO1 * gr1, } /******************************************************************* +inits a GROUP_INFO3 structure. +********************************************************************/ + +void init_samr_group_info3(GROUP_INFO3 *gr3) +{ + DEBUG(5, ("init_samr_group_info3\n")); + + gr3->unknown_1 = 0x3; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ + +BOOL samr_io_group_info3(char *desc, GROUP_INFO3 *gr3, prs_struct *ps, int depth) +{ + if (gr3 == NULL) + return False; + + prs_debug(ps, depth, desc, "samr_io_group_info3"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_uint32("unknown_1", ps, depth, &gr3->unknown_1)) + return False; + + return True; +} + +/******************************************************************* inits a GROUP_INFO4 structure. ********************************************************************/ @@ -2249,18 +2240,18 @@ static BOOL samr_group_info_ctr(char *desc, GROUP_INFO_CTR **ctr, if(!prs_uint16("switch_value1", ps, depth, &(*ctr)->switch_value1)) return False; - if(!prs_uint16("switch_value2", ps, depth, &(*ctr)->switch_value2)) - return False; switch ((*ctr)->switch_value1) { case 1: - if(!samr_io_group_info1("group_info1", - &(*ctr)->group.info1, ps, depth)) + if(!samr_io_group_info1("group_info1", &(*ctr)->group.info1, ps, depth)) + return False; + break; + case 3: + if(!samr_io_group_info3("group_info3", &(*ctr)->group.info3, ps, depth)) return False; break; case 4: - if(!samr_io_group_info4("group_info4", - &(*ctr)->group.info4, ps, depth)) + if(!samr_io_group_info4("group_info4", &(*ctr)->group.info4, ps, depth)) return False; break; default: @@ -2401,6 +2392,9 @@ BOOL samr_io_r_delete_dom_group(char *desc, SAMR_R_DELETE_DOM_GROUP * r_u, if(!prs_align(ps)) return False; + if(!smb_io_pol_hnd("pol", &r_u->pol, ps, depth)) + return False; + if(!prs_ntstatus("status", ps, depth, &r_u->status)) return False; @@ -3390,6 +3384,63 @@ BOOL samr_io_r_enum_dom_aliases(char *desc, SAMR_R_ENUM_DOM_ALIASES * r_u, } /******************************************************************* +inits a ALIAS_INFO1 structure. +********************************************************************/ + +void init_samr_alias_info1(ALIAS_INFO1 * al1, char *acct_name, uint32 num_member, char *acct_desc) +{ + int acct_len_name = acct_name != NULL ? strlen(acct_name) : 0; + int acct_len_desc = acct_desc != NULL ? strlen(acct_desc) : 0; + + DEBUG(5, ("init_samr_alias_info1\n")); + + init_uni_hdr(&al1->hdr_acct_name, acct_len_name); + init_unistr2(&al1->uni_acct_name, acct_name, acct_len_name); + + al1->num_member=num_member; + + init_uni_hdr(&al1->hdr_acct_desc, acct_len_desc); + init_unistr2(&al1->uni_acct_desc, acct_desc, acct_len_desc); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ + +BOOL samr_io_alias_info1(char *desc, ALIAS_INFO1 * al1, + prs_struct *ps, int depth) +{ + if (al1 == NULL) + return False; + + prs_debug(ps, depth, desc, "samr_io_alias_info1"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!smb_io_unihdr("hdr_acct_name", &al1->hdr_acct_name, ps, depth)) + return False; + if(!prs_uint32("num_member", ps, depth, &al1->num_member)) + return False; + if(!smb_io_unihdr("hdr_acct_desc", &al1->hdr_acct_desc, ps, depth)) + return False; + + if(!smb_io_unistr2("uni_acct_name", &al1->uni_acct_name, + al1->hdr_acct_name.buffer, ps, depth)) + return False; + + if(!prs_align(ps)) + return False; + + if(!smb_io_unistr2("uni_acct_desc", &al1->uni_acct_desc, + al1->hdr_acct_desc.buffer, ps, depth)) + return False; + + return True; +} + +/******************************************************************* inits a ALIAS_INFO3 structure. ********************************************************************/ @@ -3447,6 +3498,10 @@ BOOL samr_alias_info_ctr(char *desc, ALIAS_INFO_CTR * ctr, return False; switch (ctr->switch_value1) { + case 1: + if(!samr_io_alias_info1("alias_info1", &ctr->alias.info1, ps, depth)) + return False; + break; case 3: if(!samr_io_alias_info3("alias_info3", &ctr->alias.info3, ps, depth)) return False; @@ -4754,6 +4809,8 @@ BOOL samr_io_r_delete_dom_user(char *desc, SAMR_R_DELETE_DOM_USER * r_u, if(!prs_align(ps)) return False; + if(!smb_io_pol_hnd("pol", &r_u->pol, ps, depth)) + return False; if(!prs_ntstatus("status", ps, depth, &r_u->status)) return False; @@ -4834,7 +4891,7 @@ reads or writes a structure. void init_samr_q_create_user(SAMR_Q_CREATE_USER * q_u, POLICY_HND *pol, - char *name, + const char *name, uint32 acb_info, uint32 access_mask) { int len_name; diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c index 20f9b5ca01e..2090e65296e 100644 --- a/source/rpc_server/srv_samr_nt.c +++ b/source/rpc_server/srv_samr_nt.c @@ -7,6 +7,7 @@ * Copyright (C) Paul Ashton 1997. * Copyright (C) Marc Jacobsen 1999. * Copyright (C) Jeremy Allison 2001. + * Copyright (C) Jean François Micouleau 1998-2001. * * 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 @@ -38,18 +39,61 @@ extern rid_name domain_group_rids[]; extern rid_name domain_alias_rids[]; extern rid_name builtin_alias_rids[]; +typedef struct _disp_info { + BOOL user_dbloaded; + BOOL group_dbloaded; + uint32 num_account; + uint32 total_size; + uint32 last_enum; + DISP_USER_INFO *disp_user_info; + DISP_GROUP_INFO *disp_group_info; +} DISP_INFO; + struct samr_info { - /* for use by the \PIPE\samr policy */ - DOM_SID sid; - uint32 status; /* some sort of flag. best to record it. comes from opnum 0x39 */ + /* for use by the \PIPE\samr policy */ + DOM_SID sid; + uint32 status; /* some sort of flag. best to record it. comes from opnum 0x39 */ + DISP_INFO disp_info; }; /******************************************************************* Function to free the per handle data. ********************************************************************/ +static void free_samr_db(struct samr_info *info) +{ + int i; + + if (info->disp_info.group_dbloaded) { + for (i=0; i<info->disp_info.num_account; i++) + SAFE_FREE(info->disp_info.disp_group_info[i].grp); + + SAFE_FREE(info->disp_info.disp_group_info); + } + + if (info->disp_info.user_dbloaded){ + for (i=0; i<info->disp_info.num_account; i++) + pdb_free_sam(info->disp_info.disp_user_info[i].sam); + + SAFE_FREE(info->disp_info.disp_user_info); + } + + info->disp_info.user_dbloaded=False; + info->disp_info.group_dbloaded=False; + info->disp_info.num_account=0; + info->disp_info.total_size=0; + info->disp_info.last_enum=0; +} + +/******************************************************************* + Function to free the per handle data. + ********************************************************************/ + static void free_samr_info(void *ptr) { + struct samr_info *info=(struct samr_info *) ptr; + + free_samr_db(info); SAFE_FREE(ptr); } @@ -79,6 +123,155 @@ static void samr_clear_sam_passwd(SAM_ACCOUNT *sam_pass) if (sam_pass->nt_pw) memset(sam_pass->nt_pw, '\0', 16); } +static NTSTATUS load_sampwd_entries(struct samr_info *info, uint16 acb_mask) +{ + SAM_ACCOUNT *pwd = NULL; + DISP_USER_INFO *pwd_array = NULL; + + DEBUG(10,("load_sampwd_entries\n")); + + /* if the snapshoot is already loaded, return */ + if (info->disp_info.user_dbloaded==True) { + DEBUG(10,("load_sampwd_entries: already in memory\n")); + return NT_STATUS_OK; + } + + if (!pdb_setsampwent(False)) { + DEBUG(0, ("load_sampwd_entries: Unable to open passdb.\n")); + return NT_STATUS_ACCESS_DENIED; + } + + for (pdb_init_sam(&pwd); pdb_getsampwent(pwd) == True; pwd=NULL, pdb_init_sam(&pwd) ) { + + if (acb_mask != 0 && !(pwd->acct_ctrl & acb_mask)) { + pdb_free_sam(pwd); + DEBUG(5,(" acb_mask %x reject\n", acb_mask)); + continue; + } + + /* Realloc some memory for the array of ptr to the SAM_ACCOUNT structs */ + if (info->disp_info.num_account % MAX_SAM_ENTRIES == 0) { + + DEBUG(10,("load_sampwd_entries: allocating more memory\n")); + pwd_array=(DISP_USER_INFO *)Realloc(info->disp_info.disp_user_info, + (info->disp_info.num_account+MAX_SAM_ENTRIES)*sizeof(DISP_USER_INFO)); + + if (pwd_array==NULL) + return NT_STATUS_NO_MEMORY; + + info->disp_info.disp_user_info=pwd_array; + } + + /* link the SAM_ACCOUNT to the array */ + info->disp_info.disp_user_info[info->disp_info.num_account].sam=pwd; + + DEBUG(10,("load_sampwd_entries: entry: %d\n", info->disp_info.num_account)); + + info->disp_info.num_account++; + } + + pdb_endsampwent(); + + /* the snapshoot is in memory, we're ready to enumerate fast */ + + info->disp_info.user_dbloaded=True; + info->disp_info.last_enum=0; + + DEBUG(12,("load_sampwd_entries: done\n")); + + return NT_STATUS_OK; +} + +/* + * This is a really ugly hack to make this interface work in the 2.2.x code. JRA. + */ + +static int setup_fake_group_map(GROUP_MAP **ret_map) +{ + static GROUP_MAP map[2]; + static BOOL group_map_init; + extern DOM_SID global_sam_sid; + + if (group_map_init) { + *ret_map = &map[0]; + return sizeof(map)/sizeof(GROUP_MAP); + } + + group_map_init = True; + + map[0].gid = (gid_t)-1; + sid_copy(&map[0].sid, &global_sam_sid); + sid_append_rid(&map[1].sid, DOMAIN_GROUP_RID_ADMINS); + map[0].sid_name_use = SID_NAME_DOM_GRP; + fstrcpy(map[0].nt_name, "Domain Admins"); + fstrcpy(map[0].comment, "Administrators for the domain"); + map[0].privilege = 0; + + map[1].gid = (gid_t)-1; + sid_copy(&map[1].sid, &global_sam_sid); + sid_append_rid(&map[1].sid, DOMAIN_GROUP_RID_USERS); + map[1].sid_name_use = SID_NAME_DOM_GRP; + fstrcpy(map[1].nt_name, "Domain Users"); + fstrcpy(map[1].comment, "Users in the domain"); + map[1].privilege = 0; + + *ret_map = &map[0]; + return sizeof(map)/sizeof(GROUP_MAP); +} + +static NTSTATUS load_group_domain_entries(struct samr_info *info, DOM_SID *sid) +{ + GROUP_MAP *map; + DISP_GROUP_INFO *grp_array = NULL; + uint32 group_entries = 0; + uint32 i; + + DEBUG(10,("load_group_domain_entries\n")); + + /* if the snapshoot is already loaded, return */ + if (info->disp_info.group_dbloaded==True) { + DEBUG(10,("load_group_domain_entries: already in memory\n")); + return NT_STATUS_OK; + } + + /* + * This is a really ugly hack to make this interface work in the 2.2.x code. JRA. + */ + + group_entries = setup_fake_group_map(&map); + + info->disp_info.num_account=group_entries; + + grp_array=(DISP_GROUP_INFO *)malloc(info->disp_info.num_account*sizeof(DISP_GROUP_INFO)); + + if (group_entries!=0 && grp_array==NULL) { + return NT_STATUS_NO_MEMORY; + } + + info->disp_info.disp_group_info=grp_array; + + for (i=0; i<group_entries; i++) { + + grp_array[i].grp=(DOMAIN_GRP *)malloc(sizeof(DOMAIN_GRP)); + + fstrcpy(grp_array[i].grp->name, map[i].nt_name); + fstrcpy(grp_array[i].grp->comment, map[i].comment); + sid_split_rid(&map[i].sid, &grp_array[i].grp->rid); + grp_array[i].grp->attr=SID_NAME_DOM_GRP; + } + + SAFE_FREE(map); + + /* the snapshoot is in memory, we're ready to enumerate fast */ + + info->disp_info.group_dbloaded=True; + info->disp_info.last_enum=0; + + DEBUG(12,("load_group_domain_entries: done\n")); + + return NT_STATUS_OK; +} + /******************************************************************* This next function should be replaced with something that dynamically returns the correct user info..... JRA. @@ -90,7 +283,7 @@ static NTSTATUS get_sampwd_entries(SAM_USER_INFO_21 *pw_buf, int start_idx, { SAM_ACCOUNT *pwd = NULL; BOOL not_finished = True; - + (*num_entries) = 0; (*total_entries) = 0; @@ -104,45 +297,50 @@ static NTSTATUS get_sampwd_entries(SAM_USER_INFO_21 *pw_buf, int start_idx, pdb_free_sam(pwd); return NT_STATUS_ACCESS_DENIED; } - + while (((not_finished = pdb_getsampwent(pwd)) != False) - && (*num_entries) < max_num_entries) + && (*num_entries) < max_num_entries) { - int user_name_len; + int user_name_len; + + if (start_idx > 0) { - if (start_idx > 0) { - /* skip the requested number of entries. - not very efficient, but hey... */ pdb_reset_sam(pwd); + + /* skip the requested number of entries. + not very efficient, but hey... */ start_idx--; continue; - } - + } + user_name_len = strlen(pdb_get_username(pwd))+1; init_unistr2(&pw_buf[(*num_entries)].uni_user_name, pdb_get_username(pwd), user_name_len); init_uni_hdr(&pw_buf[(*num_entries)].hdr_user_name, user_name_len); pw_buf[(*num_entries)].user_rid = pwd->user_rid; memset((char *)pw_buf[(*num_entries)].nt_pwd, '\0', 16); - + /* Now check if the NT compatible password is available. */ if (pdb_get_nt_passwd(pwd)) memcpy( pw_buf[(*num_entries)].nt_pwd , pdb_get_nt_passwd(pwd), 16); - + pw_buf[(*num_entries)].acb_info = pdb_get_acct_ctrl(pwd); - + DEBUG(5, ("entry idx: %d user %s, rid 0x%x, acb %x", - (*num_entries), pdb_get_username(pwd), pdb_get_user_rid(pwd), pdb_get_acct_ctrl(pwd) )); - + (*num_entries), pdb_get_username(pwd), pdb_get_user_rid(pwd), pdb_get_acct_ctrl(pwd) )); + if (acb_mask == 0 || (pwd->acct_ctrl & acb_mask)) { DEBUG(5,(" acb_mask %x accepts\n", acb_mask)); (*num_entries)++; - } else + } else { DEBUG(5,(" acb_mask %x rejects\n", acb_mask)); + } (*total_entries)++; + pdb_reset_sam(pwd); - } + } + pdb_endsampwent(); pdb_free_sam(pwd); @@ -152,6 +350,7 @@ static NTSTATUS get_sampwd_entries(SAM_USER_INFO_21 *pw_buf, int start_idx, return NT_STATUS_OK; } +#if 0 static NTSTATUS jf_get_sampwd_entries(SAM_USER_INFO_21 *pw_buf, int start_idx, int *total_entries, uint32 *num_entries, int max_num_entries, uint16 acb_mask) @@ -231,259 +430,6 @@ static NTSTATUS jf_get_sampwd_entries(SAM_USER_INFO_21 *pw_buf, int start_idx, else return NT_STATUS_OK; } - -/* - * These next two functions are not used. Tagged - * for deletion - */ - -#if 0 -/******************************************************************* - This function uses the username map file and tries to map a UNIX - user name to an DOS name. (Sort of the reverse of the - map_username() function.) Since more than one DOS name can map - to the UNIX name, to reverse the mapping you have to specify - which corresponding DOS name you want; that's where the name_idx - parameter comes in. Returns the string requested or NULL if it - fails or can't complete the request for any reason. This doesn't - handle group names (starting with '@') or names starting with - '+' or '&'. If they are encountered, they are skipped. -********************************************************************/ - -static char *unmap_unixname(char *unix_user_name, int name_idx) -{ - char *mapfile = lp_username_map(); - char **lines; - static pstring tok; - int i; - - if (!*unix_user_name) return NULL; - if (!*mapfile) return NULL; - - lines = file_lines_load(mapfile, NULL,False); - if (!lines) { - DEBUG(0,("unmap_unixname: can't open username map %s\n", mapfile)); - return NULL; - } - - DEBUG(5,("unmap_unixname: scanning username map %s, index: %d\n", mapfile, name_idx)); - - for (i=0; lines[i]; i++) { - char *unixname = lines[i]; - char *dosname = strchr(unixname,'='); - - if (!dosname) - continue; - - *dosname++ = 0; - - while (isspace(*unixname)) - unixname++; - if ('!' == *unixname) { - unixname++; - while (*unixname && isspace(*unixname)) - unixname++; - } - - if (!*unixname || strchr("#;",*unixname)) - continue; - - if (strncmp(unixname, unix_user_name, strlen(unix_user_name))) - continue; - - /* We have matched the UNIX user name */ - - while(next_token(&dosname, tok, LIST_SEP, sizeof(tok))) { - if (!strchr("@&+", *tok)) { - name_idx--; - if (name_idx < 0 ) { - break; - } - } - } - - if (name_idx >= 0) { - DEBUG(0,("unmap_unixname: index too high - not that many DOS names\n")); - file_lines_free(lines); - return NULL; - } else { - file_lines_free(lines); - return tok; - } - } - - DEBUG(0,("unmap_unixname: Couldn't find the UNIX user name\n")); - file_lines_free(lines); - return NULL; -} - -/******************************************************************* - This function sets up a list of users taken from the list of - users that UNIX knows about, as well as all the user names that - Samba maps to a valid UNIX user name. (This should work with - /etc/passwd or NIS.) -********************************************************************/ - -static BOOL get_passwd_entries(SAM_USER_INFO_21 *pw_buf, - int start_idx, - int *total_entries, int *num_entries, - int max_num_entries, - uint16 acb_mask) -{ - static struct passwd *pwd = NULL; - static uint32 pw_rid; - static BOOL orig_done = False; - static int current_idx = 0; - static int mapped_idx = 0; - char *sep; - - DEBUG(5, ("get_passwd_entries: retrieving a list of UNIX users\n")); - - (*num_entries) = 0; - (*total_entries) = 0; - - /* Skip all this stuff if we're in appliance mode */ - - if (lp_hide_local_users()) goto done; - - if (pw_buf == NULL) return False; - - if (current_idx == 0) { - sys_setpwent(); - } - - /* These two cases are inefficient, but should be called very rarely */ - /* they are the cases where the starting index isn't picking up */ - /* where we left off last time. It is efficient when it starts over */ - /* at zero though. */ - if (start_idx > current_idx) { - /* We aren't far enough; advance to start_idx */ - while (current_idx <= start_idx) { - char *unmap_name; - - if(!orig_done) { - if ((pwd = sys_getpwent()) == NULL) break; - current_idx++; - orig_done = True; - } - - while (((unmap_name = unmap_unixname(pwd->pw_name, mapped_idx)) != NULL) && - (current_idx < start_idx)) { - current_idx++; - mapped_idx++; - } - - if (unmap_name == NULL) { - orig_done = False; - mapped_idx = 0; - } - } - } else if (start_idx < current_idx) { - /* We are already too far; start over and advance to start_idx */ - sys_endpwent(); - sys_setpwent(); - current_idx = 0; - mapped_idx = 0; - orig_done = False; - while (current_idx < start_idx) { - char *unmap_name; - - if(!orig_done) { - if ((pwd = sys_getpwent()) == NULL) break; - current_idx++; - orig_done = True; - } - - while (((unmap_name = unmap_unixname(pwd->pw_name, mapped_idx)) != NULL) && - (current_idx < start_idx)) { - current_idx++; - mapped_idx++; - } - - if (unmap_name == NULL) { - orig_done = False; - mapped_idx = 0; - } - } - } - - sep = lp_winbind_separator(); - - /* now current_idx == start_idx */ - while ((*num_entries) < max_num_entries) { - int user_name_len; - char *unmap_name; - - /* This does the original UNIX user itself */ - if(!orig_done) { - if ((pwd = sys_getpwent()) == NULL) break; - - /* Don't enumerate winbind users as they are not local */ - - if (strchr(pwd->pw_name, *sep) != NULL) { - continue; - } - - user_name_len = strlen(pwd->pw_name); - - /* skip the trust account stored in the /etc/passwd file */ - if (pwd->pw_name[user_name_len-1]=='$') - continue; - - pw_rid = pdb_uid_to_user_rid(pwd->pw_uid); - ZERO_STRUCTP(&pw_buf[(*num_entries)]); - init_unistr2(&pw_buf[(*num_entries)].uni_user_name, pwd->pw_name, user_name_len); - init_uni_hdr(&pw_buf[(*num_entries)].hdr_user_name, user_name_len); - pw_buf[(*num_entries)].user_rid = pw_rid; - memset((char *)pw_buf[(*num_entries)].nt_pwd, '\0', 16); - - pw_buf[(*num_entries)].acb_info = ACB_NORMAL; - - DEBUG(5, ("get_passwd_entries: entry idx %d user %s, rid 0x%x\n", (*num_entries), pwd->pw_name, pw_rid)); - - (*num_entries)++; - (*total_entries)++; - current_idx++; - orig_done = True; - } - - /* This does all the user names that map to the UNIX user */ - while (((unmap_name = unmap_unixname(pwd->pw_name, mapped_idx)) != NULL) && - (*num_entries < max_num_entries)) { - user_name_len = strlen(unmap_name); - ZERO_STRUCTP(&pw_buf[(*num_entries)]); - init_unistr2(&pw_buf[(*num_entries)].uni_user_name, unmap_name, user_name_len); - init_uni_hdr(&pw_buf[(*num_entries)].hdr_user_name, user_name_len); - pw_buf[(*num_entries)].user_rid = pw_rid; - memset((char *)pw_buf[(*num_entries)].nt_pwd, '\0', 16); - - pw_buf[(*num_entries)].acb_info = ACB_NORMAL; - - DEBUG(5, ("get_passwd_entries: entry idx %d user %s, rid 0x%x\n", (*num_entries), pwd->pw_name, pw_rid)); - - (*num_entries)++; - (*total_entries)++; - current_idx++; - mapped_idx++; - } - - if (unmap_name == NULL) { - /* done with 'aliases', go on to next UNIX user */ - orig_done = False; - mapped_idx = 0; - } - } - - if (pwd == NULL) { - /* totally done, reset everything */ - sys_endpwent(); - current_idx = 0; - mapped_idx = 0; - } - -done: - return (*num_entries) > 0; -} #endif /******************************************************************* @@ -984,85 +930,116 @@ NTSTATUS _samr_enum_dom_aliases(pipes_struct *p, SAMR_Q_ENUM_DOM_ALIASES *q_u, S /******************************************************************* samr_reply_query_dispinfo ********************************************************************/ - NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_R_QUERY_DISPINFO *r_u) { - SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]; - DOMAIN_GRP grps[MAX_SAM_ENTRIES]; - uint16 acb_mask = ACB_NORMAL; - uint32 num_entries = 0; - int orig_num_entries = 0; - int total_entries = 0; - uint32 data_size = 0; - DOM_SID sid; - NTSTATUS disp_ret; + struct samr_info *info = NULL; + uint32 struct_size=0x20; /* W2K always reply that, client doesn't care */ + uint16 acb_mask; + + 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 temp_size=0, total_data_size=0; + NTSTATUS disp_ret; DEBUG(5, ("samr_reply_query_dispinfo: %d\n", __LINE__)); - r_u->status = NT_STATUS_OK; - if (!get_lsa_policy_samr_sid(p, &q_u->domain_pol, &sid)) + /* find the policy handle. open a policy on it. */ + if (!find_policy_by_hnd(p, &q_u->domain_pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; - /* decide how many entries to get depending on the max_entries - and max_size passed by client */ + /* + * calculate how many entries we will return. + * based on + * - the number of entries the client asked + * - our limit on that + * - the starting point (enumeration context) + * - the buffer size the client will accept + */ + + /* + * We are a lot more like W2K. Instead of reading the SAM + * each time to find the records we need to send back, + * we read it once and link that copy to the sam handle. + * For large user list (over the MAX_SAM_ENTRIES) + * it's a definitive win. + * second point to notice: between enumerations + * our sam is now the same as it's a snapshoot. + * third point: got rid of the static SAM_USER_21 struct + * no more intermediate. + * con: it uses much more memory, as a full copy is stored + * in memory. + * + * If you want to change it, think twice and think + * of the second point , that's really important. + * + * JFM, 12/20/2001 + */ + + /* Get what we need from the password database */ - if(q_u->max_entries > MAX_SAM_ENTRIES) - q_u->max_entries = MAX_SAM_ENTRIES; + if (q_u->switch_level==2) + acb_mask = ACB_WSTRUST; + else + acb_mask = ACB_NORMAL; /* Get what we need from the password database */ switch (q_u->switch_level) { - case 0x2: - acb_mask = ACB_WSTRUST; - /* Fall through */ - case 0x1: - case 0x4: - become_root(); -#if 0 - r_u->status = get_passwd_entries(pass, q_u->start_idx, &total_entries, &num_entries, - MAX_SAM_ENTRIES, acb_mask); -#endif -#if 0 - /* - * Which should we use here ? JRA. - */ - r_u->status = get_sampwd_entries(pass, q_u->start_idx, &total_entries, &num_entries, - MAX_SAM_ENTRIES, acb_mask); -#endif -#if 1 - r_u->status = jf_get_sampwd_entries(pass, q_u->start_idx, &total_entries, &num_entries, - MAX_SAM_ENTRIES, acb_mask); -#endif - unbecome_root(); - if (NT_STATUS_IS_ERR(r_u->status)) { - DEBUG(5, ("get_sampwd_entries: failed\n")); - return r_u->status; - } - break; - case 0x3: - case 0x5: - r_u->status = get_group_domain_entries(grps, &sid, q_u->start_idx, &num_entries, MAX_SAM_ENTRIES); - break; - default: - DEBUG(0,("_samr_query_dispinfo: Unknown info level (%u)\n", (unsigned int)q_u->switch_level )); - return NT_STATUS_INVALID_INFO_CLASS; + case 0x1: + case 0x2: + case 0x4: + if (enum_context!=0 && info->disp_info.user_dbloaded==False) + return NT_STATUS_UNSUCCESSFUL; + + become_root(); + r_u->status=load_sampwd_entries(info, acb_mask); + unbecome_root(); + if (NT_STATUS_IS_ERR(r_u->status)) { + DEBUG(5, ("_samr_query_dispinfo: load_sampwd_entries failed\n")); + return r_u->status; + } + break; + case 0x3: + case 0x5: + if (enum_context!=0 && info->disp_info.group_dbloaded==False) + return NT_STATUS_UNSUCCESSFUL; + + r_u->status = load_group_domain_entries(info, &info->sid); + if (NT_STATUS_IS_ERR(r_u->status)) + return r_u->status; + break; + default: + DEBUG(0,("_samr_query_dispinfo: Unknown info level (%u)\n", (unsigned int)q_u->switch_level )); + return NT_STATUS_INVALID_INFO_CLASS; } - orig_num_entries = num_entries; - - if (num_entries > q_u->max_entries) - num_entries = q_u->max_entries; + /* first limit the number of entries we will return */ + if(max_entries > MAX_SAM_ENTRIES) { + DEBUG(5, ("samr_reply_query_dispinfo: client requested %d entries, limiting to %d\n", max_entries, MAX_SAM_ENTRIES)); + max_entries = MAX_SAM_ENTRIES; + } - if (num_entries > MAX_SAM_ENTRIES) { - num_entries = MAX_SAM_ENTRIES; - DEBUG(5, ("limiting number of entries to %d\n", num_entries)); + if (enum_context > info->disp_info.num_account) { + DEBUG(5, ("samr_reply_query_dispinfo: enumeration handle over total entries\n")); + return NT_STATUS_OK; } - /* Ensure password info is never given out here. PARANOIA... JRA */ - samr_clear_passwd_fields(pass, num_entries); + /* verify we won't overflow */ + if (max_entries > info->disp_info.num_account-enum_context) { + max_entries = info->disp_info.num_account-enum_context; + DEBUG(5, ("samr_reply_query_dispinfo: only %d entries to return\n", max_entries)); + } - data_size = q_u->max_size; + /* calculate the size and limit on the number of entries we will return */ + temp_size=(enum_context+max_entries)*struct_size; + + if (temp_size>max_size) { + max_entries=max_size/struct_size; + DEBUG(5, ("samr_reply_query_dispinfo: buffer size limits to only %d entries\n", max_entries)); + } if (!(ctr = (SAM_DISPINFO_CTR *)talloc_zero(p->mem_ctx,sizeof(SAM_DISPINFO_CTR)))) return NT_STATUS_NO_MEMORY; @@ -1072,63 +1049,68 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_ /* Now create reply structure */ switch (q_u->switch_level) { case 0x1: - if (num_entries) { - if (!(ctr->sam.info1 = (SAM_DISPINFO_1 *)talloc_zero(p->mem_ctx,num_entries*sizeof(SAM_DISPINFO_1)))) + if (max_entries) { + if (!(ctr->sam.info1 = (SAM_DISPINFO_1 *)talloc_zero(p->mem_ctx,max_entries*sizeof(SAM_DISPINFO_1)))) return NT_STATUS_NO_MEMORY; } - disp_ret = init_sam_dispinfo_1(p->mem_ctx,ctr->sam.info1, &num_entries, &data_size, q_u->start_idx, pass); + disp_ret = init_sam_dispinfo_1(p->mem_ctx, ctr->sam.info1, max_entries, enum_context, info->disp_info.disp_user_info); if (NT_STATUS_IS_ERR(disp_ret)) return disp_ret; break; case 0x2: - if (num_entries) { - if (!(ctr->sam.info2 = (SAM_DISPINFO_2 *)talloc_zero(p->mem_ctx,num_entries*sizeof(SAM_DISPINFO_2)))) + if (max_entries) { + if (!(ctr->sam.info2 = (SAM_DISPINFO_2 *)talloc_zero(p->mem_ctx,max_entries*sizeof(SAM_DISPINFO_2)))) return NT_STATUS_NO_MEMORY; } - disp_ret = init_sam_dispinfo_2(p->mem_ctx,ctr->sam.info2, &num_entries, &data_size, q_u->start_idx, pass); + disp_ret = init_sam_dispinfo_2(p->mem_ctx, ctr->sam.info2, max_entries, enum_context, info->disp_info.disp_user_info); if (NT_STATUS_IS_ERR(disp_ret)) return disp_ret; break; case 0x3: - if (num_entries) { - if (!(ctr->sam.info3 = (SAM_DISPINFO_3 *)talloc_zero(p->mem_ctx,num_entries*sizeof(SAM_DISPINFO_3)))) + if (max_entries) { + if (!(ctr->sam.info3 = (SAM_DISPINFO_3 *)talloc_zero(p->mem_ctx,max_entries*sizeof(SAM_DISPINFO_3)))) return NT_STATUS_NO_MEMORY; } - disp_ret = init_sam_dispinfo_3(p->mem_ctx,ctr->sam.info3, &num_entries, &data_size, q_u->start_idx, grps); + disp_ret = init_sam_dispinfo_3(p->mem_ctx, ctr->sam.info3, max_entries, enum_context, info->disp_info.disp_group_info); if (NT_STATUS_IS_ERR(disp_ret)) return disp_ret; break; case 0x4: - if (num_entries) { - if (!(ctr->sam.info4 = (SAM_DISPINFO_4 *)talloc_zero(p->mem_ctx,num_entries*sizeof(SAM_DISPINFO_4)))) + if (max_entries) { + if (!(ctr->sam.info4 = (SAM_DISPINFO_4 *)talloc_zero(p->mem_ctx,max_entries*sizeof(SAM_DISPINFO_4)))) return NT_STATUS_NO_MEMORY; } - disp_ret = init_sam_dispinfo_4(p->mem_ctx,ctr->sam.info4, &num_entries, &data_size, q_u->start_idx, pass); + disp_ret = init_sam_dispinfo_4(p->mem_ctx, ctr->sam.info4, max_entries, enum_context, info->disp_info.disp_user_info); if (NT_STATUS_IS_ERR(disp_ret)) return disp_ret; break; case 0x5: - if (num_entries) { - if (!(ctr->sam.info5 = (SAM_DISPINFO_5 *)talloc_zero(p->mem_ctx,num_entries*sizeof(SAM_DISPINFO_5)))) + if (max_entries) { + if (!(ctr->sam.info5 = (SAM_DISPINFO_5 *)talloc_zero(p->mem_ctx,max_entries*sizeof(SAM_DISPINFO_5)))) return NT_STATUS_NO_MEMORY; } - disp_ret = init_sam_dispinfo_5(p->mem_ctx,ctr->sam.info5, &num_entries, &data_size, q_u->start_idx, grps); + disp_ret = init_sam_dispinfo_5(p->mem_ctx, ctr->sam.info5, max_entries, enum_context, info->disp_info.disp_group_info); if (NT_STATUS_IS_ERR(disp_ret)) return disp_ret; break; + default: ctr->sam.info = NULL; return NT_STATUS_INVALID_INFO_CLASS; } - DEBUG(5, ("_samr_query_dispinfo: %d\n", __LINE__)); + /* calculate the total size */ + total_data_size=info->disp_info.num_account*struct_size; - if (num_entries < orig_num_entries) - return STATUS_MORE_ENTRIES; + if (enum_context+max_entries < info->disp_info.num_account) + r_u->status = STATUS_MORE_ENTRIES; - init_samr_r_query_dispinfo(r_u, num_entries, data_size, q_u->switch_level, ctr, r_u->status); + DEBUG(5, ("_samr_query_dispinfo: %d\n", __LINE__)); + + init_samr_r_query_dispinfo(r_u, max_entries, total_data_size, temp_size, q_u->switch_level, ctr, r_u->status); return r_u->status; + } /******************************************************************* @@ -1829,53 +1811,107 @@ NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, S NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SAMR_R_QUERY_DOMAIN_INFO *r_u) { - SAM_UNK_CTR *ctr; + struct samr_info *info = NULL; + SAM_UNK_CTR *ctr; + uint32 min_pass_len,pass_hist,flag; + time_t u_expire, u_min_age; + NTTIME nt_expire, nt_min_age; + + time_t u_lock_duration, u_reset_time; + NTTIME nt_lock_duration, nt_reset_time; + uint32 lockout; + + time_t u_logout; + NTTIME nt_logout; + + uint32 num_users=0, num_groups=0, num_aliases=0; if ((ctr = (SAM_UNK_CTR *)talloc_zero(p->mem_ctx, sizeof(SAM_UNK_CTR))) == NULL) return NT_STATUS_NO_MEMORY; - ZERO_STRUCTP(ctr); + ZERO_STRUCTP(ctr); - r_u->status = NT_STATUS_OK; + r_u->status = NT_STATUS_OK; - DEBUG(5,("_samr_query_dom_info: %d\n", __LINE__)); + DEBUG(5,("_samr_query_dom_info: %d\n", __LINE__)); - /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, &q_u->domain_pol, NULL)) - return NT_STATUS_INVALID_HANDLE; + /* find the policy handle. open a policy on it. */ + if (!find_policy_by_hnd(p, &q_u->domain_pol, (void **)&info)) + return NT_STATUS_INVALID_HANDLE; - switch (q_u->switch_value) { - case 0x01: - init_unk_info1(&ctr->info.inf1); - break; - case 0x02: + switch (q_u->switch_value) { + case 0x01: + /* Use defaults until we merge with HEAD db. JRA */ + min_pass_len = MINPASSWDLENGTH; /* 5 chars minimum */ + pass_hist = 0; /* don't keep any old password */ + flag = 0; /* don't force user to logon */ + u_expire = MAX_PASSWORD_AGE; /* 21 days */ + u_min_age = 0; /* 0 days */ + + 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, + flag, nt_expire, nt_min_age); + break; + case 0x02: + become_root(); + r_u->status=load_sampwd_entries(info, ACB_NORMAL); + unbecome_root(); + if (NT_STATUS_IS_ERR(r_u->status)) { + DEBUG(5, ("_samr_query_dispinfo: load_sampwd_entries failed\n")); + return r_u->status; + } + num_users=info->disp_info.num_account; + free_samr_db(info); + + r_u->status=load_group_domain_entries(info, &global_sam_sid); + if (NT_STATUS_IS_ERR(r_u->status)) { + DEBUG(5, ("_samr_query_dispinfo: load_group_domain_entries failed\n")); + return r_u->status; + } + num_groups=info->disp_info.num_account; + free_samr_db(info); + /* The time call below is to get a sequence number for the sam. FIXME !!! JRA. */ - init_unk_info2(&ctr->info.inf2, global_myworkgroup, global_myname, (uint32) time(NULL)); - break; - case 0x03: - init_unk_info3(&ctr->info.inf3); - break; - case 0x05: - init_unk_info5(&ctr->info.inf5, global_myname); - break; - case 0x06: - init_unk_info6(&ctr->info.inf6); - break; - case 0x07: - init_unk_info7(&ctr->info.inf7); - break; - case 0x0c: - init_unk_info12(&ctr->info.inf12); - break; - default: - return NT_STATUS_INVALID_INFO_CLASS; - } + init_unk_info2(&ctr->info.inf2, global_myworkgroup, global_myname, (uint32) time(NULL), + num_users, num_groups, num_aliases); + break; + case 0x03: + /* Use defaults until we merge with HEAD db. JRA */ + u_logout = -1; /* don't force logout */ + unix_to_nt_time_abs(&nt_logout, u_logout); + init_unk_info3(&ctr->info.inf3, nt_logout); + break; + case 0x05: + init_unk_info5(&ctr->info.inf5, global_myname); + break; + case 0x06: + init_unk_info6(&ctr->info.inf6); + break; + case 0x07: + init_unk_info7(&ctr->info.inf7); + break; + case 0x0c: + /* Use defaults until we merge with HEAD db. JRA */ + u_lock_duration = 0; /* lockout for 0 minutes */ + u_reset_time = 0; /* reset immediatly */ + lockout = 0; /* don't lockout */ + + 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); + break; + default: + return NT_STATUS_INVALID_INFO_CLASS; + } - init_samr_r_query_dom_info(r_u, q_u->switch_value, ctr, NT_STATUS_OK); + init_samr_r_query_dom_info(r_u, q_u->switch_value, ctr, NT_STATUS_OK); - DEBUG(5,("_samr_query_dom_info: %d\n", __LINE__)); + DEBUG(5,("_samr_query_dom_info: %d\n", __LINE__)); - return r_u->status; + return r_u->status; } /******************************************************************* |