[PATCH] LDAP PASSWD SYNC v01

Stefan (metze) Metzmacher metze at metzemix.de
Thu Aug 1 06:20:02 GMT 2002


Hi Andrew,
here's the patch...

It adds a new parameter to smb.conf 'ldap passwd sync = Yes | No | Only':

Yes -> try to update the password on the LDAP-Server via extended operations.
No -> didn't try to update the passwd
Only -> This only the Passchange via  extended operations is done.
             and lmPassword, ntPassword, pwdLastSet are not updated/added

this is only availible if the ldap libs support LDAP_EXOP_X_MODIFY_PASSWD.




metze
-----------------------------------------------------------------------------
Stefan "metze" Metzmacher <metze at metzemix.de>
-------------- next part --------------
diff -Npur --exclude=CVS HEAD/source/include/smb.h HEAD-pdb/source/include/smb.h
--- HEAD/source/include/smb.h	Thu Aug  1 07:25:08 2002
+++ HEAD-pdb/source/include/smb.h	Thu Aug  1 10:11:05 2002
@@ -1375,6 +1375,9 @@ enum schema_types {SCHEMA_COMPAT, SCHEMA
 /* LDAP SSL options */
 enum ldap_ssl_types {LDAP_SSL_ON, LDAP_SSL_OFF, LDAP_SSL_START_TLS};
 
+/* LDAP PASSWD SYNC methods */
+enum ldap_passwd_sync_types {LDAP_PASSWD_SYNC_ON, LDAP_PASSWD_SYNC_OFF, LDAP_PASSWD_SYNC_ONLY};
+
 /* Remote architectures we know about. */
 enum remote_arch_types {RA_UNKNOWN, RA_WFWG, RA_OS2, RA_WIN95, RA_WINNT, RA_WIN2K, RA_SAMBA};
 
diff -Npur --exclude=CVS HEAD/source/param/loadparm.c HEAD-pdb/source/param/loadparm.c
--- HEAD/source/param/loadparm.c	Thu Aug  1 07:25:09 2002
+++ HEAD-pdb/source/param/loadparm.c	Thu Aug  1 10:57:08 2002
@@ -205,11 +205,13 @@ typedef struct
 	int iLockSpinTime;
 	char *szLdapMachineSuffix;
 	char *szLdapUserSuffix;
-	int ldap_port;
 	int ldap_ssl;
 	char *szLdapSuffix;
 	char *szLdapFilter;
 	char *szLdapAdminDn;
+#ifdef LDAP_EXOP_X_MODIFY_PASSWD
+	int ldap_passwd_sync; 
+#endif /* LDAP_EXOP_X_MODIFY_PASSWD */	
 	BOOL bMsAddPrinterWizard;
 	BOOL bDNSproxy;
 	BOOL bWINSsupport;
@@ -590,6 +592,20 @@ static struct enum_list enum_ldap_ssl[] 
 	{-1, NULL}
 };
 
+static struct enum_list enum_ldap_passwd_sync[] = {
+	{LDAP_PASSWD_SYNC_ON, "Yes"},
+	{LDAP_PASSWD_SYNC_ON, "yes"},
+	{LDAP_PASSWD_SYNC_ON, "on"},
+	{LDAP_PASSWD_SYNC_ON, "On"},
+	{LDAP_PASSWD_SYNC_OFF, "no"},
+	{LDAP_PASSWD_SYNC_OFF, "No"},
+	{LDAP_PASSWD_SYNC_OFF, "off"},
+	{LDAP_PASSWD_SYNC_OFF, "Off"},
+	{LDAP_PASSWD_SYNC_ONLY, "Only"},
+	{LDAP_PASSWD_SYNC_ONLY, "only"},
+	{-1, NULL}
+};
+
 /* Types of machine we can announce as. */
 #define ANNOUNCE_AS_NT_SERVER 1
 #define ANNOUNCE_AS_WIN95 2
@@ -968,6 +984,9 @@ static struct parm_struct parm_table[] =
 	{"ldap filter", P_STRING, P_GLOBAL, &Globals.szLdapFilter, NULL, NULL, 0},
 	{"ldap admin dn", P_STRING, P_GLOBAL, &Globals.szLdapAdminDn, NULL, NULL, 0},
 	{"ldap ssl", P_ENUM, P_GLOBAL, &Globals.ldap_ssl, NULL, enum_ldap_ssl, 0},
+#ifdef LDAP_EXOP_X_MODIFY_PASSWD	
+	{"ldap passwd sync", P_ENUM, P_GLOBAL, &Globals.ldap_passwd_sync, NULL, enum_ldap_passwd_sync, 0},
+#endif /* LDAP_EXOP_X_MODIFY_PASSWD */
 
 	{"Miscellaneous Options", P_SEP, P_SEPARATOR},
 	{"add share command", P_STRING, P_GLOBAL, &Globals.szAddShareCommand, NULL, NULL, 0},
@@ -1334,6 +1353,9 @@ static void init_globals(void)
 	string_set(&Globals.szLdapFilter, "(&(uid=%u)(objectclass=sambaAccount))");
 	string_set(&Globals.szLdapAdminDn, "");
 	Globals.ldap_ssl = LDAP_SSL_ON;
+#ifdef LDAP_EXOP_X_MODIFY_PASSWD	
+	Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
+#endif /* LDAP_EXOP_X_MODIFY_PASSWD */	
 
 /* these parameters are set to defaults that are more appropriate
    for the increasing samba install base:
@@ -1543,6 +1565,9 @@ FN_GLOBAL_STRING(lp_ldap_user_suffix, &G
 FN_GLOBAL_STRING(lp_ldap_filter, &Globals.szLdapFilter)
 FN_GLOBAL_STRING(lp_ldap_admin_dn, &Globals.szLdapAdminDn)
 FN_GLOBAL_INTEGER(lp_ldap_ssl, &Globals.ldap_ssl)
+#ifdef LDAP_EXOP_X_MODIFY_PASSWD	
+FN_GLOBAL_INTEGER(lp_ldap_passwd_sync, &Globals.ldap_passwd_sync)
+#endif /* LDAP_EXOP_X_MODIFY_PASSWD */	
 FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand)
 FN_GLOBAL_STRING(lp_change_share_cmd, &Globals.szChangeShareCommand)
 FN_GLOBAL_STRING(lp_delete_share_cmd, &Globals.szDeleteShareCommand)
diff -Npur --exclude=CVS HEAD/source/passdb/pdb_get_set.c HEAD-pdb/source/passdb/pdb_get_set.c
--- HEAD/source/passdb/pdb_get_set.c	Wed Jul 24 07:57:11 2002
+++ HEAD-pdb/source/passdb/pdb_get_set.c	Thu Aug  1 12:18:47 2002
@@ -963,7 +963,7 @@ BOOL pdb_set_plaintext_pw_only (SAM_ACCO
 
 	data_blob_clear_free(&sampass->private.plaintext_pw);
 	
-	sampass->private.plaintext_pw = data_blob(password, len);
+	sampass->private.plaintext_pw = data_blob(password, len+1);
 
 	return True;
 }
@@ -1061,6 +1061,9 @@ BOOL pdb_set_plaintext_passwd (SAM_ACCOU
 		return False;
 
 	if (!pdb_set_lanman_passwd (sampass, new_lanman_p16)) 
+		return False;
+
+	if (!pdb_set_plaintext_pw_only (sampass, plaintext,strlen(plaintext))) 
 		return False;
 	
 	if (!pdb_set_pass_changed_now (sampass))
diff -Npur --exclude=CVS HEAD/source/passdb/pdb_ldap.c HEAD-pdb/source/passdb/pdb_ldap.c
--- HEAD/source/passdb/pdb_ldap.c	Tue Jul 30 10:39:13 2002
+++ HEAD-pdb/source/passdb/pdb_ldap.c	Thu Aug  1 15:12:50 2002
@@ -1,11 +1,12 @@
 /* 
    Unix SMB/CIFS implementation.
    LDAP protocol helper functions for SAMBA
-   Copyright (C) Gerald Carter 2001
-   Copyright (C) Shahms King 2001
-   Copyright (C) Jean Fran?ois Micouleau 1998
-   Copyright (C) Andrew Bartlett 2002
-   
+   Copyright (C) Jean Fran?ois Micouleau 	1998
+   Copyright (C) Gerald Carter 		2001
+   Copyright (C) Shahms King 			2001
+   Copyright (C) Andrew Bartlett 		2002
+   Copyright (C) Stefan (metze) Metzmacher 	2002
+    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
@@ -158,7 +159,8 @@ static const char *attr[] = {"uid", "pwd
 ******************************************************************/
 static BOOL ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP ** ldap_struct)
 {
-
+	int version;
+	
 	if (geteuid() != 0) {
 		DEBUG(0, ("ldap_open_connection: cannot access LDAP when not root..\n"));
 		return False;
@@ -171,6 +173,16 @@ static BOOL ldapsam_open_connection (str
 		DEBUG(0, ("ldap_initialize: %s\n", strerror(errno)));
 		return (False);
 	}
+
+	if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS)
+	{
+		if (version != LDAP_VERSION3)
+		{
+			version = LDAP_VERSION3;
+			ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
+		}
+	}
+
 #else 
 
 	/* Parse the string manually */
@@ -179,7 +191,6 @@ static BOOL ldapsam_open_connection (str
 		int rc;
 		int tls = LDAP_OPT_X_TLS_HARD;
 		int port = 0;
-		int version;
 		fstring protocol;
 		fstring host;
 		const char *p = ldap_state->uri; 
@@ -409,7 +420,7 @@ static int ldapsam_search_one_user (stru
 
 	DEBUG(2, ("ldapsam_search_one_user: searching for:[%s]\n", filter));
 
-	rc = ldap_search_s(ldap_struct, lp_ldap_suffix (), scope, filter, attr, 0, result);
+	rc = ldap_search_s(ldap_struct, lp_ldap_suffix (), scope, filter, (char **)attr, 0, result);
 
 	if (rc != LDAP_SUCCESS)	{
 		DEBUG(0,("ldapsam_search_one_user: Problem during the LDAP search: %s\n", 
@@ -932,9 +943,6 @@ static BOOL init_ldap_from_sam (struct l
 	slprintf(temp, sizeof(temp) - 1, "%i", rid);
 	make_a_mod(mods, ldap_op, "primaryGroupID", temp);
 
-	slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass));
-	make_a_mod(mods, ldap_op, "pwdLastSet", temp);
-
 	/* displayName, cn, and gecos should all be the same
 	   *  most easily accomplished by giving them the same OID
 	   *  gecos isn't set here b/c it should be handled by the 
@@ -977,6 +985,7 @@ static BOOL init_ldap_from_sam (struct l
 		make_a_mod(mods, ldap_op, "kickoffTime", temp);
 	}
 
+
 	if (IS_SAM_SET(sampass, FLAG_SAM_CANCHANGETIME)) {
 		slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time(sampass));
 		make_a_mod(mods, ldap_op, "pwdCanChange", temp);
@@ -987,13 +996,26 @@ static BOOL init_ldap_from_sam (struct l
 		make_a_mod(mods, ldap_op, "pwdMustChange", temp);
 	}
 
-	/* FIXME: Hours stuff goes in LDAP  */
-	pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass), pdb_get_acct_ctrl(sampass));
-	make_a_mod (mods, ldap_op, "lmPassword", temp);
+#ifdef LDAP_EXOP_X_MODIFY_PASSWD
+	if (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)
+	{
+#endif /* LDAP_EXOP_X_MODIFY_PASSWD */
+
+		pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass), pdb_get_acct_ctrl(sampass));
+		make_a_mod (mods, ldap_op, "lmPassword", temp);
 	
-	pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass), pdb_get_acct_ctrl(sampass));
-	make_a_mod (mods, ldap_op, "ntPassword", temp);
+		pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass), pdb_get_acct_ctrl(sampass));
+		make_a_mod (mods, ldap_op, "ntPassword", temp);
 	
+		slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass));
+		make_a_mod(mods, ldap_op, "pwdLastSet", temp);
+
+#ifdef LDAP_EXOP_X_MODIFY_PASSWD
+	}
+#endif /* LDAP_EXOP_X_MODIFY_PASSWD */
+
+	/* FIXME: Hours stuff goes in LDAP  */
+
 	make_a_mod (mods, ldap_op, "acctFlags", pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass),
 		NEW_PW_FORMAT_SPACE_PADDED_LEN));
 
@@ -1081,7 +1103,7 @@ static uint32 search_top_nua_rid(struct 
 	DEBUG(2, ("ldapsam_get_next_available_nua_rid: searching for:[%s]\n", final_filter));
 
 	rc = ldap_search_s(ldap_struct, lp_ldap_suffix(),
-			   LDAP_SCOPE_SUBTREE, final_filter, attr, 0,
+			   LDAP_SCOPE_SUBTREE, final_filter, (char **)attr, 0,
 			   &result);
 
 	if (rc != LDAP_SUCCESS)
@@ -1179,7 +1201,7 @@ static BOOL ldapsam_setsampwent(struct p
 	all_string_sub(filter, "%u", "*", sizeof(pstring));
 
 	rc = ldap_search_s(ldap_state->ldap_struct, lp_ldap_suffix(),
-			   LDAP_SCOPE_SUBTREE, filter, attr, 0,
+			   LDAP_SCOPE_SUBTREE, filter, (char **)attr, 0,
 			   &ldap_state->result);
 
 	if (rc != LDAP_SUCCESS)
@@ -1433,6 +1455,7 @@ static BOOL ldapsam_update_sam_account(s
 	LDAPMessage *result;
 	LDAPMessage *entry;
 	LDAPMod **mods;
+	int version;
 
 	if (!ldapsam_open_connection(ldap_state, &ldap_struct)) /* open a connection to the server */
 		return False;
@@ -1480,6 +1503,70 @@ static BOOL ldapsam_update_sam_account(s
 		return False;
 	}
 
+#ifdef LDAP_EXOP_X_MODIFY_PASSWD
+	if (ldap_get_option(ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS)
+	{
+		if (version != LDAP_VERSION3)
+		{
+			version = LDAP_VERSION3;
+			ldap_set_option (ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
+		}
+	}
+        
+	if ((lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_OFF)&&(pdb_get_plaintext_passwd(newpwd)!=NULL))
+	{
+		BerElement *ber;
+		struct berval *bv;
+		char *retoid;
+		struct berval *retdata;
+		char *new_passwd;
+
+		if ((ber = ber_alloc_t(LBER_USE_DER))==NULL)
+		{
+			DEBUG(0,("ber_alloc_t returns NULL\n"));
+			return False;
+		}
+
+		if ((new_passwd = (char *)malloc(newpwd->private.plaintext_pw.length+1))==NULL)
+		{
+			DEBUG(0,("malloc returns NULL\n"));
+			return False;
+		}
+
+		snprintf(new_passwd,newpwd->private.plaintext_pw.length,"%s",newpwd->private.plaintext_pw.data);
+
+		ber_printf (ber, "{");
+		ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID,dn);
+	        ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, new_passwd);
+	        ber_printf (ber, "N}");
+
+		free(new_passwd);
+		    			
+	        if ((rc = ber_flatten (ber, &bv))<0)
+		{
+			DEBUG(0,("ber_flatten returns a value <0\n"));
+			return False;
+		}
+		
+		ber_free(ber,1);
+		
+		if ((rc = ldap_extended_operation_s(ldap_struct, LDAP_EXOP_X_MODIFY_PASSWD,
+						    bv, NULL, NULL, &retoid, &retdata))!=LDAP_SUCCESS)
+		{
+			DEBUG(0,("LDAP Password could not be changed for user %s: %s\n",
+				pdb_get_username(newpwd),ldap_err2string(rc)));
+		} else {
+			DEBUG(3,("LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
+    
+			ber_bvfree(retdata);
+			ber_memfree(retoid);
+		}
+		ber_bvfree(bv);
+	}
+#else
+	DEBUG(10,("LDAP PASSWORD SYNC is not supported!\n"));
+#endif /* LDAP_EXOP_X_MODIFY_PASSWD */
+
 	DEBUG(2,
 	      ("successfully modified uid = %s in the LDAP database\n",
 	       pdb_get_username(newpwd)));
@@ -1502,7 +1589,8 @@ static BOOL ldapsam_add_sam_account(stru
 	LDAPMod **mods = NULL;
 	int 		ldap_op;
 	uint32		num_result;
-
+	int version;
+	
 	const char *username = pdb_get_username(newpwd);
 	if (!username || !*username) {
 		DEBUG(0, ("Cannot add user without a username!\n"));
@@ -1593,6 +1681,70 @@ static BOOL ldapsam_add_sam_account(stru
 		ldap_unbind(ldap_struct);
 		return False;
 	}
+
+#ifdef LDAP_EXOP_X_MODIFY_PASSWD
+	if (ldap_get_option(ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS)
+	{
+		if (version != LDAP_VERSION3)
+		{
+			version = LDAP_VERSION3;
+			ldap_set_option (ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
+		}
+	}
+        
+	if ((lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_OFF)&&(pdb_get_plaintext_passwd(newpwd)!=NULL))
+	{
+		BerElement *ber;
+		struct berval *bv;
+		char *retoid;
+		struct berval *retdata;
+		char *new_passwd;
+
+		if ((ber = ber_alloc_t(LBER_USE_DER))==NULL)
+		{
+			DEBUG(0,("ber_alloc_t returns NULL\n"));
+			return False;
+		}
+
+		if ((new_passwd = (char *)malloc(newpwd->private.plaintext_pw.length+1))==NULL)
+		{
+			DEBUG(0,("malloc returns NULL\n"));
+			return False;
+		}
+
+		snprintf(new_passwd,newpwd->private.plaintext_pw.length,"%s",newpwd->private.plaintext_pw.data);
+
+		ber_printf (ber, "{");
+		ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID,dn);
+	        ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, new_passwd);
+	        ber_printf (ber, "N}");
+
+		free(new_passwd);
+		    			
+	        if ((rc = ber_flatten (ber, &bv))<0)
+		{
+			DEBUG(0,("ber_flatten returns a value <0\n"));
+			return False;
+		}
+		
+		ber_free(ber,1);
+		
+		if ((rc = ldap_extended_operation_s(ldap_struct, LDAP_EXOP_X_MODIFY_PASSWD,
+						    bv, NULL, NULL, &retoid, &retdata))!=LDAP_SUCCESS)
+		{
+			DEBUG(0,("LDAP Password could not be changed for user %s: %s\n",
+				pdb_get_username(newpwd),ldap_err2string(rc)));
+		} else {
+			DEBUG(3,("LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
+    
+			ber_bvfree(retdata);
+			ber_memfree(retoid);
+		}
+		ber_bvfree(bv);
+	}
+#else
+	DEBUG(10,("LDAP PASSWORD SYNC is not supported!\n"));
+#endif /* LDAP_EXOP_X_MODIFY_PASSWD */
 	
 	DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd)));
 	ldap_mods_free(mods, 1);


More information about the samba-technical mailing list