summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-François Micouleau <jfm@samba.org>2001-12-21 13:36:14 +0000
committerJean-François Micouleau <jfm@samba.org>2001-12-21 13:36:14 +0000
commit595dd015071395bae2ffc61573c72bb9f6a77553 (patch)
tree6fa327b36d54f95299518fd3348f6a722df627c6
parent28eb6b91b22ecfebeb42c1f97dbda94764359923 (diff)
downloadsamba-595dd015071395bae2ffc61573c72bb9f6a77553.tar.gz
samba-595dd015071395bae2ffc61573c72bb9f6a77553.tar.bz2
samba-595dd015071395bae2ffc61573c72bb9f6a77553.zip
re-done all of samr_query_disp_info()
instead of enumerating the whole user db or group db every time, we store a in memory copy linked to the handle. that's much faster for large enumeration where the db can't fit in a single rpc packet. And as it's a copy, it's constant between enumeration. still some stuff to clean. But now I can fix the W95 userlist bug, as I've finally found it. J.F. (This used to be commit 3ab45215369e8e93d750f4687e9c1f7d47782590)
-rw-r--r--source3/include/rpc_samr.h12
-rw-r--r--source3/rpc_parse/parse_samr.c201
-rw-r--r--source3/rpc_server/srv_samr_nt.c396
3 files changed, 396 insertions, 213 deletions
diff --git a/source3/include/rpc_samr.h b/source3/include/rpc_samr.h
index 43ee342ed3..777dfa1e46 100644
--- a/source3/include/rpc_samr.h
+++ b/source3/include/rpc_samr.h
@@ -146,6 +146,16 @@ SamrTestPrivateFunctionsUser
#define SAMR_SET_USERINFO 0x3A
+typedef struct _DISP_USER_INFO {
+ SAM_ACCOUNT *sam;
+ uint32 size;
+} DISP_USER_INFO;
+
+typedef struct _DISP_GROUP_INFO {
+ DOMAIN_GRP *grp;
+ uint32 size;
+} DISP_GROUP_INFO;
+
typedef struct logon_hours_info
{
@@ -788,7 +798,6 @@ typedef struct samr_entry_info1
uint32 rid_user;
uint16 acb_info;
- uint16 pad;
UNIHDR hdr_acct_name;
UNIHDR hdr_user_name;
@@ -820,7 +829,6 @@ typedef struct samr_entry_info2
uint32 rid_user;
uint16 acb_info;
- uint16 pad;
UNIHDR hdr_srv_name;
UNIHDR hdr_srv_desc;
diff --git a/source3/rpc_parse/parse_samr.c b/source3/rpc_parse/parse_samr.c
index bfca495893..fdc2d560e1 100644
--- a/source3/rpc_parse/parse_samr.c
+++ b/source3/rpc_parse/parse_samr.c
@@ -934,7 +934,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);
@@ -964,7 +963,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))
@@ -1013,7 +1013,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);
@@ -1042,7 +1041,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 */
@@ -1436,62 +1436,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;
}
@@ -1548,55 +1539,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;
}
@@ -1655,35 +1638,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);
@@ -1691,15 +1672,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;
}
@@ -1758,50 +1732,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;
}
@@ -1859,46 +1823,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;
}
@@ -1948,8 +1904,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;
@@ -1960,16 +1914,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;
diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c
index b918b4dca1..1cd061369f 100644
--- a/source3/rpc_server/srv_samr_nt.c
+++ b/source3/rpc_server/srv_samr_nt.c
@@ -38,10 +38,22 @@ 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;
};
/*******************************************************************
@@ -50,6 +62,24 @@ struct samr_info {
static void free_samr_info(void *ptr)
{
+ int i;
+
+ struct samr_info *info=(struct samr_info *) ptr;
+
+ 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++)
+ SAFE_FREE(info->disp_info.disp_user_info[i].sam);
+
+ SAFE_FREE(info->disp_info.disp_user_info);
+ }
+
SAFE_FREE(ptr);
}
@@ -79,6 +109,137 @@ 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, ("get_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) ) {
+
+ uint32 len_sam_name, len_sam_full, len_sam_desc;
+
+ if (acb_mask != 0 && !(pwd->acct_ctrl & acb_mask)) {
+ pdb_free_sam(&pwd);
+ DEBUG(5,(" acb_mask %x reject\n", acb_mask));
+ continue;
+ }
+ DEBUG(0,("load_sampwd_entries: entry: %d\n", info->disp_info.num_account));
+
+ /* Realloc some memory for the array of ptr to the SAM_ACCOUNT structs */
+ if (info->disp_info.num_account % MAX_SAM_ENTRIES == 0) {
+
+ DEBUG(0,("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;
+
+ /* calculate the size needed to store the data */
+ 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));
+
+ info->disp_info.disp_user_info[info->disp_info.num_account].size=len_sam_name+
+ len_sam_full+
+ len_sam_desc;
+ /* keep the total size up to date too */
+ info->disp_info.total_size+=info->disp_info.disp_user_info[info->disp_info.num_account].size;
+
+ /*
+ * note: the size calculated are smaller than the size sent on the wire
+ * we add the SAM_ENTRY_x size later
+ */
+ DEBUG(0,("load_sampwd_entries: entry: %d size: %d total: %d\n", info->disp_info.num_account, info->disp_info.disp_user_info[info->disp_info.num_account].size,info->disp_info.total_size));
+
+ 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(10,("load_sampwd_entries: done\n"));
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS load_group_domain_entries(struct samr_info *info, DOM_SID *sid)
+{
+ GROUP_MAP *map=NULL;
+ 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;
+ }
+
+ enum_group_mapping(SID_NAME_DOM_GRP, &map, (int *)&group_entries, ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV);
+
+ 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) {
+ SAFE_FREE(map);
+ 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(10,("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.
@@ -1022,91 +1183,147 @@ 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=NULL;
- 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=0;
+ 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;
+ uint32 i;
+ 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 */
-
- DEBUG(5, ("samr_reply_query_dispinfo: max_entries before %d\n", q_u->max_entries));
+ /*
+ * 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
+ */
- if(q_u->max_entries > MAX_SAM_ENTRIES)
- q_u->max_entries = MAX_SAM_ENTRIES;
+ /*
+ * 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
+ */
- DEBUG(5, ("samr_reply_query_dispinfo: max_entries after %d\n", q_u->max_entries));
+ /* Get what we need from the password database */
+ switch (q_u->switch_level) {
+ case 0x1:
+ acb_mask = ACB_NORMAL;
+ struct_size=0x20;
+ break;
+ case 0x2:
+ acb_mask = ACB_WSTRUST;
+ struct_size=0x20;
+ break;
+ case 0x3:
+ struct_size=0x20;
+ break;
+ case 0x4:
+ acb_mask = ACB_NORMAL;
+ struct_size=0x20;
+ break;
+ case 0x5:
+ struct_size=0x20;
+ break;
+ default:
+ DEBUG(0,("_samr_query_dispinfo: Unknown info level (%u)\n", (unsigned int)q_u->switch_level ));
+ return NT_STATUS_INVALID_INFO_CLASS;
+ }
/* 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(p->mem_ctx, &grps, &sid, q_u->start_idx, &num_entries, MAX_SAM_ENTRIES);
- 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;
+ 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;
+ }
+
+ /* 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;
}
- orig_num_entries = 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;
+ }
- if (num_entries > q_u->max_entries)
- num_entries = q_u->max_entries;
- if (num_entries > MAX_SAM_ENTRIES) {
- num_entries = MAX_SAM_ENTRIES;
- DEBUG(5, ("limiting number of entries to %d\n", 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));
}
- /* Ensure password info is never given out here. PARANOIA... JRA */
- samr_clear_passwd_fields(pass, num_entries);
- data_size = q_u->max_size;
+ /* calculate the size */
+ if (q_u->switch_level==3 || q_u->switch_level==5)
+ for (i=enum_context; (i<enum_context+max_entries) && (temp_size<max_size); i++) {
+ /*temp_size+=info->disp_info.disp_group_info[i].size * 2;*/
+ temp_size+=struct_size;
+ }
+
+ else
+ for (i=enum_context; (i<enum_context+max_entries) && (temp_size<max_size); i++) {
+ /*temp_size+=info->disp_info.disp_user_info[i].size * 2;*/
+ temp_size+=struct_size;
+ }
+
+ if (i<enum_context+max_entries) {
+ max_entries=i-enum_context;
+ 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;
@@ -1116,65 +1333,72 @@ 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.total_size+(info->disp_info.num_account*struct_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;
+
}
+
/*******************************************************************
samr_reply_query_aliasinfo
********************************************************************/