[PATCH] 2.2.2 support for master/slave LDAP

David Le Corfec david.le-corfec at idealx.com
Fri Dec 21 02:59:02 GMT 2001


Hi,

It adds a "ldap master server" config param, to indicate the IP of
the master, write-only server. The "ldap server" will be read-only.
LDAP replication must be set up between master and slave, preferrably :)
Both master and slave share the other ldap parameters.
If no master given, it behaves like it should (no extra connection).

Why this patch ?
Because there's no rebinding yet in OpenLDAP SDK when a slave
returns a referral to the master (or more exactly, if referrals are
enabled, it binds on master as anonymous - though it is said to work
correctly with SASL strong auth mechs, but I don't use that).

I don't hope to see the patch in its current form to be integrated soon
in Samba for various reasons, but it could give ideas to people,
and I'll be more reassured that it never breaks if you take a look
at it too :)

Caveat:
when using a replicated ldap setup, wait some seconds after adding
an account in master (using a "add user script" directive ending with
sleep 5 :), so the user is replicated to the slave before Samba
attempts to search for it in the slave.

-david

diff -rup samba-2.2.2.orig/source/include/proto.h samba-2.2.2/source/include/proto.h
--- samba-2.2.2.orig/source/include/proto.h	Sat Oct 13 23:09:22 2001
+++ samba-2.2.2/source/include/proto.h	Mon Dec 17 18:36:23 2001
@@ -1776,6 +1776,7 @@ BOOL lp_winbind_enum_users(void);
 BOOL lp_winbind_enum_groups(void);
 char *lp_codepagedir(void);
 char *lp_ldap_server(void);
+char *lp_ldap_master_server(void);
 char *lp_ldap_suffix(void);
 char *lp_ldap_filter(void);
 char *lp_ldap_admin_dn(void);
diff -rup samba-2.2.2.orig/source/param/loadparm.c samba-2.2.2/source/param/loadparm.c
--- samba-2.2.2.orig/source/param/loadparm.c	Sat Oct 13 23:09:31 2001
+++ samba-2.2.2/source/param/loadparm.c	Thu Dec 20 20:16:07 2001
@@ -211,6 +211,7 @@ typedef struct
 	int ldap_port;
 	int ldap_ssl;
 	char *szLdapServer;
+	char *szLdapMasterServer;
 	char *szLdapSuffix;
 	char *szLdapFilter;
 	char *szLdapAdminDn;
@@ -969,6 +970,7 @@ static struct parm_struct parm_table[] =
 	{"Ldap Options", P_SEP, P_SEPARATOR},
 	
 	{"ldap server", P_STRING, P_GLOBAL, &Globals.szLdapServer, NULL, NULL, 0},
+	{"ldap master server", P_STRING, P_GLOBAL, &Globals.szLdapMasterServer, NULL, NULL, 0},
 	{"ldap port", P_INTEGER, P_GLOBAL, &Globals.ldap_port, NULL, NULL, 0}, 
 	{"ldap suffix", P_STRING, P_GLOBAL, &Globals.szLdapSuffix, NULL, NULL, 0},
 	{"ldap filter", P_STRING, P_GLOBAL, &Globals.szLdapFilter, NULL, NULL, 0},
@@ -1338,6 +1340,7 @@ static void init_globals(void)
 
 #ifdef WITH_LDAP_SAM
 	string_set(&Globals.szLdapServer, "localhost");
+	string_set(&Globals.szLdapMasterServer, "");
 	string_set(&Globals.szLdapSuffix, "");
 	string_set(&Globals.szLdapFilter, "(&(uid=%u)(objectclass=sambaAccount))");
 	string_set(&Globals.szLdapAdminDn, "");
@@ -1518,6 +1521,7 @@ FN_GLOBAL_BOOL(lp_winbind_enum_groups, &
 FN_GLOBAL_STRING(lp_codepagedir,&Globals.szCodePageDir)
 #ifdef WITH_LDAP_SAM
 FN_GLOBAL_STRING(lp_ldap_server, &Globals.szLdapServer)
+FN_GLOBAL_STRING(lp_ldap_master_server, &Globals.szLdapMasterServer)
 FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.szLdapSuffix)
 FN_GLOBAL_STRING(lp_ldap_filter, &Globals.szLdapFilter)
 FN_GLOBAL_STRING(lp_ldap_admin_dn, &Globals.szLdapAdminDn)
diff -rup samba-2.2.2.orig/source/passdb/pdb_ldap.c samba-2.2.2/source/passdb/pdb_ldap.c
--- samba-2.2.2.orig/source/passdb/pdb_ldap.c	Thu Oct 11 11:40:00 2001
+++ samba-2.2.2/source/passdb/pdb_ldap.c	Fri Dec 21 11:06:03 2001
@@ -64,10 +64,10 @@ static struct ldap_enum_info global_ldap
 
 
 /*******************************************************************
- open a connection to the ldap server.
+ open a connection to an ldap server.
 ******************************************************************/
 static BOOL
-ldap_open_connection (LDAP ** ldap_struct)
+ldap_open_server_connection (LDAP ** ldap_struct, char *ldap_server)
 {
 	int port;
 	int version, rc;
@@ -80,8 +80,8 @@ ldap_open_connection (LDAP ** ldap_struc
 		port = lp_ldap_port();
 	}
 
-	if ((*ldap_struct = ldap_init(lp_ldap_server(), port)) == NULL)	{
-		DEBUG(0, ("The LDAP server is not responding !\n"));
+	if ((*ldap_struct = ldap_init(ldap_server, port)) == NULL)	{
+		DEBUG(0, ("The LDAP server %s is not responding !\n", ldap_server));
 		return (False);
 	}
 
@@ -132,6 +132,33 @@ ldap_open_connection (LDAP ** ldap_struc
 }
 
 /*******************************************************************
+ open a connection to the ldap server (read-only if master present).
+******************************************************************/
+static BOOL
+ldap_open_connection (LDAP ** ldap_struct)
+{
+	return ldap_open_server_connection(ldap_struct, lp_ldap_server());
+}
+
+/*******************************************************************
+ open a connection to the master ldap server (write-only).
+******************************************************************/
+static BOOL
+ldap_open_master_connection (LDAP ** ldap_struct)
+{
+	return ldap_open_server_connection(ldap_struct, lp_ldap_master_server());
+}
+
+/*******************************************************************
+ check if a connection to a master server is wanted.
+******************************************************************/
+static BOOL ldap_use_master (void)
+{
+	return (strlen(lp_ldap_server()) > 0) &&
+		(strcasecmp(lp_ldap_server(), lp_ldap_master_server()));
+}
+
+/*******************************************************************
  connect to the ldap server under system privilege.
 ******************************************************************/
 static BOOL ldap_connect_system(LDAP * ldap_struct)
@@ -827,8 +858,10 @@ BOOL pdb_delete_sam_account(char *sname)
 	int rc;
 	char *dn;
 	LDAP *ldap_struct;
+	LDAP *ldap_master_struct;
 	LDAPMessage *entry;
 	LDAPMessage *result;
+	BOOL use_master;
 
 	if (!ldap_open_connection (&ldap_struct))
 		return False;
@@ -852,21 +885,49 @@ BOOL pdb_delete_sam_account(char *sname)
 	entry = ldap_first_entry (ldap_struct, result);
 	dn = ldap_get_dn (ldap_struct, entry);
 
-	rc = ldap_delete_s (ldap_struct, dn);
+	use_master = ldap_use_master();
+	if (use_master)
+	{
+		if (!ldap_open_master_connection (&ldap_master_struct))
+		{
+			ldap_unbind (ldap_struct);
+			DEBUG(0, ("Failed to delete user %s from LDAP. (open_connection)\n", sname));
+			return False;
+		}
+		if (!ldap_connect_system (ldap_master_struct)) {
+			ldap_unbind (ldap_struct);
+			ldap_unbind (ldap_master_struct);
+			DEBUG(0, ("Failed to delete user %s from LDAP. (connect_system)\n", sname));
+			return False;
+		}
+
+		rc = ldap_delete_s (ldap_master_struct, dn);
+	}
+	else
+	{
+		rc = ldap_delete_s (ldap_struct, dn);
+	}
 
 	ldap_memfree (dn);
 	if (rc != LDAP_SUCCESS) {
 		char *ld_error;
-		ldap_get_option (ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
+		if (use_master)
+			ldap_get_option (ldap_master_struct, LDAP_OPT_ERROR_STRING, &ld_error);
+		else
+			ldap_get_option (ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
 		DEBUG (0,("failed to delete user with uid = %s with: %s\n\t%s\n",
 			sname, ldap_err2string (rc), ld_error));
 		free (ld_error);
 		ldap_unbind (ldap_struct);
+		if (use_master)
+			ldap_unbind (ldap_master_struct);
 		return False;
 	}
 
 	DEBUG (2,("successfully deleted uid = %s from the LDAP database\n", sname));
 	ldap_unbind (ldap_struct);
+	if (use_master)
+		ldap_unbind (ldap_master_struct);
 	return True;
 }
 
@@ -878,9 +939,11 @@ BOOL pdb_update_sam_account(SAM_ACCOUNT 
 	int rc;
 	char *dn;
 	LDAP *ldap_struct;
+	LDAP *ldap_master_struct;
 	LDAPMessage *result;
 	LDAPMessage *entry;
 	LDAPMod **mods;
+	BOOL use_master;
 
 	if (!ldap_open_connection(&ldap_struct)) /* open a connection to the server */
 		return False;
@@ -907,19 +970,48 @@ BOOL pdb_update_sam_account(SAM_ACCOUNT 
 	entry = ldap_first_entry(ldap_struct, result);
 	dn = ldap_get_dn(ldap_struct, entry);
 
-	rc = ldap_modify_s(ldap_struct, dn, mods);
+	use_master = ldap_use_master();
+	if (use_master)
+	{
+		if (!ldap_open_master_connection(&ldap_master_struct)) /* open a connection to the server */
+		{
+			ldap_mods_free(mods, 1);
+			ldap_unbind(ldap_struct);
+			return False;
+		}
+
+		if (!ldap_connect_system(ldap_master_struct))	/* connect as system account */
+		{
+			ldap_mods_free(mods, 1);
+			ldap_unbind(ldap_struct);
+			ldap_unbind(ldap_master_struct);
+			return False;
+		}
+		rc = ldap_modify_s(ldap_master_struct, dn, mods);
+	}
+	else
+	{
+		rc = ldap_modify_s(ldap_struct, dn, mods);
+	}
 
 	if (rc != LDAP_SUCCESS)
 	{
 		char *ld_error;
-		ldap_get_option(ldap_struct, LDAP_OPT_ERROR_STRING,
-				&ld_error);
+		if (use_master)
+			ldap_get_option(ldap_master_struct, LDAP_OPT_ERROR_STRING,
+					&ld_error);
+		else
+			ldap_get_option(ldap_struct, LDAP_OPT_ERROR_STRING,
+					&ld_error);
 		DEBUG(0,
 		      ("failed to modify user with uid = %s with: %s\n\t%s\n",
 		       pdb_get_username(newpwd), ldap_err2string(rc),
 		       ld_error));
 		free(ld_error);
+		ldap_mods_free(mods, 1);
 		ldap_unbind(ldap_struct);
+		if (use_master)
+			ldap_unbind(ldap_master_struct);
 		return False;
 	}
 
@@ -928,6 +1020,8 @@ BOOL pdb_update_sam_account(SAM_ACCOUNT 
 	       pdb_get_username(newpwd)));
 	ldap_mods_free(mods, 1);
 	ldap_unbind(ldap_struct);
+	if (use_master)
+		ldap_unbind(ldap_master_struct);
 	return True;
 }
 
@@ -939,10 +1033,12 @@ BOOL pdb_add_sam_account(SAM_ACCOUNT * n
 	int rc;
 	pstring filter;
 	LDAP *ldap_struct;
+	LDAP *ldap_master_struct;
 	LDAPMessage *result;
 	pstring dn;
 	LDAPMod **mods;
 	int ldap_op = LDAP_MOD_ADD;
+	BOOL use_master;
 
 	if (!ldap_open_connection(&ldap_struct))	/* open a connection to the server */
 	{
@@ -1000,29 +1096,64 @@ BOOL pdb_add_sam_account(SAM_ACCOUNT * n
 	init_ldap_from_sam(&mods, ldap_op, newpwd);
 	make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaAccount");
 
-	if (ldap_op == LDAP_MOD_REPLACE) {
-		rc = ldap_modify_s(ldap_struct, dn, mods);
+	use_master = ldap_use_master();
+	if (use_master)
+	{
+		if (!ldap_open_master_connection(&ldap_master_struct))	/* open a connection to the server */
+		{
+			ldap_mods_free(mods, 1);
+			ldap_unbind(ldap_struct);
+			return False;
+		}
+
+		if (!ldap_connect_system(ldap_master_struct))	/* connect as system account */
+		{
+			ldap_mods_free(mods, 1);
+			ldap_unbind(ldap_struct);
+			ldap_unbind(ldap_master_struct);
+			return False;
+		}
+
+		if (ldap_op == LDAP_MOD_REPLACE) {
+			rc = ldap_modify_s(ldap_master_struct, dn, mods);
+		}
+		else {
+			rc = ldap_add_s(ldap_master_struct, dn, mods);
+		}
 	}
-	else {
-		rc = ldap_add_s(ldap_struct, dn, mods);
+	else
+	{
+		if (ldap_op == LDAP_MOD_REPLACE) {
+			rc = ldap_modify_s(ldap_struct, dn, mods);
+		}
+		else {
+			rc = ldap_add_s(ldap_struct, dn, mods);
+		}
 	}
 
 	if (rc != LDAP_SUCCESS)
 	{
 		char *ld_error;
 
-		ldap_get_option (ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
+		if (use_master)
+			ldap_get_option (ldap_master_struct, LDAP_OPT_ERROR_STRING, &ld_error);
+		else
+			ldap_get_option (ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
 		DEBUG(0,("failed to modify user with uid = %s with: %s\n\t%s\n",
 			pdb_get_username(newpwd), ldap_err2string (rc), ld_error));
 		free(ld_error);
 		ldap_mods_free(mods, 1);
 		ldap_unbind(ldap_struct);
+		if (use_master)
+			ldap_unbind(ldap_master_struct);
 		return False;
 	}
 	
 	DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd)));
 	ldap_mods_free(mods, 1);
 	ldap_unbind(ldap_struct);
+	if (use_master)
+		ldap_unbind(ldap_master_struct);
 	return True;
 }




More information about the samba-technical mailing list