[PATCH] Re: Plugable passdb (SAM) modules

Andrew Bartlett abartlet at pcug.org.au
Fri Jan 18 01:12:53 GMT 2002


Andrew Bartlett wrote:
> 
> Attached is an initial implementation of the plugable passdb backends as
> proposed below.
> 
> I've implemented it for --with-tdbsam and normal smbpasswd.  I haven't
> touched ldap or nisplus much, except in a small change in interface.

OK, next version of patch:

This one should actually compile, and passes the basic tests...

This version should allow ldap and nisplus to remain outside the new
system for the timebeing. (this functionality not yet tested - I don't
have a compatible ldap system here, and its a tempoary hack, as I want
to change the interface a bit more).

Andrew Bartlett

-- 
Andrew Bartlett                                 abartlet at pcug.org.au
Manager, Authentication Subsystems, Samba Team  abartlet at samba.org
Student Network Administrator, Hawker College   abartlet at hawkerc.net
http://samba.org     http://build.samba.org     http://hawkerc.net
-------------- next part --------------
? config.abartlet
? nsswitch/.libs
? passdb/pdb_interface.c
Index: Makefile.in
===================================================================
RCS file: /data/cvs/samba/source/Makefile.in,v
retrieving revision 1.434
diff -u -r1.434 Makefile.in
--- Makefile.in	17 Jan 2002 08:45:50 -0000	1.434
+++ Makefile.in	18 Jan 2002 07:40:20 -0000
@@ -184,7 +184,7 @@
 
 LOCKING_OBJ = locking/locking.o locking/brlock.o locking/posix.o
 
-PASSDB_OBJ = passdb/passdb.o passdb/pdb_get_set.o \
+PASSDB_OBJ = passdb/passdb.o passdb/pdb_interface.o passdb/pdb_get_set.o \
 		passdb/machine_sid.o passdb/pdb_smbpasswd.o \
 		passdb/pdb_tdb.o passdb/pdb_ldap.o \
 		passdb/pdb_nisplus.o
Index: auth/auth_unix.c
===================================================================
RCS file: /data/cvs/samba/source/auth/auth_unix.c,v
retrieving revision 1.17
diff -u -r1.17 auth_unix.c
--- auth/auth_unix.c	17 Jan 2002 08:45:52 -0000	1.17
+++ auth/auth_unix.c	18 Jan 2002 07:40:20 -0000
@@ -60,9 +60,7 @@
 	/* Now write it into the file. */
 	become_root();
 
-	/* Here, the override flag is True, because we want to ignore the
-           XXXXXXX'd out password */
-	ret = pdb_update_sam_account (sampass, True);
+	ret = pdb_update_sam_account (sampass);
 
 	unbecome_root();
 
Index: include/includes.h
===================================================================
RCS file: /data/cvs/samba/source/include/includes.h,v
retrieving revision 1.256
diff -u -r1.256 includes.h
--- include/includes.h	10 Jan 2002 00:28:09 -0000	1.256
+++ include/includes.h	18 Jan 2002 07:40:23 -0000
@@ -735,6 +735,8 @@
 
 #include "auth.h"
 
+#include "passdb.h"
+
 #include "session.h"
 
 #include "asn_1.h"
Index: include/passdb.h
===================================================================
RCS file: /data/cvs/samba/source/include/passdb.h,v
retrieving revision 1.5
diff -u -r1.5 passdb.h
--- include/passdb.h	2 Jan 2002 23:11:24 -0000	1.5
+++ include/passdb.h	18 Jan 2002 07:40:23 -0000
@@ -24,5 +24,70 @@
 #define _PASSDB_H
 
 
+/*****************************************************************
+ Functions to be implemented by the new (v2) passdb API 
+****************************************************************/
+
+typedef struct pdb_context 
+{
+	struct pdb_methods *pdb_selected;
+	
+	/* These functions are wrappers for the functions listed above.
+	   They may do extra things like re-reading a SAM_ACCOUNT on update */
+
+	BOOL (*pdb_setsampwent)(struct pdb_context *, BOOL update);
+	
+	void (*pdb_endsampwent)(struct pdb_context *);
+	
+	BOOL (*pdb_getsampwent)(struct pdb_context *, SAM_ACCOUNT *user);
+	
+	BOOL (*pdb_getsampwnam)(struct pdb_context *, SAM_ACCOUNT *sam_acct, const char *username);
+	
+	BOOL (*pdb_getsampwrid)(struct pdb_context *, SAM_ACCOUNT *sam_acct, uint32 rid);
+	
+	BOOL (*pdb_add_sam_account)(struct pdb_context *, SAM_ACCOUNT *sampass);
+	
+	BOOL (*pdb_update_sam_account)(struct pdb_context *, SAM_ACCOUNT *sampass);
+	
+	BOOL (*pdb_delete_sam_account)(struct pdb_context *, SAM_ACCOUNT *username);
+	
+	void (*free_fn)(struct pdb_context **);
+	
+	TALLOC_CTX *mem_ctx;
+	
+} PDB_CONTEXT;
+
+typedef struct pdb_methods 
+{
+	char *name; /* What name got this module */
+
+	BOOL (*setsampwent)(struct pdb_context *, BOOL update);
+	
+	void (*endsampwent)(struct pdb_context *);
+	
+	BOOL (*getsampwent)(struct pdb_context *, SAM_ACCOUNT *user);
+	
+	BOOL (*getsampwnam)(struct pdb_context *, SAM_ACCOUNT *sam_acct, const char *username);
+	
+	BOOL (*getsampwrid)(struct pdb_context *, SAM_ACCOUNT *sam_acct, uint32 rid);
+	
+	BOOL (*add_sam_account)(struct pdb_context *, const SAM_ACCOUNT *sampass);
+	
+	BOOL (*update_sam_account)(struct pdb_context *, const SAM_ACCOUNT *sampass);
+	
+	BOOL (*delete_sam_account)(struct pdb_context *, const SAM_ACCOUNT *username);
+	
+	void *private_data;  /* Private data of some kind */
+	
+	void (*free_private_data)(void **);
+
+} PDB_METHODS;
+
+
+struct pdb_init_function {
+	char *name;
+	/* Function to create a member of the authmethods list */
+	NTSTATUS (*init)(struct pdb_context *pdb_context, struct pdb_methods **pdb_method);
+};
 
 #endif /* _PASSDB_H */
Index: include/rpc_dce.h
===================================================================
RCS file: /data/cvs/samba/source/include/rpc_dce.h,v
retrieving revision 1.21
diff -u -r1.21 rpc_dce.h
--- include/rpc_dce.h	27 Aug 2001 19:46:16 -0000	1.21
+++ include/rpc_dce.h	18 Jan 2002 07:40:25 -0000
@@ -62,10 +62,13 @@
 #define NTLMSSP_REQUEST_TARGET             0x00000004
 #define NTLMSSP_NEGOTIATE_SIGN             0x00000010
 #define NTLMSSP_NEGOTIATE_SEAL             0x00000020
+#define NTLMSSP_NEGOTIATE_DATAGRAM_STYLE   0x00000040
 #define NTLMSSP_NEGOTIATE_LM_KEY           0x00000080
+#define NTLMSSP_NEGOTIATE_NETWARE          0x00000100
 #define NTLMSSP_NEGOTIATE_NTLM             0x00000200
-#define NTLMSSP_NEGOTIATE_00001000         0x00001000
-#define NTLMSSP_NEGOTIATE_00002000         0x00002000
+#define NTLMSSP_NEGOTIATE_DOMIANSUPPLIED   0x00001000
+#define NTLMSSP_NEGOTIATE_WORKSTATIONSUPP  0x00002000
+#define NTLMSSP_NEGOTIATE_LOCALCALL        0x00004000
 #define NTLMSSP_NEGOTIATE_ALWAYS_SIGN      0x00008000
 #define NTLMSSP_NEGOTIATE_NTLM2            0x00080000
 #define NTLMSSP_NEGOTIATE_TARGET_INFO      0x00800000
Index: include/smb.h
===================================================================
RCS file: /data/cvs/samba/source/include/smb.h,v
retrieving revision 1.407
diff -u -r1.407 smb.h
--- include/smb.h	17 Jan 2002 08:45:53 -0000	1.407
+++ include/smb.h	18 Jan 2002 07:40:30 -0000
@@ -658,6 +658,10 @@
 		uint32 unknown_5; /* 0x0002 0000 */
 		uint32 unknown_6; /* 0x0000 04ec */
 	} private;
+
+	char *passdb_private_info_owner;
+	void *passdb_private_info;
+
 	/* Lets see if the remaining code can get the hint that you
 	   are meant to use the pdb_...() functions. */
 	
Index: param/loadparm.c
===================================================================
RCS file: /data/cvs/samba/source/param/loadparm.c,v
retrieving revision 1.375
diff -u -r1.375 loadparm.c
--- param/loadparm.c	18 Jan 2002 02:37:55 -0000	1.375
+++ param/loadparm.c	18 Jan 2002 07:40:41 -0000
@@ -111,6 +111,7 @@
 	char *szSMBPasswdFile;
 	char *szPrivateDir;
 	char *szPassdbModulePath;
+	char *szPassdbBackend;
 	char *szPasswordServer;
 	char *szSocketOptions;
 	char *szWorkGroup;
@@ -693,6 +694,7 @@
 	{"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL, NULL, 0},
 	{"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, 0},
 	{"passdb module path", P_STRING, P_GLOBAL, &Globals.szPassdbModulePath, NULL, NULL, 0},
+	{"passdb backend", P_STRING, P_GLOBAL, &Globals.szPassdbBackend, NULL, NULL, 0},
 	{"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, 0},
 	{"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, 0},
 	{"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, 0},
@@ -1200,6 +1202,7 @@
 	string_set(&Globals.szSMBPasswdFile, dyn_SMB_PASSWD_FILE);
 	string_set(&Globals.szPrivateDir, dyn_PRIVATE_DIR);
 	string_set(&Globals.szPassdbModulePath, "");
+	string_set(&Globals.szPassdbBackend, "smbpasswd");
 
 	string_set(&Globals.szGuestaccount, GUEST_ACCOUNT);
 
@@ -1454,6 +1457,7 @@
 FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile)
 FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
 FN_GLOBAL_STRING(lp_passdb_module_path, &Globals.szPassdbModulePath)
+FN_GLOBAL_STRING(lp_passdb_backend, &Globals.szPassdbBackend)
 FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
 FN_GLOBAL_STRING(lp_printcapname, &Globals.szPrintcapname)
 FN_GLOBAL_STRING(lp_enumports_cmd, &Globals.szEnumPortsCommand)
Index: passdb/passdb.c
===================================================================
RCS file: /data/cvs/samba/source/passdb/passdb.c,v
retrieving revision 1.137
diff -u -r1.137 passdb.c
--- passdb/passdb.c	17 Jan 2002 08:45:55 -0000	1.137
+++ passdb/passdb.c	18 Jan 2002 07:40:44 -0000
@@ -32,28 +32,6 @@
 
 extern DOM_SID global_sam_sid;
 
-struct passdb_ops *pdb_ops;
-
-#if 0	/* JERRY */
-static void* pdb_handle = NULL;
-#endif
-
-/***************************************************************
- Initialize the password db operations.
-***************************************************************/
-
-BOOL initialize_password_db(BOOL reload)
-{	
-	/* 
-	 * This function is unfinished right now, so just 
-	 * ignore the details and always return True.  It 
-	 * is here only as a placeholder          --jerry 
-	 */
-	return True;
-	
-}
-
-
 /************************************************************
  Fill the SAM_ACCOUNT with default values.
  ***********************************************************/
@@ -1115,14 +1093,14 @@
 			return False;
 		}
 	} else if (local_flags & LOCAL_DELETE_USER) {
-		if (!pdb_delete_sam_account(user_name)) {
+		if (!pdb_delete_sam_account(sam_pass)) {
 			slprintf(err_str,err_str_len-1, "Failed to delete entry for user %s.\n", user_name);
 			pdb_free_sam(&sam_pass);
 			return False;
 		}
 		slprintf(msg_str, msg_str_len-1, "Deleted user %s.\n", user_name);
 	} else {
-		if(!pdb_update_sam_account(sam_pass, True)) {
+		if(!pdb_update_sam_account(sam_pass)) {
 			slprintf(err_str, err_str_len-1, "Failed to modify entry for user %s.\n", user_name);
 			pdb_free_sam(&sam_pass);
 			return False;
@@ -1137,37 +1115,5 @@
 
 	pdb_free_sam(&sam_pass);
 	return True;
-}
-
-/***************************************************************************
- Search by uid.  Wrapper around pdb_getsampwnam()
- **************************************************************************/
-
-BOOL pdb_getsampwuid (SAM_ACCOUNT* user, uid_t uid)
-{
-	struct passwd	*pw;
-	fstring		name;
-
-	if (user==NULL) {
-		DEBUG(0,("pdb_getsampwuid: SAM_ACCOUNT is NULL.\n"));
-		return False;
-	}
-
-	/*
-	 * Never trust the uid in the passdb.  Lookup the username first
-	 * and then lokup the user by name in the sam.
-	 */
-	 
-	if ((pw=getpwuid_alloc(uid)) == NULL)  {
-		DEBUG(0,("pdb_getsampwuid: getpwuid(%d) return NULL. User does not exist in Unix accounts!\n", uid));
-		return False;
-	}
-	
-	fstrcpy (name, pw->pw_name);
-
-	passwd_free(&pw);
-
-	return pdb_getsampwnam (user, name);
-
 }
 
Index: passdb/pdb_ldap.c
===================================================================
RCS file: /data/cvs/samba/source/passdb/pdb_ldap.c,v
retrieving revision 1.17
diff -u -r1.17 pdb_ldap.c
--- passdb/pdb_ldap.c	17 Jan 2002 08:45:55 -0000	1.17
+++ passdb/pdb_ldap.c	18 Jan 2002 07:40:47 -0000
@@ -840,14 +840,22 @@
 /**********************************************************************
 Delete entry from LDAP for username 
 *********************************************************************/
-BOOL pdb_delete_sam_account(const char *sname)
+BOOL pdb_delete_sam_account(SAM_ACCOUNT * sam_acct)
 {
+	const char *sname;
 	int rc;
 	char *dn;
 	LDAP *ldap_struct;
 	LDAPMessage *entry;
 	LDAPMessage *result;
 
+	if (!sam_acct) {
+		DEBUG(0, ("sam_acct was NULL!\n"));
+		return False;
+	}
+
+	sname = pdb_get_username(sam_acct);
+
 	if (!ldap_open_connection (&ldap_struct))
 		return False;
 
@@ -891,7 +899,7 @@
 /**********************************************************************
 Update SAM_ACCOUNT 
 *********************************************************************/
-BOOL pdb_update_sam_account(const SAM_ACCOUNT * newpwd, BOOL override)
+BOOL pdb_update_sam_account(SAM_ACCOUNT * newpwd)
 {
 	int rc;
 	char *dn;
@@ -952,7 +960,7 @@
 /**********************************************************************
 Add SAM_ACCOUNT to LDAP 
 *********************************************************************/
-BOOL pdb_add_sam_account(const SAM_ACCOUNT * newpwd)
+BOOL pdb_add_sam_account(SAM_ACCOUNT * newpwd)
 {
 	int rc;
 	pstring filter;
Index: passdb/pdb_nisplus.c
===================================================================
RCS file: /data/cvs/samba/source/passdb/pdb_nisplus.c,v
retrieving revision 1.17
diff -u -r1.17 pdb_nisplus.c
--- passdb/pdb_nisplus.c	2 Jan 2002 07:41:53 -0000	1.17
+++ passdb/pdb_nisplus.c	18 Jan 2002 07:40:51 -0000
@@ -1039,14 +1039,22 @@
 /*************************************************************************
  Routine to remove entry from the nisplus smbpasswd table
  *************************************************************************/
-BOOL pdb_delete_sam_account(const char *sname)
+BOOL pdb_delete_sam_account(SAM_ACCOUNT * user)
 {
+  const char *sname;
   char *pfile = lp_smb_passwd_file();
   pstring nisname;
   nis_result *result, *delresult;
   nis_object *obj;
   int i;
-  
+ 
+  if (!user) {
+	  DEBUG(0, ("no SAM_ACCOUNT specified!\n"));
+	  return False;
+  }
+
+  suser = pdb_get_username(user);
+
   if (!*pfile)
     {
       DEBUG(0, ("no SMB password file set\n"));
@@ -1095,7 +1103,7 @@
 /************************************************************************
  Routine to add an entry to the nisplus passwd file.
 *************************************************************************/
-BOOL pdb_add_sam_account(const SAM_ACCOUNT * newpwd)
+BOOL pdb_add_sam_account(SAM_ACCOUNT * newpwd)
 {
   int local_user = 0;
   char           *pfile;
@@ -1290,7 +1298,7 @@
 /************************************************************************
  Routine to modify the nisplus passwd entry.
 ************************************************************************/
-BOOL pdb_update_sam_account(const SAM_ACCOUNT * newpwd, BOOL override)
+BOOL pdb_update_sam_account(SAM_ACCOUNT * newpwd)
 {
   nis_result *result, *addresult;
   nis_object *obj;
Index: passdb/pdb_smbpasswd.c
===================================================================
RCS file: /data/cvs/samba/source/passdb/pdb_smbpasswd.c,v
retrieving revision 1.32
diff -u -r1.32 pdb_smbpasswd.c
--- passdb/pdb_smbpasswd.c	17 Jan 2002 08:45:55 -0000	1.32
+++ passdb/pdb_smbpasswd.c	18 Jan 2002 07:40:56 -0000
@@ -4,6 +4,7 @@
  * Copyright (C) Andrew Tridgell 1992-1998 
  * Modified by Jeremy Allison 1995.
  * Modified by Gerald (Jerry) Carter 2000-2001
+ * Modified by Andrew Bartlett 2002.
  * 
  * This program is free software; you can redistribute it and/or modify it under
  * the terms of the GNU General Public License as published by the Free
@@ -22,8 +23,6 @@
 
 #include "includes.h"
 
-#ifdef WITH_SMBPASSWD_SAM
-
 
 /* 
    smb_passwd is analogous to sam_passwd used everywhere
@@ -43,13 +42,20 @@
         time_t pass_last_set_time;    /* password last set time */
 };
 
-
-extern struct passdb_ops pdb_ops;
-
-/* used for maintain locks on the smbpasswd file */
-static int 	pw_file_lock_depth;
-static void 	*global_vp;
-
+struct smbpasswd_privates
+{
+	/* used for maintain locks on the smbpasswd file */
+	int 	pw_file_lock_depth;
+	
+	/* Global File pointer */
+	FILE 	*pw_file;
+	
+	/* formerly static variables */
+	struct smb_passwd pw_buf;
+	pstring  user_name;
+	unsigned char smbpwd[16];
+	unsigned char smbntpwd[16];
+};
 
 enum pwf_access_type { PWF_READ, PWF_UPDATE, PWF_CREATE };
 
@@ -116,7 +122,7 @@
  been granted to prevent race conditions. JRA.
 ****************************************************************/
 
-static void *startsmbfilepwent(const char *pfile, enum pwf_access_type type, int *lock_depth)
+static FILE *startsmbfilepwent(const char *pfile, enum pwf_access_type type, int *lock_depth)
 {
   FILE *fp = NULL;
   const char *open_mode = NULL;
@@ -238,15 +244,14 @@
   }
 
   /* We have a lock on the file. */
-  return (void *)fp;
+  return fp;
 }
 
 /***************************************************************
  End enumeration of the smbpasswd list.
 ****************************************************************/
-static void endsmbfilepwent(void *vp, int *lock_depth)
+static void endsmbfilepwent(FILE *fp, int *lock_depth)
 {
-  FILE *fp = (FILE *)vp;
 
   pw_file_unlock(fileno(fp), lock_depth);
   fclose(fp);
@@ -257,14 +262,13 @@
  Routine to return the next entry in the smbpasswd list.
  *************************************************************************/
 
-static struct smb_passwd *getsmbfilepwent(void *vp)
+static struct smb_passwd *getsmbfilepwent(struct smbpasswd_privates *smbpasswd_state, FILE *fp)
 {
   /* Static buffers we will return. */
-  static struct smb_passwd pw_buf;
-  static pstring  user_name;
-  static unsigned char smbpwd[16];
-  static unsigned char smbntpwd[16];
-  FILE *fp = (FILE *)vp;
+  struct smb_passwd *pw_buf = &smbpasswd_state->pw_buf;
+  char  *user_name = smbpasswd_state->user_name;
+  unsigned char *smbpwd = smbpasswd_state->smbpwd;
+  unsigned char *smbntpwd = smbpasswd_state->smbntpwd;
   char            linebuf[256];
   unsigned char   c;
   unsigned char  *p;
@@ -276,9 +280,9 @@
     return NULL;
   }
 
-  pdb_init_smb(&pw_buf);
+  pdb_init_smb(pw_buf);
 
-  pw_buf.acct_ctrl = ACB_NORMAL;  
+  pw_buf->acct_ctrl = ACB_NORMAL;  
 
   /*
    * Scan the file, a line at a time and check if the name matches.
@@ -370,8 +374,8 @@
       continue;
     }
 
-    pw_buf.smb_name = user_name;
-    pw_buf.smb_userid = uidval;
+    pw_buf->smb_name = user_name;
+    pw_buf->smb_userid = uidval;
 
     /*
      * Now get the password value - this should be 32 hex digits
@@ -385,10 +389,10 @@
     if (*p == '*' || *p == 'X') {
       /* Password deliberately invalid - end here. */
       DEBUG(10, ("getsmbfilepwent: entry invalidated for user %s\n", user_name));
-      pw_buf.smb_nt_passwd = NULL;
-      pw_buf.smb_passwd = NULL;
-      pw_buf.acct_ctrl |= ACB_DISABLED;
-      return &pw_buf;
+      pw_buf->smb_nt_passwd = NULL;
+      pw_buf->smb_passwd = NULL;
+      pw_buf->acct_ctrl |= ACB_DISABLED;
+      return pw_buf;
     }
 
     if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
@@ -402,28 +406,28 @@
     }
 
     if (!strncasecmp((char *) p, "NO PASSWORD", 11)) {
-      pw_buf.smb_passwd = NULL;
-      pw_buf.acct_ctrl |= ACB_PWNOTREQ;
+      pw_buf->smb_passwd = NULL;
+      pw_buf->acct_ctrl |= ACB_PWNOTREQ;
     } else {
       if (!pdb_gethexpwd((char *)p, smbpwd)) {
         DEBUG(0, ("getsmbfilepwent: Malformed Lanman password entry (non hex chars)\n"));
         continue;
       }
-      pw_buf.smb_passwd = smbpwd;
+      pw_buf->smb_passwd = smbpwd;
     }
 
     /* 
      * Now check if the NT compatible password is
      * available.
      */
-    pw_buf.smb_nt_passwd = NULL;
+    pw_buf->smb_nt_passwd = NULL;
 
     p += 33; /* Move to the first character of the line after
                 the lanman password. */
     if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) {
       if (*p != '*' && *p != 'X') {
         if(pdb_gethexpwd((char *)p,smbntpwd))
-          pw_buf.smb_nt_passwd = smbntpwd;
+          pw_buf->smb_nt_passwd = smbntpwd;
       }
       p += 33; /* Move to the first character of the line after
                   the NT password. */
@@ -435,11 +439,11 @@
     if (*p == '[')
 	{
       unsigned char *end_p = (unsigned char *)strchr_m((char *)p, ']');
-      pw_buf.acct_ctrl = pdb_decode_acct_ctrl((char*)p);
+      pw_buf->acct_ctrl = pdb_decode_acct_ctrl((char*)p);
 
       /* Must have some account type set. */
-      if(pw_buf.acct_ctrl == 0)
-        pw_buf.acct_ctrl = ACB_NORMAL;
+      if(pw_buf->acct_ctrl == 0)
+        pw_buf->acct_ctrl = ACB_NORMAL;
 
       /* Now try and get the last change time. */
       if(end_p)
@@ -459,7 +463,7 @@
              * read into a time_t as the seconds since
              * 1970 that the password was last changed.
              */
-            pw_buf.pass_last_set_time = (time_t)strtol((char *)p, NULL, 16);
+            pw_buf->pass_last_set_time = (time_t)strtol((char *)p, NULL, 16);
           }
         }
       }
@@ -470,13 +474,13 @@
        * password file as 'normal accounts'. If this changes
        * we will have to fix this code. JRA.
        */
-      if(pw_buf.smb_name[strlen(pw_buf.smb_name) - 1] == '$') {
-        pw_buf.acct_ctrl &= ~ACB_NORMAL;
-        pw_buf.acct_ctrl |= ACB_WSTRUST;
+      if(pw_buf->smb_name[strlen(pw_buf->smb_name) - 1] == '$') {
+        pw_buf->acct_ctrl &= ~ACB_NORMAL;
+        pw_buf->acct_ctrl |= ACB_WSTRUST;
       }
     }
 
-    return &pw_buf;
+    return pw_buf;
   }
 
   DEBUG(5,("getsmbfilepwent: end of file reached.\n"));
@@ -547,7 +551,7 @@
  Routine to add an entry to the smbpasswd file.
 *************************************************************************/
 
-static BOOL add_smbfilepwd_entry(const struct smb_passwd *newpwd)
+static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, const struct smb_passwd *newpwd)
 {
   char *pfile = lp_smb_passwd_file();
   struct smb_passwd *pwd = NULL;
@@ -559,11 +563,11 @@
   SMB_OFF_T offpos;
 
   /* Open the smbpassword file - for update. */
-  fp = startsmbfilepwent(pfile, PWF_UPDATE, &pw_file_lock_depth);
+  fp = startsmbfilepwent(pfile, PWF_UPDATE, &(smbpasswd_state->pw_file_lock_depth));
 
   if (fp == NULL && errno == ENOENT) {
 	/* Try again - create. */
-	fp = startsmbfilepwent(pfile, PWF_CREATE, &pw_file_lock_depth);
+	fp = startsmbfilepwent(pfile, PWF_CREATE, &(smbpasswd_state->pw_file_lock_depth));
   }
 
   if (fp == NULL) {
@@ -575,12 +579,12 @@
    * Scan the file, a line at a time and check if the name matches.
    */
 
-  while ((pwd = getsmbfilepwent(fp)) != NULL) 
+  while ((pwd = getsmbfilepwent(smbpasswd_state, fp)) != NULL) 
   {
     if (strequal(newpwd->smb_name, pwd->smb_name)) 
     {
       	DEBUG(0, ("add_smbfilepwd_entry: entry with name %s already exists\n", pwd->smb_name));
-      	endsmbfilepwent(fp, &pw_file_lock_depth);
+      	endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
       	return False;
     }
   }
@@ -598,7 +602,7 @@
   {
     	DEBUG(0, ("add_smbfilepwd_entry(sys_lseek): Failed to add entry for user %s to file %s. \
 Error was %s\n", newpwd->smb_name, pfile, strerror(errno)));
-    	endsmbfilepwent(fp, &pw_file_lock_depth);
+    	endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
     	return False;
   }
 
@@ -606,7 +610,7 @@
   {
     	DEBUG(0, ("add_smbfilepwd_entry(malloc): Failed to add entry for user %s to file %s. \
 Error was %s\n", newpwd->smb_name, pfile, strerror(errno)));
-	endsmbfilepwent(fp, &pw_file_lock_depth);
+	endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
     	return False;
   }
 
@@ -630,13 +634,13 @@
 		newpwd->smb_name, strerror(errno)));
     	}
 
-	endsmbfilepwent(fp, &pw_file_lock_depth);
+	endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
 	free(new_entry);
 	return False;
   }
 
   free(new_entry);
-  endsmbfilepwent(fp, &pw_file_lock_depth);
+  endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
   return True;
 }
 
@@ -649,10 +653,10 @@
  override = True, override XXXXXXXX'd out password or NO PASS
 ************************************************************************/
 
-static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override)
+static BOOL mod_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, const struct smb_passwd* pwd)
 {
   /* Static buffers we will return. */
-  static pstring  user_name;
+  char * user_name = smbpasswd_state->user_name;
 
   char            linebuf[256];
   char            readbuf[1024];
@@ -690,7 +694,7 @@
 
   lockfd = fileno(fp);
 
-  if (!pw_file_lock(lockfd, F_WRLCK, 5, &pw_file_lock_depth)) {
+  if (!pw_file_lock(lockfd, F_WRLCK, 5, &(smbpasswd_state->pw_file_lock_depth))) {
     DEBUG(0, ("mod_smbfilepwd_entry: unable to lock file %s\n", pfile));
     fclose(fp);
     return False;
@@ -710,7 +714,7 @@
 
     fgets(linebuf, sizeof(linebuf), fp);
     if (ferror(fp)) {
-      pw_file_unlock(lockfd, &pw_file_lock_depth);
+      pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth));
       fclose(fp);
       return False;
     }
@@ -779,7 +783,7 @@
   }
 
   if (!found_entry) {
-    pw_file_unlock(lockfd, &pw_file_lock_depth);
+    pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth));
     fclose(fp);
     return False;
   }
@@ -791,7 +795,7 @@
 
   if (!isdigit(*p)) {
     DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (uid not number)\n"));
-    pw_file_unlock(lockfd, &pw_file_lock_depth);
+    pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth));
     fclose(fp);
     return False;
   }
@@ -800,7 +804,7 @@
     p++;
   if (*p != ':') {
     DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no : after uid)\n"));
-    pw_file_unlock(lockfd, &pw_file_lock_depth);
+    pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth));
     fclose(fp);
     return False;
   }
@@ -815,30 +819,16 @@
   /* Record exact password position */
   pwd_seekpos += PTR_DIFF(p, linebuf);
 
-  if (!override && (*p == '*' || *p == 'X')) {
-    /* Password deliberately invalid - end here. */
-    DEBUG(10, ("mod_smbfilepwd_entry: entry invalidated for user %s\n", user_name));
-    pw_file_unlock(lockfd, &pw_file_lock_depth);
-    fclose(fp);
-    return False;
-  }
-
   if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
     DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (passwd too short)\n"));
-    pw_file_unlock(lockfd,&pw_file_lock_depth);
+    pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
     fclose(fp);
     return (False);
   }
 
   if (p[32] != ':') {
     DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no terminating :)\n"));
-    pw_file_unlock(lockfd,&pw_file_lock_depth);
-    fclose(fp);
-    return False;
-  }
-
-  if (!override && (*p == '*' || *p == 'X')) {
-    pw_file_unlock(lockfd,&pw_file_lock_depth);
+    pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
     fclose(fp);
     return False;
   }
@@ -849,14 +839,14 @@
               the lanman password. */
   if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
     DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (passwd too short)\n"));
-    pw_file_unlock(lockfd,&pw_file_lock_depth);
+    pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
     fclose(fp);
     return (False);
   }
 
   if (p[32] != ':') {
     DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no terminating :)\n"));
-    pw_file_unlock(lockfd,&pw_file_lock_depth);
+    pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
     fclose(fp);
     return False;
   }
@@ -966,7 +956,7 @@
 
   if(wr_len > sizeof(linebuf)) {
     DEBUG(0, ("mod_smbfilepwd_entry: line to write (%d) is too long.\n", wr_len+1));
-    pw_file_unlock(lockfd,&pw_file_lock_depth);
+    pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
     fclose(fp);
     return (False);
   }
@@ -984,7 +974,7 @@
 
   if (sys_lseek(fd, pwd_seekpos - 1, SEEK_SET) != pwd_seekpos - 1) {
     DEBUG(0, ("mod_smbfilepwd_entry: seek fail on file %s.\n", pfile));
-    pw_file_unlock(lockfd,&pw_file_lock_depth);
+    pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
     fclose(fp);
     return False;
   }
@@ -992,33 +982,33 @@
   /* Sanity check - ensure the areas we are writing are framed by ':' */
   if (read(fd, linebuf, wr_len+1) != wr_len+1) {
     DEBUG(0, ("mod_smbfilepwd_entry: read fail on file %s.\n", pfile));
-    pw_file_unlock(lockfd,&pw_file_lock_depth);
+    pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
     fclose(fp);
     return False;
   }
 
   if ((linebuf[0] != ':') || (linebuf[wr_len] != ':'))	{
     DEBUG(0, ("mod_smbfilepwd_entry: check on passwd file %s failed.\n", pfile));
-    pw_file_unlock(lockfd,&pw_file_lock_depth);
+    pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
     fclose(fp);
     return False;
   }
  
   if (sys_lseek(fd, pwd_seekpos, SEEK_SET) != pwd_seekpos) {
     DEBUG(0, ("mod_smbfilepwd_entry: seek fail on file %s.\n", pfile));
-    pw_file_unlock(lockfd,&pw_file_lock_depth);
+    pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
     fclose(fp);
     return False;
   }
 
   if (write(fd, ascii_p16, wr_len) != wr_len) {
     DEBUG(0, ("mod_smbfilepwd_entry: write failed in passwd file %s\n", pfile));
-    pw_file_unlock(lockfd,&pw_file_lock_depth);
+    pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
     fclose(fp);
     return False;
   }
 
-  pw_file_unlock(lockfd,&pw_file_lock_depth);
+  pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
   fclose(fp);
   return True;
 }
@@ -1027,7 +1017,7 @@
  Routine to delete an entry in the smbpasswd file by name.
 *************************************************************************/
 
-static BOOL del_smbfilepwd_entry(const char *name)
+static BOOL del_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, const char *name)
 {
   char *pfile = lp_smb_passwd_file();
   pstring pfile2;
@@ -1044,7 +1034,7 @@
    * it.
    */
 
-  if((fp = startsmbfilepwent(pfile, PWF_UPDATE, &pw_file_lock_depth)) == NULL) {
+  if((fp = startsmbfilepwent(pfile, PWF_UPDATE, &(smbpasswd_state->pw_file_lock_depth))) == NULL) {
     DEBUG(0, ("del_smbfilepwd_entry: unable to open file %s.\n", pfile));
     return False;
   }
@@ -1054,7 +1044,7 @@
    */
   if((fp_write = startsmbfilepwent(pfile2, PWF_CREATE, &pfile2_lockdepth)) == NULL) {
     DEBUG(0, ("del_smbfilepwd_entry: unable to open file %s.\n", pfile));
-    endsmbfilepwent(fp, &pw_file_lock_depth);
+    endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
     return False;
   }
 
@@ -1062,7 +1052,7 @@
    * Scan the file, a line at a time and check if the name matches.
    */
 
-  while ((pwd = getsmbfilepwent(fp)) != NULL) {
+  while ((pwd = getsmbfilepwent(smbpasswd_state, fp)) != NULL) {
     char *new_entry;
     size_t new_entry_length;
 
@@ -1080,7 +1070,7 @@
     	DEBUG(0, ("del_smbfilepwd_entry(malloc): Failed to copy entry for user %s to file %s. \
 Error was %s\n", pwd->smb_name, pfile2, strerror(errno)));
 	unlink(pfile2);
-	endsmbfilepwent(fp, &pw_file_lock_depth);
+	endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
 	endsmbfilepwent(fp_write, &pfile2_lockdepth);
 	return False;
     }
@@ -1092,7 +1082,7 @@
     	DEBUG(0, ("del_smbfilepwd_entry(write): Failed to copy entry for user %s to file %s. \
 Error was %s\n", pwd->smb_name, pfile2, strerror(errno)));
       	unlink(pfile2);
-	endsmbfilepwent(fp, &pw_file_lock_depth);
+	endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
 	endsmbfilepwent(fp_write, &pfile2_lockdepth);
 	free(new_entry);
 	return False;
@@ -1108,7 +1098,7 @@
   if(fflush(fp_write) != 0) 
   {
   	DEBUG(0, ("del_smbfilepwd_entry: Failed to flush file %s. Error was %s\n", pfile2, strerror(errno)));
-	endsmbfilepwent(fp, &pw_file_lock_depth);
+	endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
 	endsmbfilepwent(fp_write,&pfile2_lockdepth);
 	return False;
   }
@@ -1121,7 +1111,7 @@
     unlink(pfile2);
   }
   
-  endsmbfilepwent(fp, &pw_file_lock_depth);
+  endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
   endsmbfilepwent(fp_write,&pfile2_lockdepth);
   return True;
 }
@@ -1273,21 +1263,24 @@
 	
 	return True;
 }
+
 /*****************************************************************
  Functions to be implemented by the new passdb API 
  ****************************************************************/
-BOOL pdb_setsampwent (BOOL update)
+static BOOL smbpasswd_setsampwent (struct pdb_context *context, BOOL update)
 {
-	global_vp = startsmbfilepwent(lp_smb_passwd_file(), 
-	                        update ? PWF_UPDATE : PWF_READ, 
-			        &pw_file_lock_depth);
+	struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data;
+	
+	smbpasswd_state->pw_file = startsmbfilepwent(lp_smb_passwd_file(), 
+						       update ? PWF_UPDATE : PWF_READ, 
+						       &(smbpasswd_state->pw_file_lock_depth));
 				   
 	/* did we fail?  Should we try to create it? */
-	if (!global_vp && update && errno == ENOENT) 
+	if (!smbpasswd_state->pw_file && update && errno == ENOENT) 
 	{
 		FILE *fp;
 		/* slprintf(msg_str,msg_str_len-1,
-			"smbpasswd file did not exist - attempting to create it.\n"); */
+		   "smbpasswd file did not exist - attempting to create it.\n"); */
 		DEBUG(0,("smbpasswd file did not exist - attempting to create it.\n"));
 		fp = sys_fopen(lp_smb_passwd_file(), "w");
 		if (fp) 
@@ -1296,31 +1289,33 @@
 			fclose(fp);
 		}
 		
-		global_vp = startsmbfilepwent(lp_smb_passwd_file(), 
-		                        update ? PWF_UPDATE : PWF_READ, 
-			                &pw_file_lock_depth);
+		smbpasswd_state->pw_file = startsmbfilepwent(lp_smb_passwd_file(), 
+							     update ? PWF_UPDATE : PWF_READ, 
+							     &(smbpasswd_state->pw_file_lock_depth));
 	}
 	
-	return (global_vp != NULL);		   
+	return (smbpasswd_state->pw_file != NULL);		   
 }
 
-void pdb_endsampwent (void)
+static void smbpasswd_endsampwent (struct pdb_context *context)
 {
-	endsmbfilepwent(global_vp, &pw_file_lock_depth);
+	struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data;
+	endsmbfilepwent(smbpasswd_state->pw_file, &(smbpasswd_state->pw_file_lock_depth));
 }
  
 /*****************************************************************
  ****************************************************************/
-BOOL pdb_getsampwent(SAM_ACCOUNT *user)
+static BOOL smbpasswd_getsampwent(struct pdb_context *context, SAM_ACCOUNT *user)
 {
+	struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data;
 	struct smb_passwd *pw_buf=NULL;
 	BOOL done = False;
 	DEBUG(5,("pdb_getsampwent\n"));
 
 	if (user==NULL) {
-		DEBUG(5,("pdb_getsampwent: user is NULL\n"));
+		DEBUG(5,("pdb_getsampwent (smbpasswd): user is NULL\n"));
 #if 0
-		smb_panic("NULL pointer passed to pdb_getsampwent\n");
+		smb_panic("NULL pointer passed to getsampwent (smbpasswd)\n");
 #endif
 		return False;
 	}
@@ -1328,7 +1323,7 @@
 	while (!done)
 	{
 		/* do we have an entry? */
-		pw_buf = getsmbfilepwent(global_vp);
+		pw_buf = getsmbfilepwent(smbpasswd_state, smbpasswd_state->pw_file);
 		if (pw_buf == NULL) 
 			return False;
 
@@ -1339,7 +1334,7 @@
 			done = True;
 	}
 
-	DEBUG(5,("pdb_getsampwent:done\n"));
+	DEBUG(5,("getsampwent (smbpasswd): done\n"));
 
 	/* success */
 	return True;
@@ -1351,15 +1346,16 @@
  call getpwnam() for unix account information until we have found
  the correct entry
  ***************************************************************/
-BOOL pdb_getsampwnam(SAM_ACCOUNT *sam_acct, const char *username)
+static BOOL smbpasswd_getsampwnam(struct pdb_context *context, SAM_ACCOUNT *sam_acct, const char *username)
 {
+	struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data;
 	struct smb_passwd *smb_pw;
 	void *fp = NULL;
 	char *domain = NULL;
 	char *user = NULL;
 	fstring name;
 
-	DEBUG(10, ("pdb_getsampwnam: search by name: %s\n", username));
+	DEBUG(10, ("getsampwnam (smbpasswd): search by name: %s\n", username));
 
 	
 	/* break the username from the domain if we have 
@@ -1379,7 +1375,7 @@
 	/* startsmbfilepwent() is used here as we don't want to lookup
 	   the UNIX account in the local system password file until
 	   we have a match.  */
-	fp = startsmbfilepwent(lp_smb_passwd_file(), PWF_READ, &pw_file_lock_depth);
+	fp = startsmbfilepwent(lp_smb_passwd_file(), PWF_READ, &(smbpasswd_state->pw_file_lock_depth));
 
 	if (fp == NULL) {
 		DEBUG(0, ("unable to open passdb database.\n"));
@@ -1391,20 +1387,20 @@
 	if ( domain )
 		map_username(user);
 
-	while ( ((smb_pw=getsmbfilepwent(fp)) != NULL)&& (!strequal(smb_pw->smb_name, username)) )
+	while ( ((smb_pw=getsmbfilepwent(smbpasswd_state, fp)) != NULL)&& (!strequal(smb_pw->smb_name, username)) )
 		/* do nothing....another loop */ ;
 	
-	endsmbfilepwent(fp, &pw_file_lock_depth);
+	endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
 
 
 	/* did we locate the username in smbpasswd  */
 	if (smb_pw == NULL)
 		return False;
 	
-	DEBUG(10, ("pdb_getsampwnam: found by name: %s\n", smb_pw->smb_name));
+	DEBUG(10, ("getsampwnam (smbpasswd): found by name: %s\n", smb_pw->smb_name));
 
 	if (!sam_acct) {
-		DEBUG(10,("pdb_getsampwnam:SAM_ACCOUNT is NULL\n"));
+		DEBUG(10,("getsampwnam (smbpasswd): SAM_ACCOUNT is NULL\n"));
 #if 0
 		smb_panic("NULL pointer passed to pdb_getsampwnam\n");
 #endif
@@ -1420,35 +1416,36 @@
 }
 
 
-BOOL pdb_getsampwrid(SAM_ACCOUNT *sam_acct,uint32 rid)
+static BOOL smbpasswd_getsampwrid(struct pdb_context *context, SAM_ACCOUNT *sam_acct,uint32 rid)
 {
+	struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data;
 	struct smb_passwd *smb_pw;
 	void *fp = NULL;
 
 	DEBUG(10, ("pdb_getsampwrid: search by rid: %d\n", rid));
 
 	/* Open the sam password file - not for update. */
-	fp = startsmbfilepwent(lp_smb_passwd_file(), PWF_READ, &pw_file_lock_depth);
+	fp = startsmbfilepwent(lp_smb_passwd_file(), PWF_READ, &(smbpasswd_state->pw_file_lock_depth));
 
 	if (fp == NULL) {
 		DEBUG(0, ("unable to open passdb database.\n"));
 		return False;
 	}
 
-	while ( ((smb_pw=getsmbfilepwent(fp)) != NULL) && (pdb_uid_to_user_rid(smb_pw->smb_userid) != rid) )
+	while ( ((smb_pw=getsmbfilepwent(smbpasswd_state, fp)) != NULL) && (pdb_uid_to_user_rid(smb_pw->smb_userid) != rid) )
       		/* do nothing */ ;
 
-	endsmbfilepwent(fp, &pw_file_lock_depth);
+	endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
 
 
 	/* did we locate the username in smbpasswd  */
 	if (smb_pw == NULL)
 		return False;
 	
-	DEBUG(10, ("pdb_getsampwrid: found by name: %s\n", smb_pw->smb_name));
+	DEBUG(10, ("getsampwrid (smbpasswd): found by name: %s\n", smb_pw->smb_name));
 		
 	if (!sam_acct) {
-		DEBUG(10,("pdb_getsampwrid:SAM_ACCOUNT is NULL\n"));
+		DEBUG(10,("getsampwrid: (smbpasswd) SAM_ACCOUNT is NULL\n"));
 #if 0
 		smb_panic("NULL pointer passed to pdb_getsampwrid\n");
 #endif
@@ -1463,8 +1460,9 @@
 	return True;
 }
 
-BOOL pdb_add_sam_account(const SAM_ACCOUNT *sampass)
+static BOOL smbpasswd_add_sam_account(struct pdb_context *context, const SAM_ACCOUNT *sampass)
 {
+	struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data;
 	struct smb_passwd smb_pw;
 	
 	/* convert the SAM_ACCOUNT */
@@ -1473,15 +1471,16 @@
 	}
 	
 	/* add the entry */
-	if(!add_smbfilepwd_entry(&smb_pw)) {
+	if(!add_smbfilepwd_entry(smbpasswd_state, &smb_pw)) {
 		return False;
 	}
-
+	
 	return True;
 }
 
-BOOL pdb_update_sam_account(const SAM_ACCOUNT *sampass, BOOL override)
+static BOOL smbpasswd_update_sam_account(struct pdb_context *context, const SAM_ACCOUNT *sampass)
 {
+	struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data;
 	struct smb_passwd smb_pw;
 	
 	/* convert the SAM_ACCOUNT */
@@ -1489,19 +1488,58 @@
 		return False;
 	
 	/* update the entry */
-	if(!mod_smbfilepwd_entry(&smb_pw, override))
+	if(!mod_smbfilepwd_entry(smbpasswd_state, &smb_pw))
 		return False;
 		
 	return True;
 }
 
-BOOL pdb_delete_sam_account (const char* username)
+static BOOL smbpasswd_delete_sam_account (struct pdb_context *context, const SAM_ACCOUNT *sampass)
+{
+	struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data;
+
+	const char *username = pdb_get_username(sampass);
+
+	return del_smbfilepwd_entry(smbpasswd_state, username);
+}
+
+static void free_private_data(void **vp) 
 {
-	return del_smbfilepwd_entry(username);
+	struct smbpasswd_privates **privates = (struct smbpasswd_privates**)vp;
+	
+	endsmbfilepwent((*privates)->pw_file, &((*privates)->pw_file_lock_depth));
+	
+	*privates = NULL;
+	/* No need to free any further, as it is talloc()ed */
 }
 
-#else
- /* Do *NOT* make this function static. It breaks the compile on gcc. JRA */
- void smbpass_dummy_function(void) { } /* stop some compilers complaining */
-#endif /* WTH_SMBPASSWD_SAM*/
 
+NTSTATUS pdb_init_smbpasswd(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method)
+{
+	NTSTATUS nt_status;
+
+	if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
+		return nt_status;
+	}
+
+	(*pdb_method)->setsampwent = smbpasswd_setsampwent;
+	(*pdb_method)->endsampwent = smbpasswd_endsampwent;
+	(*pdb_method)->getsampwent = smbpasswd_getsampwent;
+	(*pdb_method)->getsampwnam = smbpasswd_getsampwnam;
+	(*pdb_method)->getsampwrid = smbpasswd_getsampwrid;
+	(*pdb_method)->add_sam_account = smbpasswd_add_sam_account;
+	(*pdb_method)->update_sam_account = smbpasswd_update_sam_account;
+	(*pdb_method)->delete_sam_account = smbpasswd_delete_sam_account;
+
+	/* Setup private data and free function */
+
+	(*pdb_method)->private_data = (struct smbpasswd_privates *)talloc(pdb_context->mem_ctx, sizeof(struct smbpasswd_privates));
+
+	if (!(*pdb_method)->private_data) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	(*pdb_method)->free_private_data = free_private_data;
+
+	return NT_STATUS_OK;
+}
Index: passdb/pdb_tdb.c
===================================================================
RCS file: /data/cvs/samba/source/passdb/pdb_tdb.c,v
retrieving revision 1.41
diff -u -r1.41 pdb_tdb.c
--- passdb/pdb_tdb.c	17 Jan 2002 08:45:55 -0000	1.41
+++ passdb/pdb_tdb.c	18 Jan 2002 07:40:58 -0000
@@ -4,6 +4,7 @@
  * Copyright (C) Simo Sorce 2000
  * Copyright (C) Gerald Carter 2000
  * Copyright (C) Jeremy Allison 2001
+ * Copyright (C) Andrew Bartlett 2002
  * 
  * This program is free software; you can redistribute it and/or modify it under
  * the terms of the GNU General Public License as published by the Free
@@ -30,16 +31,11 @@
 #define USERPREFIX		"USER_"
 #define RIDPREFIX		"RID_"
 
-extern int 		DEBUGLEVEL;
-
 struct tdb_enum_info {
 	TDB_CONTEXT 	*passwd_tdb;
 	TDB_DATA 	key;
 };
 
-static struct tdb_enum_info 	global_tdb_ent;
-/*static SAM_ACCOUNT 		global_sam_pass;*/
-
 /**********************************************************************
  Intialize a SAM_ACCOUNT struct from a BYTE buffer of size len
  *********************************************************************/
@@ -387,35 +383,42 @@
  Open the TDB passwd database for SAM account enumeration.
 ****************************************************************/
 
-BOOL pdb_setsampwent(BOOL update)
+static BOOL tdbsam_setsampwent(struct pdb_context *context, BOOL update)
 {
 	pstring		tdbfile;
+	struct tdb_enum_info *tdb_state = (struct tdb_enum_info *)context->pdb_selected->private_data;
 	
 	get_private_directory(tdbfile);
 	pstrcat (tdbfile, PASSDB_FILE_NAME);
 	
 	/* Open tdb passwd */
-	if (!(global_tdb_ent.passwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, update?(O_RDWR|O_CREAT):O_RDONLY, 0600)))
+	if (!(tdb_state->passwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, update?(O_RDWR|O_CREAT):O_RDONLY, 0600)))
 	{
 		DEBUG(0, ("Unable to open/create TDB passwd\n"));
 		return False;
 	}
 	
-	global_tdb_ent.key = tdb_firstkey(global_tdb_ent.passwd_tdb);
+	tdb_state->key = tdb_firstkey(tdb_state->passwd_tdb);
 
 	return True;
 }
 
+static void close_tdb(struct tdb_enum_info *tdb_state) 
+{
+	if (tdb_state->passwd_tdb) {
+		tdb_close(tdb_state->passwd_tdb);
+		tdb_state->passwd_tdb = NULL;
+	}
+}
+
 /***************************************************************
  End enumeration of the TDB passwd list.
 ****************************************************************/
 
-void pdb_endsampwent(void)
+static void tdbsam_endsampwent(struct pdb_context *context)
 {
-	if (global_tdb_ent.passwd_tdb) {
-		tdb_close(global_tdb_ent.passwd_tdb);
-		global_tdb_ent.passwd_tdb = NULL;
-	}
+	struct tdb_enum_info *tdb_state = (struct tdb_enum_info *)context->pdb_selected->private_data;
+	close_tdb(tdb_state);
 	
 	DEBUG(7, ("endtdbpwent: closed sam database.\n"));
 }
@@ -424,8 +427,9 @@
  Get one SAM_ACCOUNT from the TDB (next in line)
 *****************************************************************/
 
-BOOL pdb_getsampwent(SAM_ACCOUNT *user)
+static BOOL tdbsam_getsampwent(struct pdb_context *context, SAM_ACCOUNT *user)
 {
+	struct tdb_enum_info *tdb_state = (struct tdb_enum_info *)context->pdb_selected->private_data;
 	TDB_DATA 	data;
 	struct passwd	*pw;
 	uid_t		uid;
@@ -442,17 +446,17 @@
 	}
 
 	/* skip all non-USER entries (eg. RIDs) */
-	while ((global_tdb_ent.key.dsize != 0) && (strncmp(global_tdb_ent.key.dptr, prefix, prefixlen)))
+	while ((tdb_state->key.dsize != 0) && (strncmp(tdb_state->key.dptr, prefix, prefixlen)))
 		/* increment to next in line */
-		global_tdb_ent.key = tdb_nextkey(global_tdb_ent.passwd_tdb, global_tdb_ent.key);
+		tdb_state->key = tdb_nextkey(tdb_state->passwd_tdb, tdb_state->key);
 
 	/* do we have an valid interation pointer? */
-	if(global_tdb_ent.passwd_tdb == NULL) {
+	if(tdb_state->passwd_tdb == NULL) {
 		DEBUG(0,("pdb_get_sampwent: Bad TDB Context pointer.\n"));
 		return False;
 	}
 
-	data = tdb_fetch(global_tdb_ent.passwd_tdb, global_tdb_ent.key);
+	data = tdb_fetch(tdb_state->passwd_tdb, tdb_state->key);
 	if (!data.dptr) {
 		DEBUG(5,("pdb_getsampwent: database entry not found.\n"));
 		return False;
@@ -497,7 +501,7 @@
 	pdb_set_homedir(user, sam_subst, True);
 
 	/* increment to next in line */
-	global_tdb_ent.key = tdb_nextkey(global_tdb_ent.passwd_tdb, global_tdb_ent.key);
+	tdb_state->key = tdb_nextkey(tdb_state->passwd_tdb, tdb_state->key);
 
 	return True;
 }
@@ -506,7 +510,7 @@
  Lookup a name in the SAM TDB
 ******************************************************************/
 
-BOOL pdb_getsampwnam (SAM_ACCOUNT *user, const char *sname)
+static BOOL tdbsam_getsampwnam (struct pdb_context *context, SAM_ACCOUNT *user, const char *sname)
 {
 	TDB_CONTEXT 	*pwd_tdb;
 	TDB_DATA 	data, key;
@@ -601,7 +605,7 @@
  Search by rid
  **************************************************************************/
 
-BOOL pdb_getsampwrid (SAM_ACCOUNT *user, uint32 rid)
+static BOOL tdbsam_getsampwrid (struct pdb_context *context, SAM_ACCOUNT *user, uint32 rid)
 {
 	TDB_CONTEXT 		*pwd_tdb;
 	TDB_DATA 		data, key;
@@ -649,9 +653,8 @@
  Delete a SAM_ACCOUNT
 ****************************************************************************/
 
-BOOL pdb_delete_sam_account(const char *sname)
+static BOOL tdbsam_delete_sam_account(struct pdb_context *pdb_context, const SAM_ACCOUNT *sam_pass)
 {
-	SAM_ACCOUNT	*sam_pass = NULL;
 	TDB_CONTEXT 	*pwd_tdb;
 	TDB_DATA 	key, data;
 	fstring 	keystr;
@@ -659,7 +662,7 @@
 	uint32		rid;
 	fstring		name;
 	
-	unix_strlower(sname, -1, name, sizeof(name));
+	unix_strlower(pdb_get_username(sam_pass), -1, name, sizeof(name));
 	
 	get_private_directory(tdbfile);
 	pstrcat (tdbfile, PASSDB_FILE_NAME);
@@ -675,33 +678,8 @@
 	key.dptr = keystr;
 	key.dsize = strlen (keystr) + 1;
 	
-	/* get the record */
-	data = tdb_fetch (pwd_tdb, key);
-	if (!data.dptr) {
-		DEBUG(5,("pdb_delete_sam_account (TDB): error fetching database.\n"));
-		DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
-		tdb_close (pwd_tdb);
-		return False;
-	}
-  
-  	/* unpack the buffer */
-	if (!NT_STATUS_IS_OK(pdb_init_sam (&sam_pass))) {
-		tdb_close (pwd_tdb);
-		return False;
-	}
-	
-	if (!init_sam_from_buffer (sam_pass, data.dptr, data.dsize)) {
-		DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n"));
-		tdb_close (pwd_tdb);
-		SAFE_FREE(data.dptr);
-		return False;
-	}
-	SAFE_FREE(data.dptr);
-
 	rid = pdb_get_user_rid(sam_pass);
 
-	pdb_free_sam (&sam_pass);
-	
 	/* it's outaa here!  8^) */
 	if (tdb_delete(pwd_tdb, key) != TDB_SUCCESS) {
 		DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
@@ -734,8 +712,9 @@
  Update the TDB SAM
 ****************************************************************************/
 
-static BOOL tdb_update_sam(const SAM_ACCOUNT* newpwd, BOOL override, int flag)
+static BOOL tdb_update_sam(struct pdb_context *context, const SAM_ACCOUNT* newpwd, int flag)
 {
+	struct tdb_enum_info *tdb_state = (struct tdb_enum_info *)context->pdb_selected->private_data;
 	TDB_CONTEXT 	*pwd_tdb = NULL;
 	TDB_DATA 	key, data;
 	uint8		*buf = NULL;
@@ -769,9 +748,9 @@
 	key.dsize = strlen (keystr) + 1;
 
 	/* invalidate the existing TDB iterator if it is open */
-	if (global_tdb_ent.passwd_tdb) {
-		tdb_close(global_tdb_ent.passwd_tdb);
-		global_tdb_ent.passwd_tdb = NULL;
+	if (tdb_state->passwd_tdb) {
+		tdb_close(tdb_state->passwd_tdb);
+		tdb_state->passwd_tdb = NULL;
 	}
 
  	/* open the account TDB passwd*/
@@ -819,21 +798,67 @@
  Modifies an existing SAM_ACCOUNT
 ****************************************************************************/
 
-BOOL pdb_update_sam_account (const SAM_ACCOUNT *newpwd, BOOL override)
+static BOOL tdbsam_update_sam_account (struct pdb_context *context, const SAM_ACCOUNT *newpwd)
 {
-	return (tdb_update_sam(newpwd, override, TDB_MODIFY));
+	return (tdb_update_sam(context, newpwd, TDB_MODIFY));
 }
 
 /***************************************************************************
  Adds an existing SAM_ACCOUNT
 ****************************************************************************/
 
-BOOL pdb_add_sam_account (const SAM_ACCOUNT *newpwd)
+static BOOL tdbsam_add_sam_account (struct pdb_context *context, const SAM_ACCOUNT *newpwd)
 {
-	return (tdb_update_sam(newpwd, True, TDB_INSERT));
+	return (tdb_update_sam(context, newpwd, TDB_INSERT));
+}
+
+static void free_private_data(void **vp) 
+{
+	struct tdb_enum_info **tdb_state = (struct tdb_enum_info **)vp;
+	close_tdb(*tdb_state);
+	*tdb_state = NULL;
+
+	/* No need to free any further, as it is talloc()ed */
+}
+
+
+NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method)
+{
+	NTSTATUS nt_status;
+
+	if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
+		return nt_status;
+	}
+
+	(*pdb_method)->setsampwent = tdbsam_setsampwent;
+	(*pdb_method)->endsampwent = tdbsam_endsampwent;
+	(*pdb_method)->getsampwent = tdbsam_getsampwent;
+	(*pdb_method)->getsampwnam = tdbsam_getsampwnam;
+	(*pdb_method)->getsampwrid = tdbsam_getsampwrid;
+	(*pdb_method)->add_sam_account = tdbsam_add_sam_account;
+	(*pdb_method)->update_sam_account = tdbsam_update_sam_account;
+	(*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
+
+	/* TODO: Setup private data and free */
+
+	(*pdb_method)->private_data = talloc(pdb_context->mem_ctx, sizeof(struct tdb_enum_info));
+
+	if (!(*pdb_method)->private_data) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	(*pdb_method)->free_private_data = free_private_data;
+
+	return NT_STATUS_OK;
 }
 
 #else
-	/* Do *NOT* make this function static. It breaks the compile on gcc. JRA */
-	void samtdb_dummy_function(void) { } /* stop some compilers complaining */
-#endif /* WITH_TDB_SAM */
+
+NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method)
+{
+	DEBUG(0, ("tdbsam not compiled in!\n"));
+	return NT_STATUS_UNSUCCESSFUL;
+}
+
+
+#endif
Index: rpc_server/srv_samr_nt.c
===================================================================
RCS file: /data/cvs/samba/source/rpc_server/srv_samr_nt.c,v
retrieving revision 1.76
diff -u -r1.76 srv_samr_nt.c
--- rpc_server/srv_samr_nt.c	17 Jan 2002 08:45:56 -0000	1.76
+++ rpc_server/srv_samr_nt.c	18 Jan 2002 07:41:06 -0000
@@ -2214,7 +2214,7 @@
 		return False;
 	}
 
-	if(!pdb_update_sam_account(pwd, True)) {
+	if(!pdb_update_sam_account(pwd)) {
 		pdb_free_sam(&pwd);
 		return False;
 	}
@@ -2258,7 +2258,7 @@
 		return False; 
 	}
  
-	if(!pdb_update_sam_account(pwd, True)) {
+	if(!pdb_update_sam_account(pwd)) {
 		pdb_free_sam(&pwd);
 		return False;
  	}
@@ -2297,7 +2297,7 @@
 	 */
  
 	/* write the change out */
-	if(!pdb_update_sam_account(pwd, True)) {
+	if(!pdb_update_sam_account(pwd)) {
 		pdb_free_sam(&pwd);
 		return False;
  	}
@@ -2360,7 +2360,7 @@
  
 	ZERO_STRUCT(plaintext_buf);
  
-	if(!pdb_update_sam_account(pwd, True)) {
+	if(!pdb_update_sam_account(pwd)) {
 		pdb_free_sam(&pwd);
 		return False;
 	}
@@ -2421,7 +2421,7 @@
 	DEBUG(5,("set_user_info_pw: pdb_update_sam_account()\n"));
  
 	/* update the SAMBA password */
-	if(!pdb_update_sam_account(pwd, True)) {
+	if(!pdb_update_sam_account(pwd)) {
 		pdb_free_sam(&pwd);
 		return False;
  	}
@@ -3085,7 +3085,7 @@
 	smb_delete_user(pdb_get_username(sam_pass));
 
 	/* and delete the samba side */
-	if (!pdb_delete_sam_account(pdb_get_username(sam_pass))) {
+	if (!pdb_delete_sam_account(sam_pass)) {
 		DEBUG(5,("_samr_delete_dom_user:Failed to delete entry for user %s.\n", pdb_get_username(sam_pass)));
 		pdb_free_sam(&sam_pass);
 		return NT_STATUS_CANNOT_DELETE;
Index: smbd/chgpasswd.c
===================================================================
RCS file: /data/cvs/samba/source/smbd/chgpasswd.c,v
retrieving revision 1.85
diff -u -r1.85 chgpasswd.c
--- smbd/chgpasswd.c	17 Jan 2002 08:45:56 -0000	1.85
+++ smbd/chgpasswd.c	18 Jan 2002 07:41:07 -0000
@@ -718,7 +718,7 @@
  
 	/* Now flush the sam_passwd struct to persistent storage */
 	become_root();
-	ret = pdb_update_sam_account (sampass, False);
+	ret = pdb_update_sam_account (sampass);
 	unbecome_root();
 
 	return ret;
@@ -928,7 +928,7 @@
 
 	/* Now write it into the file. */
 	become_root();
-	ret = pdb_update_sam_account (hnd, False);
+	ret = pdb_update_sam_account (hnd);
 	unbecome_root();
 
 	return ret;
Index: smbd/lanman.c
===================================================================
RCS file: /data/cvs/samba/source/smbd/lanman.c,v
retrieving revision 1.65
diff -u -r1.65 lanman.c
--- smbd/lanman.c	11 Jan 2002 19:10:23 -0000	1.65
+++ smbd/lanman.c	18 Jan 2002 07:41:17 -0000
@@ -1923,8 +1923,6 @@
   fstring user;
   fstring pass1,pass2;
 
-  struct passwd *passwd;
-
   pull_ascii_fstring(user,p);
 
   p = skip_string(p,1);
@@ -1952,26 +1950,13 @@
   (void)map_username(user);
 
   /*
-   * Do any UNIX username case mangling.
-   */
-  passwd = Get_Pwnam_Modify( user );
-
-  /*
    * Attempt to verify the old password against smbpasswd entries
    * Win98 clients send old and new password in plaintext for this call.
    */
 
   {
-    fstring saved_pass2;
     SAM_ACCOUNT *sampass=NULL;
 
-    /*
-     * Save the new password as change_oem_password overwrites it
-     * with zeros.
-     */
-
-    fstrcpy(saved_pass2, pass2);
-
     if (check_plaintext_password(user,pass1,strlen(pass1),&sampass) &&
         change_oem_password(sampass,pass2))
     {
@@ -1983,7 +1968,7 @@
        * be done.
        */
 
-      if(lp_unix_password_sync() && !chgpasswd(user,pass1,saved_pass2,False))
+      if(lp_unix_password_sync() && !chgpasswd(pdb_get_username(sampass),pass1,pass2,False))
         SSVAL(*rparam,0,NERR_badpass);
     }
  	pdb_free_sam(&sampass);
@@ -1997,6 +1982,15 @@
 
   if(SVAL(*rparam,0) != NERR_Success)
   {
+	  struct passwd *passwd;
+
+	    /*
+	     * Do any UNIX username case mangling.
+	     */
+	  
+	  passwd = Get_Pwnam_Modify( user );
+	  
+
 	  if NT_STATUS_IS_OK(pass_check(passwd, user, pass1, 
 					strlen(pass1), NULL, False)) 
 		  {
Index: utils/pdbedit.c
===================================================================
RCS file: /data/cvs/samba/source/utils/pdbedit.c,v
retrieving revision 1.31
diff -u -r1.31 pdbedit.c
--- utils/pdbedit.c	15 Jan 2002 01:02:12 -0000	1.31
+++ utils/pdbedit.c	18 Jan 2002 07:41:18 -0000
@@ -213,7 +213,7 @@
 	if (profile)
 		pdb_set_profile_path (sam_pwent, profile, True);
 	
-	if (pdb_update_sam_account (sam_pwent, True))
+	if (pdb_update_sam_account (sam_pwent))
 		print_user_info (username, True, False);
 	else {
 		fprintf (stderr, "Unable to modify entry!\n");
@@ -340,7 +340,16 @@
 
 static int delete_user_entry (char *username)
 {
-	return pdb_delete_sam_account (username);
+	SAM_ACCOUNT *samaccount;
+
+	pdb_init_sam(&samaccount);
+
+	if (!pdb_getsampwnam(samaccount, username)) {
+		fprintf (stderr, "user %s does not exist in the passdb\n", username);
+		return -1;
+	}
+
+	return pdb_delete_sam_account (samaccount);
 }
 
 /*********************************************************
@@ -350,11 +359,20 @@
 static int delete_machine_entry (char *machinename)
 {
 	char name[16];
+	SAM_ACCOUNT *samaccount;
 	
 	safe_strcpy (name, machinename, 16);
 	if (name[strlen(name)] != '$')
 		safe_strcat (name, "$", 16);
-	return pdb_delete_sam_account (name);
+
+	pdb_init_sam(&samaccount);
+
+	if (!pdb_getsampwnam(samaccount, name)) {
+		fprintf (stderr, "user %s does not exist in the passdb\n", name);
+		return -1;
+	}
+
+	return pdb_delete_sam_account (samaccount);
 }
 
 /*********************************************************
--- /dev/null	Wed May  6 06:32:27 1998
+++ passdb/pdb_interface.c	Fri Jan 18 11:17:26 2002
@@ -0,0 +1,373 @@
+/* 
+   Unix SMB/Netbios implementation.
+   Version 3.0
+   Password and authentication handling
+   Copyright (C) Andrew Bartlett		    2002
+      
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (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"
+
+/** List of various built-in passdb modules */
+
+const struct pdb_init_function builtin_pdb_init_functions[] = {
+	{ "smbpasswd", pdb_init_smbpasswd },
+	{ "tdbsam", pdb_init_tdbsam },
+#if 0
+	{ "ldap", pdb_init_ldap },
+	{ "nisplus", pdb_init_nisplus },	
+	{ "unix", pdb_init_unix },
+#endif
+	{ NULL, NULL}
+};
+
+static BOOL context_setsampwent(struct pdb_context *context, BOOL update)
+{
+	if ((!context) || (!context->pdb_selected)) {
+		DEBUG(0, ("invalid pdb_context specified!\n"));
+		return False;
+	}
+	
+	return context->pdb_selected->setsampwent(context, update);
+}
+
+static void context_endsampwent(struct pdb_context *context)
+{
+	if ((!context) || (!context->pdb_selected)) {
+		DEBUG(0, ("invalid pdb_context specified!\n"));
+		return;
+	}
+	
+	context->pdb_selected->endsampwent(context);
+}
+
+static BOOL context_getsampwent(struct pdb_context *context, SAM_ACCOUNT *user)
+{
+	if ((!context) || (!context->pdb_selected)) {
+		DEBUG(0, ("invalid pdb_context specified!\n"));
+		return False;
+	}
+	
+	return context->pdb_selected->getsampwent(context, user);
+}
+
+static BOOL context_getsampwnam(struct pdb_context *context, SAM_ACCOUNT *sam_acct, const char *username)
+{
+	if ((!context) || (!context->pdb_selected)) {
+		DEBUG(0, ("invalid pdb_context specified!\n"));
+		return False;
+	}
+	
+	return context->pdb_selected->getsampwnam(context, sam_acct, username);
+}
+
+static BOOL context_getsampwrid(struct pdb_context *context, SAM_ACCOUNT *sam_acct, uint32 rid)
+{
+	if ((!context) || (!context->pdb_selected)) {
+		DEBUG(0, ("invalid pdb_context specified!\n"));
+		return False;
+	}
+	
+	return context->pdb_selected->getsampwrid(context, sam_acct, rid);
+}
+
+static BOOL context_add_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct)
+{
+	if ((!context) || (!context->pdb_selected)) {
+		DEBUG(0, ("invalid pdb_context specified!\n"));
+		return False;
+	}
+	
+	/** @todo  This is where a 're-read on add' should be done */
+  
+	return context->pdb_selected->add_sam_account(context, sam_acct);
+}
+
+static BOOL context_update_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct)
+{
+	if ((!context) || (!context->pdb_selected)) {
+		DEBUG(0, ("invalid pdb_context specified!\n"));
+		return False;
+	}
+	
+	/** @todo  This is where a 're-read on update' should be done */
+	
+	return context->pdb_selected->update_sam_account(context, sam_acct);
+}
+
+static BOOL context_delete_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct)
+{
+	if ((!context) || (!context->pdb_selected)) {
+		DEBUG(0, ("invalid pdb_context specified!\n"));
+		return False;
+	}
+	
+	return context->pdb_selected->delete_sam_account(context, sam_acct);
+}
+
+static void free_pdb_context(struct pdb_context **context) 
+{
+	if (((*context)->pdb_selected) && ((*context)->pdb_selected->free_private_data)) {
+		(*context)->pdb_selected->free_private_data((*context)->pdb_selected->private_data);
+	}
+
+	talloc_destroy((*context)->mem_ctx);
+	*context = NULL;
+}
+
+/******************************************************************
+ Make a pdb_context from scratch.
+*******************************************************************/
+
+static NTSTATUS make_pdb_context(struct pdb_context **context) 
+{
+	TALLOC_CTX *mem_ctx;
+	
+	mem_ctx = talloc_init_named("pdb_context internal allocation context");
+
+	if (!mem_ctx) {
+		DEBUG(0, ("make_pdb_context: talloc init failed!\n"));
+		return NT_STATUS_NO_MEMORY;
+	}		
+
+	*context = talloc(mem_ctx, sizeof(**context));
+	if (!*context) {
+		DEBUG(0, ("make_pdb_context: talloc failed!\n"));
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	ZERO_STRUCTP(*context);
+
+	(*context)->mem_ctx = mem_ctx;
+
+	(*context)->pdb_setsampwent = context_setsampwent;
+	(*context)->pdb_endsampwent = context_endsampwent;
+	(*context)->pdb_getsampwent = context_getsampwent;
+	(*context)->pdb_getsampwnam = context_getsampwnam;
+	(*context)->pdb_getsampwrid = context_getsampwrid;
+	(*context)->pdb_add_sam_account = context_add_sam_account;
+	(*context)->pdb_update_sam_account = context_update_sam_account;
+	(*context)->pdb_delete_sam_account = context_delete_sam_account;
+
+	(*context)->free_fn = free_pdb_context;
+	
+	return NT_STATUS_OK;
+}
+
+
+/******************************************************************
+ Make a pdb_context, given a text string.
+*******************************************************************/
+
+NTSTATUS make_pdb_context_name(struct pdb_context **context, char *selected) 
+{
+	/* HINT: Don't store 'selected' becouse its often an lp_ string and will 'go away' */
+	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+	int i;
+	
+	if (!NT_STATUS_IS_OK(nt_status = make_pdb_context(context))) {
+		return nt_status;
+	}
+	
+	DEBUG(5,("Attempting to find an passdb backend to match %s\n", selected));
+	for (i = 0; builtin_pdb_init_functions[i].name; i++)
+	{
+		if (strequal(builtin_pdb_init_functions[i].name, selected))
+		{
+			DEBUG(5,("Found pdb backend %s (at pos %d)\n", selected, i));
+			if (NT_STATUS_IS_OK(nt_status 
+					    = builtin_pdb_init_functions[i].init(*context, &(*context)->pdb_selected))) {
+				DEBUG(5,("pdb backend %s has a valid init\n", selected));
+				(*context)->pdb_selected->name = builtin_pdb_init_functions[i].name;
+			} else {
+				DEBUG(0,("pdb backend %s did not correctly init (error was %s)\n", selected, get_nt_error_msg(nt_status)));
+			}
+			break;
+		}
+	}
+	
+	if (!(*context)->pdb_selected) {
+		DEBUG(0,("failed to select passdb backed!\n"));
+		talloc_destroy((*context)->mem_ctx);
+		*context = NULL;
+		return nt_status;
+	}
+
+	return NT_STATUS_OK;
+}
+
+
+/******************************************************************
+ Return an already initilised pdb_context, to facilitate backward 
+ compatiablity (see functions below).
+*******************************************************************/
+
+static struct pdb_context *pdb_get_static_context(BOOL reload) 
+{
+	static struct pdb_context *pdb_context = NULL;
+	
+	if ((pdb_context) && (reload)) {
+		pdb_context->free_fn(&pdb_context);
+		if (!NT_STATUS_IS_OK(make_pdb_context_name(&pdb_context, lp_passdb_backend()))) {
+			return NULL;
+		}
+	}
+	
+	if (!pdb_context) {
+		if (!NT_STATUS_IS_OK(make_pdb_context_name(&pdb_context, lp_passdb_backend()))) {
+			return NULL;
+		}
+	}
+	
+	return pdb_context;
+}
+
+#if !defined(WITH_LDAP_SAM) && !defined(WITH_NISPLUS_SAM)
+
+/******************************************************************
+ Backward compatability functions for the original passdb interface
+*******************************************************************/
+
+BOOL pdb_setsampwent(BOOL update) 
+{
+	struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+	return pdb_context->pdb_setsampwent(pdb_context, update);
+}
+
+void pdb_endsampwent(void) 
+{
+	struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+	pdb_context->pdb_endsampwent(pdb_context);
+}
+
+BOOL pdb_getsampwent(SAM_ACCOUNT *user) 
+{
+	struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+	return pdb_context->pdb_getsampwent(pdb_context, user);
+}
+
+BOOL pdb_getsampwnam(SAM_ACCOUNT *sam_acct, const char *username) 
+{
+	struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+	return pdb_context->pdb_getsampwnam(pdb_context, sam_acct, username);
+}
+
+BOOL pdb_getsampwrid(SAM_ACCOUNT *sam_acct, uint32 rid) 
+{
+	struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+	return pdb_context->pdb_getsampwrid(pdb_context, sam_acct, rid);
+}
+
+BOOL pdb_add_sam_account(SAM_ACCOUNT *sam_acct) 
+{
+	struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+	return pdb_context->pdb_add_sam_account(pdb_context, sam_acct);
+}
+
+BOOL pdb_update_sam_account(SAM_ACCOUNT *sam_acct) 
+{
+	struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+	return pdb_context->pdb_update_sam_account(pdb_context, sam_acct);
+}
+
+BOOL pdb_delete_sam_account(SAM_ACCOUNT *sam_acct) 
+{
+	struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+	return pdb_context->pdb_delete_sam_account(pdb_context, sam_acct);
+}
+
+#endif /* !defined(WITH_LDAP_SAM) && !defined(WITH_NISPLUS_SAM) */
+
+/***************************************************************
+ Initialize the static context (at smbd startup etc). 
+
+ If uninitialised, context will auto-init on first use.
+***************************************************************/
+
+BOOL initialize_password_db(BOOL reload)
+{	
+
+	return (pdb_get_static_context(reload) != NULL);
+
+	/* 
+	 * This function is unfinished right now, so just 
+	 * ignore the details and always return True.  It 
+	 * is here only as a placeholder          --jerry 
+	 */
+
+}
+
+/***************************************************************************
+ Search by uid.  Wrapper around pdb_getsampwnam()
+ **************************************************************************/
+
+BOOL pdb_getsampwuid (SAM_ACCOUNT* user, uid_t uid)
+{
+	struct passwd	*pw;
+	fstring		name;
+
+	if (user==NULL) {
+		DEBUG(0,("pdb_getsampwuid: SAM_ACCOUNT is NULL.\n"));
+		return False;
+	}
+
+	/*
+	 * Never trust the uid in the passdb.  Lookup the username first
+	 * and then lokup the user by name in the sam.
+	 */
+	 
+	if ((pw=getpwuid_alloc(uid)) == NULL)  {
+		DEBUG(0,("pdb_getsampwuid: getpwuid(%d) return NULL. User does not exist in Unix accounts!\n", uid));
+		return False;
+	}
+	
+	fstrcpy (name, pw->pw_name);
+
+	passwd_free(&pw);
+
+	return pdb_getsampwnam (user, name);
+
+}
+
+
+NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods) 
+{
+	*methods = talloc(mem_ctx, sizeof(struct pdb_methods));
+
+	if (!*methods) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	ZERO_STRUCTP(*methods);
+
+	return NT_STATUS_OK;
+}
+
+
+
+
+
+
+
+


More information about the samba-technical mailing list