summaryrefslogtreecommitdiff
path: root/source3/rpc_server/srv_samr_nt.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/rpc_server/srv_samr_nt.c')
-rw-r--r--source3/rpc_server/srv_samr_nt.c818
1 files changed, 238 insertions, 580 deletions
diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c
index 84c78eab64..fe54476cc9 100644
--- a/source3/rpc_server/srv_samr_nt.c
+++ b/source3/rpc_server/srv_samr_nt.c
@@ -43,14 +43,12 @@ 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;
- uint32 num_user_account;
- SAM_ACCOUNT *disp_user_info;
- BOOL group_dbloaded;
- uint32 num_group_account;
- DOMAIN_GRP *disp_group_info;
+typedef struct disp_info {
+ struct pdb_search *users;
+ struct pdb_search *machines;
+ struct pdb_search *groups;
+ struct pdb_search *aliases;
+ struct pdb_search *builtins;
} DISP_INFO;
struct samr_info {
@@ -238,10 +236,9 @@ static struct samr_info *get_samr_info_by_sid(DOM_SID *psid)
mem_ctx = talloc_init("samr_info for domain sid %s", sid_str);
- if ((info = TALLOC_P(mem_ctx, struct samr_info)) == NULL)
+ if ((info = TALLOC_ZERO_P(mem_ctx, struct samr_info)) == NULL)
return NULL;
- ZERO_STRUCTP(info);
DEBUG(10,("get_samr_info_by_sid: created new info for sid %s\n", sid_str));
if (psid) {
sid_copy( &info->sid, psid);
@@ -256,33 +253,22 @@ static struct samr_info *get_samr_info_by_sid(DOM_SID *psid)
Function to free the per handle data.
********************************************************************/
-static void free_samr_users(struct samr_info *info)
-{
- int i;
-
- if (info->disp_info.user_dbloaded){
- for (i=0; i<info->disp_info.num_user_account; i++) {
- SAM_ACCOUNT *sam = &info->disp_info.disp_user_info[i];
- /* Not really a free, actually a 'clear' */
- pdb_free_sam(&sam);
- }
- }
- info->disp_info.user_dbloaded=False;
- info->disp_info.num_user_account=0;
-}
-
/*******************************************************************
Function to free the per handle data.
********************************************************************/
static void free_samr_db(struct samr_info *info)
{
- /* Groups are talloced */
-
- free_samr_users(info);
-
- info->disp_info.group_dbloaded=False;
- info->disp_info.num_group_account=0;
+ pdb_search_destroy(info->disp_info.users);
+ info->disp_info.users = NULL;
+ pdb_search_destroy(info->disp_info.machines);
+ info->disp_info.machines = NULL;
+ pdb_search_destroy(info->disp_info.groups);
+ info->disp_info.groups = NULL;
+ pdb_search_destroy(info->disp_info.aliases);
+ info->disp_info.aliases = NULL;
+ pdb_search_destroy(info->disp_info.builtins);
+ info->disp_info.builtins = NULL;
}
static void free_samr_info(void *ptr)
@@ -309,154 +295,30 @@ static void samr_clear_sam_passwd(SAM_ACCOUNT *sam_pass)
pdb_set_nt_passwd(sam_pass, NULL, PDB_DEFAULT);
}
-
-static NTSTATUS load_sampwd_entries(struct samr_info *info, uint16 acb_mask, BOOL only_machines)
+static uint32 count_sam_users(struct disp_info *info, uint16 acct_flags)
{
- SAM_ACCOUNT *pwd = NULL;
- SAM_ACCOUNT *pwd_array = NULL;
- NTSTATUS nt_status = NT_STATUS_OK;
- TALLOC_CTX *mem_ctx = info->mem_ctx;
- uint16 query_acb_mask = acb_mask;
-
- DEBUG(10,("load_sampwd_entries\n"));
-
- /* if the snapshoot is already loaded, return */
- if ((info->disp_info.user_dbloaded==True)
- && (info->acb_mask == acb_mask)
- && (info->only_machines == only_machines)) {
- DEBUG(10,("load_sampwd_entries: already in memory\n"));
- return NT_STATUS_OK;
- }
-
- free_samr_users(info);
-
- if (only_machines) {
- query_acb_mask |= ACB_WSTRUST;
- query_acb_mask |= ACB_SVRTRUST;
- }
-
- if (!pdb_setsampwent(False, query_acb_mask)) {
- DEBUG(0, ("load_sampwd_entries: Unable to open passdb.\n"));
- return NT_STATUS_ACCESS_DENIED;
- }
-
- for (; (NT_STATUS_IS_OK(nt_status = pdb_init_sam_talloc(mem_ctx, &pwd)))
- && pdb_getsampwent(pwd) == True; pwd=NULL) {
-
- if (only_machines) {
- if (!((pdb_get_acct_ctrl(pwd) & ACB_WSTRUST)
- || (pdb_get_acct_ctrl(pwd) & ACB_SVRTRUST))) {
- DEBUG(5,("load_sampwd_entries: '%s' is not a machine account - ACB: %x - skipping\n", pdb_get_username(pwd), acb_mask));
- pdb_free_sam(&pwd);
- continue;
- }
- } else {
- if (acb_mask != 0 && !(pdb_get_acct_ctrl(pwd) & 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_user_account % MAX_SAM_ENTRIES == 0) {
-
- DEBUG(10,("load_sampwd_entries: allocating more memory\n"));
- pwd_array=TALLOC_REALLOC_ARRAY(mem_ctx, info->disp_info.disp_user_info, SAM_ACCOUNT,
- info->disp_info.num_user_account+MAX_SAM_ENTRIES);
-
- if (pwd_array==NULL)
- return NT_STATUS_NO_MEMORY;
-
- info->disp_info.disp_user_info=pwd_array;
- }
-
- /* Copy the SAM_ACCOUNT into the array */
- info->disp_info.disp_user_info[info->disp_info.num_user_account]=*pwd;
-
- DEBUG(10,("load_sampwd_entries: entry: %d\n", info->disp_info.num_user_account));
-
- info->disp_info.num_user_account++;
- }
-
- pdb_endsampwent();
-
- /* the snapshoot is in memory, we're ready to enumerate fast */
-
- info->acb_mask = acb_mask;
- info->only_machines = only_machines;
- info->disp_info.user_dbloaded=True;
-
- DEBUG(10,("load_sampwd_entries: done\n"));
-
- return nt_status;
+ struct samr_displayentry *entry;
+ if (info->users == NULL)
+ info->users = pdb_search_users(acct_flags);
+ if (info->users == NULL)
+ return 0;
+ /* Fetch the last possible entry, thus trigger an enumeration */
+ pdb_search_entries(info->users, 0xffffffff, 1, &entry);
+ return info->users->num_entries;
}
-static NTSTATUS load_group_domain_entries(struct samr_info *info, DOM_SID *sid)
+static uint32 count_sam_groups(struct disp_info *info)
{
- GROUP_MAP *map=NULL;
- DOMAIN_GRP *grp_array = NULL;
- uint32 group_entries = 0;
- uint32 i;
- TALLOC_CTX *mem_ctx = info->mem_ctx;
- BOOL ret;
-
- 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;
- }
-
- if (sid_equal(sid, &global_sid_Builtin)) {
- /* No domain groups for now in the BUILTIN domain */
- info->disp_info.num_group_account=0;
- info->disp_info.disp_group_info=NULL;
- info->disp_info.group_dbloaded=True;
- return NT_STATUS_OK;
- }
-
- become_root();
- ret = pdb_enum_group_mapping(SID_NAME_DOM_GRP, &map, (int *)&group_entries, ENUM_ONLY_MAPPED);
- unbecome_root();
-
- if ( !ret ) {
- DEBUG(1, ("load_group_domain_entries: pdb_enum_group_mapping() failed!\n"));
- return NT_STATUS_NO_MEMORY;
- }
-
-
- info->disp_info.num_group_account=group_entries;
-
- grp_array=TALLOC_ARRAY(mem_ctx, DOMAIN_GRP, info->disp_info.num_group_account);
- if (group_entries!=0 && grp_array==NULL) {
- DEBUG(1, ("load_group_domain_entries: talloc() failed for grp_array!\n"));
- SAFE_FREE(map);
- return NT_STATUS_NO_MEMORY;
- }
-
- info->disp_info.disp_group_info=grp_array;
-
- for (i=0; i<group_entries; i++) {
- fstrcpy(grp_array[i].name, map[i].nt_name);
- fstrcpy(grp_array[i].comment, map[i].comment);
- sid_split_rid(&map[i].sid, &grp_array[i].rid);
- grp_array[i].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;
-
- DEBUG(10,("load_group_domain_entries: done\n"));
-
- return NT_STATUS_OK;
+ struct samr_displayentry *entry;
+ if (info->groups == NULL)
+ info->groups = pdb_search_groups();
+ if (info->groups == NULL)
+ return 0;
+ /* Fetch the last possible entry, thus trigger an enumeration */
+ pdb_search_entries(info->groups, 0xffffffff, 1, &entry);
+ return info->groups->num_entries;
}
-
/*******************************************************************
_samr_close_hnd
********************************************************************/
@@ -656,20 +518,14 @@ NTSTATUS _samr_query_sec_obj(pipes_struct *p, SAMR_Q_QUERY_SEC_OBJ *q_u, SAMR_R_
makes a SAM_ENTRY / UNISTR2* structure from a user list.
********************************************************************/
-static NTSTATUS make_user_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UNISTR2 **uni_name_pp,
- uint32 num_entries, uint32 start_idx, SAM_ACCOUNT *disp_user_info,
- DOM_SID *domain_sid)
+static NTSTATUS make_user_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp,
+ UNISTR2 **uni_name_pp,
+ uint32 num_entries, uint32 start_idx,
+ struct samr_displayentry *entries)
{
uint32 i;
SAM_ENTRY *sam;
UNISTR2 *uni_name;
- SAM_ACCOUNT *pwd = NULL;
- UNISTR2 uni_temp_name;
- const char *temp_name;
- const DOM_SID *user_sid;
- uint32 user_rid;
- fstring user_sid_string;
- fstring domain_sid_string;
*sam_pp = NULL;
*uni_name_pp = NULL;
@@ -687,31 +543,20 @@ static NTSTATUS make_user_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UN
}
for (i = 0; i < num_entries; i++) {
- pwd = &disp_user_info[i+start_idx];
- temp_name = pdb_get_username(pwd);
-
+ UNISTR2 uni_temp_name;
/*
* usrmgr expects a non-NULL terminated string with
* trust relationships
*/
- if (pdb_get_acct_ctrl(pwd) & ACB_DOMTRUST) {
- init_unistr2(&uni_temp_name, temp_name, UNI_FLAGS_NONE);
+ if (entries[i].acct_flags & ACB_DOMTRUST) {
+ init_unistr2(&uni_temp_name, entries[i].account_name,
+ UNI_FLAGS_NONE);
} else {
- init_unistr2(&uni_temp_name, temp_name, UNI_STR_TERMINATE);
+ init_unistr2(&uni_temp_name, entries[i].account_name,
+ UNI_STR_TERMINATE);
}
- user_sid = pdb_get_user_sid(pwd);
-
- if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) {
- DEBUG(0, ("make_user_sam_entry_list: User %s has SID %s, which conflicts with "
- "the domain sid %s. Failing operation.\n",
- temp_name,
- sid_to_string(user_sid_string, user_sid),
- sid_to_string(domain_sid_string, domain_sid)));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- init_sam_entry(&sam[i], &uni_temp_name, user_rid);
+ init_sam_entry(&sam[i], &uni_temp_name, entries[i].rid);
copy_unistr2(&uni_name[i], &uni_temp_name);
}
@@ -728,15 +573,12 @@ NTSTATUS _samr_enum_dom_users(pipes_struct *p, SAMR_Q_ENUM_DOM_USERS *q_u,
SAMR_R_ENUM_DOM_USERS *r_u)
{
struct samr_info *info = NULL;
- uint32 struct_size=0x20; /* W2K always reply that, client doesn't care */
int num_account;
uint32 enum_context=q_u->start_idx;
- uint32 max_size=q_u->max_size;
- uint32 temp_size;
enum remote_arch_types ra_type = get_remote_arch();
int max_sam_entries = (ra_type == RA_WIN95) ? MAX_SAM_ENTRIES_W95 : MAX_SAM_ENTRIES_W2K;
uint32 max_entries = max_sam_entries;
- DOM_SID domain_sid;
+ struct samr_displayentry *entries = NULL;
r_u->status = NT_STATUS_OK;
@@ -744,8 +586,6 @@ NTSTATUS _samr_enum_dom_users(pipes_struct *p, SAMR_Q_ENUM_DOM_USERS *q_u,
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
- domain_sid = info->sid;
-
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(info->acc_granted,
SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
"_samr_enum_dom_users"))) {
@@ -755,60 +595,36 @@ NTSTATUS _samr_enum_dom_users(pipes_struct *p, SAMR_Q_ENUM_DOM_USERS *q_u,
DEBUG(5,("_samr_enum_dom_users: %d\n", __LINE__));
become_root();
- r_u->status=load_sampwd_entries(info, q_u->acb_mask, False);
+ if (info->disp_info.users == NULL)
+ info->disp_info.users = pdb_search_users(q_u->acb_mask);
+ if (info->disp_info.users == NULL)
+ return NT_STATUS_ACCESS_DENIED;
+ num_account = pdb_search_entries(info->disp_info.users,
+ enum_context, max_entries,
+ &entries);
unbecome_root();
-
- if (!NT_STATUS_IS_OK(r_u->status))
- return r_u->status;
-
- num_account = info->disp_info.num_user_account;
- if (enum_context > num_account) {
- DEBUG(5, ("_samr_enum_dom_users: enumeration handle over total entries\n"));
+ if (num_account == 0) {
+ DEBUG(5, ("_samr_enum_dom_users: enumeration handle over "
+ "total entries\n"));
return NT_STATUS_OK;
}
- /* verify we won't overflow */
- if (max_entries > num_account-enum_context) {
- max_entries = num_account-enum_context;
- DEBUG(5, ("_samr_enum_dom_users: only %d entries to return\n", max_entries));
- }
-
- /* calculate the size and limit on the number of entries we will return */
- temp_size=max_entries*struct_size;
-
- if (temp_size>max_size) {
- max_entries=MIN((max_size/struct_size),max_entries);;
- DEBUG(5, ("_samr_enum_dom_users: buffer size limits to only %d entries\n", max_entries));
- }
-
- /*
- * Note from JRA. total_entries is not being used here. Currently if there is a
- * large user base then it looks like NT will enumerate until get_sampwd_entries
- * returns False due to num_entries being zero. This will cause an access denied
- * return. I don't think this is right and needs further investigation. Note that
- * this is also the same in the TNG code (I don't think that has been tested with
- * a very large user list as MAX_SAM_ENTRIES is set to 600).
- *
- * I also think that one of the 'num_entries' return parameters is probably
- * the "max entries" parameter - but in the TNG code they're all currently set to the same
- * value (again I think this is wrong).
- */
-
- r_u->status = make_user_sam_entry_list(p->mem_ctx, &r_u->sam, &r_u->uni_acct_name,
- max_entries, enum_context,
- info->disp_info.disp_user_info,
- &domain_sid);
+ r_u->status = make_user_sam_entry_list(p->mem_ctx, &r_u->sam,
+ &r_u->uni_acct_name,
+ num_account, enum_context,
+ entries);
if (!NT_STATUS_IS_OK(r_u->status))
return r_u->status;
- if (enum_context+max_entries < num_account)
+ if (max_entries <= num_account)
r_u->status = STATUS_MORE_ENTRIES;
DEBUG(5, ("_samr_enum_dom_users: %d\n", __LINE__));
- init_samr_r_enum_dom_users(r_u, q_u->start_idx + max_entries, max_entries);
+ init_samr_r_enum_dom_users(r_u, q_u->start_idx + num_account,
+ num_account);
DEBUG(5,("_samr_enum_dom_users: %d\n", __LINE__));
@@ -819,8 +635,10 @@ NTSTATUS _samr_enum_dom_users(pipes_struct *p, SAMR_Q_ENUM_DOM_USERS *q_u,
makes a SAM_ENTRY / UNISTR2* structure from a group list.
********************************************************************/
-static void make_group_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UNISTR2 **uni_name_pp,
- uint32 num_sam_entries, DOMAIN_GRP *grp)
+static void make_group_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp,
+ UNISTR2 **uni_name_pp,
+ uint32 num_sam_entries,
+ struct samr_displayentry *entries)
{
uint32 i;
SAM_ENTRY *sam;
@@ -844,8 +662,9 @@ static void make_group_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UNIST
/*
* JRA. I think this should include the null. TNG does not.
*/
- init_unistr2(&uni_name[i], grp[i].name, UNI_STR_TERMINATE);
- init_sam_entry(&sam[i], &uni_name[i], grp[i].rid);
+ init_unistr2(&uni_name[i], entries[i].account_name,
+ UNI_STR_TERMINATE);
+ init_sam_entry(&sam[i], &uni_name[i], entries[i].rid);
}
*sam_pp = sam;
@@ -853,179 +672,107 @@ static void make_group_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UNIST
}
/*******************************************************************
- Get the group entries - similar to get_sampwd_entries().
- ******************************************************************/
-
-static NTSTATUS get_group_domain_entries( TALLOC_CTX *ctx,
- DOMAIN_GRP **d_grp, DOM_SID *sid, uint32 start_idx,
- uint32 *p_num_entries, uint32 max_entries )
-{
- GROUP_MAP *map=NULL;
- int i;
- uint32 group_entries = 0;
- uint32 num_entries = 0;
- NTSTATUS result = NT_STATUS_OK;
-
- *p_num_entries = 0;
-
- /* access checks for the users were performed higher up. become/unbecome_root()
- needed for some passdb backends to enumerate groups */
-
- become_root();
- pdb_enum_group_mapping(SID_NAME_DOM_GRP, &map, (int *)&group_entries,
- ENUM_ONLY_MAPPED);
- unbecome_root();
-
- num_entries=group_entries-start_idx;
-
- /* limit the number of entries */
- if (num_entries>max_entries) {
- DEBUG(5,("Limiting to %d entries\n", max_entries));
- num_entries=max_entries;
- result = STATUS_MORE_ENTRIES;
- }
-
- *d_grp=TALLOC_ZERO_ARRAY(ctx, DOMAIN_GRP, num_entries);
- if (num_entries!=0 && *d_grp==NULL){
- SAFE_FREE(map);
- return NT_STATUS_NO_MEMORY;
- }
-
- for (i=0; i<num_entries; i++) {
- fstrcpy((*d_grp)[i].name, map[i+start_idx].nt_name);
- fstrcpy((*d_grp)[i].comment, map[i+start_idx].comment);
- sid_split_rid(&map[i+start_idx].sid, &(*d_grp)[i].rid);
- (*d_grp)[i].attr=SID_NAME_DOM_GRP;
- }
-
- SAFE_FREE(map);
-
- *p_num_entries = num_entries;
-
- DEBUG(10,("get_group_domain_entries: returning %d entries\n",
- *p_num_entries));
-
- return result;
-}
-
-/*******************************************************************
- Wrapper for enumerating local groups
- ******************************************************************/
-
-static NTSTATUS get_alias_entries( TALLOC_CTX *ctx, DOMAIN_GRP **d_grp,
- const DOM_SID *sid, uint32 start_idx,
- uint32 *p_num_entries, uint32 max_entries )
-{
- struct acct_info *info;
- int i;
- BOOL res;
-
- become_root();
- res = pdb_enum_aliases(sid, start_idx, max_entries,
- p_num_entries, &info);
- unbecome_root();
-
- if (!res)
- return NT_STATUS_ACCESS_DENIED;
-
- if (*p_num_entries == 0)
- return NT_STATUS_OK;
-
- *d_grp = TALLOC_ARRAY(ctx, DOMAIN_GRP, *p_num_entries);
-
- if (*d_grp == NULL) {
- SAFE_FREE(info);
- return NT_STATUS_NO_MEMORY;
- }
-
- for (i=0; i<*p_num_entries; i++) {
- fstrcpy((*d_grp)[i].name, info[i].acct_name);
- fstrcpy((*d_grp)[i].comment, info[i].acct_desc);
- (*d_grp)[i].rid = info[i].rid;
- (*d_grp)[i].attr = SID_NAME_ALIAS;
- }
-
- SAFE_FREE(info);
- return NT_STATUS_OK;
-}
-
-/*******************************************************************
samr_reply_enum_dom_groups
********************************************************************/
NTSTATUS _samr_enum_dom_groups(pipes_struct *p, SAMR_Q_ENUM_DOM_GROUPS *q_u, SAMR_R_ENUM_DOM_GROUPS *r_u)
{
- DOMAIN_GRP *grp=NULL;
- uint32 num_entries;
- DOM_SID sid;
- uint32 acc_granted;
+ struct samr_info *info = NULL;
+ struct samr_displayentry *groups;
+ uint32 num_groups;
r_u->status = NT_STATUS_OK;
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid, &acc_granted))
+ /* find the policy handle. open a policy on it. */
+ if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
-
- if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_DOMAIN_ENUM_ACCOUNTS, "_samr_enum_dom_groups"))) {
+
+ r_u->status = access_check_samr_function(info->acc_granted,
+ SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
+ "_samr_enum_dom_groups");
+ if (!NT_STATUS_IS_OK(r_u->status))
return r_u->status;
- }
DEBUG(5,("samr_reply_enum_dom_groups: %d\n", __LINE__));
/* the domain group array is being allocated in the function below */
- r_u->status = get_group_domain_entries(p->mem_ctx, &grp, &sid,
- q_u->start_idx, &num_entries,
- MAX_SAM_ENTRIES);
- if (!NT_STATUS_IS_OK(r_u->status) &&
- !NT_STATUS_EQUAL(r_u->status, STATUS_MORE_ENTRIES))
- return r_u->status;
+ become_root();
+ if (info->disp_info.groups == NULL)
+ info->disp_info.groups = pdb_search_groups();
+ unbecome_root();
+ if (info->disp_info.groups == NULL)
+ return NT_STATUS_ACCESS_DENIED;
+
+ become_root();
+ num_groups = pdb_search_entries(info->disp_info.groups, q_u->start_idx,
+ MAX_SAM_ENTRIES, &groups);
+ unbecome_root();
+
make_group_sam_entry_list(p->mem_ctx, &r_u->sam, &r_u->uni_grp_name,
- num_entries, grp);
+ num_groups, groups);
- init_samr_r_enum_dom_groups(r_u, q_u->start_idx+num_entries,
- num_entries);
+ init_samr_r_enum_dom_groups(r_u, q_u->start_idx, num_groups);
DEBUG(5,("samr_enum_dom_groups: %d\n", __LINE__));
return r_u->status;
}
-
/*******************************************************************
samr_reply_enum_dom_aliases
********************************************************************/
NTSTATUS _samr_enum_dom_aliases(pipes_struct *p, SAMR_Q_ENUM_DOM_ALIASES *q_u, SAMR_R_ENUM_DOM_ALIASES *r_u)
{
- DOMAIN_GRP *grp=NULL;
- uint32 num_entries = 0;
- fstring sid_str;
- DOM_SID sid;
+ struct samr_info *info;
+ struct samr_displayentry *aliases;
+ struct pdb_search **search = NULL;
+ uint32 num_aliases = 0;
NTSTATUS status;
- uint32 acc_granted;
-
+
r_u->status = NT_STATUS_OK;
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid, &acc_granted))
+ /* find the policy handle. open a policy on it. */
+ if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
- if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_DOMAIN_ENUM_ACCOUNTS, "_samr_enum_dom_aliases"))) {
+ r_u->status = access_check_samr_function(info->acc_granted,
+ SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
+ "_samr_enum_dom_aliases");
+ if (!NT_STATUS_IS_OK(r_u->status))
return r_u->status;
- }
-
- sid_to_string(sid_str, &sid);
- DEBUG(5,("samr_reply_enum_dom_aliases: sid %s\n", sid_str));
- status = get_alias_entries(p->mem_ctx, &grp, &sid, q_u->start_idx,
- &num_entries, MAX_SAM_ENTRIES);
- if (!NT_STATUS_IS_OK(status)) return status;
+ DEBUG(5,("samr_reply_enum_dom_aliases: sid %s\n",
+ sid_string_static(&info->sid)));
+
+ if (sid_check_is_domain(&info->sid))
+ search = &info->disp_info.aliases;
+ if (sid_check_is_builtin(&info->sid))
+ search = &info->disp_info.builtins;
+
+ if (search == NULL) return NT_STATUS_INVALID_HANDLE;
+
+ become_root();
+ if (*search == NULL)
+ *search = pdb_search_aliases(&info->sid);
+ unbecome_root();
+
+ if (*search == NULL) return NT_STATUS_ACCESS_DENIED;
- make_group_sam_entry_list(p->mem_ctx, &r_u->sam, &r_u->uni_grp_name, num_entries, grp);
+ become_root();
+ num_aliases = pdb_search_entries(*search, q_u->start_idx,
+ MAX_SAM_ENTRIES, &aliases);
+ unbecome_root();
+
+ make_group_sam_entry_list(p->mem_ctx, &r_u->sam, &r_u->uni_grp_name,
+ num_aliases, aliases);
- /*safe_free(grp);*/
+ if (!NT_STATUS_IS_OK(status)) return status;
- init_samr_r_enum_dom_aliases(r_u, q_u->start_idx + num_entries, num_entries);
+ init_samr_r_enum_dom_aliases(r_u, q_u->start_idx + num_aliases,
+ num_aliases);
DEBUG(5,("samr_enum_dom_aliases: %d\n", __LINE__));
@@ -1053,6 +800,7 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u,
enum remote_arch_types ra_type = get_remote_arch();
int max_sam_entries = (ra_type == RA_WIN95) ? MAX_SAM_ENTRIES_W95 : MAX_SAM_ENTRIES_W2K;
DOM_SID domain_sid;
+ struct samr_displayentry *entries = NULL;
DEBUG(5, ("samr_reply_query_dispinfo: %d\n", __LINE__));
r_u->status = NT_STATUS_OK;
@@ -1091,68 +839,29 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u,
* JFM, 12/20/2001
*/
- /* Get what we need from the password database */
- switch (q_u->switch_level) {
- case 0x1:
- /* When playing with usrmgr, this is necessary
- if you want immediate refresh after editing
- a user. I would like to do this after the
- setuserinfo2, but we do not have access to
- the domain handle in that call, only to the
- user handle. Where else does this hurt?
- -- Volker
- */
-#if 0
- /* We cannot do this here - it kills performace. JRA. */
- free_samr_users(info);
-#endif
- case 0x2:
- case 0x4:
- become_root();
- /* Level 2 is for all machines, otherwise only 'normal' users */
- r_u->status=load_sampwd_entries(info, ACB_NORMAL, q_u->switch_level==2);
- unbecome_root();
- if (!NT_STATUS_IS_OK(r_u->status)) {
- DEBUG(5, ("_samr_query_dispinfo: load_sampwd_entries failed\n"));
- return r_u->status;
- }
- num_account = info->disp_info.num_user_account;
- break;
- case 0x3:
- case 0x5:
- r_u->status = load_group_domain_entries(info, &info->sid);
- if (!NT_STATUS_IS_OK(r_u->status))
- return r_u->status;
- num_account = info->disp_info.num_group_account;
- break;
- default:
- DEBUG(0,("_samr_query_dispinfo: Unknown info level (%u)\n", (unsigned int)q_u->switch_level ));
- return NT_STATUS_INVALID_INFO_CLASS;
+ if ((q_u->switch_level < 1) || (q_u->switch_level > 5)) {
+ DEBUG(0,("_samr_query_dispinfo: Unknown info level (%u)\n",
+ (unsigned int)q_u->switch_level ));
+ 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));
+ 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 (enum_context > num_account) {
- DEBUG(5, ("samr_reply_query_dispinfo: enumeration handle over total entries\n"));
- return NT_STATUS_NO_MORE_ENTRIES;
- }
-
- /* verify we won't overflow */
- if (max_entries > num_account-enum_context) {
- max_entries = num_account-enum_context;
- DEBUG(5, ("samr_reply_query_dispinfo: only %d entries to return\n", max_entries));
- }
+ /* calculate the size and limit on the number of entries we will
+ * return */
- /* calculate the size and limit on the number of entries we will return */
temp_size=max_entries*struct_size;
if (temp_size>max_size) {
max_entries=MIN((max_size/struct_size),max_entries);;
- DEBUG(5, ("samr_reply_query_dispinfo: buffer size limits to only %d entries\n", max_entries));
+ DEBUG(5, ("samr_reply_query_dispinfo: buffer size limits to "
+ "only %d entries\n", max_entries));
}
if (!(ctr = TALLOC_ZERO_P(p->mem_ctx,SAM_DISPINFO_CTR)))
@@ -1160,61 +869,80 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u,
ZERO_STRUCTP(ctr);
+ become_root();
+
+ switch (q_u->switch_level) {
+ case 0x1:
+ case 0x4:
+ if (info->disp_info.users == NULL)
+ info->disp_info.users = pdb_search_users(ACB_NORMAL);
+ if (info->disp_info.users == NULL)
+ return NT_STATUS_ACCESS_DENIED;
+ num_account = pdb_search_entries(info->disp_info.users,
+ enum_context, max_entries,
+ &entries);
+ break;
+ case 0x2:
+ if (info->disp_info.machines == NULL)
+ info->disp_info.machines =
+ pdb_search_users(ACB_WSTRUST|ACB_SVRTRUST);
+ if (info->disp_info.machines == NULL)
+ return NT_STATUS_ACCESS_DENIED;
+ num_account = pdb_search_entries(info->disp_info.machines,
+ enum_context, max_entries,
+ &entries);
+ break;
+ case 0x3:
+ case 0x5:
+ if (info->disp_info.groups == NULL)
+ info->disp_info.groups = pdb_search_groups();
+ if (info->disp_info.groups == NULL)
+ return NT_STATUS_ACCESS_DENIED;
+ num_account = pdb_search_entries(info->disp_info.groups,
+ enum_context, max_entries,
+ &entries);
+ break;
+ default:
+ smb_panic("info class changed");
+ break;
+ }
+ unbecome_root();
+
/* Now create reply structure */
switch (q_u->switch_level) {
case 0x1:
- if (max_entries) {
- if (!(ctr->sam.info1 = TALLOC_ZERO_ARRAY(p->mem_ctx,SAM_DISPINFO_1,max_entries)))
- return NT_STATUS_NO_MEMORY;
- }
- disp_ret = init_sam_dispinfo_1(p->mem_ctx, ctr->sam.info1, max_entries, enum_context,
- info->disp_info.disp_user_info, &domain_sid);
- if (!NT_STATUS_IS_OK(disp_ret))
- return disp_ret;
+ disp_ret = init_sam_dispinfo_1(p->mem_ctx, &ctr->sam.info1,
+ num_account, enum_context,
+ entries);
break;
case 0x2:
- if (max_entries) {
- if (!(ctr->sam.info2 = TALLOC_ZERO_ARRAY(p->mem_ctx,SAM_DISPINFO_2,max_entries)))
- return NT_STATUS_NO_MEMORY;
- }
- disp_ret = init_sam_dispinfo_2(p->mem_ctx, ctr->sam.info2, max_entries, enum_context,
- info->disp_info.disp_user_info, &domain_sid);
- if (!NT_STATUS_IS_OK(disp_ret))
- return disp_ret;
+ disp_ret = init_sam_dispinfo_2(p->mem_ctx, &ctr->sam.info2,
+ num_account, enum_context,
+ entries);
break;
case 0x3:
- if (max_entries) {
- if (!(ctr->sam.info3 = TALLOC_ZERO_ARRAY(p->mem_ctx,SAM_DISPINFO_3,max_entries)))
- return NT_STATUS_NO_MEMORY;
- }
- 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_OK(disp_ret))
- return disp_ret;
+ disp_ret = init_sam_dispinfo_3(p->mem_ctx, &ctr->sam.info3,
+ num_account, enum_context,
+ entries);
break;
case 0x4:
- if (max_entries) {
- if (!(ctr->sam.info4 = TALLOC_ZERO_ARRAY(p->mem_ctx,SAM_DISPINFO_4,max_entries)))
- return NT_STATUS_NO_MEMORY;
- }
- 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_OK(disp_ret))
- return disp_ret;
+ disp_ret = init_sam_dispinfo_4(p->mem_ctx, &ctr->sam.info4,
+ num_account, enum_context,
+ entries);
break;
case 0x5:
- if (max_entries) {
- if (!(ctr->sam.info5 = TALLOC_ZERO_ARRAY(p->mem_ctx,SAM_DISPINFO_5,max_entries)))
- return NT_STATUS_NO_MEMORY;
- }
- 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_OK(disp_ret))
- return disp_ret;
+ disp_ret = init_sam_dispinfo_5(p->mem_ctx, &ctr->sam.info5,
+ num_account, enum_context,
+ entries);
break;
-
default:
- ctr->sam.info = NULL;
- return NT_STATUS_INVALID_INFO_CLASS;
+ smb_panic("info class changed");
+ break;
}
+ if (!NT_STATUS_IS_OK(disp_ret))
+ return disp_ret;
+
/* calculate the total size */
total_data_size=num_account*struct_size;
@@ -1223,7 +951,9 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u,
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);
+ init_samr_r_query_dispinfo(r_u, num_account, total_data_size,
+ temp_size, q_u->switch_level, ctr,
+ r_u->status);
return r_u->status;
@@ -2106,23 +1836,11 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
flag, nt_expire, nt_min_age);
break;
case 0x02:
- become_root();
- r_u->status=load_sampwd_entries(info, ACB_NORMAL, False);
+ become_root();
+ num_users=count_sam_users(&info->disp_info,
+ ACB_NORMAL);
+ num_groups=count_sam_groups(&info->disp_info);
unbecome_root();
- if (!NT_STATUS_IS_OK(r_u->status)) {
- DEBUG(5, ("_samr_query_dispinfo: load_sampwd_entries failed\n"));
- return r_u->status;
- }
- num_users=info->disp_info.num_user_account;
- free_samr_db(info);
-
- r_u->status=load_group_domain_entries(info, get_global_sam_sid());
- if (!NT_STATUS_IS_OK(r_u->status)) {
- DEBUG(5, ("_samr_query_dispinfo: load_group_domain_entries failed\n"));
- return r_u->status;
- }
- num_groups=info->disp_info.num_group_account;
- free_samr_db(info);
account_policy_get(AP_TIME_TO_LOGOUT, &account_policy_temp);
u_logout = account_policy_temp;
@@ -4380,13 +4098,9 @@ NTSTATUS _samr_remove_sid_foreign_domain(pipes_struct *p,
SAMR_Q_REMOVE_SID_FOREIGN_DOMAIN *q_u,
SAMR_R_REMOVE_SID_FOREIGN_DOMAIN *r_u)
{
- DOM_SID delete_sid, alias_sid;
- SAM_ACCOUNT *sam_pass=NULL;
+ DOM_SID delete_sid, domain_sid;
uint32 acc_granted;
- GROUP_MAP map;
- BOOL is_user = False;
NTSTATUS result;
- enum SID_NAME_USE type = SID_NAME_UNKNOWN;
sid_copy( &delete_sid, &q_u->sid.sid );
@@ -4395,7 +4109,8 @@ NTSTATUS _samr_remove_sid_foreign_domain(pipes_struct *p,
/* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->dom_pol, &alias_sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, &q_u->dom_pol, &domain_sid,
+ &acc_granted))
return NT_STATUS_INVALID_HANDLE;
result = access_check_samr_function(acc_granted, STD_RIGHT_DELETE_ACCESS,
@@ -4405,80 +4120,33 @@ NTSTATUS _samr_remove_sid_foreign_domain(pipes_struct *p,
return result;
DEBUG(8, ("_samr_remove_sid_foreign_domain:sid is %s\n",
- sid_string_static(&alias_sid)));
-
- /* make sure we can handle this */
-
- if ( sid_check_is_domain(&alias_sid) )
- type = SID_NAME_DOM_GRP;
- else if ( sid_check_is_builtin(&alias_sid) )
- type = SID_NAME_ALIAS;
-
- if ( type == SID_NAME_UNKNOWN ) {
- DEBUG(10, ("_samr_remove_sid_foreign_domain: can't operate on what we don't own!\n"));
- return NT_STATUS_OK;
- }
+ sid_string_static(&domain_sid)));
- /* check if the user exists before trying to delete */
-
- pdb_init_sam(&sam_pass);
-
- if ( pdb_getsampwsid(sam_pass, &delete_sid) ) {
- is_user = True;
- } else {
- /* maybe it is a group */
- if( !pdb_getgrsid(&map, delete_sid) ) {
- DEBUG(3,("_samr_remove_sid_foreign_domain: %s is not a user or a group!\n",
- sid_string_static(&delete_sid)));
- result = NT_STATUS_INVALID_SID;
- goto done;
- }
- }
-
/* we can only delete a user from a group since we don't have
nested groups anyways. So in the latter case, just say OK */
-
- if ( is_user ) {
- GROUP_MAP *mappings = NULL;
- int num_groups, i;
- struct group *grp2;
-
- if ( pdb_enum_group_mapping(type, &mappings, &num_groups, False) && num_groups>0 ) {
-
- /* interate over the groups */
- for ( i=0; i<num_groups; i++ ) {
- grp2 = getgrgid(mappings[i].gid);
-
- if ( !grp2 ) {
- DEBUG(0,("_samr_remove_sid_foreign_domain: group mapping without UNIX group!\n"));
- continue;
- }
-
- if ( !user_in_unix_group_list(pdb_get_username(sam_pass), grp2->gr_name) )
- continue;
-
- smb_delete_user_group(grp2->gr_name, pdb_get_username(sam_pass));
-
- if ( user_in_unix_group_list(pdb_get_username(sam_pass), grp2->gr_name) ) {
- /* should we fail here ? */
- DEBUG(0,("_samr_remove_sid_foreign_domain: Delete user [%s] from group [%s] failed!\n",
- pdb_get_username(sam_pass), grp2->gr_name ));
- continue;
- }
-
- DEBUG(10,("_samr_remove_sid_foreign_domain: Removed user [%s] from group [%s]!\n",
- pdb_get_username(sam_pass), grp2->gr_name ));
- }
-
- SAFE_FREE(mappings);
- }
+ /* TODO: The above comment nowadays is bogus. Since we have nested
+ * groups now, and aliases members are never reported out of the unix
+ * group membership, the "just say OK" makes this call a no-op. For
+ * us. This needs fixing however. */
+
+ /* I've only ever seen this in the wild when deleting a user from
+ * usrmgr.exe. domain_sid is the builtin domain, and the sid to delete
+ * is the user about to be deleted. I very much suspect this is the
+ * only application of this call. To verify this, let people report
+ * other cases. */
+
+ if (!sid_check_is_builtin(&domain_sid)) {
+ DEBUG(1,("_samr_remove_sid_foreign_domain: domain_sid = %s, "
+ "global_sam_sid() = %s\n",
+ sid_string_static(&domain_sid),
+ sid_string_static(get_global_sam_sid())));
+ DEBUGADD(1,("please report to samba-technical@samba.org!\n"));
+ return NT_STATUS_OK;
}
-
- result = NT_STATUS_OK;
-done:
- pdb_free_sam(&sam_pass);
+
+ result = NT_STATUS_OK;
return result;
}
@@ -4545,21 +4213,11 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW
break;
case 0x02:
become_root();
- r_u->status=load_sampwd_entries(info, ACB_NORMAL, False);
+ num_users = count_sam_users(&info->disp_info,
+ ACB_NORMAL);
+ num_groups = count_sam_groups(&info->disp_info);
unbecome_root();
- if (!NT_STATUS_IS_OK(r_u->status)) {
- DEBUG(5, ("_samr_unknown_2e: load_sampwd_entries failed\n"));
- return r_u->status;
- }
- num_users=info->disp_info.num_user_account;
- free_samr_db(info);
-
- r_u->status=load_group_domain_entries(info, get_global_sam_sid());
- if (NT_STATUS_IS_ERR(r_u->status)) {
- DEBUG(5, ("_samr_unknown_2e: load_group_domain_entries failed\n"));
- return r_u->status;
- }
- num_groups=info->disp_info.num_group_account;
+
free_samr_db(info);
account_policy_get(AP_TIME_TO_LOGOUT, &account_policy_temp);