samba ldap 2.2.1a patch (should apply again 2.2 CVS as well)

Shahms E. King shahms at shahms.com
Fri Jul 20 20:51:05 GMT 2001


I've cleaned up the LDAP code in samba so that it follows a coherenet 
schema as well as actually working.  This code compiles and works, and 
has been ported to the new passdb interface, but that forward port has 
some quirks and bugs which will remain until the new interface is 
backported to 2.2.x

--Shahms
-------------- next part --------------
diff -urN samba-2.2.1a/source/configure.in samba-2.2.1a-shahms/source/configure.in
--- samba-2.2.1a/source/configure.in	Mon Jul  9 17:12:50 2001
+++ samba-2.2.1a-shahms/source/configure.in	Thu Jul 12 08:21:18 2001
@@ -1712,22 +1712,24 @@
 # --jerry
 #
 # check for a LDAP password database
-#AC_MSG_CHECKING(whether to use LDAP password database)
-#AC_ARG_WITH(ldap,
-#[  --with-ldap     Include LDAP support
-#  --without-ldap  Don't include LDAP support (default)],
-#[ case "$withval" in
-#  yes)
-#    AC_MSG_RESULT(yes)
-#    AC_DEFINE(WITH_LDAP)
+AC_MSG_CHECKING(whether to use LDAP password database)
+AC_ARG_WITH(ldap,
+[  --with-ldap     Include LDAP support
+  --without-ldap  Don't include LDAP support (default)],
+[ case "$withval" in
+  yes)
+    AC_MSG_RESULT(yes)
+    AC_DEFINE(WITH_LDAP)
+    LIBS="-lldap -llber -lresolv $LIBS"
 #    AC_MSG_ERROR([LDAP password database not supported in this version.])
-#    ;;
-#  *)
-#    AC_MSG_RESULT(no)
-#    ;;
-#  esac ],
-#  AC_MSG_RESULT(no)
-#)
+    ;;
+  *)
+    AC_MSG_RESULT(no)
+    ;;
+  esac ],
+  AC_MSG_RESULT(no)
+)
+
 
 #################################################
 # check for a NISPLUS password database
diff -urN samba-2.2.1a/source/include/smb.h samba-2.2.1a-shahms/source/include/smb.h
--- samba-2.2.1a/source/include/smb.h	Thu Jul  5 19:01:30 2001
+++ samba-2.2.1a-shahms/source/include/smb.h	Fri Jul 20 12:05:09 2001
@@ -1448,6 +1448,9 @@
 #endif /* DEVELOPER */
 };
 
+/* LDAP schema types */
+enum schema_types {SCHEMA_COMPAT, SCHEMA_AD, SCHEMA_SAMBA};
+
 /* Remote architectures we know about. */
 enum remote_arch_types {RA_UNKNOWN, RA_WFWG, RA_OS2, RA_WIN95, RA_WINNT, RA_WIN2K, RA_SAMBA};
 
diff -urN samba-2.2.1a/source/param/loadparm.c samba-2.2.1a-shahms/source/param/loadparm.c
--- samba-2.2.1a/source/param/loadparm.c	Thu Jul 12 15:44:08 2001
+++ samba-2.2.1a-shahms/source/param/loadparm.c	Fri Jul 20 12:04:45 2001
@@ -152,11 +152,6 @@
 	char *szNetbiosAliases;
 	char *szDomainOtherSIDs;
 	char *szNameResolveOrder;
-	char *szLdapServer;
-	char *szLdapSuffix;
-	char *szLdapFilter;
-	char *szLdapRoot;
-	char *szLdapRootPassword;
 	char *szPanicAction;
 	char *szAddUserScript;
 	char *szDelUserScript;
@@ -211,6 +206,12 @@
 	int winbind_cache_time;
 #ifdef WITH_LDAP
 	int ldap_port;
+	int  ldap_schema;
+	char *szLdapServer;
+	char *szLdapSuffix;
+	char *szLdapFilter;
+	char *szLdapRoot;
+	char *szLdapRootPassword;
 #endif				/* WITH_LDAP */
 #ifdef WITH_SSL
 	int sslVersion;
@@ -571,6 +572,14 @@
 	{-1, NULL}
 };
 
+static struct enum_list enum_ldap_schema[] = {
+	{SCHEMA_COMPAT, "compat"},
+	{SCHEMA_AD, "ad"},
+	{SCHEMA_AD, "active directory"},
+	{SCHEMA_SAMBA, "samba"},
+	{-1, NULL}
+};
+
 /* Types of machine we can announce as. */
 #define ANNOUNCE_AS_NT_SERVER 1
 #define ANNOUNCE_AS_WIN95 2
@@ -942,6 +951,7 @@
 	{"ldap filter", P_STRING, P_GLOBAL, &Globals.szLdapFilter, NULL, NULL, 0},
 	{"ldap root", P_STRING, P_GLOBAL, &Globals.szLdapRoot, NULL, NULL, 0},
 	{"ldap root passwd", P_STRING, P_GLOBAL, &Globals.szLdapRootPassword, NULL, NULL, 0},
+	{"ldap schema", P_ENUM, P_GLOBAL, &Globals.ldap_schema, NULL, enum_ldap_schema, 0},
 #endif /* WITH_LDAP */
 
 	{"Miscellaneous Options", P_SEP, P_SEPARATOR},
@@ -1280,12 +1290,6 @@
 	Globals.oplock_break_wait_time = 0;	/* By Default, 0 msecs. */
 	Globals.enhanced_browsing = True; 
 
-#ifdef WITH_LDAP
-	/* default values for ldap */
-	string_set(&Globals.szLdapServer, "localhost");
-	Globals.ldap_port = 389;
-#endif /* WITH_LDAP */
-
 #ifdef WITH_SSL
 	Globals.sslVersion = SMB_SSL_V23;
 	string_set(&Globals.sslHostsRequire, "");
@@ -1303,6 +1307,16 @@
 	Globals.sslCompatibility = False;
 #endif /* WITH_SSL */
 
+#ifdef WITH_LDAP
+	string_set(&Globals.szLdapServer, "localhost");
+	string_set(&Globals.szLdapSuffix, "");
+	string_set(&Globals.szLdapFilter, "(&(uid=%u)(objectclass=sambaAccount))");
+	string_set(&Globals.szLdapRoot, "");
+	string_set(&Globals.szLdapRootPassword, "");
+	Globals.ldap_port = 389;
+	Globals.ldap_schema = SCHEMA_COMPAT;
+	
+#endif /* WITH_LDAP */
 /* these parameters are set to defaults that are more appropriate
    for the increasing samba install base:
 
@@ -1336,7 +1350,7 @@
 	string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
 	string_set(&Globals.szWinbindSeparator, "\\");
 	Globals.winbind_cache_time = 15;
-
+	
 	/*
 	 * This must be done last as it checks the value in 
 	 * client_code_page.
@@ -1476,6 +1490,8 @@
 FN_GLOBAL_STRING(lp_ldap_filter, &Globals.szLdapFilter)
 FN_GLOBAL_STRING(lp_ldap_root, &Globals.szLdapRoot)
 FN_GLOBAL_STRING(lp_ldap_rootpasswd, &Globals.szLdapRootPassword)
+FN_GLOBAL_INTEGER(lp_ldap_schema, &Globals.ldap_schema)
+FN_GLOBAL_INTEGER(lp_ldap_port, &Globals.ldap_port)
 #endif /* WITH_LDAP */
 FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand)
 FN_GLOBAL_STRING(lp_change_share_cmd, &Globals.szChangeShareCommand)
@@ -1569,9 +1585,6 @@
 FN_GLOBAL_INTEGER(lp_map_to_guest, &Globals.map_to_guest)
 FN_GLOBAL_INTEGER(lp_min_passwd_length, &Globals.min_passwd_length)
 FN_GLOBAL_INTEGER(lp_oplock_break_wait_time, &Globals.oplock_break_wait_time)
-#ifdef WITH_LDAP
-FN_GLOBAL_INTEGER(lp_ldap_port, &Globals.ldap_port)
-#endif				/* WITH_LDAP */
 FN_LOCAL_STRING(lp_preexec, szPreExec)
 FN_LOCAL_STRING(lp_postexec, szPostExec)
 FN_LOCAL_STRING(lp_rootpreexec, szRootPreExec)
diff -urN samba-2.2.1a/source/passdb/ldap.c samba-2.2.1a-shahms/source/passdb/ldap.c
--- samba-2.2.1a/source/passdb/ldap.c	Fri Feb 25 14:25:24 2000
+++ samba-2.2.1a-shahms/source/passdb/ldap.c	Fri Jul 20 13:35:36 2001
@@ -1,7 +1,8 @@
 /* 
    Unix SMB/Netbios implementation.
-   Version 1.9.
+   Version 2.9.
    LDAP protocol helper functions for SAMBA
+   Copyright (C) Shahms King 2001
    Copyright (C) Jean François Micouleau 1998
    
    This program is free software; you can redistribute it and/or modify
@@ -20,24 +21,47 @@
    
 */
 
+#include "includes.h"
+
 #ifdef WITH_LDAP
+/* TODO:
+*  persistent connections: don't make a new connection for each LDAP op
+*  perhaps ldap_init() and ldap_bind? on ldap_initialize_database
+*
+*  SSL/SASL support, I don't like keeping plaintext passwords in the 
+*  smb.conf file, nor do I like sending them over the wire, SSL let's us
+*  do Cert. based auth with the server
+*/
 
-#include "includes.h"
+/* NOTE: this will NOT work against an Active Directory server
+*  due to the fact that the two password fields cannot be retrieved
+*  from a server; recommend using security = domain in this situation
+*  and/or winbind
+*/
 
 #include <lber.h>
 #include <ldap.h>
 
-#define ADD_USER 1
-#define MODIFY_USER 2
+#define SAM_ACCOUNT struct sam_passwd
 
 extern int DEBUGLEVEL;
 
+struct ldap_enum_info
+{
+	LDAP *ldap_struct;
+	LDAPMessage *result;
+	LDAPMessage *entry;
+};
+
+static struct ldap_enum_info global_ldap_ent;
+
 /*******************************************************************
  open a connection to the ldap serve.
 ******************************************************************/	
 static BOOL ldap_open_connection(LDAP **ldap_struct)
 {
-	if ( (*ldap_struct = ldap_open(lp_ldap_server(),lp_ldap_port()) ) == NULL)
+	/* OpenLDAP prefers ldap_init(), and is depreciating ldap_open() */
+	if ( (*ldap_struct = ldap_init(lp_ldap_server(),lp_ldap_port()) ) == NULL) 
 	{
 		DEBUG( 0, ( "The LDAP server is not responding !\n" ) );
 		return( False );
@@ -53,7 +77,7 @@
 ******************************************************************/	
 static BOOL ldap_connect_anonymous(LDAP *ldap_struct)
 {
-	if ( ldap_simple_bind_s(ldap_struct,lp_ldap_root(),lp_ldap_rootpasswd()) ! = LDAP_SUCCESS)
+	if ( ldap_simple_bind_s(ldap_struct,NULL,NULL) != LDAP_SUCCESS)
 	{
 		DEBUG( 0, ( "Couldn't bind to the LDAP server !\n" ) );
 		return(False);
@@ -67,7 +91,7 @@
 ******************************************************************/	
 static BOOL ldap_connect_system(LDAP *ldap_struct)
 {
-	if ( ldap_simple_bind_s(ldap_struct,lp_ldap_root(),lp_ldap_rootpasswd()) ! = LDAP_SUCCESS)
+	if ( ldap_simple_bind_s(ldap_struct,lp_ldap_root(),lp_ldap_rootpasswd()) != LDAP_SUCCESS)
 	{
 		DEBUG( 0, ( "Couldn't bind to the LDAP server!\n" ) );
 		return(False);
@@ -81,7 +105,7 @@
 ******************************************************************/	
 static BOOL ldap_connect_user(LDAP *ldap_struct, char *user, char *password)
 {
-	if ( ldap_simple_bind_s(ldap_struct,lp_ldap_root(),lp_ldap_rootpasswd()) ! = LDAP_SUCCESS)
+	if ( ldap_simple_bind_s(ldap_struct,user,password) != LDAP_SUCCESS)
 	{
 		DEBUG( 0, ( "Couldn't bind to the LDAP server !\n" ) );
 		return(False);
@@ -95,16 +119,16 @@
 ******************************************************************/	
 static BOOL ldap_search_one_user(LDAP *ldap_struct, char *filter, LDAPMessage **result)
 {	
-	int scope = LDAP_SCOPE_ONELEVEL;
+	int scope = LDAP_SCOPE_SUBTREE;
 	int rc;
 		
 	DEBUG(2,("ldap_search_one_user: searching for:[%s]\n", filter));
 		
 	rc = ldap_search_s(ldap_struct, lp_ldap_suffix(), scope, filter, NULL, 0, result);
 
-	if (rc ! = LDAP_SUCCESS )
+	if (rc != LDAP_SUCCESS )
 	{
-		DEBUG( 0, ( "Problem during the LDAP search\n" ) );
+		DEBUG( 0, ( "Problem during the LDAP search: %s\n",ldap_err2string(rc) ) );
 		return(False);
 	}
 	return (True);
@@ -137,7 +161,7 @@
 {	
 	pstring filter;
 	
-	slprintf(filter, sizeof(pstring)-1, "uidAccount = %d", uid);
+	slprintf(filter, sizeof(pstring)-1, "uidNumber=%d", uid);
 	
 	if ( !ldap_search_one_user(ldap_struct, filter, result) )
 	{	
@@ -153,221 +177,16 @@
 {
 	char **valeurs;
 	
-	if ( (valeurs = ldap_get_values(ldap_struct, entry, attribute)) ! = NULL) 
+	if ( (valeurs = ldap_get_values(ldap_struct, entry, attribute)) != NULL) 
 	{
 		pstrcpy(value, valeurs[0]);
 		ldap_value_free(valeurs);
-		DEBUG(3,("get_single_attribute:	[%s] = [%s]\n", attribute, value));	
+		DEBUG(2,("get_single_attribute:	[%s] = [%s]\n", attribute, value));	
 	}
 	else
 	{
 		value = NULL;
-	}
-}
-
-/*******************************************************************
- check if the returned entry is a sambaAccount objectclass.
-******************************************************************/	
-static BOOL ldap_check_user(LDAP *ldap_struct, LDAPMessage *entry)
-{
-	BOOL sambaAccount = False;
-	char **valeur;
-	int i;
-
-	DEBUG(2,("ldap_check_user: "));
-	valeur = ldap_get_values(ldap_struct, entry, "objectclass");
-	if (valeur! = NULL)
-	{
-		for (i = 0;valeur[i]! = NULL;i++)
-		{
-			if (!strcmp(valeur[i],"sambaAccount")) sambaAccount = True;
-		}
-	}
-	DEBUG(2,("%s\n",sambaAccount?"yes":"no"));
-	ldap_value_free(valeur);
-	return (sambaAccount);
-}
-
-/*******************************************************************
- check if the returned entry is a sambaTrust objectclass.
-******************************************************************/	
-static BOOL ldap_check_trust(LDAP *ldap_struct, LDAPMessage *entry)
-{
-	BOOL sambaTrust = False;
-	char **valeur;
-	int i;
-	
-	DEBUG(2,("ldap_check_trust: "));
-	valeur = ldap_get_values(ldap_struct, entry, "objectclass");
-	if (valeur! = NULL)
-	{
-		for (i = 0;valeur[i]! = NULL;i++)
-		{
-			if (!strcmp(valeur[i],"sambaTrust")) sambaTrust = True;
-		}
-	}	
-	DEBUG(2,("%s\n",sambaTrust?"yes":"no"));
-	ldap_value_free(valeur);	
-	return (sambaTrust);
-}
-
-/*******************************************************************
- retrieve the user's info and contruct a smb_passwd structure.
-******************************************************************/
-static void ldap_get_smb_passwd(LDAP *ldap_struct,LDAPMessage *entry, 
-                          struct smb_passwd *user)
-{	
-	static pstring user_name;
-	static pstring user_pass;
-	static pstring temp;
-	static unsigned char smblmpwd[16];
-	static unsigned char smbntpwd[16];
-
-	pdb_init_smb(user);
-
-	memset((char *)smblmpwd, '\0', sizeof(smblmpwd));
-	memset((char *)smbntpwd, '\0', sizeof(smbntpwd));
-
-	get_single_attribute(ldap_struct, entry, "cn", user_name);
-	DEBUG(2,("ldap_get_smb_passwd: user: %s\n",user_name));
-		
-#ifdef LDAP_PLAINTEXT_PASSWORD
-	get_single_attribute(ldap_struct, entry, "userPassword", temp);
-	nt_lm_owf_gen(temp, user->smb_nt_passwd, user->smb_passwd);
-	memset((char *)temp, '\0', sizeof(temp)); /* destroy local copy of the password */
-#else
-	get_single_attribute(ldap_struct, entry, "unicodePwd", temp);
-	pdb_gethexpwd(temp, smbntpwd);		
-	memset((char *)temp, '\0', sizeof(temp)); /* destroy local copy of the password */
-
-	get_single_attribute(ldap_struct, entry, "dBCSPwd", temp);
-	pdb_gethexpwd(temp, smblmpwd);		
-	memset((char *)temp, '\0', sizeof(temp)); /* destroy local copy of the password */
-#endif
-	
-	get_single_attribute(ldap_struct, entry, "userAccountControl", temp);
-	user->acct_ctrl = pdb_decode_acct_ctrl(temp);
-
-	get_single_attribute(ldap_struct, entry, "pwdLastSet", temp);
-	user->pass_last_set_time = (time_t)strtol(temp, NULL, 16);
-
-	get_single_attribute(ldap_struct, entry, "rid", temp);
-
-	/* the smb (unix) ids are not stored: they are created */
-	user->smb_userid = pdb_user_rid_to_uid (atoi(temp));
-
-	if (user->acct_ctrl & (ACB_DOMTRUST|ACB_WSTRUST|ACB_SVRTRUST) )
-	{
-		DEBUG(0,("Inconsistency in the LDAP database\n"));
-	}
-	if (user->acct_ctrl & ACB_NORMAL)
-	{
-		user->smb_name      = user_name;
-		user->smb_passwd    = smblmpwd;
-		user->smb_nt_passwd = smbntpwd;
-	}
-}
-
-/*******************************************************************
- retrieve the user's info and contruct a sam_passwd structure.
-
- calls ldap_get_smb_passwd function first, though, to save code duplication.
-
-******************************************************************/
-static void ldap_get_sam_passwd(LDAP *ldap_struct, LDAPMessage *entry, 
-                          struct sam_passwd *user)
-{	
-	static pstring user_name;
-	static pstring fullname;
-	static pstring home_dir;
-	static pstring dir_drive;
-	static pstring logon_script;
-	static pstring profile_path;
-	static pstring acct_desc;
-	static pstring workstations;
-	static pstring temp;
-	static struct smb_passwd pw_buf;
-
-	pdb_init_sam(user);
-
-	ldap_get_smb_passwd(ldap_struct, entry, &pw_buf);
-	
-	user->pass_last_set_time    = pw_buf.pass_last_set_time;
-
-	get_single_attribute(ldap_struct, entry, "logonTime", temp);
-	user->pass_last_set_time = (time_t)strtol(temp, NULL, 16);
-
-	get_single_attribute(ldap_struct, entry, "logoffTime", temp);
-	user->pass_last_set_time = (time_t)strtol(temp, NULL, 16);
-
-	get_single_attribute(ldap_struct, entry, "kickoffTime", temp);
-	user->pass_last_set_time = (time_t)strtol(temp, NULL, 16);
-
-	get_single_attribute(ldap_struct, entry, "pwdLastSet", temp);
-	user->pass_last_set_time = (time_t)strtol(temp, NULL, 16);
-
-	get_single_attribute(ldap_struct, entry, "pwdCanChange", temp);
-	user->pass_last_set_time = (time_t)strtol(temp, NULL, 16);
-
-	get_single_attribute(ldap_struct, entry, "pwdMustChange", temp);
-	user->pass_last_set_time = (time_t)strtol(temp, NULL, 16);
-
-	user->smb_name = pw_buf.smb_name;
-
-	DEBUG(2,("ldap_get_sam_passwd: user: %s\n", user_name));
-		
-	get_single_attribute(ldap_struct, entry, "userFullName", fullname);
-	user->full_name = fullname;
-
-	get_single_attribute(ldap_struct, entry, "homeDirectory", home_dir);
-	user->home_dir = home_dir;
-
-	get_single_attribute(ldap_struct, entry, "homeDrive", dir_drive);
-	user->dir_drive = dir_drive;
-
-	get_single_attribute(ldap_struct, entry, "scriptPath", logon_script);
-	user->logon_script = logon_script;
-
-	get_single_attribute(ldap_struct, entry, "profilePath", profile_path);
-	user->profile_path = profile_path;
-
-	get_single_attribute(ldap_struct, entry, "comment", acct_desc);
-	user->acct_desc = acct_desc;
-
-	get_single_attribute(ldap_struct, entry, "userWorkstations", workstations);
-	user->workstations = workstations;
-
-	user->unknown_str = NULL; /* don't know, yet! */
-	user->munged_dial = NULL; /* "munged" dial-back telephone number */
-
-	get_single_attribute(ldap_struct, entry, "rid", temp);
-	user->user_rid = atoi(temp);
-
-	get_single_attribute(ldap_struct, entry, "primaryGroupID", temp);
-	user->group_rid = atoi(temp);
-
-	/* the smb (unix) ids are not stored: they are created */
-	user->smb_userid = pw_buf.smb_userid;
-	user->smb_grpid = group_rid_to_uid(user->group_rid);
-
-	user->acct_ctrl = pw_buf.acct_ctrl;
-
-	user->unknown_3 = 0xffffff; /* don't know */
-	user->logon_divs = 168; /* hours per week */
-	user->hours_len = 21; /* 21 times 8 bits = 168 */
-	memset(user->hours, 0xff, user->hours_len); /* available at all hours */
-	user->unknown_5 = 0x00020000; /* don't know */
-	user->unknown_5 = 0x000004ec; /* don't know */
-
-	if (user->acct_ctrl & (ACB_DOMTRUST|ACB_WSTRUST|ACB_SVRTRUST) )
-	{
-		DEBUG(0,("Inconsistency in the LDAP database\n"));
-	}
-
-	if (!(user->acct_ctrl & ACB_NORMAL))
-	{
-		DEBUG(0,("User's acct_ctrl bits not set to ACT_NORMAL in LDAP database\n"));
-		return;
+		DEBUG(2,("get_single_attribute:	[%s] = [NULL]\n", attribute));	
 	}
 }
 
@@ -395,7 +214,7 @@
 		mods[0] = NULL;
 	}
 	
-	for ( i = 0; mods[ i ] ! = NULL; ++i )
+	for ( i = 0; mods[ i ] != NULL; ++i )
 	{
 		if ( mods[ i ]->mod_op == modop && 
 		    !strcasecmp( mods[ i ]->mod_type, attribute ) )
@@ -424,18 +243,18 @@
 		mods[i+1] = NULL;
 	}
 
-	if (value ! = NULL )
+	if (value != NULL )
 	{
 		j = 0;
-		if ( mods[ i ]->mod_values ! = NULL )
+		if ( mods[ i ]->mod_values != NULL )
 		{
-			for ( ; mods[ i ]->mod_values[ j ] ! = NULL; j++ );
+			for ( ; mods[ i ]->mod_values[ j ] != NULL; j++ );
 		}
 		mods[ i ]->mod_values = (char **)realloc(mods[ i ]->mod_values,
 		                                          (j+2) * sizeof( char * ));
 		if ( mods[ i ]->mod_values == NULL)
 		{
-			DEBUG(0, "make_a_mod: Memory allocation failure!\n");
+			//DEBUG(0, "make_a_mod: Memory allocation failure!\n");
 			return;
 		}
 		mods[ i ]->mod_values[ j ] = strdup(value);	
@@ -444,217 +263,455 @@
 	*modlist = mods;
 }
 
-/************************************************************************
- Add or modify an entry. Only the smb struct values
+/* New Interface is being implemented here */
 
-*************************************************************************/
-static BOOL modadd_ldappwd_entry(struct smb_passwd *newpwd, int flag)
-{
+/**********************************************************************
+ Initialize SAM_ACCOUNT from an LDAP query
+ (Based on init_sam_from_buffer in pdb_tdb.c)
+ *********************************************************************/ 
+static BOOL init_sam_from_ldap (SAM_ACCOUNT *sampass, 
+				LDAP *ldap_struct, LDAPMessage *entry)
+{
+	time_t  logon_time,
+		logoff_time,
+		kickoff_time,
+		pass_last_set_time,
+		pass_can_change_time,
+		pass_must_change_time;
+	static pstring username;
+        static pstring dir_drive;
+        static pstring unknown_str;
+        static pstring munged_dial;
+        static pstring fullname;
+        static pstring homedir;
+        static pstring logon_script;
+        static pstring profile_path;
+        static pstring acct_desc;
+        static pstring workstations;
+	static uint8 smblmpwd[16];
+	static uint8 smbntpwd[16];
+	pstring temp;
+	struct passwd	*sys_user;
+	uint32  user_rid, group_rid, unknown_3, hours_len, unknown_5, unknown_6;
+	uint16  acct_ctrl, logon_divs;
+        uint8   *hours;
+
+	get_single_attribute(ldap_struct, entry, "uid", username);	
+	DEBUG(2,("Entry found for user: %s\n",username));
 	
-	/* assume the struct is correct and filled
-	   that's the job of passdb.c to check */
-	int scope = LDAP_SCOPE_ONELEVEL;
-	int rc;
-	char *smb_name;
-	int trust = False;
-	int ldap_state;
-	pstring filter;
-	pstring dn;
-	pstring lmhash;
-	pstring nthash;
-	pstring rid;
-	pstring lst;
+	get_single_attribute(ldap_struct, entry, "pwdLastSet", temp);
+	pass_last_set_time = (time_t)strtol(temp, NULL, 16);
+
+	get_single_attribute(ldap_struct, entry, "logonTime", temp);
+	logon_time = (time_t)strtol(temp, NULL, 16);
+
+	get_single_attribute(ldap_struct, entry, "logoffTime", temp);
+	logoff_time = (time_t)strtol(temp, NULL, 16);
+
+	get_single_attribute(ldap_struct, entry, "kickoffTime", temp);
+	kickoff_time = (time_t)strtol(temp, NULL, 16);
+
+	get_single_attribute(ldap_struct, entry, "pwdCanChange", temp);
+        pass_can_change_time = (time_t)strtol(temp, NULL, 16);
+
+	get_single_attribute(ldap_struct, entry, "pwdMustChange", temp);
+        pass_must_change_time = (time_t)strtol(temp, NULL, 16);
+
+	/* recommend that 'gecos' and 'displayName' should refer to the same
+	* attribute OID.  userFullName depreciated, only used by Samba
+	* primary rules of LDAP: don't make a new attribute when one is already defined
+	* that fits your needs; using gecos then displayName then cn rather than 'userFullName'
+	*/
+
+	get_single_attribute(ldap_struct, entry, "gecos", fullname);	
+	if(!fullname)
+		get_single_attribute(ldap_struct, entry, "displayName", fullname);
+	if(!fullname)
+		get_single_attribute(ldap_struct, entry, "cn", fullname);
+
+        get_single_attribute(ldap_struct, entry, "homeDrive", dir_drive);
+        get_single_attribute(ldap_struct, entry, "scriptPath", logon_script);
+        get_single_attribute(ldap_struct, entry, "profilePath", profile_path);
+        get_single_attribute(ldap_struct, entry, "description", acct_desc);
+        get_single_attribute(ldap_struct, entry, "userWorkstations", workstations);
+
+	/* Don't know the appropriate attribute names for these two */
+	get_single_attribute(ldap_struct, entry, "rid", temp);
+	user_rid = (uint32)strtol(temp, NULL, 16);
+	get_single_attribute(ldap_struct, entry, "primaryGroupID", temp);
+	group_rid = (uint32)strtol(temp, NULL, 16);
+
+
+	/* These values MAY be in LDAP, but they can also be retrieved through 
+	*  sys_getpw*() which is how we're doing it (if you use nss_ldap, then 
+	*  these values will be stored in LDAP as well, but if not, we want the
+	*  local values to override the LDAP for this anyway 
+	*  homeDirectory attribute
+	*/
+	sys_user = sys_getpwnam(username);
+	pstrcpy(homedir, sys_user->pw_dir);
+	
+	
+	/* FIXME: hours stuff should be cleaner */
+	logon_divs = 168;
+	hours_len = 21;
+	hours = malloc(sizeof(hours) * hours_len);
+	memset(hours, 0xff, hours_len); 
+
+	switch(lp_ldap_schema())
+	{
+		case SCHEMA_COMPAT:
+			get_single_attribute(ldap_struct, entry, "lmPassword",temp);
+			pdb_gethexpwd(temp,smblmpwd);
+			memset((char *)temp, '\0', sizeof(temp));
+			get_single_attribute(ldap_struct, entry, "ntPassword",temp);
+			pdb_gethexpwd(temp, smbntpwd);
+			memset((char *)temp, '\0', sizeof(temp));
+			get_single_attribute(ldap_struct, entry, "acctFlags", temp);
+                        acct_ctrl = pdb_decode_acct_ctrl(temp);
+                        break;
+		case SCHEMA_AD:
+		case SCHEMA_SAMBA:
+		default:
+			/* must write appropriate decoding routines for dBCSPwd, unicodePwd, and userAccountControl */
+			get_single_attribute(ldap_struct, entry, "dBCSPwd", temp);
+                        pdb_gethexpwd(temp, smblmpwd); 
+                        memset((char *)temp, '\0', sizeof(temp));                        
+                        get_single_attribute(ldap_struct, entry, "unicodePwd", temp);
+                        pdb_gethexpwd(temp, smbntpwd); 
+                        memset((char *)temp, '\0', sizeof(temp)); 
+                        get_single_attribute(ldap_struct, entry, "userAccountControl", temp);
+                        acct_ctrl = pdb_decode_acct_ctrl(temp);
+                        DEBUG(0,("Schema not yet implemented\n"));
+        }
+
+	if(acct_ctrl == 0)
+                acct_ctrl |= ACB_NORMAL;
+
+
+	sampass->logon_time = logon_time;
+	sampass->logoff_time = logoff_time;
+	sampass->kickoff_time = kickoff_time;
+	sampass->pass_can_change_time = pass_can_change_time;
+	sampass->pass_must_change_time = pass_must_change_time;
+	sampass->pass_last_set_time = pass_last_set_time;
+
+	sampass->smb_name = username;
+	sampass->full_name = fullname;
+	sampass->home_dir = homedir;
+	sampass->dir_drive = dir_drive;
+	sampass->logon_script = logon_script;
+	sampass->profile_path = profile_path;
+	sampass->acct_desc = acct_desc;
+	sampass->workstations = workstations;
+	sampass->munged_dial = munged_dial;
+	sampass->smb_passwd = smblmpwd;
+	sampass->smb_nt_passwd = smbntpwd;
+
+	sampass->smb_userid = sys_user->pw_uid;
+	sampass->smb_grpid = sys_user->pw_gid;
+	sampass->user_rid = user_rid;
+	sampass->group_rid = group_rid;
+	sampass->unknown_3 = unknown_3;
+	sampass->hours_len = hours_len;
+	sampass->unknown_5 = unknown_5;
+	sampass->unknown_6 = unknown_6;
+	sampass->acct_ctrl = acct_ctrl;
+	sampass->logon_divs = logon_divs;
+	memcpy(sampass->hours, hours, hours_len);
+	
+	return True;
+}
+
+/**********************************************************************
+ Initialize SAM_ACCOUNT from an LDAP query
+ (Based on init_buffer_from_sam in pdb_tdb.c)
+ *********************************************************************/ 
+static BOOL init_ldap_from_sam (LDAPMod **mods, int ldap_state, SAM_ACCOUNT *sampass)
+{
+	time_t  logon_time,
+		logoff_time,
+		kickoff_time,
+		pass_last_set_time,
+		pass_can_change_time,
+		pass_must_change_time;
+	static pstring username;
+        static pstring dir_drive;
+        static pstring unknown_str;
+        static pstring munged_dial;
+        static pstring fullname;
+        static pstring homedir;
+        static pstring logon_script;
+        static pstring profile_path;
+        static pstring acct_desc;
+        static pstring workstations;
+	static uint8 smblmpwd[16];
+	static uint8 smbntpwd[16];
 	pstring temp;
+	uint32  user_rid, group_rid, unknown_3, hours_len, unknown_5, unknown_6;
+	uint16  acct_ctrl, logon_divs;
+        uint8   *hours;
 
-	LDAP *ldap_struct;
-	LDAPMessage *result;
-	LDAPMod **mods;
+	make_a_mod(&mods, ldap_state, "uid", sampass->smb_name);	
+	DEBUG(2,("Setting entry for user: %s\n",sampass->smb_name));
 	
-	smb_name = newpwd->smb_name;
+	slprintf(temp, sizeof(temp) - 1,"%i", sampass->pass_last_set_time);
+	make_a_mod(&mods, ldap_state, "pwdLastSet", temp);
 
-	if (!ldap_open_connection(&ldap_struct)) /* open a connection to the server */
+	slprintf(temp, sizeof(temp) - 1,"%i", sampass->logon_time);
+	make_a_mod(&mods, ldap_state, "logonTime", temp);
+
+	slprintf(temp, sizeof(temp) - 1,"%i", sampass->logoff_time);
+	make_a_mod(&mods, ldap_state, "logoffTime", temp);
+
+	slprintf(temp, sizeof(temp) - 1,"%i", sampass->kickoff_time);
+	make_a_mod(&mods, ldap_state, "kickoffTime", temp);
+
+	slprintf(temp, sizeof(temp) - 1,"%i", sampass->pass_can_change_time);
+	make_a_mod(&mods, ldap_state, "pwdCanChange", temp);
+
+	slprintf(temp, sizeof(temp) - 1,"%i", sampass->pass_must_change_time);
+	make_a_mod(&mods, ldap_state, "pwdMustChange", 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 
+	*  add-user script
+	*/	
+
+        make_a_mod(&mods, ldap_state, "displayName", sampass->full_name);
+	make_a_mod(&mods, ldap_state, "cn", sampass->full_name);
+
+        make_a_mod(&mods, ldap_state, "homeDirectory", sampass->home_dir);
+        make_a_mod(&mods, ldap_state, "homeDrive", sampass->dir_drive);
+        make_a_mod(&mods, ldap_state, "scriptPath", sampass->logon_script);
+        make_a_mod(&mods, ldap_state, "profilePath", sampass->profile_path);
+        make_a_mod(&mods, ldap_state, "description", sampass->acct_desc);
+        make_a_mod(&mods, ldap_state, "userWorkstations", sampass->workstations);
+
+	/* Don't know the appropriate attribute names for these two */
+	slprintf(temp,sizeof(temp) - 1,"%i",sampass->user_rid);
+	make_a_mod(&mods, ldap_state, "rid", temp);
+	slprintf(temp,sizeof(temp) - 1,"%i",sampass->group_rid);
+	make_a_mod(&mods, ldap_state, "primaryGroupID", temp);
+
+	/* FIXME: Hours stuff goes in LDAP?  */
+
+	switch(lp_ldap_schema())
+	{
+		case SCHEMA_COMPAT:
+			pdb_sethexpwd(temp, smblmpwd, sampass->acct_ctrl);
+			make_a_mod(&mods, ldap_state, "lmPassword", temp);
+			pdb_sethexpwd(temp, smbntpwd, sampass->acct_ctrl);
+			make_a_mod(&mods, ldap_state, "ntPassword", temp);
+			make_a_mod(&mods, ldap_state, "acctFlags", 
+					pdb_encode_acct_ctrl(sampass->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN));
+                        break;
+		case SCHEMA_AD:
+		case SCHEMA_SAMBA:
+		default:
+			/* must write appropriate decoding routines for dBCSPwd, unicodePwd, and userAccountControl */
+			pdb_sethexpwd(temp, smblmpwd, sampass->acct_ctrl);
+			make_a_mod(&mods, ldap_state, "dBCSPwd", temp);
+			pdb_sethexpwd(temp, smbntpwd, sampass->acct_ctrl);
+			make_a_mod(&mods, ldap_state, "unicodePwd", temp);
+			make_a_mod(&mods, ldap_state, "userAccountControl", 
+					pdb_encode_acct_ctrl(sampass->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN));
+                        DEBUG(0,("Schema not yet implemented\n"));
+        }
+
+	return True;
+}
+
+/**********************************************************************
+ Connect to LDAP server for password enumeration
+ *********************************************************************/ 
+static BOOL pdb_setsampwent(BOOL update)
+{
+	int rc;
+	pstring filter;
+
+	if(!ldap_open_connection(&global_ldap_ent.ldap_struct))
 	{
 		return False;
 	}
-
-	if (!ldap_connect_system(ldap_struct)) /* connect as system account */
+	if(!ldap_connect_system(global_ldap_ent.ldap_struct))
 	{
-		ldap_unbind(ldap_struct);
+		ldap_unbind(global_ldap_ent.ldap_struct);
 		return False;
 	}
-	
-	if (smb_name[strlen(smb_name)-1] == '$' )
+
+	pstrcpy(filter, lp_ldap_filter());
+	pstring_sub(filter,"%u","*");
+
+	rc = ldap_search_s(global_ldap_ent.ldap_struct, lp_ldap_suffix(), LDAP_SCOPE_SUBTREE, filter, NULL, 0, &global_ldap_ent.result);
+
+	if(rc != LDAP_SUCCESS)
 	{
-		smb_name[strlen(smb_name)-1] = '\0';
-		trust = True;
+		DEBUG(0,("LDAP search failed: %s\n",ldap_err2string(rc)));
+		ldap_msgfree(global_ldap_ent.result);
+		ldap_unbind(global_ldap_ent.ldap_struct);
+		return False;
 	}
 
-	slprintf(filter, sizeof(filter)-1,
-	         "(&(cn = %s)(|(objectclass = sambaTrust)(objectclass = sambaAccount)))",
-	         smb_name);
-	
-	rc = ldap_search_s(ldap_struct, lp_ldap_suffix(), scope, filter, NULL, 0, &result);
+	DEBUG(2,("%d entries in the base!\n", ldap_count_entries(global_ldap_ent.ldap_struct, global_ldap_ent.result) ));
+
+  	global_ldap_ent.entry = ldap_first_entry(global_ldap_ent.ldap_struct, global_ldap_ent.result);
 
-	switch (flag)
+	return True;
+}
+
+/**********************************************************************
+ End enumeration of the LDAP password list 
+ *********************************************************************/ 
+static void pdb_endsampwent(void)
+{
+	if(global_ldap_ent.ldap_struct && global_ldap_ent.result)
 	{
-		case ADD_USER:
-		{
-			if (ldap_count_entries(ldap_struct, result) ! = 0)
-			{
-				DEBUG(0,("User already in the base, with samba properties\n"));		
-				ldap_unbind(ldap_struct);
-				return False;
-			}
-			ldap_state = LDAP_MOD_ADD;
-			break;
-		}
-		case MODIFY_USER:
-		{
-			if (ldap_count_entries(ldap_struct, result) ! = 1)
-			{
-				DEBUG(0,("No user to modify !\n"));		
-				ldap_unbind(ldap_struct);
-				return False;
-			}
-			ldap_state = LDAP_MOD_REPLACE;
-			break;
-		}
-		default:
-		{
-			DEBUG(0,("How did you come here? \n"));		
-			ldap_unbind(ldap_struct);
-			return False;
-			break;
-		}
+		ldap_msgfree(global_ldap_ent.result);
+		ldap_unbind(global_ldap_ent.ldap_struct);
 	}
-	slprintf(dn, sizeof(dn)-1, "cn = %s, %s",smb_name, lp_ldap_suffix() );
+}
 
-	if (newpwd->smb_passwd ! = NULL)
+/**********************************************************************
+ Get the next entry in the LDAP password database 
+ *********************************************************************/ 
+static BOOL pdb_getsampwent(SAM_ACCOUNT *user)
+{
+	if (!global_ldap_ent.entry)
 	{
-		int i;
-		for( i = 0; i < 16; i++)
-		{
-			slprintf(&temp[2*i], sizeof(temp) - 1, "%02X", newpwd->smb_passwd[i]);
-		}
-    	
+		return False;
 	}
-	else
+	
+	global_ldap_ent.entry = ldap_next_entry(global_ldap_ent.ldap_struct, global_ldap_ent.entry);
+
+	if (global_ldap_ent.entry != NULL)
 	{
-		if (newpwd->acct_ctrl & ACB_PWNOTREQ)
-		{
-			slprintf(temp, sizeof(temp) - 1, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX");
-		}
-		else
-		{
-			slprintf(temp, sizeof(temp) - 1, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
-		}
+		return init_sam_from_ldap(user, global_ldap_ent.ldap_struct, global_ldap_ent.entry);
 	}
-	slprintf(lmhash, sizeof(lmhash)-1, "%s", temp);
+	return False;
+}
+
+/**********************************************************************
+ Get SAM_ACCOUNT entry from LDAP by username 
+ *********************************************************************/ 
+static BOOL pdb_getsampwnam (SAM_ACCOUNT *user, char *sname)
+{
+	LDAP		*ldap_struct;
+	LDAPMessage 	*result;
+	LDAPMessage	*entry;
 
-	if (newpwd->smb_nt_passwd ! = NULL)
+	if(!ldap_open_connection(&ldap_struct))
+		return False;
+	if(!ldap_connect_system(ldap_struct))
 	{
-		int i;
-   		for( i = 0; i < 16; i++)
-		{
-			slprintf(&temp[2*i], sizeof(temp) - 1, "%02X", newpwd->smb_nt_passwd[i]);
-		}
-    	
+		ldap_unbind(ldap_struct);
+		return False;
 	}
-	else
+	if(!ldap_search_one_user_by_name(ldap_struct,sname,&result))
 	{
-		if (newpwd->acct_ctrl & ACB_PWNOTREQ)
-		{
-			slprintf(temp, sizeof(temp) - 1, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX");
-		}
-		else
-		{
-			slprintf(temp, sizeof(temp) - 1, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
-		}
+		ldap_unbind(ldap_struct);
+		return False;
 	}
-	slprintf(nthash, sizeof(nthash)-1, "%s", temp);
-
-	slprintf(rid, sizeof(rid)-1, "%d", uid_to_user_rid(newpwd->smb_userid) );
-	slprintf(lst, sizeof(lst)-1, "%08X", newpwd->pass_last_set_time);
-	
-	mods = NULL; 
-
-	if (trust)
+	if (ldap_count_entries(ldap_struct, result)<1)
+	{
+		DEBUG(0,("We don't find this user [%s] count=%d\n",sname,ldap_count_entries(ldap_struct, result)));
+		ldap_unbind(ldap_struct);
+		return False;
+	}
+	entry = ldap_first_entry(ldap_struct, result);
+	if(entry)
 	{
-		make_a_mod(&mods, ldap_state, "objectclass", "sambaTrust");
-		make_a_mod(&mods, ldap_state, "netbiosTrustName", smb_name);
-		make_a_mod(&mods, ldap_state, "trustPassword", nthash);
+		init_sam_from_ldap(user, ldap_struct, entry);
+		ldap_msgfree(result);
+		ldap_unbind(ldap_struct);
+		return True;
 	}
 	else
 	{
-		make_a_mod(&mods, ldap_state, "objectclass", "sambaAccount");
-		make_a_mod(&mods, ldap_state, "dBCSPwd", lmhash);
-		make_a_mod(&mods, ldap_state, "uid", smb_name);
-		make_a_mod(&mods, ldap_state, "unicodePwd", nthash);
+		ldap_msgfree(result);
+		ldap_unbind(ldap_struct);
+		return False;
 	}
+}
 	
-	make_a_mod(&mods, ldap_state, "cn", smb_name);
-	
-	make_a_mod(&mods, ldap_state, "rid", rid);
-	make_a_mod(&mods, ldap_state, "pwdLastSet", lst);
-	make_a_mod(&mods, ldap_state, "userAccountControl", pdb_encode_acct_ctrl(newpwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN));
-	
-	switch(flag)
+
+/**********************************************************************
+ Get SAM_ACCOUNT entry from LDAP by uid 
+ *********************************************************************/ 
+static BOOL pdb_getsampwuid (SAM_ACCOUNT* user, uid_t uid)
+{
+	LDAP		*ldap_struct;
+	LDAPMessage 	*result;
+	LDAPMessage	*entry;
+	struct passwd	*sys_user;
+
+	if(!ldap_open_connection(&ldap_struct))
+		return False;
+	if(!ldap_connect_system(ldap_struct))
+	{
+		ldap_unbind(ldap_struct);
+		return False;
+	}
+	if(!ldap_search_one_user_by_uid(ldap_struct, uid, &result))
 	{
-		case ADD_USER:
+		sys_user = sys_getpwuid(uid);
+		if(!sys_user)
 		{
-			ldap_add_s(ldap_struct, dn, mods);
-			DEBUG(2,("modadd_ldappwd_entry: added: cn = %s in the LDAP database\n",smb_name));
-			break;
+			ldap_unbind(ldap_struct);
+			return False;
 		}
-		case MODIFY_USER:
+		if(!ldap_search_one_user_by_name(ldap_struct, sys_user->pw_name, &result))
 		{
-			ldap_modify_s(ldap_struct, dn, mods);
-			DEBUG(2,("modadd_ldappwd_entry: changed: cn = %s in the LDAP database_n",smb_name));
-			break;
-		}
-		default:
-		{
-			DEBUG(2,("modadd_ldappwd_entry: How did you come here? \n"));		
 			ldap_unbind(ldap_struct);
 			return False;
-			break;
 		}
+
+	}
+	if (ldap_count_entries(ldap_struct, result)<1)
+	{
+		DEBUG(0,("We don't find this uid [%i] count=%d\n", uid, ldap_count_entries(ldap_struct, result)));
+		ldap_unbind(ldap_struct);
+		return False;
+	}
+	entry = ldap_first_entry(ldap_struct,result);
+	if(entry)
+	{
+		init_sam_from_ldap(user,ldap_struct,entry);
+		ldap_msgfree(result);
+		ldap_unbind(ldap_struct);
+		return True;
+	}
+	else
+	{
+		ldap_msgfree(result);
+		ldap_unbind(ldap_struct);
+		return False;
 	}
-	
-	ldap_mods_free(mods, 1);
-	
-	ldap_unbind(ldap_struct);
-	
-	return True;
 }
 
-/************************************************************************
- Add or modify an entry. everything except the smb struct
 
-*************************************************************************/
-static BOOL modadd_ldap21pwd_entry(struct sam_passwd *newpwd, int flag)
+/**********************************************************************
+ Delete entry from LDAP for username 
+ *********************************************************************/ 
+static BOOL pdb_delete_sam_account(char *sname)
+{
+	/* FIXME: make this work */
+	return False;
+}
+
+/**********************************************************************
+ Update SAM_ACCOUNT 
+ *********************************************************************/ 
+static BOOL pdb_update_sam_account (SAM_ACCOUNT *newpwd, BOOL override)
 {
-	
-	/* assume the struct is correct and filled
-	   that's the job of passdb.c to check */
-	int scope = LDAP_SCOPE_ONELEVEL;
 	int rc;
-	char *smb_name;
-	int trust = False;
-	int ldap_state;
-	pstring filter;
 	pstring dn;
-	pstring lmhash;
-	pstring nthash;
-	pstring rid;
-	pstring lst;
-	pstring temp;
-
 	LDAP *ldap_struct;
 	LDAPMessage *result;
+	LDAPMessage *entry;
 	LDAPMod **mods;
-	
-	smb_name = newpwd->smb_name;
+	pstring filter;
 
 	if (!ldap_open_connection(&ldap_struct)) /* open a connection to the server */
 	{
@@ -666,333 +723,264 @@
 		ldap_unbind(ldap_struct);
 		return False;
 	}
-	
-	if (smb_name[strlen(smb_name)-1] == '$' )
-	{
-		smb_name[strlen(smb_name)-1] = '\0';
-		trust = True;
-	}
 
-	slprintf(filter, sizeof(filter)-1,
-	         "(&(cn = %s)(|(objectclass = sambaTrust)(objectclass = sambaAccount)))",
-	         smb_name);
-	
-	rc = ldap_search_s(ldap_struct, lp_ldap_suffix(), scope, filter, NULL, 0, &result);
-
-	switch (flag)
-	{
-		case ADD_USER:
-		{
-			if (ldap_count_entries(ldap_struct, result) ! = 1)
-			{
-				DEBUG(2,("User already in the base, with samba properties\n"));		
-				ldap_unbind(ldap_struct);
-				return False;
-			}
-			ldap_state = LDAP_MOD_ADD;
-			break;
-		}
+	pstrcpy(filter,lp_ldap_filter());
+	pstring_sub(filter,"%u",newpwd->smb_name);
 
-		case MODIFY_USER:
-		{
-			if (ldap_count_entries(ldap_struct, result) ! = 1)
-			{
-				DEBUG(2,("No user to modify !\n"));		
-				ldap_unbind(ldap_struct);
-				return False;
-			}
-			ldap_state = LDAP_MOD_REPLACE;
-			break;
-		}
+	rc = ldap_search_s(ldap_struct, lp_ldap_suffix(), LDAP_SCOPE_SUBTREE, filter, NULL, 0, &result);
 
-		default:
-		{
-			DEBUG(2,("How did you come here? \n"));		
-			ldap_unbind(ldap_struct);
-			return False;
-			break;
-		}
+	if (ldap_count_entries(ldap_struct, result) == 0)
+	{
+		DEBUG(0,("No user to modify!\n"));		
+		ldap_msgfree(result);
+		ldap_unbind(ldap_struct);
+		return False;
 	}
-	slprintf(dn, sizeof(dn)-1, "cn = %s, %s",smb_name, lp_ldap_suffix() );
+
+	init_ldap_from_sam(mods, LDAP_MOD_REPLACE, newpwd);
+	
+	entry = ldap_first_entry(ldap_struct, result);
+	get_single_attribute(ldap_struct, entry, "dn", dn);
 	
-	mods = NULL; 
+	rc = ldap_modify_s(ldap_struct, dn, mods);
 
-	if (trust)
-	{
-	}
-	else
+	if( rc != LDAP_SUCCESS )
 	{
+		DEBUG(0,("failed to modify user with uid = %s with: %s\n", newpwd->smb_name, ldap_err2string(rc)));
+		ldap_unbind(ldap_struct);
+		return False;
 	}
-	
-	make_a_mod(&mods, ldap_state, "cn", smb_name);
-	
-	make_a_mod(&mods, ldap_state, "rid", rid);
-	make_a_mod(&mods, ldap_state, "pwdLastSet", lst);
-	make_a_mod(&mods, ldap_state, "userAccountControl", pdb_encode_acct_ctrl(newpwd->acct_ctrl,NEW_PW_FORMAT_SPACE_PADDED_LEN));
-	
-	ldap_modify_s(ldap_struct, dn, mods);
-	
+
+	DEBUG(2,("successfully modified uid = %s in the LDAP database\n",newpwd->smb_name));
 	ldap_mods_free(mods, 1);
-	
 	ldap_unbind(ldap_struct);
-	
 	return True;
 }
 
-/************************************************************************
- Routine to add an entry to the ldap passwd file.
-
- do not call this function directly.  use passdb.c instead.
-
-*************************************************************************/
-static BOOL add_ldappwd_entry(struct smb_passwd *newpwd)
-{
-	return (modadd_ldappwd_entry(newpwd, ADD_USER) );
-}
-
-/************************************************************************
- Routine to search the ldap passwd file for an entry matching the username.
- and then modify its password entry. We can't use the startldappwent()/
- getldappwent()/endldappwent() interfaces here as we depend on looking
- in the actual file to decide how much room we have to write data.
- override = False, normal
- override = True, override XXXXXXXX'd out password or NO PASS
-
- do not call this function directly.  use passdb.c instead.
-
-************************************************************************/
-static BOOL mod_ldappwd_entry(struct smb_passwd *pwd, BOOL override)
-{
-	return (modadd_ldappwd_entry(pwd, MODIFY_USER) );
-}
-
-/************************************************************************
- Routine to add an entry to the ldap passwd file.
-
- do not call this function directly.  use passdb.c instead.
-
-*************************************************************************/
-static BOOL add_ldap21pwd_entry(struct sam_passwd *newpwd)
-{	
-	return( modadd_ldappwd_entry(newpwd, ADD_USER)?
-	modadd_ldap21pwd_entry(newpwd, ADD_USER):False);
-}
-
-/************************************************************************
- Routine to search the ldap passwd file for an entry matching the username.
- and then modify its password entry. We can't use the startldappwent()/
- getldappwent()/endldappwent() interfaces here as we depend on looking
- in the actual file to decide how much room we have to write data.
- override = False, normal
- override = True, override XXXXXXXX'd out password or NO PASS
-
- do not call this function directly.  use passdb.c instead.
-
-************************************************************************/
-static BOOL mod_ldap21pwd_entry(struct sam_passwd *pwd, BOOL override)
-{
-	return( modadd_ldappwd_entry(pwd, MODIFY_USER)?
-	modadd_ldap21pwd_entry(pwd, MODIFY_USER):False);
-}
-
-struct ldap_enum_info
+/**********************************************************************
+ Add SAM_ACCOUNT to LDAP 
+ *********************************************************************/ 
+static BOOL pdb_add_sam_account (SAM_ACCOUNT *newpwd)
 {
+	int rc;
 	LDAP *ldap_struct;
 	LDAPMessage *result;
-	LDAPMessage *entry;
-};
-
-static struct ldap_enum_info ldap_ent;
-
-/***************************************************************
- Start to enumerate the ldap passwd list. Returns a void pointer
- to ensure no modification outside this module.
-
- do not call this function directly.  use passdb.c instead.
-
- ****************************************************************/
-static void *startldappwent(BOOL update)
-{
-	int scope = LDAP_SCOPE_ONELEVEL;
-	int rc;
-
+	LDAPMod **mods;
 	pstring filter;
+	pstring dn;
 
-	if (!ldap_open_connection(&ldap_ent.ldap_struct)) /* open a connection to the server */
+	if (!ldap_open_connection(&ldap_struct)) /* open a connection to the server */
 	{
-		return NULL;
+		return False;
 	}
 
-	if (!ldap_connect_system(ldap_ent.ldap_struct)) /* connect as system account */
+	if (!ldap_connect_system(ldap_struct)) /* connect as system account */
 	{
-		return NULL;
+		ldap_unbind(ldap_struct);
+		return False;
 	}
 
-	/* when the class is known the search is much faster */
-	switch (0)
+	pstrcpy(filter,lp_ldap_filter());
+	pstring_sub(filter,"%u",newpwd->smb_name);
+
+	rc = ldap_search_s(ldap_struct, lp_ldap_suffix(), LDAP_SCOPE_SUBTREE, filter, NULL, 0, &result);
+
+	if (ldap_count_entries(ldap_struct, result) != 0)
 	{
-		case 1:
-		{
-			pstrcpy(filter, "objectclass = sambaAccount");
-			break;
-		}
-		case 2:
-		{
-			pstrcpy(filter, "objectclass = sambaTrust");
-			break;
-		}
-		default:
-		{
-			pstrcpy(filter, "(|(objectclass = sambaTrust)(objectclass = sambaAccount))");
-			break;
-		}
+		DEBUG(0,("User already in the base, with samba properties\n"));		
+		ldap_msgfree(result);
+		ldap_unbind(ldap_struct);
+		return False;
 	}
 
-	rc = ldap_search_s(ldap_ent.ldap_struct, lp_ldap_suffix(), scope, filter, NULL, 0, &ldap_ent.result);
+	init_ldap_from_sam(mods, LDAP_MOD_ADD, newpwd);
 
-	DEBUG(2,("%d entries in the base!\n", ldap_count_entries(ldap_ent.ldap_struct, ldap_ent.result) ));
-
-  	ldap_ent.entry = ldap_first_entry(ldap_ent.ldap_struct, ldap_ent.result);
+	slprintf(dn, sizeof(dn) - 1, "cn=%s,%s", newpwd->full_name, lp_ldap_suffix());
+	
+	rc = ldap_add_s(ldap_struct, dn, mods);
 
-	return &ldap_ent;
+	if( rc != LDAP_SUCCESS )
+	{
+		DEBUG(0,("failed to add user with uid = %s with: %s\n",newpwd->smb_name,ldap_err2string(rc)));
+		ldap_unbind(ldap_struct);
+		return False;
+	}
+	DEBUG(2,("added: uid = %s in the LDAP database\n",newpwd->smb_name));
+	ldap_mods_free(mods, 1);
+	ldap_unbind(ldap_struct);
+	return True;
 }
 
-/*************************************************************************
- Routine to return the next entry in the ldap passwd list.
-
- do not call this function directly.  use passdb.c instead.
-
- *************************************************************************/
-static struct smb_passwd *getldappwent(void *vp)
+/***************************************************************
+ wrapper function for the old interface below
+ ****************************************************************/
+static void *startldappwent(BOOL update)
 {
-	static struct smb_passwd user;
-	struct ldap_enum_info *ldap_vp = (struct ldap_enum_info *)vp;
-
-	ldap_vp->entry = ldap_next_entry(ldap_vp->ldap_struct, ldap_vp->entry);
+	if(pdb_setsampwent(update))
+		return &global_ldap_ent;
 
-	if (ldap_vp->entry ! = NULL)
-	{
-		ldap_get_smb_passwd(ldap_vp->ldap_struct, ldap_vp->entry, &user);
-		return &user;
-	}
 	return NULL;
 }
 
-/*************************************************************************
- Routine to return the next entry in the ldap passwd list.
-
- do not call this function directly.  use passdb.c instead.
-
- *************************************************************************/
-static struct sam_passwd *getldap21pwent(void *vp)
+static struct smb_passwd *getldappwent(void *vp)
 {
-	static struct sam_passwd user;
-	struct ldap_enum_info *ldap_vp = (struct ldap_enum_info *)vp;
+	/* ignores the vp passed, uses global */
 
-	ldap_vp->entry = ldap_next_entry(ldap_vp->ldap_struct, ldap_vp->entry);
+	SAM_ACCOUNT user;
+
+	pdb_init_sam(&user);
+	if(pdb_getsampwent(&user))
+		return pdb_sam_to_smb(&user);
 
-	if (ldap_vp->entry ! = NULL)
-	{
-		ldap_get_sam_passwd(ldap_vp->ldap_struct, ldap_vp->entry, &user);
-		return &user;
-	}
 	return NULL;
-}
 
-/***************************************************************
- End enumeration of the ldap passwd list.
+}
 
- do not call this function directly.  use passdb.c instead.
 
-****************************************************************/
 static void endldappwent(void *vp)
 {
-	struct ldap_enum_info *ldap_vp = (struct ldap_enum_info *)vp;
-	ldap_msgfree(ldap_vp->result);
-	ldap_unbind(ldap_vp->ldap_struct);
+	pdb_endsampwent();
 }
 
-/*************************************************************************
- Return the current position in the ldap passwd list as an SMB_BIG_UINT.
- This must be treated as an opaque token.
-
- do not call this function directly.  use passdb.c instead.
-
-*************************************************************************/
 static SMB_BIG_UINT getldappwpos(void *vp)
 {
 	return (SMB_BIG_UINT)0;
 }
 
-/*************************************************************************
- Set the current position in the ldap passwd list from SMB_BIG_UINT.
- This must be treated as an opaque token.
-
- do not call this function directly.  use passdb.c instead.
-
-*************************************************************************/
 static BOOL setldappwpos(void *vp, SMB_BIG_UINT tok)
 {
 	return False;
 }
 
-/*
- * Ldap derived functions.
- */
-
 static struct smb_passwd *getldappwnam(char *name)
 {
-  return pdb_sam_to_smb(iterate_getsam21pwnam(name));
+	SAM_ACCOUNT user;
+
+	pdb_init_sam(&user);
+	if(pdb_getsampwnam(&user, name))
+		return pdb_sam_to_smb(&user); 
+
+	return NULL;
 }
 
 static struct smb_passwd *getldappwuid(uid_t smb_userid)
 {
-  return pdb_sam_to_smb(iterate_getsam21pwuid(smb_userid));
-}
+	SAM_ACCOUNT user;
 
-static struct smb_passwd *getldappwrid(uint32 user_rid)
-{
-  return pdb_sam_to_smb(iterate_getsam21pwuid(pdb_user_rid_to_uid(user_rid)));
+	pdb_init_sam(&user);
+	if(pdb_getsampwuid(&user, smb_userid))
+		return pdb_sam_to_smb(&user);
+
+	return NULL;
 }
 
-static struct smb_passwd *getldappwent(void *vp)
+static struct smb_passwd *getldappwrid(uint32 user_rid)
 {
-  return pdb_sam_to_smb(getldap21pwent(vp));
+	return getldappwuid(pdb_user_rid_to_uid(user_rid));
 }
 
 static BOOL add_ldappwd_entry(struct smb_passwd *newpwd)
 {
-  return add_ldap21pwd_entry(pdb_smb_to_sam(newpwd));
+	
+	return pdb_add_sam_account(pdb_smb_to_sam(newpwd));
 }
 
 static BOOL mod_ldappwd_entry(struct smb_passwd* pwd, BOOL override)
 {
-  return mod_ldap21pwd_entry(pdb_smb_to_sam(pwd), override);
+	return pdb_update_sam_account(pdb_smb_to_sam(pwd), override);
 }
 
 static BOOL del_ldappwd_entry(const char *name)
 {
-  return False; /* Dummy... */
+	return False; /* Dummy... */
+}
+
+static BOOL add_ldap21pwd_entry(struct sam_passwd *newpwd)
+{
+	return pdb_add_sam_account(newpwd);
+}
+
+static BOOL mod_ldap21pwd_entry(struct sam_passwd *newpwd, BOOL override)
+{
+	return pdb_update_sam_account(newpwd, override);
 }
 
 static struct sam_disp_info *getldapdispnam(char *name)
 {
-	return pdb_sam_to_dispinfo(getldap21pwnam(name));
+	struct sam_passwd *user;
+	if(pdb_getsampwnam(user, name))
+	{
+		return pdb_sam_to_dispinfo(user);
+	}
+
+	return NULL;
 }
 
 static struct sam_disp_info *getldapdisprid(uint32 rid)
 {
-	return pdb_sam_to_dispinfo(getldap21pwrid(rid));
+	struct sam_passwd *user;
+
+	if(pdb_getsampwuid(user, pdb_user_rid_to_uid(rid)))
+	{
+		return pdb_sam_to_dispinfo(user);
+	}
+
+	return NULL;
 }
 
 static struct sam_disp_info *getldapdispent(void *vp)
 {
-	return pdb_sam_to_dispinfo(getldap21pwent(vp));
+	struct sam_passwd *user;
+
+	if(pdb_getsampwent(user))
+	{
+		return pdb_sam_to_dispinfo(user);
+	}
+
+	return NULL;
+}
+
+static struct sam_passwd *getldap21pwent(void *vp)
+{
+	static SAM_ACCOUNT user;
+
+	pdb_init_sam(&user);
+	if(pdb_getsampwent(&user))
+		return &user;
+
+	return NULL;
+
+}
+
+static struct sam_passwd *getldap21pwnam(char *sname)
+{
+	static struct sam_passwd *user;
+	pdb_init_sam(user);
+
+	if(pdb_getsampwnam(user, sname))
+	{
+		return user;
+	}
+
+	return NULL;
 }
 
 static struct sam_passwd *getldap21pwuid(uid_t uid)
 {
-	return pdb_smb_to_sam(iterate_getsam21pwuid(pdb_uid_to_user_rid(uid)));
+	static struct sam_passwd *user;
+	pdb_init_sam(user);
+
+	if(pdb_getsampwuid(user, uid))
+	{
+		return user;
+	}
+
+	return NULL;
+}
+
+static struct sam_passwd *getldap21pwrid(uint32 rid)
+{
+	return getldap21pwuid(pdb_user_rid_to_uid(rid));
 }
 
 static struct passdb_ops ldap_ops =
@@ -1009,9 +997,9 @@
 	mod_ldappwd_entry,
 	del_ldappwd_entry,
 	getldap21pwent,
-	iterate_getsam21pwnam,       /* From passdb.c */
-	iterate_getsam21pwuid,       /* From passdb.c */
-	iterate_getsam21pwrid,       /* From passdb.c */
+	getldap21pwnam,     
+	getldap21pwuid,      
+	getldap21pwrid,      
 	add_ldap21pwd_entry,
 	mod_ldap21pwd_entry,
 	getldapdispnam,
@@ -1023,7 +1011,6 @@
 {
   return &ldap_ops;
 }
-
 #else
  void dummy_function(void);
  void dummy_function(void) { } /* stop some compilers complaining */


More information about the samba-technical mailing list