[PATCH] Re: Plugable passdb (SAM) modules

Andrew Bartlett abartlet at pcug.org.au
Wed Jan 16 05:39:08 GMT 2002


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.

I also need to make a few minor changes for other parts of smbd to
recompile.

The purpose of posting the patch is to get comments:  Is this something
people want, or something that people will object to?

The main feature I have gained is the ability to open more than one
passdb at a time.  New passdbs can be init'd and operated on without
interference.  This should be useful for a pdb upgrade mechanism.  (This
uses function pointers of a context structure to do the dirty work).

Andrew Bartlett wrote:
> 
> I've started on an implementation of plugable passdb modules.
> 
> My particular interst in this is to allow me to do 'intersting' things
> without having to recompile as I move betwen modules.  (Like having
> users without a unix identity and other such objectionable notions).
> 
> The idea is that there would be 'yet another smb.conf option': passdb
> backend = ...

Implemented, needs doco ;-)

> This would select from the list of available modules and load it at
> startup. (first passdb access or init).
> 
> This requries a few changes, but I intend to wrap most of them behind
> the same external interface.  Internally, each passdb module will have
> an init function that fills in and returns a struct containing function
> pointers.

Also, modules not compiled in can have a 'blank' init function that
yells this fact loudly.  This all works in much the same way as my auth
modules.

> It will also have a void * in which it can store state (file handles,
> ldap handles etc).  This should remove the need for statics.

All statics in pdb_smbpasswd and pdb_tdb are gone.  

> I'm also be implementing the 'reread' changes to the interface, where an
> add/update/delete don't 'succeed' until a re-read of the db produces a
> compatible result and the SAM_ACCOUNT passed for that user is updated.

Note done yet.

> This whole this will look much like my auth work once its all done.
> 
> The main problem with all this (once I get it coded, tested etc) is the
> fact that it will spoil all hopes of keeping 2.2 in sync on the passdb
> side of things.  This is the main reason for this e-mail:  A heads up
> and an oppotunity to say 'don't commit it any time soon' or the like...

Again, please yell.

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.433
diff -u -r1.433 Makefile.in
--- Makefile.in	12 Jan 2002 23:57:09 -0000	1.433
+++ Makefile.in	16 Jan 2002 12:50:35 -0000
@@ -182,7 +182,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: 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	16 Jan 2002 12:50:37 -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	16 Jan 2002 12:50:38 -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/smb.h
===================================================================
RCS file: /data/cvs/samba/source/include/smb.h,v
retrieving revision 1.405
diff -u -r1.405 smb.h
--- include/smb.h	15 Jan 2002 02:11:54 -0000	1.405
+++ include/smb.h	16 Jan 2002 12:50:45 -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.373
diff -u -r1.373 loadparm.c
--- param/loadparm.c	16 Jan 2002 02:38:11 -0000	1.373
+++ param/loadparm.c	16 Jan 2002 12:50:59 -0000
@@ -111,6 +111,7 @@
 	char *szSMBPasswdFile;
 	char *szPrivateDir;
 	char *szPassdbModulePath;
+	char *szPassdbBackend;
 	char *szPasswordServer;
 	char *szSocketOptions;
 	char *szWorkGroup;
@@ -692,6 +693,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},
@@ -1198,6 +1200,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);
 
@@ -1451,6 +1454,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.136
diff -u -r1.136 passdb.c
--- passdb/passdb.c	15 Jan 2002 01:14:58 -0000	1.136
+++ passdb/passdb.c	16 Jan 2002 12:51:02 -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.
  ***********************************************************/
@@ -1111,14 +1089,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;
@@ -1133,35 +1111,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=sys_getpwuid(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);
-
-	return pdb_getsampwnam (user, name);
-
 }
 
Index: passdb/pdb_ldap.c
===================================================================
RCS file: /data/cvs/samba/source/passdb/pdb_ldap.c,v
retrieving revision 1.16
diff -u -r1.16 pdb_ldap.c
--- passdb/pdb_ldap.c	2 Jan 2002 22:02:11 -0000	1.16
+++ passdb/pdb_ldap.c	16 Jan 2002 12:51:06 -0000
@@ -837,14 +837,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;
 
@@ -888,7 +896,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;
@@ -949,7 +957,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	16 Jan 2002 12:51:09 -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.31
diff -u -r1.31 pdb_smbpasswd.c
--- passdb/pdb_smbpasswd.c	31 Dec 2001 00:06:51 -0000	1.31
+++ passdb/pdb_smbpasswd.c	16 Jan 2002 12:51:12 -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
@@ -34,7 +33,7 @@
 struct smb_passwd
 {
         uid_t smb_userid;     /* this is actually the unix uid_t */
-        char *smb_name;     /* username string */
+        const char *smb_name;     /* username string */
 
         const unsigned char *smb_passwd; /* Null if no password */
         const unsigned char *smb_nt_passwd; /* Null if no password */
@@ -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;
 }
@@ -1149,7 +1139,7 @@
 	ZERO_STRUCTP(smb_pw);
 
 	smb_pw->smb_userid=uid;
-	smb_pw->smb_name=(char*)pdb_get_username(sampass);
+	smb_pw->smb_name=(const char*)pdb_get_username(sampass);
 
 	smb_pw->smb_passwd=pdb_get_lanman_passwd(sampass);
 	smb_pw->smb_nt_passwd=pdb_get_nt_passwd(sampass);
@@ -1271,21 +1261,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) 
@@ -1294,31 +1287,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;
 	}
@@ -1326,7 +1321,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;
 
@@ -1337,7 +1332,7 @@
 			done = True;
 	}
 
-	DEBUG(5,("pdb_getsampwent:done\n"));
+	DEBUG(5,("getsampwent (smbpasswd): done\n"));
 
 	/* success */
 	return True;
@@ -1349,15 +1344,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 
@@ -1377,7 +1373,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"));
@@ -1389,20 +1385,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
@@ -1418,35 +1414,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
@@ -1461,8 +1458,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 */
@@ -1471,15 +1469,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 */
@@ -1487,19 +1486,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.40
diff -u -r1.40 pdb_tdb.c
--- passdb/pdb_tdb.c	15 Jan 2002 01:02:13 -0000	1.40
+++ passdb/pdb_tdb.c	16 Jan 2002 12:51:15 -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;
@@ -495,7 +499,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;
 }
@@ -504,7 +508,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;
@@ -597,7 +601,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;
@@ -645,9 +649,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;
@@ -655,7 +658,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);
@@ -671,33 +674,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"));
@@ -730,8 +708,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;
@@ -765,9 +744,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*/
@@ -815,21 +794,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
--- /dev/null	Wed May  6 06:32:27 1998
+++ passdb/pdb_interface.c	Wed Jan 16 23:36:16 2002
@@ -0,0 +1,367 @@
+/* 
+   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;
+}
+
+/******************************************************************
+ 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);
+}
+
+
+/***************************************************************
+ 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=sys_getpwuid(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);
+
+	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