[SCM] Samba Shared Repository - branch v3-5-test updated

Karolin Seeger kseeger at samba.org
Wed Feb 10 01:55:01 MST 2010


The branch, v3-5-test has been updated
       via  8946a47... s3:passdb: only use gid_to_sid() result if the result is a group of our local sam
       via  da7cb9f... s3:pdb_ldap: don't search for the users primary group, if we already know it
       via  cb31c1d... s3:pdb_ldap: optimize ldapsam_alias_memberships() and cache ldap searches.
       via  66a48d2... s3:pdb_ldap: try to build the full unix_pw structure with ldapsam:trusted support
       via  b0c8ff9... s3:passdb: speed up pdb_get_group_sid()
       via  a1862c2... s3: Make pdb_copy_sam_account also copy the group sid
       via  0fb9938... s3: shortcut gid_to_sid when "ldapsam:trusted = yes"
      from  60fed68... Missed one check on the memcpy for bug #7063.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-5-test


- Log -----------------------------------------------------------------
commit 8946a47fcebe57f459c59ee2cb163e15901ff996
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Feb 9 12:57:01 2010 +0100

    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).

commit da7cb9feacc7cb84499c73ef463d187a7b2754e8
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Feb 5 16:20:21 2010 +0100

    s3:pdb_ldap: don't search for the users primary group, if we already know it
    
    metze
    (cherry picked from commit 6753fb1cf6a834b12b2a9dce3b1a9555390c17be)

commit cb31c1df92b195b3fb80b6e21bfba83b8cd867fd
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Feb 3 11:32:41 2010 +0100

    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)

commit 66a48d2226d245c373b744c7edea60b3daa57f0f
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Feb 4 17:19:57 2010 +0100

    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)

commit b0c8ff971934ef8aa21abece8693807e0a2ca722
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Feb 4 17:16:59 2010 +0100

    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)

commit a1862c23346959cd0aa77653bf488e0686d14376
Author: Volker Lendecke <vl at samba.org>
Date:   Sun Jan 31 15:18:51 2010 +0100

    s3: Make pdb_copy_sam_account also copy the group sid
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    (cherry picked from commit b99046fed1bf4a908ed856afb17c3c934c6d305d)

commit 0fb99386d41241f62312d4bb535976344e5d6492
Author: Stefan Metzmacher <metze at samba.org>
Date:   Sat Jan 30 22:28:19 2010 +0100

    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
    (cherry picked from commit 779821df8ecfe3ed2392582b500d26332f0b80fc)

-----------------------------------------------------------------------

Summary of changes:
 source3/include/smbldap.h    |    5 +
 source3/passdb/passdb.c      |    4 +
 source3/passdb/pdb_get_set.c |   45 +++++++-
 source3/passdb/pdb_ldap.c    |  263 +++++++++++++++++++++++++++++++++++-------
 4 files changed, 269 insertions(+), 48 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/include/smbldap.h b/source3/include/smbldap.h
index e3b03d4..ec0e9f5 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/passdb.c b/source3/passdb/passdb.c
index b2c3b94..0255edc 100644
--- a/source3/passdb/passdb.c
+++ b/source3/passdb/passdb.c
@@ -2080,6 +2080,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;
 }
diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c
index 74ed018..6126517 100644
--- a/source3/passdb/pdb_get_set.c
+++ b/source3/passdb/pdb_get_set.c
@@ -184,6 +184,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 ) {
@@ -192,7 +193,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;
 	}
 
@@ -212,15 +213,49 @@ 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)) {
+		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;
+			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 = talloc_init("pdb_get_group_sid");
+		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) {
 			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);
@@ -232,8 +267,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 
diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c
index a8d220d..ad60228 100644
--- a/source3/passdb/pdb_ldap.c
+++ b/source3/passdb/pdb_ldap.c
@@ -1029,6 +1029,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,
@@ -1036,9 +1047,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);
 		}
 	}
 
@@ -1489,6 +1559,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.
 *********************************************************************/
@@ -1507,7 +1587,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 );
@@ -1564,7 +1644,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);
@@ -2846,46 +2926,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,
@@ -3723,11 +3807,14 @@ 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;
 
 	*pp_alias_rids = NULL;
 	*p_num_alias_rids = 0;
 
 	if (sid_check_is_builtin(domain_sid)) {
+		is_builtin = true;
 		type = SID_NAME_ALIAS;
 	}
 
@@ -3761,11 +3848,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;
 
@@ -3789,14 +3885,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;
 }
 
@@ -5070,6 +5176,76 @@ 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;
+	}
+
+	if (!string_to_sid(&group_sid, group_sid_string)) {
+		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 are called only if
@@ -6420,6 +6596,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;


-- 
Samba Shared Repository


More information about the samba-cvs mailing list