From cf7d098b2c1032b51b8f5d439b29c8d20d0991ee Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Tue, 22 Mar 2005 20:50:29 +0000 Subject: r5965: Apply Volker's patch for "ldapsam trusted = yes" for samr_lookup_rids. Gives us again up to ~6x improvement on group membership lookups. (This used to be commit e2117bcb09cbd21df3b6621c2794a006418c1d9e) --- source3/include/passdb.h | 15 +++ source3/passdb/pdb_interface.c | 98 ++++++++++++++++ source3/passdb/pdb_ldap.c | 244 ++++++++++++++++++++++++++++++++++++--- source3/rpc_server/srv_samr_nt.c | 62 +++------- 4 files changed, 359 insertions(+), 60 deletions(-) (limited to 'source3') diff --git a/source3/include/passdb.h b/source3/include/passdb.h index 5a70bb45a8..ca65a4e5e8 100644 --- a/source3/include/passdb.h +++ b/source3/include/passdb.h @@ -342,6 +342,14 @@ typedef struct pdb_context DOM_SID **aliases, int *num_aliases); + NTSTATUS (*pdb_lookup_rids)(struct pdb_context *context, + TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, + int num_rids, + uint32 *rids, + const char ***names, + uint32 **attrs); + void (*free_fn)(struct pdb_context **); TALLOC_CTX *mem_ctx; @@ -440,6 +448,13 @@ typedef struct pdb_methods const DOM_SID *members, int num_members, DOM_SID **aliases, int *num); + NTSTATUS (*lookup_rids)(struct pdb_methods *methods, + TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, + int num_rids, + uint32 *rids, + const char ***names, + uint32 **attrs); void *private_data; /* Private data of some kind */ diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c index 5235750739..949ee83dcd 100644 --- a/source3/passdb/pdb_interface.c +++ b/source3/passdb/pdb_interface.c @@ -659,6 +659,26 @@ static NTSTATUS context_enum_alias_memberships(struct pdb_context *context, num_members, aliases, num); } +static NTSTATUS context_lookup_rids(struct pdb_context *context, + TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, + int num_rids, + uint32 *rids, + const char ***names, + uint32 **attrs) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + if ((!context) || (!context->pdb_methods)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return ret; + } + + return context->pdb_methods->lookup_rids(context->pdb_methods, + mem_ctx, domain_sid, num_rids, + rids, names, attrs); +} + /****************************************************************** Free and cleanup a pdb context, any associated data and anything that the attached modules might have associated. @@ -788,6 +808,7 @@ static NTSTATUS make_pdb_context(struct pdb_context **context) (*context)->pdb_del_aliasmem = context_del_aliasmem; (*context)->pdb_enum_aliasmem = context_enum_aliasmem; (*context)->pdb_enum_alias_memberships = context_enum_alias_memberships; + (*context)->pdb_lookup_rids = context_lookup_rids; (*context)->free_fn = free_pdb_context; @@ -1267,6 +1288,23 @@ BOOL pdb_enum_alias_memberships(const DOM_SID *members, int num_members, aliases, num)); } +NTSTATUS pdb_lookup_rids(TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, + int num_rids, + uint32 *rids, + const char ***names, + uint32 **attrs) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return NT_STATUS_NOT_IMPLEMENTED; + } + + return pdb_context->pdb_lookup_rids(pdb_context, mem_ctx, domain_sid, + num_rids, rids, names, attrs); +} + /*************************************************************** Initialize the static context (at smbd startup etc). @@ -1439,6 +1477,65 @@ NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods, return NT_STATUS_OK; } +NTSTATUS pdb_default_lookup_rids(struct pdb_methods *methods, + TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, + int num_rids, + uint32 *rids, + const char ***names, + uint32 **attrs) +{ + int i; + NTSTATUS result; + BOOL have_mapped = False; + BOOL have_unmapped = False; + + (*names) = TALLOC_ZERO_ARRAY(mem_ctx, const char *, num_rids); + (*attrs) = TALLOC_ZERO_ARRAY(mem_ctx, uint32, num_rids); + + if ((num_rids != 0) && (((*names) == NULL) || ((*attrs) == NULL))) + return NT_STATUS_NO_MEMORY; + + if (!sid_equal(domain_sid, get_global_sam_sid())) { + /* TODO: Sooner or later we need to look up BUILTIN rids as + * well. -- vl */ + goto done; + } + + for (i = 0; i < num_rids; i++) { + fstring tmpname; + fstring domname; + DOM_SID sid; + enum SID_NAME_USE type; + + (*attrs)[i] = SID_NAME_UNKNOWN; + + sid_copy(&sid, domain_sid); + sid_append_rid(&sid, rids[i]); + + if (lookup_sid(&sid, domname, tmpname, &type)) { + (*attrs)[i] = (uint32)type; + (*names)[i] = talloc_strdup(mem_ctx, tmpname); + if ((*names)[i] == NULL) + return NT_STATUS_NO_MEMORY; + DEBUG(5,("lookup_rids: %s:%d\n", (*names)[i], + (*attrs)[i])); + have_mapped = True; + } else { + have_unmapped = True; + } + } + + done: + + result = NT_STATUS_NONE_MAPPED; + + if (have_mapped) + result = have_unmapped ? STATUS_SOME_UNMAPPED : NT_STATUS_OK; + + return result; +} + NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods) { *methods = TALLOC_P(mem_ctx, struct pdb_methods); @@ -1478,6 +1575,7 @@ NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods) (*methods)->del_aliasmem = pdb_default_del_aliasmem; (*methods)->enum_aliasmem = pdb_default_enum_aliasmem; (*methods)->enum_alias_memberships = pdb_default_alias_memberships; + (*methods)->lookup_rids = pdb_default_lookup_rids; return NT_STATUS_OK; } diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index afbd488b85..14c764f12f 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -2208,6 +2208,39 @@ static void add_rid_to_array_unique(TALLOC_CTX *mem_ctx, *num += 1; } +static BOOL ldapsam_extract_rid_from_entry(LDAP *ldap_struct, + LDAPMessage *entry, + const DOM_SID *domain_sid, + uint32 *rid) +{ + fstring str; + DOM_SID sid; + + if (!smbldap_get_single_attribute(ldap_struct, entry, "sambaSID", + str, sizeof(str)-1)) { + DEBUG(10, ("Could not find sambaSID attribute\n")); + return False; + } + + if (!string_to_sid(&sid, str)) { + DEBUG(10, ("Could not convert string %s to sid\n", str)); + return False; + } + + if (sid_compare_domain(&sid, domain_sid) != 0) { + DEBUG(10, ("SID %s is not in expected domain %s\n", + str, sid_string_static(domain_sid))); + return False; + } + + if (!sid_peek_rid(&sid, rid)) { + DEBUG(10, ("Could not peek into RID\n")); + return False; + } + + return True; +} + static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods, TALLOC_CTX *mem_ctx, const DOM_SID *group, @@ -2254,26 +2287,16 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods, entry != NULL; entry = ldap_next_entry(conn->ldap_struct, entry)) { - fstring str; - DOM_SID sid; uint32 rid; - if (!smbldap_get_single_attribute(conn->ldap_struct, - entry, "sambaSID", - str, sizeof(str)-1)) - continue; - - if (!string_to_sid(&sid, str)) - goto done; - - if (!sid_check_is_in_our_domain(&sid)) { - DEBUG(1, ("Inconsistent SAM -- group member uid not " - "in our domain\n")); + if (!ldapsam_extract_rid_from_entry(conn->ldap_struct, + entry, + get_global_sam_sid(), + &rid)) { + DEBUG(2, ("Could not find sid from ldap entry\n")); continue; } - sid_peek_rid(&sid, &rid); - add_rid_to_array_unique(mem_ctx, rid, member_rids, num_members); } @@ -3112,6 +3135,196 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods, return NT_STATUS_OK; } +static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods, + TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, + int num_rids, + uint32 *rids, + const char ***names, + uint32 **attrs) +{ + struct ldapsam_privates *ldap_state = + (struct ldapsam_privates *)methods->private_data; + LDAP *ldap_struct = ldap_state->smbldap_state->ldap_struct; + LDAPMessage *msg = NULL; + LDAPMessage *entry; + char *allsids = NULL; + char *tmp; + int i, rc, num_mapped; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + if (!lp_parm_bool(-1, "ldapsam", "trusted", False)) + return pdb_default_lookup_rids(methods, mem_ctx, domain_sid, + num_rids, rids, names, attrs); + + if (!sid_equal(domain_sid, get_global_sam_sid())) { + /* TODO: Sooner or later we need to look up BUILTIN rids as + * well. -- vl */ + goto done; + } + + (*names) = TALLOC_ZERO_ARRAY(mem_ctx, const char *, num_rids); + (*attrs) = TALLOC_ARRAY(mem_ctx, uint32, num_rids); + + if ((num_rids != 0) && (((*names) == NULL) || ((*attrs) == NULL))) + return NT_STATUS_NO_MEMORY; + + for (i=0; ismbldap_state, + lp_ldap_user_suffix(), + LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0, + &msg); + + SAFE_FREE(filter); + } + + if (rc != LDAP_SUCCESS) + goto done; + + num_mapped = 0; + + for (entry = ldap_first_entry(ldap_struct, msg); + entry != NULL; + entry = ldap_next_entry(ldap_struct, entry)) + { + uint32 rid; + int rid_index; + fstring str; + + if (!ldapsam_extract_rid_from_entry(ldap_struct, entry, + get_global_sam_sid(), + &rid)) { + DEBUG(2, ("Could not find sid from ldap entry\n")); + continue; + } + + if (!smbldap_get_single_attribute(ldap_struct, entry, + "uid", str, sizeof(str)-1)) { + DEBUG(2, ("Could not retrieve uid attribute\n")); + continue; + } + + for (rid_index = 0; rid_index < num_rids; rid_index++) { + if (rid == rids[rid_index]) + break; + } + + if (rid_index == num_rids) { + DEBUG(2, ("Got a RID not asked for: %d\n", rid)); + continue; + } + + (*attrs)[rid_index] = SID_NAME_USER; + (*names)[rid_index] = talloc_strdup(mem_ctx, str); + if ((*names)[rid_index] == NULL) return NT_STATUS_NO_MEMORY; + + num_mapped += 1; + } + + if (num_mapped == num_rids) { + /* No need to look for groups anymore -- we're done */ + result = NT_STATUS_OK; + goto done; + } + + /* Same game for groups */ + + { + char *filter; + const char *ldap_attrs[] = { "cn", "sambaSid", NULL }; + + asprintf(&filter, ("(&(objectClass=sambaGroupMapping)(|%s))"), + allsids); + if (filter == NULL) return NT_STATUS_NO_MEMORY; + + rc = smbldap_search(ldap_state->smbldap_state, + lp_ldap_group_suffix(), + LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0, + &msg); + + SAFE_FREE(filter); + } + + if (rc != LDAP_SUCCESS) + goto done; + + for (entry = ldap_first_entry(ldap_struct, msg); + entry != NULL; + entry = ldap_next_entry(ldap_struct, entry)) + { + uint32 rid; + int rid_index; + fstring str; + + if (!ldapsam_extract_rid_from_entry(ldap_struct, entry, + get_global_sam_sid(), + &rid)) { + DEBUG(2, ("Could not find sid from ldap entry\n")); + continue; + } + + if (!smbldap_get_single_attribute(ldap_struct, entry, + "cn", str, sizeof(str)-1)) { + DEBUG(2, ("Could not retrieve cn attribute\n")); + continue; + } + + for (rid_index = 0; rid_index < num_rids; rid_index++) { + if (rid == rids[rid_index]) + break; + } + + if (rid_index == num_rids) { + DEBUG(2, ("Got a RID not asked for: %d\n", rid)); + continue; + } + + (*attrs)[rid_index] = SID_NAME_DOM_GRP; + (*names)[rid_index] = talloc_strdup(mem_ctx, str); + if ((*names)[rid_index] == NULL) return NT_STATUS_NO_MEMORY; + num_mapped += 1; + } + + result = NT_STATUS_NONE_MAPPED; + + if (num_mapped > 0) + result = (num_mapped == num_rids) ? + NT_STATUS_OK : STATUS_SOME_UNMAPPED; + done: + SAFE_FREE(allsids); + + if (msg != NULL) + ldap_msgfree(msg); + + return result; +} + /********************************************************************** Housekeeping *********************************************************************/ @@ -3169,6 +3382,7 @@ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS ** (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping; (*pdb_method)->enum_group_members = ldapsam_enum_group_members; (*pdb_method)->enum_group_memberships = ldapsam_enum_group_memberships; + (*pdb_method)->lookup_rids = ldapsam_lookup_rids; /* TODO: Setup private data and free */ diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index 19989838c7..001da3f3ea 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -1464,8 +1464,9 @@ NTSTATUS _samr_chgpasswd_user(pipes_struct *p, SAMR_Q_CHGPASSWD_USER *q_u, SAMR_ makes a SAMR_R_LOOKUP_RIDS structure. ********************************************************************/ -static BOOL make_samr_lookup_rids(TALLOC_CTX *ctx, uint32 num_names, fstring names[], - UNIHDR **pp_hdr_name, UNISTR2 **pp_uni_name) +static BOOL make_samr_lookup_rids(TALLOC_CTX *ctx, uint32 num_names, + const char **names, UNIHDR **pp_hdr_name, + UNISTR2 **pp_uni_name) { uint32 i; UNIHDR *hdr_name=NULL; @@ -1485,7 +1486,7 @@ static BOOL make_samr_lookup_rids(TALLOC_CTX *ctx, uint32 num_names, fstring nam } for (i = 0; i < num_names; i++) { - DEBUG(10, ("names[%d]:%s\n", i, names[i] ? names[i] : "")); + DEBUG(10, ("names[%d]:%s\n", i, *names[i] ? names[i] : "")); init_unistr2(&uni_name[i], names[i], UNI_FLAGS_NONE); init_uni_hdr(&hdr_name[i], &uni_name[i]); } @@ -1502,16 +1503,13 @@ static BOOL make_samr_lookup_rids(TALLOC_CTX *ctx, uint32 num_names, fstring nam NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOKUP_RIDS *r_u) { - fstring group_names[MAX_SAM_ENTRIES]; - uint32 *group_attrs = NULL; + const char **names; + uint32 *attrs = NULL; UNIHDR *hdr_name = NULL; UNISTR2 *uni_name = NULL; DOM_SID pol_sid; int num_rids = q_u->num_rids1; - int i; uint32 acc_granted; - BOOL have_mapped = False; - BOOL have_unmapped = False; r_u->status = NT_STATUS_OK; @@ -1527,11 +1525,12 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK return NT_STATUS_UNSUCCESSFUL; } - if (num_rids) { - if ((group_attrs = TALLOC_ZERO_ARRAY(p->mem_ctx, uint32, num_rids )) == NULL) - return NT_STATUS_NO_MEMORY; - } - + names = TALLOC_ZERO_ARRAY(p->mem_ctx, const char *, num_rids); + attrs = TALLOC_ZERO_ARRAY(p->mem_ctx, uint32, num_rids); + + if ((num_rids != 0) && ((names == NULL) || (attrs == NULL))) + return NT_STATUS_NO_MEMORY; + if (!sid_equal(&pol_sid, get_global_sam_sid())) { /* TODO: Sooner or later we need to look up BUILTIN rids as * well. -- vl */ @@ -1539,44 +1538,17 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK } become_root(); /* lookup_sid can require root privs */ - - for (i = 0; i < num_rids; i++) { - fstring tmpname; - fstring domname; - DOM_SID sid; - enum SID_NAME_USE type; - - group_attrs[i] = SID_NAME_UNKNOWN; - *group_names[i] = '\0'; - - sid_copy(&sid, &pol_sid); - sid_append_rid(&sid, q_u->rid[i]); - - if (lookup_sid(&sid, domname, tmpname, &type)) { - group_attrs[i] = (uint32)type; - fstrcpy(group_names[i],tmpname); - DEBUG(5,("_samr_lookup_rids: %s:%d\n", group_names[i], - group_attrs[i])); - have_mapped = True; - } else { - have_unmapped = True; - } - } - + r_u->status = pdb_lookup_rids(p->mem_ctx, &pol_sid, num_rids, q_u->rid, + &names, &attrs); unbecome_root(); done: - r_u->status = NT_STATUS_NONE_MAPPED; - - if (have_mapped) - r_u->status = - have_unmapped ? STATUS_SOME_UNMAPPED : NT_STATUS_OK; - - if(!make_samr_lookup_rids(p->mem_ctx, num_rids, group_names, &hdr_name, &uni_name)) + if(!make_samr_lookup_rids(p->mem_ctx, num_rids, names, + &hdr_name, &uni_name)) return NT_STATUS_NO_MEMORY; - init_samr_r_lookup_rids(r_u, num_rids, hdr_name, uni_name, group_attrs); + init_samr_r_lookup_rids(r_u, num_rids, hdr_name, uni_name, attrs); DEBUG(5,("_samr_lookup_rids: %d\n", __LINE__)); -- cgit