The ldap idmap backend from Anthony Liguori (aliguori@us.ibm.com):
authorJim McDonough <jmcd@samba.org>
Thu, 3 Apr 2003 03:30:25 +0000 (03:30 +0000)
committerJim McDonough <jmcd@samba.org>
Thu, 3 Apr 2003 03:30:25 +0000 (03:30 +0000)
This patch moves the ldap routines out of passdb into a generic
library and implements an LDAP backend for IDMAP.  THe backend
can be enabled with "idmap backend = ldap" in smb.conf.  THere
are also schema changes to make sure to update teh ldap schema files.
(This used to be commit 87c7c582c60521da3a93d997386fe79935012aea)

examples/LDAP/samba.schema
source3/Makefile.in
source3/include/includes.h
source3/include/smb_ldap.h [new file with mode: 0644]
source3/lib/ldap.c [new file with mode: 0644]
source3/nsswitch/winbindd_idmap.c
source3/nsswitch/winbindd_idmap_ldap.c [new file with mode: 0644]
source3/passdb/pdb_ldap.c

index e801e0b8479a443271c1f9a3c3212e7f6f2222a7..a4435564ecdfc1391befe8a73f7e9857ed41cdc4 100644 (file)
@@ -167,11 +167,11 @@ objectclass ( 1.3.6.1.4.1.7165.2.2.4 NAME 'sambaGroupMapping' SUP top AUXILIARY
 ##
 ## Used for Winbind experimentation
 ##
-#objectclass ( 1.3.6.1.4.1.7165.1.2.2.3 NAME 'uidPool' SUP top AUXILIARY
-#      DESC 'Pool for allocating UNIX uids'
-#      MUST ( uidNumber $ cn ) )
+objectclass ( 1.3.6.1.4.1.7165.1.2.2.3 NAME 'uidPool' SUP top AUXILIARY
+       DESC 'Pool for allocating UNIX uids'
+       MUST ( uidNumber $ cn ) )
 
-#objectclass ( 1.3.6.1.4.1.7165.1.2.2.4 NAME 'gidPool' SUP top AUXILIARY
-#      DESC 'Pool for allocating UNIX gids'
-#      MUST ( gidNumber $ cn ) )
+objectclass ( 1.3.6.1.4.1.7165.1.2.2.4 NAME 'gidPool' SUP top AUXILIARY
+       DESC 'Pool for allocating UNIX gids'
+       MUST ( gidNumber $ cn ) )
 
index 8ac2a053fce13af58c22995a7ba9f8d11ea2ed2e..9b2cffe86c2b72941d910041beab0e4e2f928fed 100644 (file)
@@ -275,7 +275,7 @@ PASSDB_GET_SET_OBJ = passdb/pdb_get_set.o
 
 PASSDB_OBJ = $(PASSDB_GET_SET_OBJ) passdb/passdb.o passdb/pdb_interface.o \
                passdb/machine_sid.o passdb/util_sam_sid.o passdb/pdb_compat.o \
-               passdb/privileges.o @PDB_STATIC@
+               passdb/privileges.o lib/ldap.o @PDB_STATIC@
 
 XML_OBJ = modules/xml.o
 MYSQL_OBJ = modules/mysql.o
@@ -581,6 +581,7 @@ WINBINDD_OBJ1 = \
                nsswitch/winbindd_group.o \
                nsswitch/winbindd_idmap.o \
                nsswitch/winbindd_idmap_tdb.o \
+               nsswitch/winbindd_idmap_ldap.o \
                nsswitch/winbindd_util.o  \
                nsswitch/winbindd_cache.o \
                nsswitch/winbindd_pam.o   \
@@ -597,7 +598,8 @@ WINBINDD_OBJ = \
                $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \
                $(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) \
                $(PROFILE_OBJ) $(UNIGRP_OBJ) $(IDMAP_OBJ) \
-               $(SECRETS_OBJ) $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ)
+               $(SECRETS_OBJ) $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ) \
+               lib/ldap.o
 
 WBINFO_OBJ = nsswitch/wbinfo.o libsmb/smbencrypt.o libsmb/smbdes.o $(POPT_LIB_OBJ)
 
@@ -948,7 +950,8 @@ nsswitch/libnss_wins.@SHLIBEXT@: $(NSS_OBJ)
 
 bin/winbindd@EXEEXT@: $(WINBINDD_OBJ) @BUILD_POPT@ bin/.dummy
        @echo Linking $@
-       @$(LINK) -o $@ $(WINBINDD_OBJ) $(DYNEXP) $(LIBS) @POPTLIBS@ $(ADSLIBS)
+       @$(LINK) -o $@ $(WINBINDD_OBJ) $(DYNEXP) $(LIBS) @POPTLIBS@ $(ADSLIBS) \
+               @LDAP_LIBS@
 
 nsswitch/libns_winbind.@SHLIBEXT@: $(WINBIND_NSS_PICOBJS)
        @echo "Linking $@"
index de87f82709bea4560eb2ce81a322a9ba79331a45..bf71ed54cf7298503a79dad92d24d896b292ef73 100644 (file)
@@ -856,6 +856,10 @@ struct functable {
 
 struct printjob;
 
+struct smb_ldap_privates;
+
+struct smb_ldap_privates;
+
 /***** automatically generated prototypes *****/
 #ifndef NO_PROTO_H
 #include "proto.h"
diff --git a/source3/include/smb_ldap.h b/source3/include/smb_ldap.h
new file mode 100644 (file)
index 0000000..1a30b85
--- /dev/null
@@ -0,0 +1,59 @@
+/* 
+   Unix SMB/CIFS implementation.
+   LDAP protocol helper functions for SAMBA
+   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
+   Copyright (C) Jim McDonough                  2003
+    
+   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
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   
+*/
+
+#ifndef SMB_LDAP_H
+#define SMB_LDAP_H
+
+#ifdef HAVE_LDAP
+
+#include <lber.h>
+#include <ldap.h>
+
+struct smb_ldap_privates {
+
+       /* Former statics */
+       LDAP *ldap_struct;
+       LDAPMessage *result;
+       LDAPMessage *entry;
+       int index;
+       
+       time_t last_ping;
+       /* retrive-once info */
+       const char *uri;
+       
+       BOOL permit_non_unix_accounts;
+       
+       uint32 low_nua_rid; 
+       uint32 high_nua_rid; 
+
+       char *bind_dn;
+       char *bind_secret;
+
+       struct smb_ldap_privates *next;
+};
+
+#endif
+#endif
diff --git a/source3/lib/ldap.c b/source3/lib/ldap.c
new file mode 100644 (file)
index 0000000..73ff50e
--- /dev/null
@@ -0,0 +1,718 @@
+/* 
+   Unix SMB/CIFS implementation.
+   LDAP protocol helper functions for SAMBA
+   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
+   Copyright (C) Jim McDonough                  2003
+    
+   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
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   
+*/
+
+#include "includes.h"
+
+#ifdef HAVE_LDAP
+/* TODO:
+*  persistent connections: if using NSS LDAP, many connections are made
+*      however, using only one within Samba would be nice
+*  
+*  Clean up SSL stuff, compile on OpenLDAP 1.x, 2.x, and Netscape SDK
+*
+*  Other LDAP based login attributes: accountExpires, etc.
+*  (should be the domain of Samba proper, but the sam_password/SAM_ACCOUNT
+*  structures don't have fields for some of these attributes)
+*
+*  SSL is done, but can't get the certificate based authentication to work
+*  against on my test platform (Linux 2.4, OpenLDAP 2.x)
+*/
+
+/* 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 "smb_ldap.h"
+
+/* We need an internal mapping of LDAP * -> smb_ldap_privates so we implement
+   it in terms of a VK list.  It's a little backwards but its quite efficent */
+static struct smb_ldap_privates *head;
+
+static struct smb_ldap_privates *get_internal(LDAP *ldap_struct)
+{
+       struct smb_ldap_privates *ret = head;
+
+       while (NULL != ret && ret->ldap_struct != ldap_struct) {
+               ret = ret->next;
+       }
+
+       return ret;
+}
+
+#define SMB_LDAP_DONT_PING_TIME 10     /* ping only all 10 seconds */
+
+/*******************************************************************
+ find the ldap password
+******************************************************************/
+static BOOL smb_ldap_fetch_pw(char **dn, char** pw)
+{
+       char *key = NULL;
+       size_t size;
+       
+       *dn = smb_xstrdup(lp_ldap_admin_dn());
+       
+       if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
+               SAFE_FREE(*dn);
+               DEBUG(0, ("smb_ldap_fetch_pw: asprintf failed!\n"));
+       }
+       
+       *pw=secrets_fetch(key, &size);
+       if (!size) {
+               /* Upgrade 2.2 style entry */
+               char *p;
+               char* old_style_key = strdup(*dn);
+               char *data;
+               fstring old_style_pw;
+               
+               if (!old_style_key) {
+                       DEBUG(0, ("smb_ldap_fetch_pw: strdup failed!\n"));
+                       return False;
+               }
+
+               for (p=old_style_key; *p; p++)
+                       if (*p == ',') *p = '/';
+       
+               data=secrets_fetch(old_style_key, &size);
+               if (!size && size < sizeof(old_style_pw)) {
+                       DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
+                       SAFE_FREE(old_style_key);
+                       SAFE_FREE(*dn);
+                       return False;
+               }
+
+               strncpy(old_style_pw, data, size);
+               old_style_pw[size] = 0;
+
+               SAFE_FREE(data);
+
+               if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
+                       DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
+                       SAFE_FREE(old_style_key);
+                       SAFE_FREE(*dn);
+                       return False;                   
+               }
+               if (!secrets_delete(old_style_key)) {
+                       DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
+               }
+
+               SAFE_FREE(old_style_key);
+
+               *pw = smb_xstrdup(old_style_pw);                
+       }
+       
+       return True;
+}
+
+/*******************************************************************
+ open a connection to the ldap server.
+******************************************************************/
+int smb_ldap_open_connection (struct smb_ldap_privates *ldap_state, 
+                             LDAP ** ldap_struct)
+{
+       int rc = LDAP_SUCCESS;
+       int version;
+       BOOL ldap_v3 = False;
+
+#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
+       DEBUG(10, ("smb_ldap_open_connection: %s\n", ldap_state->uri));
+       
+       if ((rc = ldap_initialize(ldap_struct, ldap_state->uri)) != LDAP_SUCCESS) {
+               DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
+               return rc;
+       }
+       
+#else 
+
+       /* Parse the string manually */
+
+       {
+               int port = 0;
+               fstring protocol;
+               fstring host;
+               const char *p = ldap_state->uri; 
+               SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
+               
+               /* skip leading "URL:" (if any) */
+               if ( strncasecmp( p, "URL:", 4 ) == 0 ) {
+                       p += 4;
+               }
+               
+               sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port);
+               
+               if (port == 0) {
+                       if (strequal(protocol, "ldap")) {
+                               port = LDAP_PORT;
+                       } else if (strequal(protocol, "ldaps")) {
+                               port = LDAPS_PORT;
+                       } else {
+                               DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
+                       }
+               }
+               
+               if ((*ldap_struct = ldap_init(host, port)) == NULL)     {
+                       DEBUG(0, ("ldap_init failed !\n"));
+                       return LDAP_OPERATIONS_ERROR;
+               }
+               
+               if (strequal(protocol, "ldaps")) {
+#ifdef LDAP_OPT_X_TLS
+                       int tls = LDAP_OPT_X_TLS_HARD;
+                       if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
+                       {
+                               DEBUG(0, ("Failed to setup a TLS session\n"));
+                       }
+                       
+                       DEBUG(3,("LDAPS option set...!\n"));
+#else
+                       DEBUG(0,("smb_ldap_open_connection: Secure connection not supported by LDAP client libraries!\n"));
+                       return LDAP_OPERATIONS_ERROR;
+#endif
+               }
+       }
+#endif
+
+       if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS)
+       {
+               if (version != LDAP_VERSION3)
+               {
+                       version = LDAP_VERSION3;
+                       if (ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) {
+                               ldap_v3 = True;
+                       }
+               } else {
+                       ldap_v3 = True;
+               }
+       }
+
+       if (lp_ldap_ssl() == LDAP_SSL_START_TLS) {
+#ifdef LDAP_OPT_X_TLS
+               if (ldap_v3) {
+                       if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS)
+                       {
+                               DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
+                                        ldap_err2string(rc)));
+                               return rc;
+                       }
+                       DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
+               } else {
+                       
+                       DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
+                       return LDAP_OPERATIONS_ERROR;
+               }
+#else
+               DEBUG(0,("smb_ldap_open_connection: StartTLS not supported by LDAP client libraries!\n"));
+               return LDAP_OPERATIONS_ERROR;
+#endif
+       }
+
+       DEBUG(2, ("smb_ldap_open_connection: connection opened\n"));
+       return rc;
+}
+
+
+/*******************************************************************
+ a rebind function for authenticated referrals
+ This version takes a void* that we can shove useful stuff in :-)
+******************************************************************/
+#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
+#else
+static int rebindproc_with_state  (LDAP * ld, char **whop, char **credp, 
+                                  int *methodp, int freeit, void *arg)
+{
+       struct smb_ldap_privates *ldap_state = arg;
+       
+       /** @TODO Should we be doing something to check what servers we rebind to?
+           Could we get a referral to a machine that we don't want to give our
+           username and password to? */
+       
+       if (freeit) {
+               SAFE_FREE(*whop);
+               memset(*credp, '\0', strlen(*credp));
+               SAFE_FREE(*credp);
+       } else {
+               DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n", 
+                         ldap_state->bind_dn));
+
+               *whop = strdup(ldap_state->bind_dn);
+               if (!*whop) {
+                       return LDAP_NO_MEMORY;
+               }
+               *credp = strdup(ldap_state->bind_secret);
+               if (!*credp) {
+                       SAFE_FREE(*whop);
+                       return LDAP_NO_MEMORY;
+               }
+               *methodp = LDAP_AUTH_SIMPLE;
+       }
+       return 0;
+}
+#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
+
+/*******************************************************************
+ a rebind function for authenticated referrals
+ This version takes a void* that we can shove useful stuff in :-)
+ and actually does the connection.
+******************************************************************/
+#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
+static int rebindproc_connect_with_state (LDAP *ldap_struct, 
+                                         LDAP_CONST char *url, 
+                                         ber_tag_t request,
+                                         ber_int_t msgid, void *arg)
+{
+       struct smb_ldap_privates *ldap_state = arg;
+       int rc;
+       DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n", 
+                ldap_state->bind_dn));
+       
+       /** @TODO Should we be doing something to check what servers we rebind to?
+           Could we get a referral to a machine that we don't want to give our
+           username and password to? */
+
+       rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
+       
+       return rc;
+}
+#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
+
+/*******************************************************************
+ Add a rebind function for authenticated referrals
+******************************************************************/
+#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
+#else
+# if LDAP_SET_REBIND_PROC_ARGS == 2
+static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
+                      int *method, int freeit )
+{
+       return rebindproc_with_state(ldap_struct, whop, credp,
+                                  method, freeit, get_internal(ldap_struct));
+       
+}
+# endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
+#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
+
+/*******************************************************************
+ a rebind function for authenticated referrals
+ this also does the connection, but no void*.
+******************************************************************/
+#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
+# if LDAP_SET_REBIND_PROC_ARGS == 2
+static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
+                              ber_int_t msgid)
+{
+       return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid, 
+                                            get_internal(ld));
+}
+# endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
+#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
+
+/*******************************************************************
+ connect to the ldap server under system privilege.
+******************************************************************/
+int smb_ldap_connect_system(struct smb_ldap_privates *ldap_state,
+                           LDAP * ldap_struct)
+{
+       int rc;
+       char *ldap_dn;
+       char *ldap_secret;
+
+       if (NULL == get_internal(ldap_struct)) {
+               ldap_state->next = head;
+       }
+
+       /* get the password */
+       if (!smb_ldap_fetch_pw(&ldap_dn, &ldap_secret))
+       {
+               DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
+               return LDAP_INVALID_CREDENTIALS;
+       }
+
+       ldap_state->bind_dn = ldap_dn;
+       ldap_state->bind_secret = ldap_secret;
+
+       /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite 
+          (OpenLDAP) doesnt' seem to support it */
+          
+       DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
+                 ldap_state->uri, ldap_dn));
+
+#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
+# if LDAP_SET_REBIND_PROC_ARGS == 2    
+       ldap_set_rebind_proc(ldap_struct, &rebindproc_connect); 
+# endif
+# if LDAP_SET_REBIND_PROC_ARGS == 3    
+       ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);  
+# endif
+#else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
+# if LDAP_SET_REBIND_PROC_ARGS == 2    
+       ldap_set_rebind_proc(ldap_struct, &rebindproc); 
+# endif
+# if LDAP_SET_REBIND_PROC_ARGS == 3    
+       ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);  
+# endif
+#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
+
+       rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
+
+       if (rc != LDAP_SUCCESS) {
+               char *ld_error;
+               ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
+                               &ld_error);
+               DEBUG(0,
+                     ("failed to bind to server with dn= %s Error: %s\n\t%s\n",
+                              ldap_dn, ldap_err2string(rc),
+                              ld_error));
+               free(ld_error);
+               return rc;
+       }
+       
+       DEBUG(2, ("ldap_connect_system: succesful connection to the LDAP server\n"));
+       return rc;
+}
+
+/**********************************************************************
+Connect to LDAP server 
+*********************************************************************/
+int smb_ldap_open(struct smb_ldap_privates *ldap_state)
+{
+       int rc;
+       SMB_ASSERT(ldap_state);
+               
+#ifndef NO_LDAP_SECURITY
+       if (geteuid() != 0) {
+               DEBUG(0, ("smb_ldap_open: cannot access LDAP when not root..\n"));
+               return  LDAP_INSUFFICIENT_ACCESS;
+       }
+#endif
+
+       if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + SMB_LDAP_DONT_PING_TIME) < time(NULL))) {
+               struct sockaddr_un addr;
+               socklen_t len;
+               int sd;
+               if (ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd) == 0 &&
+                   getpeername(sd, (struct sockaddr *) &addr, &len) < 0) {
+                       /* the other end has died. reopen. */
+                       ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
+                       ldap_state->ldap_struct = NULL;
+                       ldap_state->last_ping = (time_t)0;
+               } else {
+                       ldap_state->last_ping = time(NULL);
+               } 
+       }
+
+       if (ldap_state->ldap_struct != NULL) {
+               DEBUG(5,("smb_ldap_open: allready connected to the LDAP server\n"));
+               return LDAP_SUCCESS;
+       }
+
+       if ((rc = smb_ldap_open_connection(ldap_state, &ldap_state->ldap_struct))) {
+               return rc;
+       }
+
+       if ((rc = smb_ldap_connect_system(ldap_state, ldap_state->ldap_struct))) {
+               ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
+               ldap_state->ldap_struct = NULL;
+               return rc;
+       }
+
+
+       ldap_state->last_ping = time(NULL);
+       DEBUG(4,("The LDAP server is succesful connected\n"));
+
+       return LDAP_SUCCESS;
+}
+
+/**********************************************************************
+Disconnect from LDAP server 
+*********************************************************************/
+NTSTATUS smb_ldap_close(struct smb_ldap_privates *ldap_state)
+{
+       if (!ldap_state)
+               return NT_STATUS_INVALID_PARAMETER;
+               
+       if (ldap_state->ldap_struct != NULL) {
+               ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
+               ldap_state->ldap_struct = NULL;
+       }
+       
+       DEBUG(5,("The connection to the LDAP server was closed\n"));
+       /* maybe free the results here --metze */
+       
+       return NT_STATUS_OK;
+}
+
+static int smb_ldap_retry_open(struct smb_ldap_privates *ldap_state, int *attempts)
+{
+       int rc;
+
+       SMB_ASSERT(ldap_state && attempts);
+               
+       if (*attempts != 0) {
+               /* we retry after 0.5, 2, 4.5, 8, 12.5, 18, 24.5 seconds */
+               msleep((((*attempts)*(*attempts))/2)*1000);
+       }
+       (*attempts)++;
+
+       if ((rc = smb_ldap_open(ldap_state))) {
+               DEBUG(0,("Connection to LDAP Server failed for the %d try!\n",*attempts));
+               return rc;
+       } 
+       
+       return LDAP_SUCCESS;            
+}
+
+
+int smb_ldap_search(struct smb_ldap_privates *ldap_state, 
+                   const char *base, int scope, const char *filter, 
+                   const char *attrs[], int attrsonly, 
+                   LDAPMessage **res)
+{
+       int             rc = LDAP_SERVER_DOWN;
+       int             attempts = 0;
+       
+       SMB_ASSERT(ldap_state);
+
+       while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
+               
+               if ((rc = smb_ldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
+                       continue;
+               
+               rc = ldap_search_s(ldap_state->ldap_struct, base, scope, 
+                                  filter, attrs, attrsonly, res);
+       }
+       
+       if (rc == LDAP_SERVER_DOWN) {
+               DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
+               smb_ldap_close(ldap_state);     
+       }
+       
+       return rc;
+}
+
+int smb_ldap_modify(struct smb_ldap_privates *ldap_state, char *dn, 
+                   LDAPMod *attrs[])
+{
+       int             rc = LDAP_SERVER_DOWN;
+       int             attempts = 0;
+       
+       if (!ldap_state)
+               return (-1);
+
+       while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
+               
+               if ((rc = smb_ldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
+                       continue;
+               
+               rc = ldap_modify_s(ldap_state->ldap_struct, dn, attrs);
+       }
+       
+       if (rc == LDAP_SERVER_DOWN) {
+               DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
+               smb_ldap_close(ldap_state);     
+       }
+       
+       return rc;
+}
+
+int smb_ldap_add(struct smb_ldap_privates *ldap_state, const char *dn,
+                LDAPMod *attrs[])
+{
+       int             rc = LDAP_SERVER_DOWN;
+       int             attempts = 0;
+       
+       if (!ldap_state)
+               return (-1);
+
+       while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
+               
+               if ((rc = smb_ldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
+                       continue;
+               
+               rc = ldap_add_s(ldap_state->ldap_struct, dn, attrs);
+       }
+       
+       if (rc == LDAP_SERVER_DOWN) {
+               DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
+               smb_ldap_close(ldap_state);     
+       }
+               
+       return rc;
+}
+
+int smb_ldap_delete(struct smb_ldap_privates *ldap_state, char *dn)
+{
+       int             rc = LDAP_SERVER_DOWN;
+       int             attempts = 0;
+       
+       if (!ldap_state)
+               return (-1);
+
+       while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
+               
+               if ((rc = smb_ldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
+                       continue;
+               
+               rc = ldap_delete_s(ldap_state->ldap_struct, dn);
+       }
+       
+       if (rc == LDAP_SERVER_DOWN) {
+               DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
+               smb_ldap_close(ldap_state);     
+       }
+               
+       return rc;
+}
+
+int smb_ldap_extended_operation(struct smb_ldap_privates *ldap_state,
+                               LDAP_CONST char *reqoid,
+                               struct berval *reqdata,
+                               LDAPControl **serverctrls,
+                               LDAPControl **clientctrls, char **retoidp,
+                               struct berval **retdatap)
+{
+       int             rc = LDAP_SERVER_DOWN;
+       int             attempts = 0;
+       
+       if (!ldap_state)
+               return (-1);
+
+       while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
+               
+               if ((rc = smb_ldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
+                       continue;
+               
+               rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, reqdata, serverctrls, clientctrls, retoidp, retdatap);
+       }
+       
+       if (rc == LDAP_SERVER_DOWN) {
+               DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
+               smb_ldap_close(ldap_state);     
+       }
+               
+       return rc;
+}
+
+/*******************************************************************
+search an attribute and return the first value found.
+******************************************************************/
+BOOL smb_ldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
+                                  const char *attribute, pstring value)
+{
+       char **values;
+
+       if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
+               value = NULL;
+               DEBUG (10, ("smb_ldap_get_single_attribute: [%s] = [<does not exist>]\n", attribute));
+               
+               return False;
+       }
+       
+       pstrcpy(value, values[0]);
+       ldap_value_free(values);
+#ifdef DEBUG_PASSWORDS
+       DEBUG (100, ("smb_ldap_get_single_attribute: [%s] = [%s]\n", attribute, value));
+#endif 
+       return True;
+}
+  
+
+/************************************************************************
+Routine to manage the LDAPMod structure array
+manage memory used by the array, by each struct, and values
+
+************************************************************************/
+void smb_ldap_make_a_mod (LDAPMod *** modlist, int modop, 
+                         const char *attribute, const char *value)
+{
+       LDAPMod **mods;
+       int i;
+       int j;
+
+       mods = *modlist;
+
+       if (attribute == NULL || *attribute == '\0')
+               return;
+
+       if (value == NULL || *value == '\0')
+               return;
+
+       if (mods == NULL) 
+       {
+               mods = (LDAPMod **) malloc(sizeof(LDAPMod *));
+               if (mods == NULL)
+               {
+                       DEBUG(0, ("smb_ldap_make_a_mod: out of memory!\n"));
+                       return;
+               }
+               mods[0] = NULL;
+       }
+
+       for (i = 0; mods[i] != NULL; ++i) {
+               if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute))
+                       break;
+       }
+
+       if (mods[i] == NULL)
+       {
+               mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *));
+               if (mods == NULL)
+               {
+                       DEBUG(0, ("smb_ldap_make_a_mod: out of memory!\n"));
+                       return;
+               }
+               mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
+               if (mods[i] == NULL)
+               {
+                       DEBUG(0, ("smb_ldap_make_a_mod: out of memory!\n"));
+                       return;
+               }
+               mods[i]->mod_op = modop;
+               mods[i]->mod_values = NULL;
+               mods[i]->mod_type = strdup(attribute);
+               mods[i + 1] = NULL;
+       }
+
+       if (value != NULL)
+       {
+               j = 0;
+               if (mods[i]->mod_values != NULL) {
+                       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, ("smb_ldap_make_a_mod: Memory allocation failure!\n"));
+                       return;
+               }
+               mods[i]->mod_values[j] = strdup(value);
+               mods[i]->mod_values[j + 1] = NULL;
+       }
+       *modlist = mods;
+}
+
+#endif
index 4b4d9eb8d29df520388612570dee8a4398c59f65..23f4b4d0815aacf34f18e450b478d475617779aa 100644 (file)
@@ -28,7 +28,7 @@ static struct {
   struct winbindd_idmap_methods *methods;
 } builtin_winbindd_idmap_functions[] = {
   { "tdb", winbind_idmap_reg_tdb, NULL },
-  /*  { "ldap", winbind_idmap_reg_ldap, NULL },*/
+  { "ldap", winbind_idmap_reg_ldap, NULL },
   { NULL, NULL, NULL }
 };
 
diff --git a/source3/nsswitch/winbindd_idmap_ldap.c b/source3/nsswitch/winbindd_idmap_ldap.c
new file mode 100644 (file)
index 0000000..b0b260e
--- /dev/null
@@ -0,0 +1,394 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   Winbind daemon - user related function
+
+   Copyright (C) Jim McDonough <jmcd@us.ibm.com>      2003
+   
+   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
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "winbindd.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
+
+#ifdef HAVE_LDAP
+
+#include <lber.h>
+#include <ldap.h>
+
+#include "smb_ldap.h"
+
+/* Globals */
+static struct smb_ldap_privates *ldap_state;
+
+static const char *attr[] = { "uid", "rid", "domain", "uidNumber", 
+                             "gidNumber", NULL };
+
+static const char *pool_attr[] = {"uidNumber", "gidNumber", "cn", NULL};
+
+static const char *group_attr[] = {"gidNumber", "ntSid", NULL};
+
+static long ldap_allocate_id(BOOL is_user)
+{
+       int rc, count;
+       LDAPMessage *result;
+       int scope = LDAP_SCOPE_SUBTREE;
+       long ret = 0;
+       int sanity = 0;
+
+       do {
+               rc = smb_ldap_search(ldap_state, lp_ldap_suffix(), scope, is_user?"cn=UID Pool":"cn=GID Pool", pool_attr, 0, &result);
+
+               if (LDAP_SUCCESS != rc) {
+                       DEBUG(0,("ldap_allocate_id: No ID pool found in directory\n"));
+                       return 0;
+               }
+               
+               count = ldap_count_entries(ldap_state->ldap_struct, result);
+               
+               if (1 < count) {
+                       DEBUG(0,("ldap_allocate_id: Multiple UID pools found in directory?\n"));
+                       break;
+               } else if (1 == count) {
+                       LDAPMessage *entry = 
+                               ldap_first_entry(ldap_state->ldap_struct, 
+                                                result);
+                       LDAPMod **mods = NULL;
+                       pstring temp;
+                       
+                       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, is_user?"uidNumber":"gidNumber", temp)) {
+                               return False;
+                       }
+                       ret = atol(temp);
+                       smb_ldap_make_a_mod(&mods, LDAP_MOD_DELETE, 
+                                           is_user?"uidNumber":"gidNumber",
+                                           temp);
+                       slprintf(temp, sizeof(temp) - 1, "%i", ret + 1);
+                       smb_ldap_make_a_mod(&mods, LDAP_MOD_ADD, is_user?"uidNumber":"gidNumber", temp);
+                       slprintf(temp, sizeof(temp) - 1, "cn=%cID Pool,%s", is_user?'U':'G', lp_ldap_user_suffix());
+                       rc = smb_ldap_modify(ldap_state, temp, mods);
+                       ldap_mods_free(mods, 1);
+               } else {
+                       DEBUG(0,("ldap_allocate_id: unexpected number of entries returned\n"));
+                       break;
+               }
+       } while (LDAP_NO_SUCH_ATTRIBUTE == rc && ++sanity < 100);
+
+       return ret;
+}
+
+/*****************************************************************************
+ Initialise idmap database. 
+*****************************************************************************/
+static BOOL ldap_idmap_init(void)
+{
+       static struct smb_ldap_privates state;
+       ldap_state = &state;
+
+#ifdef WITH_LDAP_SAMCONFIG
+       {
+               int ldap_port = lp_ldap_port();
+
+               /* remap default port if not using SSL */
+               if (lp_ldap_ssl() != LDAP_SSL_ON && ldap_port == 636) {
+                       ldap_port = 389;
+               }
+
+               ldap_state->uri = asprintf("%s://%s:d", 
+                                          lp_ldap_ssl() == LDAP_SSL_ON ? "ldaps" : "ldap", 
+                                          lp_ldap_server(), ldap_port);
+               if (!ldap_state->uri) {
+                       DEBUG(0,("Out of memory\n"));
+                       return False;
+               }
+       }
+#else
+       ldap_state->uri = "ldap://localhost";
+#endif
+       return True;
+}
+
+static BOOL ldap_get_sid_from_uid(uid_t uid, DOM_SID * sid)
+{
+       pstring filter;
+       int scope = LDAP_SCOPE_SUBTREE;
+       int rc, count;
+       LDAPMessage *result;
+
+       slprintf(filter, sizeof(filter) - 1, "uidNumber=%i", uid);
+
+       DEBUG(2, ("ldap_get_sid_from_uid: searching for:[%s]\n", filter));
+
+       rc = smb_ldap_search(ldap_state, lp_ldap_suffix(), scope, filter, attr, 0, &result);
+       if (LDAP_SUCCESS != rc) {
+               DEBUG(0,("ldap_get_sid_from_uid: user search failed\n"));
+               return False;
+       }
+       
+       count = ldap_count_entries(ldap_state->ldap_struct, result);
+       if (1 < count) {
+               DEBUG(0,("More than one user exists where: %s\n", filter));
+               ldap_msgfree(result);
+               return False;
+       } else if (1 == count) {
+               /* we found the user, get the users RID */
+               LDAPMessage *entry = ldap_first_entry(ldap_state->ldap_struct, 
+                                                     result);
+               pstring temp, domain;
+               uint32 rid;
+               struct winbindd_domain *wb_dom;
+
+               if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "domain", domain)) {
+                       return False;
+               }
+               if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "rid", temp)) {
+                       return False;
+               }
+               rid = (uint32)atol(temp);
+               wb_dom = find_domain_from_name(domain);
+
+               if (!wb_dom) {
+                       DEBUG(0,("ldap_get_sid_from_uid: could not find domain %s\n", domain));
+                       return False;
+               }
+
+               sid_copy(sid, &wb_dom->sid);
+               sid_append_rid(sid, rid);
+       } else {
+               /* 0 entries? that ain't right */
+               DEBUG(0,("ldap_get_sid_from_uid: not user entry found for %s\n", filter));
+       }
+
+       return True;
+}
+
+static BOOL ldap_get_uid_from_sid(DOM_SID *sid, uid_t *uid)
+{
+       pstring filter;
+       int scope = LDAP_SCOPE_SUBTREE;
+       int rc, count;
+       LDAPMessage *result;
+       uint32 rid = 0;
+       struct winbindd_domain *wb_dom;
+       DOM_SID dom_sid;
+
+       sid_copy(&dom_sid, sid);
+
+       if (!sid_split_rid(&dom_sid, &rid)) {
+               DEBUG(0,("ldap_get_uid_from_sid: sid does not contain an rid\n"));
+               return False;
+       }
+
+       if (!(wb_dom = find_domain_from_sid(&dom_sid))) {
+               DEBUG(0,("ldap_get_uid_from_sid: cannot lookup domain from sid\n"));
+               return False;
+       }
+
+       slprintf(filter, sizeof(filter) - 1, "rid=%d,domain=%s,objectClass=sambaAccount", rid, wb_dom->name);
+
+       DEBUG(2, ("ldap_get_uid_from_sid: searching for:[%s]\n", filter));
+
+       rc = smb_ldap_search(ldap_state, lp_ldap_suffix(), scope, filter, attr, 0, &result);
+       if (LDAP_NO_SUCH_OBJECT == rc) {
+               LDAPMod **mods = NULL;
+               pstring temp;
+               fstring dom, name;
+               int sid_type;
+
+               winbindd_lookup_name_by_sid(sid, dom, name, 
+                                           (enum SID_USE_TYPE *)&sid_type);
+               slprintf(temp, sizeof(temp) - 1, "%i", rid);
+               smb_ldap_make_a_mod(&mods, LDAP_MOD_ADD, "rid", temp);
+
+               *uid = ldap_allocate_id(True);
+               slprintf(temp, sizeof(temp) - 1, "%i", *uid);
+               smb_ldap_make_a_mod(&mods, LDAP_MOD_ADD, "uidNumber", temp);
+
+               smb_ldap_make_a_mod(&mods, LDAP_MOD_ADD, "uid", name);
+               smb_ldap_make_a_mod(&mods, LDAP_MOD_ADD, "objectClass", "sambaAccount");
+               smb_ldap_make_a_mod(&mods, LDAP_MOD_ADD, "objectClass", "account");
+               slprintf(temp, sizeof(temp) - 1, "uid=%s,%s", name, lp_ldap_user_suffix());
+               rc = smb_ldap_modify(ldap_state, temp, mods);
+
+               ldap_mods_free(mods, 1);
+               if (LDAP_SUCCESS != rc) {
+                       return False;
+               }
+       } else if (LDAP_SUCCESS == rc) {
+               count = ldap_count_entries(ldap_state->ldap_struct, result);
+               if (1 < count) {
+                       DEBUG(0,("More than one user exists where: %s\n", filter));
+                       ldap_msgfree(result);
+                       return False;
+               } else if (1 == count) {
+                       /* we found the user, get the idNumber */
+                       LDAPMessage *entry = ldap_first_entry(ldap_state->ldap_struct, result);
+                       pstring temp;
+                       
+                       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "uidNumber", temp)) {
+                               return False;
+                       }
+                       *uid = atol(temp);
+               } else {
+                       DEBUG(0,("ldap_get_uid_from_sid: zero entries returned?\n"));
+                       return False;
+               }
+       } else {
+               DEBUG(0,("ldap_get_uid_from_sid: unknown error querying user info\n"));
+               return False;
+       }
+                          
+       return True;
+}
+
+static BOOL ldap_get_sid_from_gid(gid_t gid, DOM_SID * sid)
+{
+       pstring filter;
+       int scope = LDAP_SCOPE_SUBTREE;
+       int rc, count;
+       LDAPMessage *result;
+
+       slprintf(filter, sizeof(filter) - 1, "gidNumber=%i,objectClass=sambaGroupMapping", gid);
+
+       DEBUG(2, ("ldap_get_sid_from_gid: searching for:[%s]\n", filter));
+
+       rc = smb_ldap_search(ldap_state, lp_ldap_suffix(), scope, filter, attr, 0, &result);
+       if (LDAP_SUCCESS != rc) {
+               DEBUG(0,("ldap_get_sid_from_gid: user search failed\n"));
+               return False;
+       }
+       
+       count = ldap_count_entries(ldap_state->ldap_struct, result);
+       if (1 < count) {
+               DEBUG(0,("More than one group exists where: %s\n", filter));
+               ldap_msgfree(result);
+               return False;
+       } else if (1 == count) {
+               LDAPMessage *entry = ldap_first_entry(ldap_state->ldap_struct, 
+                                                     result);
+               pstring str_sid;
+
+               if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "ntSid", str_sid)) {
+                       return False;
+               }
+
+               string_to_sid(sid, str_sid);
+       } else {
+               /* 0 entries? that ain't right */
+               DEBUG(0,("ldap_get_sid_from_gid: not group entry found for %s\n", filter));
+       }
+
+       return True;
+}
+
+static BOOL ldap_get_gid_from_sid(DOM_SID *sid, gid_t *gid)
+{
+       pstring filter;
+       int scope = LDAP_SCOPE_SUBTREE;
+       int rc, count;
+       LDAPMessage *result;
+       fstring str_sid;
+
+       sid_to_string(str_sid, sid);
+
+       slprintf(filter, sizeof(filter) - 1, "ntSid=%d,objectClass=sambaGroupMapping", str_sid);
+
+       DEBUG(2, ("ldap_get_gid_from_sid: searching for:[%s]\n", filter));
+
+       rc = smb_ldap_search(ldap_state, lp_ldap_suffix(), scope, filter, attr, 0, &result);
+       if (LDAP_NO_SUCH_OBJECT == rc) {
+               LDAPMod **mods = NULL;
+               pstring temp;
+
+               *gid = ldap_allocate_id(False);
+               slprintf(temp, sizeof(temp) - 1, "%i", *gid);
+               smb_ldap_make_a_mod(&mods, LDAP_MOD_ADD, "gidNumber", temp);
+               smb_ldap_make_a_mod(&mods, LDAP_MOD_ADD, "objectClass", "sambaGroupMapping");
+               smb_ldap_make_a_mod(&mods, LDAP_MOD_ADD, "objectClass", "account");
+               slprintf(temp, sizeof(temp) - 1, "gidNumber=%i,%s", *gid, lp_ldap_user_suffix());
+               rc = smb_ldap_modify(ldap_state, temp, mods);
+
+               ldap_mods_free(mods, 1);
+               if (LDAP_SUCCESS != rc) {
+                       return False;
+               }
+       } else if (LDAP_SUCCESS == rc) {
+               count = ldap_count_entries(ldap_state->ldap_struct, result);
+               if (1 < count) {
+                       DEBUG(0,("More than one group exists where: %s\n", filter));
+                       ldap_msgfree(result);
+                       return False;
+               } else if (1 == count) {
+                       LDAPMessage *entry = ldap_first_entry(ldap_state->ldap_struct, result);
+                       pstring temp;
+                       
+                       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber", temp)) {
+                               return False;
+                       }
+                       *gid = atol(temp);
+               } else {
+                       DEBUG(0,("ldap_get_gid_from_sid: zero entries returned?\n"));
+                       return False;
+               }
+       } else {
+               DEBUG(0,("ldap_get_gid_from_sid: unknown error querying user info\n"));
+               return False;
+       }
+                          
+       return True;
+}
+
+static BOOL ldap_idmap_close(void)
+{
+       smb_ldap_close(ldap_state);
+       ldap_state = 0;
+       return True;
+}
+
+static void ldap_idmap_status(void)
+{
+       DEBUG(0, ("winbindd idmap status:\n"));
+       DEBUG(0, ("Using LDAP\n"));
+}
+
+struct winbind_idmap_methods ldap_idmap_methods = {
+       ldap_idmap_init,
+
+       ldap_get_sid_from_uid,
+       ldap_get_sid_from_gid,
+
+       ldap_get_uid_from_sid,
+       ldap_get_gid_from_sid,
+
+       ldap_idmap_close,
+
+       ldap_idmap_status
+};
+
+#endif
+
+BOOL winbind_idmap_reg_ldap(struct winbind_idmap_methods **meth)
+{
+#ifdef HAVE_LDAP
+       *meth = &ldap_idmap_methods;
+
+       return True;
+#else
+       DEBUG(0,("winbind_idmap_reg_ldap: LDAP support not compiled\n"));
+       return False;
+#endif
+}
index 264de8d0f03f9a5fecc7363c27f9c1113b71c1c3..eaef7f37a7b62dd76e6555a5eecd5de5b00d2c36 100644 (file)
@@ -6,6 +6,7 @@
    Copyright (C) Shahms King                   2001
    Copyright (C) Andrew Bartlett               2002
    Copyright (C) Stefan (metze) Metzmacher     2002
+   Copyright (C) Jim McDonough                  2003
     
    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
 #include <lber.h>
 #include <ldap.h>
 
+#include "smb_ldap.h"
+
 #ifndef SAM_ACCOUNT
 #define SAM_ACCOUNT struct sam_passwd
 #endif
 
-struct ldapsam_privates {
-
-       /* Former statics */
-       LDAP *ldap_struct;
-       LDAPMessage *result;
-       LDAPMessage *entry;
-       int index;
-       
-       time_t last_ping;
-       /* retrive-once info */
-       const char *uri;
-       
-       BOOL permit_non_unix_accounts;
-       
-       uint32 low_nua_rid; 
-       uint32 high_nua_rid; 
-
-       char *bind_dn;
-       char *bind_secret;
-};
-
-#define LDAPSAM_DONT_PING_TIME 10      /* ping only all 10 seconds */
-
-static struct ldapsam_privates *static_ldap_state;
-
-static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state);
+static uint32 ldapsam_get_next_available_nua_rid(struct smb_ldap_privates *ldap_state);
 
 /*******************************************************************
  find the ldap password
@@ -157,496 +135,17 @@ static const char *attr[] = {"uid", "pwdLastSet", "logonTime",
                             "uidNumber", "gidNumber", 
                             "homeDirectory", NULL };
 
-/*******************************************************************
- open a connection to the ldap server.
-******************************************************************/
-static int ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP ** ldap_struct)
-{
-       int rc = LDAP_SUCCESS;
-       int version;
-       BOOL ldap_v3 = False;
-
-#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
-       DEBUG(10, ("ldapsam_open_connection: %s\n", ldap_state->uri));
-       
-       if ((rc = ldap_initialize(ldap_struct, ldap_state->uri)) != LDAP_SUCCESS) {
-               DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
-               return rc;
-       }
-       
-#else 
-
-       /* Parse the string manually */
-
-       {
-               int port = 0;
-               fstring protocol;
-               fstring host;
-               const char *p = ldap_state->uri; 
-               SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
-               
-               /* skip leading "URL:" (if any) */
-               if ( strncasecmp( p, "URL:", 4 ) == 0 ) {
-                       p += 4;
-               }
-               
-               sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port);
-               
-               if (port == 0) {
-                       if (strequal(protocol, "ldap")) {
-                               port = LDAP_PORT;
-                       } else if (strequal(protocol, "ldaps")) {
-                               port = LDAPS_PORT;
-                       } else {
-                               DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
-                       }
-               }
-               
-               if ((*ldap_struct = ldap_init(host, port)) == NULL)     {
-                       DEBUG(0, ("ldap_init failed !\n"));
-                       return LDAP_OPERATIONS_ERROR;
-               }
-               
-               if (strequal(protocol, "ldaps")) {
-#ifdef LDAP_OPT_X_TLS
-                       int tls = LDAP_OPT_X_TLS_HARD;
-                       if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
-                       {
-                               DEBUG(0, ("Failed to setup a TLS session\n"));
-                       }
-                       
-                       DEBUG(3,("LDAPS option set...!\n"));
-#else
-                       DEBUG(0,("ldapsam_open_connection: Secure connection not supported by LDAP client libraries!\n"));
-                       return LDAP_OPERATIONS_ERROR;
-#endif
-               }
-       }
-#endif
-
-       if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS)
-       {
-               if (version != LDAP_VERSION3)
-               {
-                       version = LDAP_VERSION3;
-                       if (ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) {
-                               ldap_v3 = True;
-                       }
-               } else {
-                       ldap_v3 = True;
-               }
-       }
-
-       if (lp_ldap_ssl() == LDAP_SSL_START_TLS) {
-#ifdef LDAP_OPT_X_TLS
-               if (ldap_v3) {
-                       if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS)
-                       {
-                               DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
-                                        ldap_err2string(rc)));
-                               return rc;
-                       }
-                       DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
-               } else {
-                       
-                       DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
-                       return LDAP_OPERATIONS_ERROR;
-               }
-#else
-               DEBUG(0,("ldapsam_open_connection: StartTLS not supported by LDAP client libraries!\n"));
-               return LDAP_OPERATIONS_ERROR;
-#endif
-       }
-
-       DEBUG(2, ("ldapsam_open_connection: connection opened\n"));
-       return rc;
-}
-
-
-/*******************************************************************
- a rebind function for authenticated referrals
- This version takes a void* that we can shove useful stuff in :-)
-******************************************************************/
-#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
-#else
-static int rebindproc_with_state  (LDAP * ld, char **whop, char **credp, 
-                                  int *methodp, int freeit, void *arg)
-{
-       struct ldapsam_privates *ldap_state = arg;
-       
-       /** @TODO Should we be doing something to check what servers we rebind to?
-           Could we get a referral to a machine that we don't want to give our
-           username and password to? */
-       
-       if (freeit) {
-               SAFE_FREE(*whop);
-               memset(*credp, '\0', strlen(*credp));
-               SAFE_FREE(*credp);
-       } else {
-               DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n", 
-                         ldap_state->bind_dn));
-
-               *whop = strdup(ldap_state->bind_dn);
-               if (!*whop) {
-                       return LDAP_NO_MEMORY;
-               }
-               *credp = strdup(ldap_state->bind_secret);
-               if (!*credp) {
-                       SAFE_FREE(*whop);
-                       return LDAP_NO_MEMORY;
-               }
-               *methodp = LDAP_AUTH_SIMPLE;
-       }
-       return 0;
-}
-#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
-
-/*******************************************************************
- a rebind function for authenticated referrals
- This version takes a void* that we can shove useful stuff in :-)
- and actually does the connection.
-******************************************************************/
-#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
-static int rebindproc_connect_with_state (LDAP *ldap_struct, 
-                                         LDAP_CONST char *url, 
-                                         ber_tag_t request,
-                                         ber_int_t msgid, void *arg)
-{
-       struct ldapsam_privates *ldap_state = arg;
-       int rc;
-       DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n", 
-                ldap_state->bind_dn));
-       
-       /** @TODO Should we be doing something to check what servers we rebind to?
-           Could we get a referral to a machine that we don't want to give our
-           username and password to? */
-
-       rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
-       
-       return rc;
-}
-#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
-
-/*******************************************************************
- Add a rebind function for authenticated referrals
-******************************************************************/
-#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
-#else
-# if LDAP_SET_REBIND_PROC_ARGS == 2
-static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
-                      int *method, int freeit )
-{
-       return rebindproc_with_state(ldap_struct, whop, credp,
-                                  method, freeit, static_ldap_state);
-       
-}
-# endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
-#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
-
-/*******************************************************************
- a rebind function for authenticated referrals
- this also does the connection, but no void*.
-******************************************************************/
-#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
-# if LDAP_SET_REBIND_PROC_ARGS == 2
-static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
-                              ber_int_t msgid)
-{
-       return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid, 
-                                            static_ldap_state);
-}
-# endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
-#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
-
-/*******************************************************************
- connect to the ldap server under system privilege.
-******************************************************************/
-static int ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * ldap_struct)
-{
-       int rc;
-       char *ldap_dn;
-       char *ldap_secret;
-
-       /* The rebind proc needs this *HACK*.  We are not multithreaded, so
-          this will work, but it's not nice. */
-       static_ldap_state = ldap_state;
-
-       /* get the password */
-       if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret))
-       {
-               DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
-               return LDAP_INVALID_CREDENTIALS;
-       }
-
-       ldap_state->bind_dn = ldap_dn;
-       ldap_state->bind_secret = ldap_secret;
-
-       /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite 
-          (OpenLDAP) doesnt' seem to support it */
-          
-       DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
-                 ldap_state->uri, ldap_dn));
-
-#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
-# if LDAP_SET_REBIND_PROC_ARGS == 2    
-       ldap_set_rebind_proc(ldap_struct, &rebindproc_connect); 
-# endif
-# if LDAP_SET_REBIND_PROC_ARGS == 3    
-       ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);  
-# endif
-#else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
-# if LDAP_SET_REBIND_PROC_ARGS == 2    
-       ldap_set_rebind_proc(ldap_struct, &rebindproc); 
-# endif
-# if LDAP_SET_REBIND_PROC_ARGS == 3    
-       ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);  
-# endif
-#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
-
-       rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
-
-       if (rc != LDAP_SUCCESS) {
-               char *ld_error = NULL;
-               ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
-                               &ld_error);
-               DEBUG(0,
-                     ("failed to bind to server with dn= %s Error: %s\n\t%s\n",
-                              ldap_dn ? ld_error : "(unknown)", ldap_err2string(rc),
-                              ld_error));
-               SAFE_FREE(ld_error);
-               return rc;
-       }
-       
-       DEBUG(2, ("ldap_connect_system: succesful connection to the LDAP server\n"));
-       return rc;
-}
-
-/**********************************************************************
-Connect to LDAP server 
-*********************************************************************/
-static int ldapsam_open(struct ldapsam_privates *ldap_state)
-{
-       int rc;
-       SMB_ASSERT(ldap_state);
-               
-#ifndef NO_LDAP_SECURITY
-       if (geteuid() != 0) {
-               DEBUG(0, ("ldapsam_open: cannot access LDAP when not root..\n"));
-               return  LDAP_INSUFFICIENT_ACCESS;
-       }
-#endif
-
-       if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + LDAPSAM_DONT_PING_TIME) < time(NULL))) {
-               struct sockaddr_un addr;
-               socklen_t len;
-               int sd;
-               if (ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd) == 0 &&
-                   getpeername(sd, (struct sockaddr *) &addr, &len) < 0) {
-                       /* the other end has died. reopen. */
-                       ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
-                       ldap_state->ldap_struct = NULL;
-                       ldap_state->last_ping = (time_t)0;
-               } else {
-                       ldap_state->last_ping = time(NULL);
-               } 
-       }
-
-       if (ldap_state->ldap_struct != NULL) {
-               DEBUG(5,("ldapsam_open: allready connected to the LDAP server\n"));
-               return LDAP_SUCCESS;
-       }
-
-       if ((rc = ldapsam_open_connection(ldap_state, &ldap_state->ldap_struct))) {
-               return rc;
-       }
-
-       if ((rc = ldapsam_connect_system(ldap_state, ldap_state->ldap_struct))) {
-               ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
-               ldap_state->ldap_struct = NULL;
-               return rc;
-       }
-
-
-       ldap_state->last_ping = time(NULL);
-       DEBUG(4,("The LDAP server is succesful connected\n"));
-
-       return LDAP_SUCCESS;
-}
-
-/**********************************************************************
-Disconnect from LDAP server 
-*********************************************************************/
-static NTSTATUS ldapsam_close(struct ldapsam_privates *ldap_state)
-{
-       if (!ldap_state)
-               return NT_STATUS_INVALID_PARAMETER;
-               
-       if (ldap_state->ldap_struct != NULL) {
-               ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
-               ldap_state->ldap_struct = NULL;
-       }
-       
-       DEBUG(5,("The connection to the LDAP server was closed\n"));
-       /* maybe free the results here --metze */
-       
-       return NT_STATUS_OK;
-}
-
-static int ldapsam_retry_open(struct ldapsam_privates *ldap_state, int *attempts)
-{
-       int rc;
-
-       SMB_ASSERT(ldap_state && attempts);
-               
-       if (*attempts != 0) {
-               /* we retry after 0.5, 2, 4.5, 8, 12.5, 18, 24.5 seconds */
-               msleep((((*attempts)*(*attempts))/2)*1000);
-       }
-       (*attempts)++;
-
-       if ((rc = ldapsam_open(ldap_state))) {
-               DEBUG(0,("Connection to LDAP Server failed for the %d try!\n",*attempts));
-               return rc;
-       } 
-       
-       return LDAP_SUCCESS;            
-}
-
-
-static int ldapsam_search(struct ldapsam_privates *ldap_state, 
-                         const char *base, int scope, const char *filter, 
-                         const char *attrs[], int attrsonly, 
-                         LDAPMessage **res)
-{
-       int             rc = LDAP_SERVER_DOWN;
-       int             attempts = 0;
-       
-       SMB_ASSERT(ldap_state);
-
-       while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
-               
-               if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
-                       continue;
-               
-               rc = ldap_search_s(ldap_state->ldap_struct, base, scope, 
-                                  filter, attrs, attrsonly, res);
-       }
-       
-       if (rc == LDAP_SERVER_DOWN) {
-               DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
-               ldapsam_close(ldap_state);      
-       }
-       
-       return rc;
-}
-
-static int ldapsam_modify(struct ldapsam_privates *ldap_state, char *dn, LDAPMod *attrs[])
-{
-       int             rc = LDAP_SERVER_DOWN;
-       int             attempts = 0;
-       
-       if (!ldap_state)
-               return (-1);
-
-       while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
-               
-               if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
-                       continue;
-               
-               rc = ldap_modify_s(ldap_state->ldap_struct, dn, attrs);
-       }
-       
-       if (rc == LDAP_SERVER_DOWN) {
-               DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
-               ldapsam_close(ldap_state);      
-       }
-       
-       return rc;
-}
-
-static int ldapsam_add(struct ldapsam_privates *ldap_state, const char *dn, LDAPMod *attrs[])
-{
-       int             rc = LDAP_SERVER_DOWN;
-       int             attempts = 0;
-       
-       if (!ldap_state)
-               return (-1);
-
-       while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
-               
-               if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
-                       continue;
-               
-               rc = ldap_add_s(ldap_state->ldap_struct, dn, attrs);
-       }
-       
-       if (rc == LDAP_SERVER_DOWN) {
-               DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
-               ldapsam_close(ldap_state);      
-       }
-               
-       return rc;
-}
-
-static int ldapsam_delete(struct ldapsam_privates *ldap_state, char *dn)
-{
-       int             rc = LDAP_SERVER_DOWN;
-       int             attempts = 0;
-       
-       if (!ldap_state)
-               return (-1);
-
-       while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
-               
-               if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
-                       continue;
-               
-               rc = ldap_delete_s(ldap_state->ldap_struct, dn);
-       }
-       
-       if (rc == LDAP_SERVER_DOWN) {
-               DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
-               ldapsam_close(ldap_state);      
-       }
-               
-       return rc;
-}
-
-static int ldapsam_extended_operation(struct ldapsam_privates *ldap_state, LDAP_CONST char *reqoid, struct berval *reqdata, LDAPControl **serverctrls, LDAPControl **clientctrls, char **retoidp, struct berval **retdatap)
-{
-       int             rc = LDAP_SERVER_DOWN;
-       int             attempts = 0;
-       
-       if (!ldap_state)
-               return (-1);
-
-       while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
-               
-               if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
-                       continue;
-               
-               rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, reqdata, serverctrls, clientctrls, retoidp, retdatap);
-       }
-       
-       if (rc == LDAP_SERVER_DOWN) {
-               DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
-               ldapsam_close(ldap_state);      
-       }
-               
-       return rc;
-}
-
 /*******************************************************************
  run the search by name.
 ******************************************************************/
-static int ldapsam_search_one_user (struct ldapsam_privates *ldap_state, const char *filter, LDAPMessage ** result)
+static int ldapsam_search_one_user (struct smb_ldap_privates *ldap_state, const char *filter, LDAPMessage ** result)
 {
        int scope = LDAP_SCOPE_SUBTREE;
        int rc;
 
        DEBUG(2, ("ldapsam_search_one_user: searching for:[%s]\n", filter));
 
-       rc = ldapsam_search(ldap_state, lp_ldap_suffix (), scope, filter, attr, 0, result);
+       rc = smb_ldap_search(ldap_state, lp_ldap_suffix (), scope, filter, attr, 0, result);
 
        if (rc != LDAP_SUCCESS) {
                char *ld_error = NULL;
@@ -665,7 +164,7 @@ static int ldapsam_search_one_user (struct ldapsam_privates *ldap_state, const c
 /*******************************************************************
  run the search by name.
 ******************************************************************/
-static int ldapsam_search_one_user_by_name (struct ldapsam_privates *ldap_state, const char *user,
+static int ldapsam_search_one_user_by_name (struct smb_ldap_privates *ldap_state, const char *user,
                             LDAPMessage ** result)
 {
        pstring filter;
@@ -696,7 +195,7 @@ static int ldapsam_search_one_user_by_name (struct ldapsam_privates *ldap_state,
 /*******************************************************************
  run the search by uid.
 ******************************************************************/
-static int ldapsam_search_one_user_by_uid(struct ldapsam_privates *ldap_state, 
+static int ldapsam_search_one_user_by_uid(struct smb_ldap_privates *ldap_state, 
                                          int uid,
                                          LDAPMessage ** result)
 {
@@ -730,7 +229,7 @@ static int ldapsam_search_one_user_by_uid(struct ldapsam_privates *ldap_state,
 /*******************************************************************
  run the search by rid.
 ******************************************************************/
-static int ldapsam_search_one_user_by_rid (struct ldapsam_privates *ldap_state, 
+static int ldapsam_search_one_user_by_rid (struct smb_ldap_privates *ldap_state, 
                                           uint32 rid,
                                           LDAPMessage ** result)
 {
@@ -750,111 +249,11 @@ static int ldapsam_search_one_user_by_rid (struct ldapsam_privates *ldap_state,
        return rc;
 }
 
-/*******************************************************************
-search an attribute and return the first value found.
-******************************************************************/
-static BOOL get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
-                                 const char *attribute, pstring value)
-{
-       char **values;
-
-       if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
-               value = NULL;
-               DEBUG (10, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute));
-               
-               return False;
-       }
-       
-       pstrcpy(value, values[0]);
-       ldap_value_free(values);
-#ifdef DEBUG_PASSWORDS
-       DEBUG (100, ("get_single_attribute: [%s] = [%s]\n", attribute, value));
-#endif 
-       return True;
-}
-
-/************************************************************************
-Routine to manage the LDAPMod structure array
-manage memory used by the array, by each struct, and values
-
-************************************************************************/
-static void make_a_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
-{
-       LDAPMod **mods;
-       int i;
-       int j;
-
-       mods = *modlist;
-
-       if (attribute == NULL || *attribute == '\0')
-               return;
-
-#if 0
-       /* Why do we need this??? -- vl */
-               if (value == NULL || *value == '\0')
-               return;
-#endif
-
-       if (mods == NULL) 
-       {
-               mods = (LDAPMod **) malloc(sizeof(LDAPMod *));
-               if (mods == NULL)
-               {
-                       DEBUG(0, ("make_a_mod: out of memory!\n"));
-                       return;
-               }
-               mods[0] = NULL;
-       }
-
-       for (i = 0; mods[i] != NULL; ++i) {
-               if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute))
-                       break;
-       }
-
-       if (mods[i] == NULL)
-       {
-               mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *));
-               if (mods == NULL)
-               {
-                       DEBUG(0, ("make_a_mod: out of memory!\n"));
-                       return;
-               }
-               mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
-               if (mods[i] == NULL)
-               {
-                       DEBUG(0, ("make_a_mod: out of memory!\n"));
-                       return;
-               }
-               mods[i]->mod_op = modop;
-               mods[i]->mod_values = NULL;
-               mods[i]->mod_type = strdup(attribute);
-               mods[i + 1] = NULL;
-       }
-
-       if (value != NULL)
-       {
-               j = 0;
-               if (mods[i]->mod_values != NULL) {
-                       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"));
-                       return;
-               }
-               mods[i]->mod_values[j] = strdup(value);
-               mods[i]->mod_values[j + 1] = NULL;
-       }
-       *modlist = mods;
-}
-
 /*******************************************************************
  Delete complete object or objectclass and attrs from
  object found in search_result depending on lp_ldap_delete_dn
 ******************************************************************/
-static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
+static NTSTATUS ldapsam_delete_entry(struct smb_ldap_privates *ldap_state,
                                     LDAPMessage *result,
                                     const char *objectclass,
                                     const char **attrs)
@@ -877,7 +276,7 @@ static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
 
        if (lp_ldap_delete_dn()) {
                NTSTATUS ret = NT_STATUS_OK;
-               rc = ldapsam_delete(ldap_state, dn);
+               rc = smb_ldap_delete(ldap_state, dn);
 
                if (rc != LDAP_SUCCESS) {
                        DEBUG(0, ("Could not delete object %s\n", dn));
@@ -901,7 +300,7 @@ static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
                for (attrib = attrs; *attrib != NULL; attrib++) {
                        if (StrCaseCmp(*attrib, name) == 0) {
                                DEBUG(10, ("deleting attribute %s\n", name));
-                               make_a_mod(&mods, LDAP_MOD_DELETE, name, NULL);
+                               smb_ldap_make_a_mod(&mods, LDAP_MOD_DELETE, name, NULL);
                        }
                }
 
@@ -912,9 +311,9 @@ static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
                ber_free(ptr, 0);
        }
        
-       make_a_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass);
+       smb_ldap_make_a_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass);
 
-       rc = ldapsam_modify(ldap_state, dn, mods);
+       rc = smb_ldap_modify(ldap_state, dn, mods);
        ldap_mods_free(mods, 1);
 
        if (rc != LDAP_SUCCESS) {
@@ -938,7 +337,7 @@ static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
 /**********************************************************************
 Initialize SAM_ACCOUNT from an LDAP query (unix attributes only)
 *********************************************************************/
-static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state, 
+static BOOL get_unix_attributes (struct smb_ldap_privates *ldap_state, 
                                SAM_ACCOUNT * sampass,
                                LDAPMessage * entry)
 {
@@ -967,15 +366,15 @@ static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state,
        }
        ldap_value_free(ldap_values);
 
-       if (!get_single_attribute(ldap_state->ldap_struct, entry, "homeDirectory", homedir)) 
+       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "homeDirectory", homedir)) 
                return False;
        
-       if (!get_single_attribute(ldap_state->ldap_struct, entry, "uidNumber", temp))
+       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "uidNumber", temp))
                return False;
        
        uid = (uid_t)atol(temp);
        
-       if (!get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber", temp))
+       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber", temp))
                return False;
        
        gid = (gid_t)atol(temp);
@@ -993,7 +392,7 @@ static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state,
 Initialize SAM_ACCOUNT from an LDAP query
 (Based on init_sam_from_buffer in pdb_tdb.c)
 *********************************************************************/
-static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, 
+static BOOL init_sam_from_ldap (struct smb_ldap_privates *ldap_state, 
                                SAM_ACCOUNT * sampass,
                                LDAPMessage * entry)
 {
@@ -1054,7 +453,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
                return False;
        }
        
-       get_single_attribute(ldap_state->ldap_struct, entry, "uid", username);
+       smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "uid", username);
        DEBUG(2, ("Entry found for user: %s\n", username));
 
        pstrcpy(nt_username, username);
@@ -1066,12 +465,12 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
        pdb_set_domain(sampass, domain, PDB_DEFAULT);
        pdb_set_nt_username(sampass, nt_username, PDB_SET);
 
-       get_single_attribute(ldap_state->ldap_struct, entry, "rid", temp);
+       smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "rid", temp);
        user_rid = (uint32)atol(temp);
 
        pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
 
-       if (!get_single_attribute(ldap_state->ldap_struct, entry, "primaryGroupID", temp)) {
+       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "primaryGroupID", temp)) {
                group_rid = 0;
        } else {
                group_rid = (uint32)atol(temp);
@@ -1119,42 +518,42 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
                }
        }
 
-       if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdLastSet", temp)) {
+       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "pwdLastSet", temp)) {
                /* leave as default */
        } else {
                pass_last_set_time = (time_t) atol(temp);
                pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
        }
 
-       if (!get_single_attribute(ldap_state->ldap_struct, entry, "logonTime", temp)) {
+       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "logonTime", temp)) {
                /* leave as default */
        } else {
                logon_time = (time_t) atol(temp);
                pdb_set_logon_time(sampass, logon_time, PDB_SET);
        }
 
-       if (!get_single_attribute(ldap_state->ldap_struct, entry, "logoffTime", temp)) {
+       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "logoffTime", temp)) {
                /* leave as default */
        } else {
                logoff_time = (time_t) atol(temp);
                pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
        }
 
-       if (!get_single_attribute(ldap_state->ldap_struct, entry, "kickoffTime", temp)) {
+       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "kickoffTime", temp)) {
                /* leave as default */
        } else {
                kickoff_time = (time_t) atol(temp);
                pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
        }
 
-       if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdCanChange", temp)) {
+       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "pwdCanChange", temp)) {
                /* leave as default */
        } else {
                pass_can_change_time = (time_t) atol(temp);
                pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
        }
 
-       if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdMustChange", temp)) {
+       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "pwdMustChange", temp)) {
                /* leave as default */
        } else {
                pass_must_change_time = (time_t) atol(temp);
@@ -1167,9 +566,9 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
         * that fits your needs; using cn then displayName rather than 'userFullName'
         */
 
-       if (!get_single_attribute(ldap_state->ldap_struct, entry,
+       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry,
                                  "displayName", fullname)) {
-               if (!get_single_attribute(ldap_state->ldap_struct, entry,
+               if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry,
                                          "cn", fullname)) {
                        /* leave as default */
                } else {
@@ -1179,7 +578,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
                pdb_set_fullname(sampass, fullname, PDB_SET);
        }
 
-       if (!get_single_attribute(ldap_state->ldap_struct, entry, "homeDrive", dir_drive)) {
+       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "homeDrive", dir_drive)) {
                pdb_set_dir_drive(sampass, talloc_sub_specified(sampass->mem_ctx, 
                                                                  lp_logon_drive(),
                                                                  username, domain, 
@@ -1189,7 +588,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
                pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
        }
 
-       if (!get_single_attribute(ldap_state->ldap_struct, entry, "smbHome", homedir)) {
+       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "smbHome", homedir)) {
                pdb_set_homedir(sampass, talloc_sub_specified(sampass->mem_ctx, 
                                                                  lp_logon_home(),
                                                                  username, domain, 
@@ -1199,7 +598,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
                pdb_set_homedir(sampass, homedir, PDB_SET);
        }
 
-       if (!get_single_attribute(ldap_state->ldap_struct, entry, "scriptPath", logon_script)) {
+       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "scriptPath", logon_script)) {
                pdb_set_logon_script(sampass, talloc_sub_specified(sampass->mem_ctx, 
                                                                     lp_logon_script(),
                                                                     username, domain, 
@@ -1209,7 +608,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
                pdb_set_logon_script(sampass, logon_script, PDB_SET);
        }
 
-       if (!get_single_attribute(ldap_state->ldap_struct, entry, "profilePath", profile_path)) {
+       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "profilePath", profile_path)) {
                pdb_set_profile_path(sampass, talloc_sub_specified(sampass->mem_ctx, 
                                                                     lp_logon_path(),
                                                                     username, domain, 
@@ -1219,13 +618,13 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
                pdb_set_profile_path(sampass, profile_path, PDB_SET);
        }
 
-       if (!get_single_attribute(ldap_state->ldap_struct, entry, "description", acct_desc)) {
+       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "description", acct_desc)) {
                /* leave as default */
        } else {
                pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
        }
 
-       if (!get_single_attribute(ldap_state->ldap_struct, entry, "userWorkstations", workstations)) {
+       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "userWorkstations", workstations)) {
                /* leave as default */;
        } else {
                pdb_set_workstations(sampass, workstations, PDB_SET);
@@ -1237,7 +636,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
        hours_len = 21;
        memset(hours, 0xff, hours_len);
 
-       if (!get_single_attribute (ldap_state->ldap_struct, entry, "lmPassword", temp)) {
+       if (!smb_ldap_get_single_attribute (ldap_state->ldap_struct, entry, "lmPassword", temp)) {
                /* leave as default */
        } else {
                pdb_gethexpwd(temp, smblmpwd);
@@ -1247,7 +646,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
                ZERO_STRUCT(smblmpwd);
        }
 
-       if (!get_single_attribute (ldap_state->ldap_struct, entry, "ntPassword", temp)) {
+       if (!smb_ldap_get_single_attribute (ldap_state->ldap_struct, entry, "ntPassword", temp)) {
                /* leave as default */
        } else {
                pdb_gethexpwd(temp, smbntpwd);
@@ -1257,7 +656,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
                ZERO_STRUCT(smbntpwd);
        }
 
-       if (!get_single_attribute (ldap_state->ldap_struct, entry, "acctFlags", temp)) {
+       if (!smb_ldap_get_single_attribute (ldap_state->ldap_struct, entry, "acctFlags", temp)) {
                acct_ctrl |= ACB_NORMAL;
        } else {
                acct_ctrl = pdb_decode_acct_ctrl(temp);
@@ -1325,7 +724,7 @@ static void make_ldap_mod(LDAP *ldap_struct, LDAPMessage *existing,
           the old value, should it exist. */
 
        if ((newval != NULL) && (strlen(newval) > 0)) {
-               make_a_mod(mods, LDAP_MOD_ADD, attribute, newval);
+               smb_ldap_make_a_mod(mods, LDAP_MOD_ADD, attribute, newval);
        }
 
        if (values == NULL) {
@@ -1340,7 +739,7 @@ static void make_ldap_mod(LDAP *ldap_struct, LDAPMessage *existing,
           deny the complete operation if somebody changed the
           attribute behind our back. */
 
-       make_a_mod(mods, LDAP_MOD_DELETE, attribute, values[0]);
+       smb_ldap_make_a_mod(mods, LDAP_MOD_DELETE, attribute, values[0]);
        ldap_value_free(values);
 }
 
@@ -1348,7 +747,7 @@ static void make_ldap_mod(LDAP *ldap_struct, LDAPMessage *existing,
 Initialize SAM_ACCOUNT from an LDAP query
 (Based on init_buffer_from_sam in pdb_tdb.c)
 *********************************************************************/
-static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, 
+static BOOL init_ldap_from_sam (struct smb_ldap_privates *ldap_state, 
                                LDAPMessage *existing,
                                LDAPMod *** mods, const SAM_ACCOUNT * sampass,
                                BOOL (*need_update)(const SAM_ACCOUNT *,
@@ -1534,7 +933,7 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
 /**********************************************************************
 Connect to LDAP server and find the next available RID.
 *********************************************************************/
-static uint32 check_nua_rid_is_avail(struct ldapsam_privates *ldap_state, uint32 top_rid) 
+static uint32 check_nua_rid_is_avail(struct smb_ldap_privates *ldap_state, uint32 top_rid) 
 {
        LDAPMessage *result;
        uint32 final_rid = (top_rid & (~USER_RID_TYPE)) + RID_MULTIPLIER;
@@ -1565,7 +964,7 @@ static uint32 check_nua_rid_is_avail(struct ldapsam_privates *ldap_state, uint32
 /**********************************************************************
 Extract the RID from an LDAP entry
 *********************************************************************/
-static uint32 entry_to_user_rid(struct ldapsam_privates *ldap_state, LDAPMessage *entry) {
+static uint32 entry_to_user_rid(struct smb_ldap_privates *ldap_state, LDAPMessage *entry) {
        uint32 rid;
        SAM_ACCOUNT *user = NULL;
        if (!NT_STATUS_IS_OK(pdb_init_sam(&user))) {
@@ -1588,7 +987,7 @@ static uint32 entry_to_user_rid(struct ldapsam_privates *ldap_state, LDAPMessage
 /**********************************************************************
 Connect to LDAP server and find the next available RID.
 *********************************************************************/
-static uint32 search_top_nua_rid(struct ldapsam_privates *ldap_state)
+static uint32 search_top_nua_rid(struct smb_ldap_privates *ldap_state)
 {
        int rc;
        pstring filter;
@@ -1609,7 +1008,7 @@ static uint32 search_top_nua_rid(struct ldapsam_privates *ldap_state)
 #endif 
        DEBUG(2, ("ldapsam_get_next_available_nua_rid: searching for:[%s]\n", final_filter));
 
-       rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
+       rc = smb_ldap_search(ldap_state, lp_ldap_suffix(),
                           LDAP_SCOPE_SUBTREE, final_filter, attr, 0,
                           &result);
 
@@ -1658,7 +1057,7 @@ static uint32 search_top_nua_rid(struct ldapsam_privates *ldap_state)
 /**********************************************************************
 Connect to LDAP server and find the next available RID.
 *********************************************************************/
-static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state) {
+static uint32 ldapsam_get_next_available_nua_rid(struct smb_ldap_privates *ldap_state) {
        uint32 next_nua_rid;
        uint32 top_nua_rid;
 
@@ -1675,14 +1074,14 @@ Connect to LDAP server for password enumeration
 *********************************************************************/
 static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
 {
-       struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+       struct smb_ldap_privates *ldap_state = (struct smb_ldap_privates *)my_methods->private_data;
        int rc;
        pstring filter;
 
        pstrcpy(filter, lp_ldap_filter());
        all_string_sub(filter, "%u", "*", sizeof(pstring));
 
-       rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
+       rc = smb_ldap_search(ldap_state, lp_ldap_suffix(),
                           LDAP_SCOPE_SUBTREE, filter, attr, 0,
                           &ldap_state->result);
 
@@ -1710,7 +1109,7 @@ End enumeration of the LDAP password list
 *********************************************************************/
 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
 {
-       struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+       struct smb_ldap_privates *ldap_state = (struct smb_ldap_privates *)my_methods->private_data;
        if (ldap_state->result) {
                ldap_msgfree(ldap_state->result);
                ldap_state->result = NULL;
@@ -1723,13 +1122,9 @@ Get the next entry in the LDAP password database
 static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
 {
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-       struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+       struct smb_ldap_privates *ldap_state = (struct smb_ldap_privates *)my_methods->private_data;
        BOOL bret = False;
 
-       /* The rebind proc needs this *HACK*.  We are not multithreaded, so
-          this will work, but it's not nice. */
-       static_ldap_state = ldap_state;
-
        while (!bret) {
                if (!ldap_state->entry)
                        return ret;
@@ -1750,7 +1145,7 @@ Get SAM_ACCOUNT entry from LDAP by username
 static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
 {
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-       struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+       struct smb_ldap_privates *ldap_state = (struct smb_ldap_privates *)my_methods->private_data;
        LDAPMessage *result;
        LDAPMessage *entry;
        int count;
@@ -1794,8 +1189,8 @@ Get SAM_ACCOUNT entry from LDAP by rid
 static NTSTATUS ldapsam_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT *user, uint32 rid)
 {
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-       struct ldapsam_privates *ldap_state = 
-               (struct ldapsam_privates *)my_methods->private_data;
+       struct smb_ldap_privates *ldap_state = 
+               (struct smb_ldap_privates *)my_methods->private_data;
        LDAPMessage *result;
        LDAPMessage *entry;
        int count;
@@ -1850,7 +1245,7 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
                                     SAM_ACCOUNT *newpwd, char *dn,
                                     LDAPMod **mods, int ldap_op, BOOL pdb_add)
 {
-       struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+       struct smb_ldap_privates *ldap_state = (struct smb_ldap_privates *)my_methods->private_data;
        int rc;
        
        if (!my_methods || !newpwd || !dn) {
@@ -1864,11 +1259,11 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
                switch(ldap_op)
                {
                        case LDAP_MOD_ADD: 
-                               make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "account");
-                               rc = ldapsam_add(ldap_state, dn, mods);
+                               smb_ldap_make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "account");
+                               rc = smb_ldap_add(ldap_state, dn, mods);
                                break;
                        case LDAP_MOD_REPLACE: 
-                               rc = ldapsam_modify(ldap_state, dn ,mods);
+                               rc = smb_ldap_modify(ldap_state, dn ,mods);
                                break;
                        default:        
                                DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
@@ -1915,7 +1310,7 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
                
                ber_free(ber,1);
 
-               if ((rc = ldapsam_extended_operation(ldap_state, LDAP_EXOP_X_MODIFY_PASSWD,
+               if ((rc = smb_ldap_extended_operation(ldap_state, 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)));
@@ -1938,7 +1333,7 @@ Delete entry from LDAP for username
 *********************************************************************/
 static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
 {
-       struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+       struct smb_ldap_privates *ldap_state = (struct smb_ldap_privates *)my_methods->private_data;
        const char *sname;
        int rc;
        LDAPMessage *result;
@@ -1985,7 +1380,7 @@ Update SAM_ACCOUNT
 static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
 {
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-       struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+       struct smb_ldap_privates *ldap_state = (struct smb_ldap_privates *)my_methods->private_data;
        int rc;
        char *dn;
        LDAPMessage *result;
@@ -2057,7 +1452,7 @@ Add SAM_ACCOUNT to LDAP
 static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
 {
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-       struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+       struct smb_ldap_privates *ldap_state = (struct smb_ldap_privates *)my_methods->private_data;
        int rc;
        pstring filter;
        LDAPMessage *result = NULL;
@@ -2136,7 +1531,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
                return NT_STATUS_UNSUCCESSFUL;
        }
        
-       make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaAccount");
+       smb_ldap_make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaAccount");
 
        ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, True);
        if (NT_STATUS_IS_ERR(ret)) {
@@ -2153,15 +1548,15 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
 
 static void free_private_data(void **vp) 
 {
-       struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
+       struct smb_ldap_privates **ldap_state = (struct smb_ldap_privates **)vp;
 
-       ldapsam_close(*ldap_state);
+       smb_ldap_close(*ldap_state);
 
        if ((*ldap_state)->bind_secret) {
                memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
        }
 
-       ldapsam_close(*ldap_state);
+       smb_ldap_close(*ldap_state);
                
        SAFE_FREE((*ldap_state)->bind_dn);
        SAFE_FREE((*ldap_state)->bind_secret);
@@ -2176,7 +1571,7 @@ static const char *group_attr[] = {"cn", "ntSid", "ntGroupType",
                                   "displayName", "description",
                                   NULL };
                                   
-static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
+static int ldapsam_search_one_group (struct smb_ldap_privates *ldap_state,
                                     const char *filter,
                                     LDAPMessage ** result)
 {
@@ -2185,7 +1580,7 @@ static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
 
        DEBUG(2, ("ldapsam_search_one_group: searching for:[%s]\n", filter));
 
-       rc = ldapsam_search(ldap_state, lp_ldap_suffix (), scope,
+       rc = smb_ldap_search(ldap_state, lp_ldap_suffix (), scope,
                            filter, group_attr, 0, result);
 
        if (rc != LDAP_SUCCESS) {
@@ -2203,7 +1598,7 @@ static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
        return rc;
 }
 
-static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
+static BOOL init_group_from_ldap(struct smb_ldap_privates *ldap_state,
                                 GROUP_MAP *map, LDAPMessage *entry)
 {
        pstring temp;
@@ -2214,7 +1609,7 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
                return False;
        }
 
-       if (!get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber",
+       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber",
                                  temp)) {
                DEBUG(0, ("Mandatory attribute gidNumber not found\n"));
                return False;
@@ -2223,14 +1618,14 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
 
        map->gid = (gid_t)atol(temp);
 
-       if (!get_single_attribute(ldap_state->ldap_struct, entry, "ntSid",
+       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "ntSid",
                                  temp)) {
                DEBUG(0, ("Mandatory attribute ntSid not found\n"));
                return False;
        }
        string_to_sid(&map->sid, temp);
 
-       if (!get_single_attribute(ldap_state->ldap_struct, entry, "ntGroupType",
+       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "ntGroupType",
                                  temp)) {
                DEBUG(0, ("Mandatory attribute ntGroupType not found\n"));
                return False;
@@ -2243,11 +1638,11 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
                return False;
        }
 
-       if (!get_single_attribute(ldap_state->ldap_struct, entry, "displayName",
+       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "displayName",
                                  temp)) {
                DEBUG(3, ("Attribute displayName not found\n"));
                temp[0] = '\0';
-               if (!get_single_attribute(ldap_state->ldap_struct, entry, "cn",
+               if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "cn",
                                          temp)) {
                        DEBUG(0, ("Attributes cn not found either "
                                  "for gidNumber(%i)\n",map->gid));
@@ -2256,7 +1651,7 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
        }
        fstrcpy(map->nt_name, temp);
 
-       if (!get_single_attribute(ldap_state->ldap_struct, entry, "description",
+       if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "description",
                                  temp)) {
                DEBUG(3, ("Attribute description not found\n"));
                temp[0] = '\0';
@@ -2298,8 +1693,8 @@ static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
                                 const char *filter,
                                 GROUP_MAP *map)
 {
-       struct ldapsam_privates *ldap_state =
-               (struct ldapsam_privates *)methods->private_data;
+       struct smb_ldap_privates *ldap_state =
+               (struct smb_ldap_privates *)methods->private_data;
        LDAPMessage *result;
        LDAPMessage *entry;
        int count;
@@ -2378,7 +1773,7 @@ static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
        return ldapsam_getgroup(methods, filter, map);
 }
 
-static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
+static int ldapsam_search_one_group_by_gid(struct smb_ldap_privates *ldap_state,
                                           gid_t gid,
                                           LDAPMessage **result)
 {
@@ -2393,8 +1788,8 @@ static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
 static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
                                                GROUP_MAP *map)
 {
-       struct ldapsam_privates *ldap_state =
-               (struct ldapsam_privates *)methods->private_data;
+       struct smb_ldap_privates *ldap_state =
+               (struct smb_ldap_privates *)methods->private_data;
        LDAPMessage *result = NULL;
        LDAPMod **mods = NULL;
 
@@ -2444,10 +1839,10 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       make_a_mod(&mods, LDAP_MOD_ADD, "objectClass",
+       smb_ldap_make_a_mod(&mods, LDAP_MOD_ADD, "objectClass",
                   "sambaGroupMapping");
 
-       rc = ldapsam_modify(ldap_state, dn, mods);
+       rc = smb_ldap_modify(ldap_state, dn, mods);
        ldap_mods_free(mods, 1);
 
        if (rc != LDAP_SUCCESS) {
@@ -2467,8 +1862,8 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
 static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
                                                   GROUP_MAP *map)
 {
-       struct ldapsam_privates *ldap_state =
-               (struct ldapsam_privates *)methods->private_data;
+       struct smb_ldap_privates *ldap_state =
+               (struct smb_ldap_privates *)methods->private_data;
        int rc;
        char *dn;
        LDAPMessage *result;
@@ -2504,7 +1899,7 @@ static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       rc = ldapsam_modify(ldap_state, dn, mods);
+       rc = smb_ldap_modify(ldap_state, dn, mods);
 
        ldap_mods_free(mods, 1);
 
@@ -2524,8 +1919,8 @@ static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
 static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
                                                   DOM_SID sid)
 {
-       struct ldapsam_privates *ldap_state =
-               (struct ldapsam_privates *)methods->private_data;
+       struct smb_ldap_privates *ldap_state =
+               (struct smb_ldap_privates *)methods->private_data;
        pstring sidstring, filter;
        LDAPMessage *result;
        int rc;
@@ -2553,12 +1948,12 @@ static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
 static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods,
                                    BOOL update)
 {
-       struct ldapsam_privates *ldap_state =
-               (struct ldapsam_privates *)my_methods->private_data;
+       struct smb_ldap_privates *ldap_state =
+               (struct smb_ldap_privates *)my_methods->private_data;
        const char *filter = "(objectClass=sambaGroupMapping)";
        int rc;
 
-       rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
+       rc = smb_ldap_search(ldap_state, lp_ldap_suffix(),
                            LDAP_SCOPE_SUBTREE, filter,
                            group_attr, 0, &ldap_state->result);
 
@@ -2590,13 +1985,9 @@ static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
                                    GROUP_MAP *map)
 {
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-       struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+       struct smb_ldap_privates *ldap_state = (struct smb_ldap_privates *)my_methods->private_data;
        BOOL bret = False;
 
-       /* The rebind proc needs this *HACK*.  We are not multithreaded, so
-          this will work, but it's not nice. */
-       static_ldap_state = ldap_state;
-
        while (!bret) {
                if (!ldap_state->entry)
                        return ret;
@@ -2664,7 +2055,7 @@ static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
 NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
 {
        NTSTATUS nt_status;
-       struct ldapsam_privates *ldap_state;
+       struct smb_ldap_privates *ldap_state;
 
        if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
                return nt_status;
@@ -2691,7 +2082,7 @@ NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, co
 
        /* TODO: Setup private data and free */
 
-       ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct ldapsam_privates));
+       ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct smb_ldap_privates));
 
        if (!ldap_state) {
                DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
@@ -2729,7 +2120,7 @@ NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, co
 NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
 {
        NTSTATUS nt_status;
-       struct ldapsam_privates *ldap_state;
+       struct smb_ldap_privates *ldap_state;
        uint32 low_nua_uid, high_nua_uid;
 
        if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam(pdb_context, pdb_method, location))) {