summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2001-12-22 00:16:37 +0000
committerJeremy Allison <jra@samba.org>2001-12-22 00:16:37 +0000
commitf2ba4343e416b2e66bda087a3626be9e16368c56 (patch)
treea4f38a35b8796d6218eb9beb117f28fd96d8bf19
parentde33a4a7784f30d61545f21b5ff57b13bc037c98 (diff)
downloadsamba-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.h52
-rw-r--r--source/include/rpc_samr.h38
-rw-r--r--source/lib/time.c126
-rw-r--r--source/rpc_parse/parse_misc.c2
-rw-r--r--source/rpc_parse/parse_samr.c375
-rw-r--r--source/rpc_server/srv_samr_nt.c808
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;
}
/*******************************************************************