From 87d326ba81b7f05f72ca19e4902d78e7b4716c89 Mon Sep 17 00:00:00 2001 From: =?utf-8?q?Bj=C3=B6rn=20Jacke?= Date: Sat, 31 Oct 2009 00:45:09 +0100 Subject: [PATCH 01/15] s3:ldap: don't search when no values where found (cherry picked from commit 70063522065ab3e5a21fb11db0097b808aa11100) Signed-off-by: Stefan Metzmacher --- source3/passdb/pdb_ldap.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index 0d498c8..3cf1df4 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -2671,7 +2671,7 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods, values = ldap_get_values(conn->ldap_struct, entry, "memberUid"); - if (values) { + if ((values != NULL) && (values[0] != NULL)) { filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(|", LDAP_OBJ_SAMBASAMACCOUNT); if (filter == NULL) { -- 1.6.3.3 From 79c70fa9f543688a5179b3b88b6f5e7f9fd60a98 Mon Sep 17 00:00:00 2001 From: =?utf-8?q?Bj=C3=B6rn=20Jacke?= Date: Fri, 30 Oct 2009 21:50:41 +0100 Subject: [PATCH 02/15] =?utf-8?q?=D1=953:ldap:=20search=20for=20account=20policies=20in=20objectclass=20sambaDomain,=20not=20* =20(cherry=20picked=20from=20commit=20e5f41591504769b5c7beb5a35bb0f95b33d27a8b)?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stefan Metzmacher --- source3/passdb/pdb_ldap.c | 7 ++++++- 1 files changed, 6 insertions(+), 1 deletions(-) diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index 3cf1df4..d1d3611 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -3844,6 +3844,7 @@ static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods int count; int rc; char **vals = NULL; + char *filter; const char *policy_attr = NULL; struct ldapsam_privates *ldap_state = @@ -3867,8 +3868,12 @@ static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods attrs[0] = policy_attr; attrs[1] = NULL; + filter = talloc_asprintf(NULL, "(objectClass=%s)", LDAP_OBJ_DOMINFO); + if (filter == NULL) { + return NT_STATUS_NO_MEMORY; + } rc = smbldap_search(ldap_state->smbldap_state, ldap_state->domain_dn, - LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0, + LDAP_SCOPE_BASE, filter, attrs, 0, &result); if (rc != LDAP_SUCCESS) { -- 1.6.3.3 From d46b2031cdd387e89475c5eacba4a7798b6ed5b1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 18 May 2009 16:04:04 +0200 Subject: [PATCH 03/15] Fix large paged search Signed-off-by: Michael Adam (cherry picked from commit afb06a8af3c4e86ef9960c8beb19a22f5fd0f3c2) Signed-off-by: Stefan Metzmacher --- source3/passdb/pdb_ldap.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index d1d3611..9bf40b1 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -4311,6 +4311,7 @@ static bool ldapsam_search_firstpage(struct pdb_search *search) if (state->current_entry == NULL) { ldap_msgfree(state->entries); state->entries = NULL; + return false; } return True; -- 1.6.3.3 From 7a7a167589515e481162dabe968f61606976ebba Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 13 Nov 2009 15:51:33 +0100 Subject: [PATCH 04/15] s3:smbd: make idmap cache persistent for "ldapsam:trusted". This stores the mappings found in the idmap cache (which lives inside gencache). This cache is already read in sid_to_Xid() and Xid_to_sid() for ldapsam:trusted, this fills the opposite direction, massively reducing the number of ldap roundtrips across smbd restarts. Michael (cherry picked from commit d5537cbbf931f0bca519371bfd084fb0051acd57) Signed-off-by: Stefan Metzmacher --- source3/passdb/pdb_ldap.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index 9bf40b1..c897187 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -1037,6 +1037,7 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state, /* We've got a uid, feed the cache */ uid_t uid = strtoul(temp, NULL, 10); store_uid_sid_cache(pdb_get_user_sid(sampass), uid); + idmap_cache_set_sid2uid(pdb_get_user_sid(sampass), uid); } } @@ -2437,6 +2438,7 @@ for gidNumber(%lu)\n",(unsigned long)map->gid)); if (lp_parm_bool(-1, "ldapsam", "trusted", false)) { store_gid_sid_cache(&map->sid, map->gid); + idmap_cache_set_sid2gid(&map->sid, map->gid); } TALLOC_FREE(ctx); @@ -4942,6 +4944,7 @@ static bool ldapsam_sid_to_id(struct pdb_methods *methods, id->gid = strtoul(gid_str, NULL, 10); *type = (enum lsa_SidType)strtoul(value, NULL, 10); + idmap_cache_set_sid2gid(sid, id->gid); ret = True; goto done; } @@ -4958,6 +4961,7 @@ static bool ldapsam_sid_to_id(struct pdb_methods *methods, id->uid = strtoul(value, NULL, 10); *type = SID_NAME_USER; + idmap_cache_set_sid2uid(sid, id->uid); ret = True; done: -- 1.6.3.3 From c4444ff1c58ce90232c426f742863eaa2067f6f6 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 13 Nov 2009 16:16:50 +0100 Subject: [PATCH 05/15] s3:smbd: also fill the memcache with sid<->id mappings in ldapsam_sid_to_id() not only the persistent idmap cache. Michael (cherry picked from commit ee2565bd461ccfb916c5290c883e5ced3af72141) Signed-off-by: Stefan Metzmacher --- source3/passdb/pdb_ldap.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index c897187..4022555 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -4944,6 +4944,7 @@ static bool ldapsam_sid_to_id(struct pdb_methods *methods, id->gid = strtoul(gid_str, NULL, 10); *type = (enum lsa_SidType)strtoul(value, NULL, 10); + store_gid_sid_cache(sid, id->gid); idmap_cache_set_sid2gid(sid, id->gid); ret = True; goto done; @@ -4961,6 +4962,7 @@ static bool ldapsam_sid_to_id(struct pdb_methods *methods, id->uid = strtoul(value, NULL, 10); *type = SID_NAME_USER; + store_uid_sid_cache(sid, id->uid); idmap_cache_set_sid2uid(sid, id->uid); ret = True; -- 1.6.3.3 From 4b8c63af643b6e440973c184b04cc07fb4d570d8 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 16 Nov 2009 11:37:18 +0100 Subject: [PATCH 06/15] s3: shortcut uid_to_sid when "ldapsam:trusted = yes" The normal uid_to_sid behaviour is to call sys_getpwuid() to get the name for the given uid and then call the getsampwnam passdb method for the resulting name. In the ldapsam:trusted case we can reduce the uid_to_sid operation to one simple search for the uidNumber attribute and only get the sambaSID attribute from the correspoinding LDAP object. This reduces the number of ldap roundtrips for this operation. Michael (cherry picked from commit 37dcc8a400ea41fb0a0559c9922cc41ac28ad045) Signed-off-by: Stefan Metzmacher --- source3/passdb/pdb_ldap.c | 75 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 75 insertions(+), 0 deletions(-) diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index 4022555..66db0eb 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -4971,6 +4971,80 @@ static bool ldapsam_sid_to_id(struct pdb_methods *methods, return ret; } +/** + * Find the SID for a uid. + * This is shortcut is only used if ldapsam:trusted is set to true. + */ +static bool ldapsam_uid_to_sid(struct pdb_methods *methods, uid_t uid, + DOM_SID *sid) +{ + struct ldapsam_privates *priv = + (struct ldapsam_privates *)methods->private_data; + char *filter; + const char *attrs[] = { "sambaSID", NULL }; + LDAPMessage *result = NULL; + LDAPMessage *entry = NULL; + bool ret = false; + char *user_sid_string; + DOM_SID *user_sid; + int rc; + TALLOC_CTX *tmp_ctx = talloc_stackframe(); + + filter = talloc_asprintf(tmp_ctx, + "(&(uidNumber=%u)" + "(objectClass=%s)" + "(objectClass=%s))", + (unsigned int)uid, + LDAP_OBJ_POSIXACCOUNT, + LDAP_OBJ_SAMBASAMACCOUNT); + if (filter == NULL) { + DEBUG(3, ("talloc_asprintf failed\n")); + goto done; + } + + rc = smbldap_search_suffix(priv->smbldap_state, filter, attrs, &result); + if (rc != LDAP_SUCCESS) { + goto done; + } + talloc_autofree_ldapmsg(tmp_ctx, result); + + if (ldap_count_entries(priv2ld(priv), result) != 1) { + DEBUG(3, ("ERROR: Got %d entries for uid %u, expected one\n", + ldap_count_entries(priv2ld(priv), result), + (unsigned int)uid)); + goto done; + } + + entry = ldap_first_entry(priv2ld(priv), result); + + user_sid_string = smbldap_talloc_single_attribute(priv2ld(priv), entry, + "sambaSID", tmp_ctx); + if (user_sid_string == NULL) { + DEBUG(1, ("Could not find sambaSID in object '%s'\n", + smbldap_talloc_dn(tmp_ctx, priv2ld(priv), entry))); + goto done; + } + + user_sid = string_sid_talloc(tmp_ctx, user_sid_string); + if (user_sid == NULL) { + DEBUG(3, ("Error calling sid_string_talloc for sid '%s'\n", + user_sid_string)); + goto done; + } + + sid_copy(sid, user_sid); + + store_uid_sid_cache(sid, uid); + idmap_cache_set_sid2uid(sid, uid); + + ret = true; + + done: + TALLOC_FREE(tmp_ctx); + return ret; +} + + /* * The following functions is called only if * ldapsam:trusted and ldapsam:editposix are @@ -6330,6 +6404,7 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location) ldapsam_enum_group_memberships; (*pdb_method)->lookup_rids = ldapsam_lookup_rids; (*pdb_method)->sid_to_id = ldapsam_sid_to_id; + (*pdb_method)->uid_to_sid = ldapsam_uid_to_sid; if (lp_parm_bool(-1, "ldapsam", "editposix", False)) { (*pdb_method)->create_user = ldapsam_create_user; -- 1.6.3.3 From aac09124a11a98d65e6d16aeb5dde52bdddbcfad Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sat, 14 Nov 2009 01:12:22 +0100 Subject: [PATCH 07/15] s3:is_trusted_domain: shortcut if domain name is NULL or empty This saves some roundtrips to LDAP in an ldapsm setup. Michael (cherry picked from commit 0aa5a60d3033fddd652eb4ea89abdf97db912df3) Signed-off-by: Stefan Metzmacher --- source3/auth/auth_util.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index b743c12..7754984 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -2176,6 +2176,10 @@ bool is_trusted_domain(const char* dom_name) if ( lp_server_role() == ROLE_STANDALONE ) return False; + if (dom_name == NULL || dom_name[0] == '\0') { + return false; + } + /* if we are a DC, then check for a direct trust relationships */ if ( IS_DC ) { -- 1.6.3.3 From 41e3aa2b85ab72fa80da6af36d60c55730e34c4c Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sat, 14 Nov 2009 01:21:42 +0100 Subject: [PATCH 08/15] s3:is_trusted_domain: shortcut if domain name == global_sam_name A domain can't have a trust with itself. This saves some roundtrips to the ldap server for ldapsam. Michael (cherry picked from commit dc3a90cf21813526854c12db126d08ebf32f8ae5) Signed-off-by: Stefan Metzmacher --- source3/auth/auth_util.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index 7754984..89aa4a3 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -2180,6 +2180,10 @@ bool is_trusted_domain(const char* dom_name) return false; } + if (strequal(dom_name, get_global_sam_name())) { + return false; + } + /* if we are a DC, then check for a direct trust relationships */ if ( IS_DC ) { -- 1.6.3.3 From 6af56087b52a86a77abc012f6e1bca52a712ca83 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 30 Jan 2010 22:28:19 +0100 Subject: [PATCH 09/15] s3: shortcut gid_to_sid when "ldapsam:trusted = yes" The normal gid_to_sid behaviour is to call sys_getgrgid() to get the name for the given gid and then call the getsamgrnam passdb method for the resulting name. In the ldapsam:trusted case we can reduce the gid_to_sid operation to one simple search for the gidNumber attribute and only get the sambaSID attribute from the correspoinding LDAP object. This reduces the number of ldap roundtrips for this operation. metze (similar to commit 0fb99386d41241f62312d4bb535976344e5d6492) --- source3/passdb/pdb_ldap.c | 72 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 72 insertions(+), 0 deletions(-) diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index 66db0eb..d9894c1 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -5044,6 +5044,77 @@ static bool ldapsam_uid_to_sid(struct pdb_methods *methods, uid_t uid, return ret; } +/** + * Find the SID for a gid. + * This is shortcut is only used if ldapsam:trusted is set to true. + */ +static bool ldapsam_gid_to_sid(struct pdb_methods *methods, gid_t gid, + DOM_SID *sid) +{ + struct ldapsam_privates *priv = + (struct ldapsam_privates *)methods->private_data; + char *filter; + const char *attrs[] = { "sambaSID", NULL }; + LDAPMessage *result = NULL; + LDAPMessage *entry = NULL; + bool ret = false; + char *group_sid_string; + DOM_SID *group_sid; + int rc; + TALLOC_CTX *tmp_ctx = talloc_stackframe(); + + filter = talloc_asprintf(tmp_ctx, + "(&(gidNumber=%u)" + "(objectClass=%s))", + (unsigned int)gid, + LDAP_OBJ_GROUPMAP); + if (filter == NULL) { + DEBUG(3, ("talloc_asprintf failed\n")); + goto done; + } + + rc = smbldap_search_suffix(priv->smbldap_state, filter, attrs, &result); + if (rc != LDAP_SUCCESS) { + goto done; + } + talloc_autofree_ldapmsg(tmp_ctx, result); + + if (ldap_count_entries(priv2ld(priv), result) != 1) { + DEBUG(3, ("ERROR: Got %d entries for gid %u, expected one\n", + ldap_count_entries(priv2ld(priv), result), + (unsigned int)gid)); + goto done; + } + + entry = ldap_first_entry(priv2ld(priv), result); + + group_sid_string = smbldap_talloc_single_attribute(priv2ld(priv), entry, + "sambaSID", tmp_ctx); + if (group_sid_string == NULL) { + DEBUG(1, ("Could not find sambaSID in object '%s'\n", + smbldap_talloc_dn(tmp_ctx, priv2ld(priv), entry))); + goto done; + } + + group_sid = string_sid_talloc(tmp_ctx, group_sid_string); + if (group_sid == NULL) { + DEBUG(3, ("Error calling sid_string_talloc for sid '%s'\n", + group_sid_string)); + goto done; + } + + sid_copy(sid, group_sid); + + store_gid_sid_cache(sid, gid); + idmap_cache_set_sid2gid(sid, gid); + + ret = true; + + done: + TALLOC_FREE(tmp_ctx); + return ret; +} + /* * The following functions is called only if @@ -6405,6 +6476,7 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location) (*pdb_method)->lookup_rids = ldapsam_lookup_rids; (*pdb_method)->sid_to_id = ldapsam_sid_to_id; (*pdb_method)->uid_to_sid = ldapsam_uid_to_sid; + (*pdb_method)->gid_to_sid = ldapsam_gid_to_sid; if (lp_parm_bool(-1, "ldapsam", "editposix", False)) { (*pdb_method)->create_user = ldapsam_create_user; -- 1.6.3.3 From 4c20827ae30889ff9dc0175543970bd1bfebf23e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 31 Jan 2010 15:18:51 +0100 Subject: [PATCH 10/15] s3: Make pdb_copy_sam_account also copy the group sid Signed-off-by: Stefan Metzmacher (cherry picked from commit b99046fed1bf4a908ed856afb17c3c934c6d305d) (cherry picked from commit a1862c23346959cd0aa77653bf488e0686d14376) Signed-off-by: Stefan Metzmacher --- source3/passdb/passdb.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index aad16da..6ba67ef 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -2077,6 +2077,10 @@ bool pdb_copy_sam_account(struct samu *dst, struct samu *src ) } } + if (src->group_sid) { + pdb_set_group_sid(dst, src->group_sid, PDB_SET); + } + free(buf); return True; } -- 1.6.3.3 From cdf121cf766957740cb3cc4cdaa553476efa68d9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 4 Feb 2010 17:16:59 +0100 Subject: [PATCH 11/15] s3:passdb: speed up pdb_get_group_sid() Use the cached version gid_to_sid() instead of pdb_gid_to_sid(). And also avoid the expensive lookup_sid() call for wellkown domain groups. metze (cherry picked from commit e10d0869567436902c8b8cfb50f8c64148d554cb) (cherry picked from commit b0c8ff971934ef8aa21abece8693807e0a2ca722) Signed-off-by: Stefan Metzmacher --- source3/passdb/pdb_get_set.c | 33 ++++++++++++++++++++++++++++----- 1 files changed, 28 insertions(+), 5 deletions(-) diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c index c79caf2..39a85fa 100644 --- a/source3/passdb/pdb_get_set.c +++ b/source3/passdb/pdb_get_set.c @@ -191,7 +191,7 @@ const DOM_SID *pdb_get_group_sid(struct samu *sampass) /* generate the group SID from the user's primary Unix group */ - if ( !(gsid = TALLOC_P( sampass, DOM_SID )) ) { + if ( !(gsid = TALLOC_ZERO_P( sampass, DOM_SID )) ) { return NULL; } @@ -211,15 +211,38 @@ const DOM_SID *pdb_get_group_sid(struct samu *sampass) return NULL; } - if ( pdb_gid_to_sid(pwd->pw_gid, gsid) ) { + gid_to_sid(gsid, pwd->pw_gid); + if (!is_null_sid(gsid)) { enum lsa_SidType type = SID_NAME_UNKNOWN; - TALLOC_CTX *mem_ctx = talloc_init("pdb_get_group_sid"); + TALLOC_CTX *mem_ctx; bool lookup_ret; + const DOM_SID *usid = pdb_get_user_sid(sampass); + DOM_SID dgsid; + uint32_t rid; + + sid_copy(&dgsid, gsid); + sid_split_rid(&dgsid, &rid); + if (sid_equal(&dgsid, get_global_sam_sid())) { + /* + * As shortcut for the expensive lookup_sid call + * compare the domain sid part + */ + switch (rid) { + case DOMAIN_RID_ADMINS: + case DOMAIN_RID_USERS: + sampass->group_sid = gsid; + return sampass->group_sid; + } + } + mem_ctx = talloc_init("pdb_get_group_sid"); if (!mem_ctx) { return NULL; } + DEBUG(10,("do lookup_sid(%s) for group of user %s\n", + sid_string_dbg(gsid), sid_string_dbg(usid))); + /* Now check that it's actually a domain group and not something else */ lookup_ret = lookup_sid(mem_ctx, gsid, NULL, NULL, &type); @@ -231,8 +254,8 @@ const DOM_SID *pdb_get_group_sid(struct samu *sampass) return sampass->group_sid; } - DEBUG(3, ("Primary group for user %s is a %s and not a domain group\n", - pwd->pw_name, sid_type_lookup(type))); + DEBUG(3, ("Primary group %s for user %s is a %s and not a domain group\n", + sid_string_dbg(gsid), pwd->pw_name, sid_type_lookup(type))); } /* Just set it to the 'Domain Users' RID of 512 which will -- 1.6.3.3 From 74562438141b477dbc7519a1757b7a9af9f2be3e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 4 Feb 2010 17:19:57 +0100 Subject: [PATCH 12/15] s3:pdb_ldap: try to build the full unix_pw structure with ldapsam:trusted support And also store the gid_to_sid mappings in the idmap_cache. metze (cherry picked from commit 25038fa85ff69962ca0975f31802218a897aa1ec) (cherry picked from commit 66a48d2226d245c373b744c7edea60b3daa57f0f) Signed-off-by: Stefan Metzmacher --- source3/passdb/pdb_ldap.c | 90 ++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 85 insertions(+), 5 deletions(-) diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index d9894c1..5423e32 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -1028,6 +1028,17 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state, } if (lp_parm_bool(-1, "ldapsam", "trusted", False)) { + struct passwd unix_pw; + bool have_uid = false; + bool have_gid = false; + DOM_SID mapped_gsid; + const DOM_SID *primary_gsid; + + ZERO_STRUCT(unix_pw); + + unix_pw.pw_name = username; + unix_pw.pw_passwd = discard_const_p(char, "x"); + temp = smbldap_talloc_single_attribute( priv2ld(ldap_state), entry, @@ -1035,9 +1046,68 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state, ctx); if (temp) { /* We've got a uid, feed the cache */ - uid_t uid = strtoul(temp, NULL, 10); - store_uid_sid_cache(pdb_get_user_sid(sampass), uid); - idmap_cache_set_sid2uid(pdb_get_user_sid(sampass), uid); + unix_pw.pw_uid = strtoul(temp, NULL, 10); + have_uid = true; + } + temp = smbldap_talloc_single_attribute( + priv2ld(ldap_state), + entry, + "gidNumber", + ctx); + if (temp) { + /* We've got a uid, feed the cache */ + unix_pw.pw_gid = strtoul(temp, NULL, 10); + have_gid = true; + } + unix_pw.pw_gecos = smbldap_talloc_single_attribute( + priv2ld(ldap_state), + entry, + "gecos", + ctx); + if (unix_pw.pw_gecos) { + unix_pw.pw_gecos = fullname; + } + unix_pw.pw_dir = smbldap_talloc_single_attribute( + priv2ld(ldap_state), + entry, + "homeDirectory", + ctx); + if (unix_pw.pw_dir) { + unix_pw.pw_dir = discard_const_p(char, ""); + } + unix_pw.pw_shell = smbldap_talloc_single_attribute( + priv2ld(ldap_state), + entry, + "loginShell", + ctx); + if (unix_pw.pw_shell) { + unix_pw.pw_shell = discard_const_p(char, ""); + } + + if (have_uid && have_gid) { + sampass->unix_pw = tcopy_passwd(sampass, &unix_pw); + } else { + sampass->unix_pw = Get_Pwnam_alloc(sampass, unix_pw.pw_name); + } + + if (sampass->unix_pw == NULL) { + DEBUG(0,("init_sam_from_ldap: Failed to find Unix account for %s\n", + pdb_get_username(sampass))); + goto fn_exit; + } + + store_uid_sid_cache(pdb_get_user_sid(sampass), + sampass->unix_pw->pw_uid); + idmap_cache_set_sid2uid(pdb_get_user_sid(sampass), + sampass->unix_pw->pw_uid); + + gid_to_sid(&mapped_gsid, sampass->unix_pw->pw_gid); + primary_gsid = pdb_get_group_sid(sampass); + if (primary_gsid && sid_equal(primary_gsid, &mapped_gsid)) { + store_gid_sid_cache(primary_gsid, + sampass->unix_pw->pw_gid); + idmap_cache_set_sid2uid(primary_gsid, + sampass->unix_pw->pw_gid); } } @@ -1488,6 +1558,16 @@ static void append_attr(TALLOC_CTX *mem_ctx, const char ***attr_list, (*attr_list)[i+1] = NULL; } +static void ldapsam_add_unix_attributes(TALLOC_CTX *mem_ctx, + const char ***attr_list) +{ + append_attr(mem_ctx, attr_list, "uidNumber"); + append_attr(mem_ctx, attr_list, "gidNumber"); + append_attr(mem_ctx, attr_list, "homeDirectory"); + append_attr(mem_ctx, attr_list, "loginShell"); + append_attr(mem_ctx, attr_list, "gecos"); +} + /********************************************************************** Get struct samu entry from LDAP by username. *********************************************************************/ @@ -1506,7 +1586,7 @@ static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, struct samu append_attr(user, &attr_list, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_MOD_TIMESTAMP)); - append_attr(user, &attr_list, "uidNumber"); + ldapsam_add_unix_attributes(user, &attr_list); rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list); TALLOC_FREE( attr_list ); @@ -1563,7 +1643,7 @@ static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state, get_userattr_key2string( ldap_state->schema_ver, LDAP_ATTR_MOD_TIMESTAMP)); - append_attr(tmp_ctx, &attr_list, "uidNumber"); + ldapsam_add_unix_attributes(tmp_ctx, &attr_list); rc = ldapsam_search_suffix_by_sid(ldap_state, sid, result, attr_list); TALLOC_FREE(tmp_ctx); -- 1.6.3.3 From cfded80875a6f43868a5cd3bc7b36837e1b2667f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 3 Feb 2010 11:32:41 +0100 Subject: [PATCH 13/15] s3:pdb_ldap: optimize ldapsam_alias_memberships() and cache ldap searches. ldapsam_alias_memberships() does the same LDAP search twice, triggered via add_aliases() from create_local_nt_token(). This happens when no domain aliases are used. metze (cherry picked from commit 49ace81e19de231825216cbf07c7422687131bb6) (cherry picked from commit cb31c1df92b195b3fb80b6e21bfba83b8cd867fd) Signed-off-by: Stefan Metzmacher --- source3/include/smbldap.h | 5 +++++ source3/passdb/pdb_ldap.c | 36 +++++++++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/source3/include/smbldap.h b/source3/include/smbldap.h index 726d5f7..7383670 100644 --- a/source3/include/smbldap.h +++ b/source3/include/smbldap.h @@ -196,6 +196,11 @@ struct ldapsam_privates { /* ldap server location parameter */ char *location; + + struct { + char *filter; + LDAPMessage *result; + } search_cache; }; /* Functions shared between pdb_ldap.c and pdb_nds.c. */ diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index 5423e32..e1ae8a3 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -3791,8 +3791,11 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods, int rc; char *filter; enum lsa_SidType type = SID_NAME_USE_NONE; + bool is_builtin = false; + bool sid_added = false; if (sid_check_is_builtin(domain_sid)) { + is_builtin = true; type = SID_NAME_ALIAS; } @@ -3822,11 +3825,20 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods, return NT_STATUS_NO_MEMORY; } - rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_suffix(), - LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result); - - if (rc != LDAP_SUCCESS) - return NT_STATUS_UNSUCCESSFUL; + if (is_builtin && + ldap_state->search_cache.filter && + strcmp(ldap_state->search_cache.filter, filter) == 0) { + filter = talloc_move(filter, &ldap_state->search_cache.filter); + result = ldap_state->search_cache.result; + ldap_state->search_cache.result = NULL; + } else { + rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_suffix(), + LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result); + if (rc != LDAP_SUCCESS) { + return NT_STATUS_UNSUCCESSFUL; + } + talloc_autofree_ldapmsg(filter, result); + } ldap_struct = ldap_state->smbldap_state->ldap_struct; @@ -3850,14 +3862,24 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods, if (!sid_peek_check_rid(domain_sid, &sid, &rid)) continue; + sid_added = true; + if (!add_rid_to_array_unique(mem_ctx, rid, pp_alias_rids, p_num_alias_rids)) { - ldap_msgfree(result); return NT_STATUS_NO_MEMORY; } } - ldap_msgfree(result); + if (!is_builtin && !sid_added) { + TALLOC_FREE(ldap_state->search_cache.filter); + /* + * Note: result is a talloc child of filter because of the + * talloc_autofree_ldapmsg() usage + */ + ldap_state->search_cache.filter = talloc_move(ldap_state, &filter); + ldap_state->search_cache.result = result; + } + return NT_STATUS_OK; } -- 1.6.3.3 From 3ddfb1138197a1effd1ff4049f67d25251cc8a1b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 5 Feb 2010 16:20:21 +0100 Subject: [PATCH 14/15] s3:pdb_ldap: don't search for the users primary group, if we already know it metze (cherry picked from commit 6753fb1cf6a834b12b2a9dce3b1a9555390c17be) (cherry picked from commit da7cb9feacc7cb84499c73ef463d187a7b2754e8) Signed-off-by: Stefan Metzmacher --- source3/passdb/pdb_ldap.c | 66 ++++++++++++++++++++++++--------------------- 1 files changed, 35 insertions(+), 31 deletions(-) diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index e1ae8a3..f95f912 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -2915,46 +2915,50 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods, if (escape_name == NULL) return NT_STATUS_NO_MEMORY; - /* retrieve the users primary gid */ - filter = talloc_asprintf(mem_ctx, - "(&(objectClass=%s)(uid=%s))", - LDAP_OBJ_SAMBASAMACCOUNT, - escape_name); - if (filter == NULL) { - ret = NT_STATUS_NO_MEMORY; - goto done; - } + if (user->unix_pw) { + primary_gid = user->unix_pw->pw_gid; + } else { + /* retrieve the users primary gid */ + filter = talloc_asprintf(mem_ctx, + "(&(objectClass=%s)(uid=%s))", + LDAP_OBJ_SAMBASAMACCOUNT, + escape_name); + if (filter == NULL) { + ret = NT_STATUS_NO_MEMORY; + goto done; + } - rc = smbldap_search(conn, lp_ldap_suffix(), - LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result); + rc = smbldap_search(conn, lp_ldap_suffix(), + LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result); - if (rc != LDAP_SUCCESS) - goto done; + if (rc != LDAP_SUCCESS) + goto done; - talloc_autofree_ldapmsg(mem_ctx, result); + talloc_autofree_ldapmsg(mem_ctx, result); - count = ldap_count_entries(priv2ld(ldap_state), result); + count = ldap_count_entries(priv2ld(ldap_state), result); - switch (count) { - case 0: - DEBUG(1, ("User account [%s] not found!\n", pdb_get_username(user))); - ret = NT_STATUS_NO_SUCH_USER; - goto done; - case 1: - entry = ldap_first_entry(priv2ld(ldap_state), result); + switch (count) { + case 0: + DEBUG(1, ("User account [%s] not found!\n", pdb_get_username(user))); + ret = NT_STATUS_NO_SUCH_USER; + goto done; + case 1: + entry = ldap_first_entry(priv2ld(ldap_state), result); - gidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", mem_ctx); - if (!gidstr) { - DEBUG (1, ("Unable to find the member's gid!\n")); + gidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", mem_ctx); + if (!gidstr) { + DEBUG (1, ("Unable to find the member's gid!\n")); + ret = NT_STATUS_INTERNAL_DB_CORRUPTION; + goto done; + } + primary_gid = strtoul(gidstr, NULL, 10); + break; + default: + DEBUG(1, ("found more than one account with the same user name ?!\n")); ret = NT_STATUS_INTERNAL_DB_CORRUPTION; goto done; } - primary_gid = strtoul(gidstr, NULL, 10); - break; - default: - DEBUG(1, ("found more than one account with the same user name ?!\n")); - ret = NT_STATUS_INTERNAL_DB_CORRUPTION; - goto done; } filter = talloc_asprintf(mem_ctx, -- 1.6.3.3 From 0df213f1f63dab60b810b8b57a2d5375b1005c81 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 9 Feb 2010 12:57:01 +0100 Subject: [PATCH 15/15] s3:passdb: only use gid_to_sid() result if the result is a group of our local sam Otherwise retry with pdb_gid_to_sid(). metze (cherry picked from commit 4dc2be2264926fe415e4e40e212f94793c9831d1) Last seven patches address bug #7116 (pdb_ldap performance fixes). (cherry picked from commit 8946a47fcebe57f459c59ee2cb163e15901ff996) Signed-off-by: Stefan Metzmacher --- source3/passdb/pdb_get_set.c | 20 ++++++++++++++++---- 1 files changed, 16 insertions(+), 4 deletions(-) diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c index 39a85fa..1155050 100644 --- a/source3/passdb/pdb_get_set.c +++ b/source3/passdb/pdb_get_set.c @@ -183,6 +183,7 @@ const DOM_SID *pdb_get_group_sid(struct samu *sampass) { DOM_SID *gsid; struct passwd *pwd; + bool need_lookup_sid = false; /* Return the cached group SID if we have that */ if ( sampass->group_sid ) { @@ -213,10 +214,6 @@ const DOM_SID *pdb_get_group_sid(struct samu *sampass) gid_to_sid(gsid, pwd->pw_gid); if (!is_null_sid(gsid)) { - enum lsa_SidType type = SID_NAME_UNKNOWN; - TALLOC_CTX *mem_ctx; - bool lookup_ret; - const DOM_SID *usid = pdb_get_user_sid(sampass); DOM_SID dgsid; uint32_t rid; @@ -232,8 +229,23 @@ const DOM_SID *pdb_get_group_sid(struct samu *sampass) case DOMAIN_RID_USERS: sampass->group_sid = gsid; return sampass->group_sid; + default: + need_lookup_sid = true; + break; + } + } else { + ZERO_STRUCTP(gsid); + if (pdb_gid_to_sid(pwd->pw_gid, gsid)) { + need_lookup_sid = true; } } + } + + if (need_lookup_sid) { + enum lsa_SidType type = SID_NAME_UNKNOWN; + TALLOC_CTX *mem_ctx; + bool lookup_ret; + const DOM_SID *usid = pdb_get_user_sid(sampass); mem_ctx = talloc_init("pdb_get_group_sid"); if (!mem_ctx) { -- 1.6.3.3