samdb: Rework samdb_connect_url() to return LDB error code and an error string
[samba.git] / source3 / passdb / pdb_smbpasswd.c
index 94bd9bf31cf5b053c8075518975ce8eb90931d77..9c381471ddae384328541af58f401568f0a2f9e6 100644 (file)
  * 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.
+ * this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "includes.h"
+#include "passdb.h"
+#include "system/passwd.h"
+#include "system/filesys.h"
+#include "../librpc/gen_ndr/samr.h"
+#include "../libcli/security/security.h"
+#include "passdb/pdb_smbpasswd.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_PASSDB
    else.  However, smb_passwd is limited to the information
    stored by an smbpasswd entry 
  */
+
 struct smb_passwd
 {
-        uint32 smb_userid;        /* this is actually the unix uid_t */
+        uint32_t smb_userid;      /* this is actually the unix uid_t */
         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 */
 
-        uint16 acct_ctrl;             /* account info (ACB_xxxx bit-mask) */
+        uint16_t acct_ctrl;             /* account info (ACB_xxxx bit-mask) */
         time_t pass_last_set_time;    /* password last set time */
 };
 
@@ -48,13 +53,13 @@ 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;
+       fstring user_name;
        unsigned char smbpwd[16];
        unsigned char smbntpwd[16];
 
@@ -70,7 +75,7 @@ static SIG_ATOMIC_T gotalarm;
  Signal function to tell us we timed out.
 ****************************************************************/
 
-static void gotalarm_sig(void)
+static void gotalarm_sig(int signum)
 {
        gotalarm = 1;
 }
@@ -80,14 +85,14 @@ static void gotalarm_sig(void)
  seconds.
 ****************************************************************/
 
-static BOOL do_file_lock(int fd, int waitsecs, int type)
+static bool do_file_lock(int fd, int waitsecs, int type)
 {
-       SMB_STRUCT_FLOCK lock;
+       struct flock lock;
        int             ret;
        void (*oldsig_handler)(int);
 
        gotalarm = 0;
-       oldsig_handler = CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
+       oldsig_handler = CatchSignal(SIGALRM, gotalarm_sig);
 
        lock.l_type = type;
        lock.l_whence = SEEK_SET;
@@ -97,11 +102,11 @@ static BOOL do_file_lock(int fd, int waitsecs, int type)
 
        alarm(waitsecs);
        /* Note we must *NOT* use sys_fcntl here ! JRA */
-       ret = fcntl(fd, SMB_F_SETLKW, &lock);
+       ret = fcntl(fd, F_SETLKW, &lock);
        alarm(0);
-       CatchSignal(SIGALRM, SIGNAL_CAST oldsig_handler);
+       CatchSignal(SIGALRM, oldsig_handler);
 
-       if (gotalarm) {
+       if (gotalarm && ret == -1) {
                DEBUG(0, ("do_file_lock: failed to %s file.\n",
                        type == F_UNLCK ? "unlock" : "lock"));
                return False;
@@ -114,7 +119,7 @@ static BOOL do_file_lock(int fd, int waitsecs, int type)
  Lock an fd. Abandon after waitsecs seconds.
 ****************************************************************/
 
-static BOOL pw_file_lock(int fd, int type, int secs, int *plock_depth)
+static bool pw_file_lock(int fd, int type, int secs, int *plock_depth)
 {
        if (fd < 0) {
                return False;
@@ -137,9 +142,9 @@ static BOOL pw_file_lock(int fd, int type, int secs, int *plock_depth)
  Unlock an fd. Abandon after waitsecs seconds.
 ****************************************************************/
 
-static BOOL pw_file_unlock(int fd, int *plock_depth)
+static bool pw_file_unlock(int fd, int *plock_depth)
 {
-       BOOL ret=True;
+       bool ret=True;
 
        if (fd == 0 || *plock_depth == 0) {
                return True;
@@ -169,7 +174,7 @@ static void pdb_init_smb(struct smb_passwd *user)
        if (user == NULL) 
                return;
        ZERO_STRUCTP (user);
-       
+
        user->pass_last_set_time = (time_t)0;
 }
 
@@ -209,10 +214,10 @@ static FILE *startsmbfilepwent(const char *pfile, enum pwf_access_type type, int
                                int i, fd = -1;
 
                                for(i = 0; i < 5; i++) {
-                                       if((fd = sys_open(pfile, O_CREAT|O_TRUNC|O_EXCL|O_RDWR, 0600))!=-1) {
+                                       if((fd = open(pfile, O_CREAT|O_TRUNC|O_EXCL|O_RDWR, 0600))!=-1) {
                                                break;
                                        }
-                                       sys_usleep(200); /* Spin, spin... */
+                                       usleep(200); /* Spin, spin... */
                                }
                                if(fd == -1) {
                                        DEBUG(0,("startsmbfilepwent_internal: too many race conditions \
@@ -224,19 +229,22 @@ creating file %s\n", pfile));
                                lock_type = F_WRLCK;
                                break;
                        }
+               default:
+                       DEBUG(10, ("Invalid open mode: %d\n", type));
+                       return NULL;
        }
-                      
+
        for(race_loop = 0; race_loop < 5; race_loop++) {
                DEBUG(10, ("startsmbfilepwent_internal: opening file %s\n", pfile));
 
-               if((fp = sys_fopen(pfile, open_mode)) == NULL) {
+               if((fp = fopen(pfile, open_mode)) == NULL) {
 
                        /*
                         * If smbpasswd file doesn't exist, then create new one. This helps to avoid
                         * confusing error msg when adding user account first time.
                         */
                        if (errno == ENOENT) {
-                               if ((fp = sys_fopen(pfile, "a+")) != NULL) {
+                               if ((fp = fopen(pfile, "a+")) != NULL) {
                                        DEBUG(0, ("startsmbfilepwent_internal: file %s did not \
 exist. File successfully created.\n", pfile));
                                } else {
@@ -277,7 +285,7 @@ Error was %s\n", pfile, strerror(errno) ));
                         * prevent infinate loops. JRA.
                         */
 
-                       if (sys_stat(pfile,&sbuf1) != 0) {
+                       if (sys_stat(pfile, &sbuf1, false) != 0) {
                                DEBUG(0, ("startsmbfilepwent_internal: unable to stat file %s. \
 Error was %s\n", pfile, strerror(errno)));
                                pw_file_unlock(fileno(fp), lock_depth);
@@ -285,7 +293,7 @@ Error was %s\n", pfile, strerror(errno)));
                                return NULL;
                        }
 
-                       if (sys_fstat(fileno(fp),&sbuf2) != 0) {
+                       if (sys_fstat(fileno(fp), &sbuf2, false) != 0) {
                                DEBUG(0, ("startsmbfilepwent_internal: unable to fstat file %s. \
 Error was %s\n", pfile, strerror(errno)));
                                pw_file_unlock(fileno(fp), lock_depth);
@@ -293,7 +301,7 @@ Error was %s\n", pfile, strerror(errno)));
                                return NULL;
                        }
 
-                       if( sbuf1.st_ino == sbuf2.st_ino) {
+                       if( sbuf1.st_ex_ino == sbuf2.st_ex_ino) {
                                /* No race. */
                                break;
                        }
@@ -438,12 +446,6 @@ static struct smb_passwd *getsmbfilepwent(struct smbpasswd_privates *smbpasswd_s
                        continue;
                }
 
-               /*
-                * As 256 is shorter than a pstring we don't need to check
-                * length here - if this ever changes....
-                */
-               SMB_ASSERT(sizeof(pstring) > sizeof(linebuf));
-
                strncpy(user_name, linebuf, PTR_DIFF(p, linebuf));
                user_name[PTR_DIFF(p, linebuf)] = '\0';
 
@@ -548,7 +550,7 @@ static struct smb_passwd *getsmbfilepwent(struct smbpasswd_privates *smbpasswd_s
                        }
                        if(*p == ':') {
                                p++;
-                               if(*p && (StrnCaseCmp((char *)p, "LCT-", 4)==0)) {
+                               if(*p && (strncasecmp_m((char *)p, "LCT-", 4)==0)) {
                                        int i;
                                        p += 4;
                                        for(i = 0; i < 8; i++) {
@@ -621,7 +623,7 @@ static char *format_new_smbpasswd_entry(const struct smb_passwd *newpwd)
        /* Add the account encoding and the last change time. */
        slprintf((char *)p, new_entry_length - 1 - (p - new_entry),  "%s:LCT-%08X:\n",
                pdb_encode_acct_ctrl(newpwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN),
-               (uint32)newpwd->pass_last_set_time);
+               (uint32_t)newpwd->pass_last_set_time);
 
        return new_entry;
 }
@@ -640,7 +642,7 @@ static NTSTATUS add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state,
        int fd;
        size_t new_entry_length;
        char *new_entry;
-       SMB_OFF_T offpos;
+       off_t offpos;
  
        /* Open the smbpassword file - for update. */
        fp = startsmbfilepwent(pfile, PWF_UPDATE, &smbpasswd_state->pw_file_lock_depth);
@@ -676,9 +678,9 @@ static NTSTATUS add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state,
         */
        fd = fileno(fp);
 
-       if((offpos = sys_lseek(fd, 0, SEEK_END)) == -1) {
+       if((offpos = lseek(fd, 0, SEEK_END)) == -1) {
                NTSTATUS result = map_nt_error_from_unix(errno);
-               DEBUG(0, ("add_smbfilepwd_entry(sys_lseek): Failed to add entry for user %s to file %s. \
+               DEBUG(0, ("add_smbfilepwd_entry(lseek): Failed to add entry for user %s to file %s. \
 Error was %s\n", newpwd->smb_name, pfile, strerror(errno)));
                endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
                return result;
@@ -704,7 +706,7 @@ Error was %s\n", newpwd->smb_name, pfile, strerror(errno)));
 Error was %s\n", wr_len, newpwd->smb_name, pfile, strerror(errno)));
 
                /* Remove the entry we just wrote. */
-               if(sys_ftruncate(fd, offpos) == -1) {
+               if(ftruncate(fd, offpos) == -1) {
                        DEBUG(0, ("add_smbfilepwd_entry: ERROR failed to ftruncate file %s. \
 Error was %s. Password file may be corrupt ! Please examine by hand !\n", 
                                newpwd->smb_name, strerror(errno)));
@@ -729,13 +731,14 @@ Error was %s. Password file may be corrupt ! Please examine by hand !\n",
  override = True, override XXXXXXXX'd out password or NO PASS
 ************************************************************************/
 
-static BOOL mod_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, const struct smb_passwd* pwd)
+static bool mod_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, const struct smb_passwd* pwd)
 {
        /* Static buffers we will return. */
-       pstring user_name;
+       fstring user_name;
 
        char *status;
-       char linebuf[256];
+#define LINEBUF_SIZE 255
+       char linebuf[LINEBUF_SIZE + 1];
        char readbuf[1024];
        int c;
        fstring ascii_p16;
@@ -745,10 +748,10 @@ static BOOL mod_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, con
        FILE *fp;
        int lockfd;
        const char *pfile = smbpasswd_state->smbpasswd_file;
-       BOOL found_entry = False;
-       BOOL got_pass_last_set_time = False;
+       bool found_entry = False;
+       bool got_pass_last_set_time = False;
 
-       SMB_OFF_T pwd_seekpos = 0;
+       off_t pwd_seekpos = 0;
 
        int i;
        int wr_len;
@@ -760,7 +763,7 @@ static BOOL mod_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, con
        }
        DEBUG(10, ("mod_smbfilepwd_entry: opening file %s\n", pfile));
 
-       fp = sys_fopen(pfile, "r+");
+       fp = fopen(pfile, "r+");
 
        if (fp == NULL) {
                DEBUG(0, ("mod_smbfilepwd_entry: unable to open file %s\n", pfile));
@@ -786,11 +789,11 @@ static BOOL mod_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, con
         */
        status = linebuf;
        while (status && !feof(fp)) {
-               pwd_seekpos = sys_ftell(fp);
+               pwd_seekpos = ftell(fp);
 
                linebuf[0] = '\0';
 
-               status = fgets(linebuf, sizeof(linebuf), fp);
+               status = fgets(linebuf, LINEBUF_SIZE, fp);
                if (status == NULL && ferror(fp)) {
                        pw_file_unlock(lockfd, &smbpasswd_state->pw_file_lock_depth);
                        fclose(fp);
@@ -848,13 +851,6 @@ static BOOL mod_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, con
                        continue;
                }
 
-               /*
-                * As 256 is shorter than a pstring we don't need to check
-                * length here - if this ever changes....
-                */
-
-               SMB_ASSERT(sizeof(user_name) > sizeof(linebuf));
-
                strncpy(user_name, linebuf, PTR_DIFF(p, linebuf));
                user_name[PTR_DIFF(p, linebuf)] = '\0';
                if (strequal(user_name, pwd->smb_name)) {
@@ -981,7 +977,7 @@ This is no longer supported.!\n", pwd->smb_name));
                        p++;
 
                        /* We should be pointing at the LCT entry. */
-                       if((linebuf_len > (PTR_DIFF(p, linebuf) + 13)) && (StrnCaseCmp((char *)p, "LCT-", 4) == 0)) {
+                       if((linebuf_len > (PTR_DIFF(p, linebuf) + 13)) && (strncasecmp_m((char *)p, "LCT-", 4) == 0)) {
                                p += 4;
                                for(i = 0; i < 8; i++) {
                                        if(p[i] == '\0' || !isxdigit(p[i])) {
@@ -996,7 +992,7 @@ This is no longer supported.!\n", pwd->smb_name));
                                         */
                                        got_pass_last_set_time = True;
                                } /* i == 8 */
-                       } /* *p && StrnCaseCmp() */
+                       } /* *p && strncasecmp_m() */
                } /* p == ':' */
        } /* p == '[' */
 
@@ -1017,16 +1013,16 @@ This is no longer supported.!\n", pwd->smb_name));
                slprintf(&ascii_p16[strlen(ascii_p16)], 
                        sizeof(ascii_p16)-(strlen(ascii_p16)+1),
                        "%s:LCT-%08X:", 
-                       encode_bits, (uint32)pwd->pass_last_set_time );
+                       encode_bits, (uint32_t)pwd->pass_last_set_time );
                wr_len = strlen(ascii_p16);
        }
 
 #ifdef DEBUG_PASSWORD
        DEBUG(100,("mod_smbfilepwd_entry: "));
-       dump_data(100, (uint8 *)ascii_p16, wr_len);
+       dump_data(100, (uint8_t *)ascii_p16, wr_len);
 #endif
 
-       if(wr_len > sizeof(linebuf)) {
+       if(wr_len > LINEBUF_SIZE) {
                DEBUG(0, ("mod_smbfilepwd_entry: line to write (%d) is too long.\n", wr_len+1));
                pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
                fclose(fp);
@@ -1044,7 +1040,7 @@ This is no longer supported.!\n", pwd->smb_name));
 
        fd = fileno(fp);
 
-       if (sys_lseek(fd, pwd_seekpos - 1, SEEK_SET) != pwd_seekpos - 1) {
+       if (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,&smbpasswd_state->pw_file_lock_depth);
                fclose(fp);
@@ -1066,7 +1062,7 @@ This is no longer supported.!\n", pwd->smb_name));
                return False;
        }
  
-       if (sys_lseek(fd, pwd_seekpos, SEEK_SET) != pwd_seekpos) {
+       if (lseek(fd, pwd_seekpos, SEEK_SET) != pwd_seekpos) {
                DEBUG(0, ("mod_smbfilepwd_entry: seek fail on file %s.\n", pfile));
                pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
                fclose(fp);
@@ -1089,16 +1085,21 @@ This is no longer supported.!\n", pwd->smb_name));
  Routine to delete an entry in the smbpasswd file by name.
 *************************************************************************/
 
-static BOOL del_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, const char *name)
+static bool del_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, const char *name)
 {
        const char *pfile = smbpasswd_state->smbpasswd_file;
-       pstring pfile2;
+       char *pfile2 = NULL;
        struct smb_passwd *pwd = NULL;
        FILE *fp = NULL;
        FILE *fp_write = NULL;
        int pfile2_lockdepth = 0;
 
-       slprintf(pfile2, sizeof(pfile2)-1, "%s.%u", pfile, (unsigned)sys_getpid() );
+       pfile2 = talloc_asprintf(talloc_tos(),
+                       "%s.%u",
+                       pfile, (unsigned)getpid());
+       if (!pfile2) {
+               return false;
+       }
 
        /*
         * Open the smbpassword file - for update. It needs to be update
@@ -1180,7 +1181,7 @@ Error was %s\n", pwd->smb_name, pfile2, strerror(errno)));
        if(rename(pfile2,pfile) != 0) {
                unlink(pfile2);
        }
-  
+
        endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
        endsmbfilepwent(fp_write,&pfile2_lockdepth);
        return True;
@@ -1192,9 +1193,9 @@ Error was %s\n", pwd->smb_name, pfile2, strerror(errno)));
  should only stay around as long as the struct samu does.
  ********************************************************************/
 
-static BOOL build_smb_pass (struct smb_passwd *smb_pw, const struct samu *sampass)
+static bool build_smb_pass (struct smb_passwd *smb_pw, const struct samu *sampass)
 {
-       uint32 rid;
+       uint32_t rid;
 
        if (sampass == NULL) 
                return False;
@@ -1202,12 +1203,12 @@ static BOOL build_smb_pass (struct smb_passwd *smb_pw, const struct samu *sampas
 
        if (!IS_SAM_DEFAULT(sampass, PDB_USERSID)) {
                rid = pdb_get_user_rid(sampass);
-               
+
                /* If the user specified a RID, make sure its able to be both stored and retreived */
-               if (rid == DOMAIN_USER_RID_GUEST) {
-                       struct passwd *passwd = getpwnam_alloc(NULL, lp_guestaccount());
+               if (rid == DOMAIN_RID_GUEST) {
+                       struct passwd *passwd = Get_Pwnam_alloc(NULL, lp_guest_account());
                        if (!passwd) {
-                               DEBUG(0, ("Could not find guest account via getpwnam()! (%s)\n", lp_guestaccount()));
+                               DEBUG(0, ("Could not find guest account via Get_Pwnam_alloc()! (%s)\n", lp_guest_account()));
                                return False;
                        }
                        smb_pw->smb_userid=passwd->pw_uid;
@@ -1235,11 +1236,11 @@ static BOOL build_smb_pass (struct smb_passwd *smb_pw, const struct samu *sampas
  Create a struct samu from a smb_passwd struct
  ********************************************************************/
 
-static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state, 
+static bool build_sam_account(struct smbpasswd_privates *smbpasswd_state, 
                              struct samu *sam_pass, const struct smb_passwd *pw_buf)
 {
        struct passwd *pwfile;
-       
+
        if ( !sam_pass ) {
                DEBUG(5,("build_sam_account: struct samu is NULL\n"));
                return False;
@@ -1252,20 +1253,22 @@ static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state,
                "%u is not in unix passwd database!\n", pw_buf->smb_name, pw_buf->smb_userid));
                        return False;
        }
-       
+
        if ( !NT_STATUS_IS_OK( samu_set_unix(sam_pass, pwfile )) )
                return False;
-               
+
        TALLOC_FREE(pwfile);
 
        /* set remaining fields */
-               
-       pdb_set_nt_passwd (sam_pass, pw_buf->smb_nt_passwd, PDB_SET);
-       pdb_set_lanman_passwd (sam_pass, pw_buf->smb_passwd, PDB_SET);                  
+
+       if (!pdb_set_nt_passwd (sam_pass, pw_buf->smb_nt_passwd, PDB_SET))
+               return False;
+       if (!pdb_set_lanman_passwd (sam_pass, pw_buf->smb_passwd, PDB_SET))
+               return False;
        pdb_set_acct_ctrl (sam_pass, pw_buf->acct_ctrl, PDB_SET);
        pdb_set_pass_last_set_time (sam_pass, pw_buf->pass_last_set_time, PDB_SET);
        pdb_set_pass_can_change_time (sam_pass, pw_buf->pass_last_set_time, PDB_SET);
-       
+
        return True;
 }
 
@@ -1273,79 +1276,6 @@ static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state,
  Functions to be implemented by the new passdb API 
  ****************************************************************/
 
-static NTSTATUS smbpasswd_setsampwent (struct pdb_methods *my_methods, BOOL update, uint32 acb_mask)
-{
-       struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
-       
-       smbpasswd_state->pw_file = startsmbfilepwent(smbpasswd_state->smbpasswd_file, 
-                                                      update ? PWF_UPDATE : PWF_READ, 
-                                                      &(smbpasswd_state->pw_file_lock_depth));
-                                  
-       /* did we fail?  Should we try to create it? */
-       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"); */
-               DEBUG(0,("smbpasswd file did not exist - attempting to create it.\n"));
-               fp = sys_fopen(smbpasswd_state->smbpasswd_file, "w");
-               if (fp) {
-                       fprintf(fp, "# Samba SMB password file\n");
-                       fclose(fp);
-               }
-               
-               smbpasswd_state->pw_file = startsmbfilepwent(smbpasswd_state->smbpasswd_file, 
-                                                            update ? PWF_UPDATE : PWF_READ, 
-                                                            &(smbpasswd_state->pw_file_lock_depth));
-       }
-       
-       if (smbpasswd_state->pw_file != NULL)
-               return NT_STATUS_OK;
-       else
-               return NT_STATUS_UNSUCCESSFUL;  
-}
-
-static void smbpasswd_endsampwent (struct pdb_methods *my_methods)
-{
-       struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
-       endsmbfilepwent(smbpasswd_state->pw_file, &(smbpasswd_state->pw_file_lock_depth));
-}
-/*****************************************************************
- ****************************************************************/
-
-static NTSTATUS smbpasswd_getsampwent(struct pdb_methods *my_methods, struct samu *user)
-{
-       NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
-       struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
-       struct smb_passwd *pw_buf=NULL;
-       BOOL done = False;
-
-       DEBUG(5,("pdb_getsampwent\n"));
-
-       if ( !user ) {
-               DEBUG(5,("pdb_getsampwent (smbpasswd): user is NULL\n"));
-               return nt_status;
-       }
-
-       while (!done) {
-               /* do we have an entry? */
-               pw_buf = getsmbfilepwent(smbpasswd_state, smbpasswd_state->pw_file);
-               if (pw_buf == NULL) 
-                       return nt_status;
-
-               /* build the struct samu entry from the smb_passwd struct. 
-                  We loop in case the user in the pdb does not exist in 
-                  the local system password file */
-               if (build_sam_account(smbpasswd_state, user, pw_buf))
-                       done = True;
-       }
-
-       DEBUG(5,("getsampwent (smbpasswd): done\n"));
-
-       /* success */
-       return NT_STATUS_OK;
-}
-
 /****************************************************************
  Search smbpasswd file by iterating over the entries.  Do not
  call getpwnam() for unix account information until we have found
@@ -1374,21 +1304,21 @@ static NTSTATUS smbpasswd_getsampwnam(struct pdb_methods *my_methods,
 
        while ( ((smb_pw=getsmbfilepwent(smbpasswd_state, fp)) != NULL)&& (!strequal(smb_pw->smb_name, username)) )
                /* do nothing....another loop */ ;
-       
+
        endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
 
 
        /* did we locate the username in smbpasswd  */
        if (smb_pw == NULL)
                return nt_status;
-       
+
        DEBUG(10, ("getsampwnam (smbpasswd): found by name: %s\n", smb_pw->smb_name));
 
        if (!sam_acct) {
                DEBUG(10,("getsampwnam (smbpasswd): struct samu is NULL\n"));
                return nt_status;
        }
-               
+
        /* now build the struct samu */
        if (!build_sam_account(smbpasswd_state, sam_acct, smb_pw))
                return nt_status;
@@ -1397,23 +1327,23 @@ static NTSTATUS smbpasswd_getsampwnam(struct pdb_methods *my_methods,
        return NT_STATUS_OK;
 }
 
-static NTSTATUS smbpasswd_getsampwsid(struct pdb_methods *my_methods, struct samu *sam_acct, const DOM_SID *sid)
+static NTSTATUS smbpasswd_getsampwsid(struct pdb_methods *my_methods, struct samu *sam_acct, const struct dom_sid *sid)
 {
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
        struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
        struct smb_passwd *smb_pw;
        FILE *fp = NULL;
-       fstring sid_str;
-       uint32 rid;
-       
-       DEBUG(10, ("smbpasswd_getsampwrid: search by sid: %s\n", sid_to_string(sid_str, sid)));
+       uint32_t rid;
+
+       DEBUG(10, ("smbpasswd_getsampwrid: search by sid: %s\n",
+                  sid_string_dbg(sid)));
 
        if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid))
                return NT_STATUS_UNSUCCESSFUL;
 
        /* More special case 'guest account' hacks... */
-       if (rid == DOMAIN_USER_RID_GUEST) {
-               const char *guest_account = lp_guestaccount();
+       if (rid == DOMAIN_RID_GUEST) {
+               const char *guest_account = lp_guest_account();
                if (!(guest_account && *guest_account)) {
                        DEBUG(1, ("Guest account not specfied!\n"));
                        return nt_status;
@@ -1438,9 +1368,9 @@ static NTSTATUS smbpasswd_getsampwsid(struct pdb_methods *my_methods, struct sam
        /* did we locate the username in smbpasswd  */
        if (smb_pw == NULL)
                return nt_status;
-       
+
        DEBUG(10, ("getsampwrid (smbpasswd): found by name: %s\n", smb_pw->smb_name));
-               
+
        if (!sam_acct) {
                DEBUG(10,("getsampwrid: (smbpasswd) struct samu is NULL\n"));
                return nt_status;
@@ -1451,10 +1381,11 @@ static NTSTATUS smbpasswd_getsampwsid(struct pdb_methods *my_methods, struct sam
                return nt_status;
 
        /* build_sam_account might change the SID on us, if the name was for the guest account */
-       if (NT_STATUS_IS_OK(nt_status) && !sid_equal(pdb_get_user_sid(sam_acct), sid)) {
-               fstring sid_string1, sid_string2;
-               DEBUG(1, ("looking for user with sid %s instead returned %s for account %s!?!\n",
-                         sid_to_string(sid_string1, sid), sid_to_string(sid_string2, pdb_get_user_sid(sam_acct)), pdb_get_username(sam_acct)));
+       if (NT_STATUS_IS_OK(nt_status) && !dom_sid_equal(pdb_get_user_sid(sam_acct), sid)) {
+               DEBUG(1, ("looking for user with sid %s instead returned %s "
+                         "for account %s!?!\n", sid_string_dbg(sid),
+                         sid_string_dbg(pdb_get_user_sid(sam_acct)),
+                         pdb_get_username(sam_acct)));
                return NT_STATUS_NO_SUCH_USER;
        }
 
@@ -1466,12 +1397,12 @@ static NTSTATUS smbpasswd_add_sam_account(struct pdb_methods *my_methods, struct
 {
        struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
        struct smb_passwd smb_pw;
-       
+
        /* convert the struct samu */
        if (!build_smb_pass(&smb_pw, sampass)) {
                return NT_STATUS_UNSUCCESSFUL;
        }
-       
+
        /* add the entry */
        return add_smbfilepwd_entry(smbpasswd_state, &smb_pw);
 }
@@ -1480,19 +1411,19 @@ static NTSTATUS smbpasswd_update_sam_account(struct pdb_methods *my_methods, str
 {
        struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
        struct smb_passwd smb_pw;
-       
+
        /* convert the struct samu */
        if (!build_smb_pass(&smb_pw, sampass)) {
                DEBUG(0, ("smbpasswd_update_sam_account: build_smb_pass failed!\n"));
                return NT_STATUS_UNSUCCESSFUL;
        }
-       
+
        /* update the entry */
        if(!mod_smbfilepwd_entry(smbpasswd_state, &smb_pw)) {
                DEBUG(0, ("smbpasswd_update_sam_account: mod_smbfilepwd_entry failed!\n"));
                return NT_STATUS_UNSUCCESSFUL;
        }
-       
+
        return NT_STATUS_OK;
 }
 
@@ -1512,24 +1443,25 @@ static NTSTATUS smbpasswd_rename_sam_account (struct pdb_methods *my_methods,
                                              struct samu *old_acct,
                                              const char *newname)
 {
-       pstring rename_script;
+       char *rename_script = NULL;
        struct samu *new_acct = NULL;
-       BOOL interim_account = False;
+       bool interim_account = False;
+       TALLOC_CTX *ctx = talloc_tos();
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
 
-       if (!*(lp_renameuser_script()))
+       if (!*(lp_rename_user_script(talloc_tos())))
                goto done;
 
        if ( !(new_acct = samu_new( NULL )) ) {
                return NT_STATUS_NO_MEMORY;
        }
-       
+
        if ( !pdb_copy_sam_account( new_acct, old_acct ) 
                || !pdb_set_username(new_acct, newname, PDB_CHANGED)) 
        {
                goto done;
        }
-       
+
        ret = smbpasswd_add_sam_account(my_methods, new_acct);
        if (!NT_STATUS_IS_OK(ret))
                goto done;
@@ -1537,17 +1469,39 @@ static NTSTATUS smbpasswd_rename_sam_account (struct pdb_methods *my_methods,
        interim_account = True;
 
        /* rename the posix user */
-       pstrcpy(rename_script, lp_renameuser_script());
+       rename_script = lp_rename_user_script(ctx);
+       if (!rename_script) {
+               ret = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
 
        if (*rename_script) {
                int rename_ret;
 
-               string_sub2(rename_script, "%unew", newname, sizeof(pstring), 
-                           True, False, True);
-               string_sub2(rename_script, "%uold", pdb_get_username(old_acct), 
-                           sizeof(pstring), True, False, True);
+               rename_script = talloc_string_sub2(ctx,
+                                       rename_script,
+                                       "%unew",
+                                       newname,
+                                       true,
+                                       false,
+                                       true);
+               if (!rename_script) {
+                       ret = NT_STATUS_NO_MEMORY;
+                       goto done;
+               }
+               rename_script = talloc_string_sub2(ctx,
+                                       rename_script,
+                                       "%uold",
+                                       pdb_get_username(old_acct),
+                                       true,
+                                       false,
+                                       true);
+               if (!rename_script) {
+                       ret = NT_STATUS_NO_MEMORY;
+                       goto done;
+               }
 
-               rename_ret = smbrun(rename_script, NULL);
+               rename_ret = smbrun(rename_script, NULL, NULL);
 
                DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n", rename_script, rename_ret));
 
@@ -1555,8 +1509,8 @@ static NTSTATUS smbpasswd_rename_sam_account (struct pdb_methods *my_methods,
                        smb_nscd_flush_user_cache();
                }
 
-               if (rename_ret) 
-                       goto done; 
+               if (rename_ret)
+                       goto done;
         } else {
                goto done;
        }
@@ -1564,32 +1518,160 @@ static NTSTATUS smbpasswd_rename_sam_account (struct pdb_methods *my_methods,
        smbpasswd_delete_sam_account(my_methods, old_acct);
        interim_account = False;
 
-done:  
+done:
        /* cleanup */
        if (interim_account)
                smbpasswd_delete_sam_account(my_methods, new_acct);
 
        if (new_acct)
                TALLOC_FREE(new_acct);
-       
+
        return (ret);   
 }
 
-static BOOL smbpasswd_rid_algorithm(struct pdb_methods *methods)
+static uint32_t smbpasswd_capabilities(struct pdb_methods *methods)
 {
-       return True;
+       return 0;
 }
 
 static void free_private_data(void **vp) 
 {
        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 */
 }
 
+struct smbpasswd_search_state {
+       uint32_t acct_flags;
+
+       struct samr_displayentry *entries;
+       uint32_t num_entries;
+       ssize_t array_size;
+       uint32_t current;
+};
+
+static void smbpasswd_search_end(struct pdb_search *search)
+{
+       struct smbpasswd_search_state *state = talloc_get_type_abort(
+               search->private_data, struct smbpasswd_search_state);
+       TALLOC_FREE(state);
+}
+
+static bool smbpasswd_search_next_entry(struct pdb_search *search,
+                                       struct samr_displayentry *entry)
+{
+       struct smbpasswd_search_state *state = talloc_get_type_abort(
+               search->private_data, struct smbpasswd_search_state);
+
+       if (state->current == state->num_entries) {
+               return false;
+       }
+
+       entry->idx = state->entries[state->current].idx;
+       entry->rid = state->entries[state->current].rid;
+       entry->acct_flags = state->entries[state->current].acct_flags;
+
+       entry->account_name = talloc_strdup(
+               search, state->entries[state->current].account_name);
+       entry->fullname = talloc_strdup(
+               search, state->entries[state->current].fullname);
+       entry->description = talloc_strdup(
+               search, state->entries[state->current].description);
+
+       if ((entry->account_name == NULL) || (entry->fullname == NULL)
+           || (entry->description == NULL)) {
+               DEBUG(0, ("talloc_strdup failed\n"));
+               return false;
+       }
+
+       state->current += 1;
+       return true;
+}
+
+static bool smbpasswd_search_users(struct pdb_methods *methods,
+                                  struct pdb_search *search,
+                                  uint32_t acct_flags)
+{
+       struct smbpasswd_privates *smbpasswd_state =
+               (struct smbpasswd_privates*)methods->private_data;
+
+       struct smbpasswd_search_state *search_state;
+       struct smb_passwd *pwd;
+       FILE *fp;
+
+       search_state = talloc_zero(search, struct smbpasswd_search_state);
+       if (search_state == NULL) {
+               DEBUG(0, ("talloc failed\n"));
+               return false;
+       }
+       search_state->acct_flags = acct_flags;
+
+       fp = startsmbfilepwent(smbpasswd_state->smbpasswd_file, PWF_READ,
+                              &smbpasswd_state->pw_file_lock_depth);
+
+       if (fp == NULL) {
+               DEBUG(10, ("Unable to open smbpasswd file.\n"));
+               TALLOC_FREE(search_state);
+               return false;
+       }
+
+       while ((pwd = getsmbfilepwent(smbpasswd_state, fp)) != NULL) {
+               struct samr_displayentry entry;
+               struct samu *user;
+
+               if ((acct_flags != 0)
+                   && ((acct_flags & pwd->acct_ctrl) == 0)) {
+                       continue;
+               }
+
+               user = samu_new(talloc_tos());
+               if (user == NULL) {
+                       DEBUG(0, ("samu_new failed\n"));
+                       break;
+               }
+
+               if (!build_sam_account(smbpasswd_state, user, pwd)) {
+                       /* Already got debug msgs... */
+                       break;
+               }
+
+               ZERO_STRUCT(entry);
+
+               entry.acct_flags = pdb_get_acct_ctrl(user);
+               sid_peek_rid(pdb_get_user_sid(user), &entry.rid);
+               entry.account_name = talloc_strdup(
+                       search_state, pdb_get_username(user));
+               entry.fullname = talloc_strdup(
+                       search_state, pdb_get_fullname(user));
+               entry.description = talloc_strdup(
+                       search_state, pdb_get_acct_desc(user));
+
+               TALLOC_FREE(user);
+
+               if ((entry.account_name == NULL) || (entry.fullname == NULL)
+                   || (entry.description == NULL)) {
+                       DEBUG(0, ("talloc_strdup failed\n"));
+                       break;
+               }
+
+               ADD_TO_LARGE_ARRAY(search_state, struct samr_displayentry,
+                                  entry, &search_state->entries,
+                                  &search_state->num_entries,
+                                  &search_state->array_size);
+       }
+
+       endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
+
+       search->private_data = search_state;
+       search->next_entry = smbpasswd_search_next_entry;
+       search->search_end = smbpasswd_search_end;
+
+       return true;
+}
+
 static NTSTATUS pdb_init_smbpasswd( struct pdb_methods **pdb_method, const char *location )
 {
        NTSTATUS nt_status;
@@ -1601,21 +1683,19 @@ static NTSTATUS pdb_init_smbpasswd( struct pdb_methods **pdb_method, const char
 
        (*pdb_method)->name = "smbpasswd";
 
-       (*pdb_method)->setsampwent = smbpasswd_setsampwent;
-       (*pdb_method)->endsampwent = smbpasswd_endsampwent;
-       (*pdb_method)->getsampwent = smbpasswd_getsampwent;
        (*pdb_method)->getsampwnam = smbpasswd_getsampwnam;
        (*pdb_method)->getsampwsid = smbpasswd_getsampwsid;
        (*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;
        (*pdb_method)->rename_sam_account = smbpasswd_rename_sam_account;
+       (*pdb_method)->search_users = smbpasswd_search_users;
 
-       (*pdb_method)->rid_algorithm = smbpasswd_rid_algorithm;
+       (*pdb_method)->capabilities = smbpasswd_capabilities;
 
        /* Setup private data and free function */
 
-       if ( !(privates = TALLOC_ZERO_P( *pdb_method, struct smbpasswd_privates )) ) {
+       if ( !(privates = talloc_zero( *pdb_method, struct smbpasswd_privates )) ) {
                DEBUG(0, ("talloc() failed for smbpasswd private_data!\n"));
                return NT_STATUS_NO_MEMORY;
        }
@@ -1627,7 +1707,7 @@ static NTSTATUS pdb_init_smbpasswd( struct pdb_methods **pdb_method, const char
        } else {
                privates->smbpasswd_file = talloc_strdup(*pdb_method, lp_smb_passwd_file());
        }
-       
+
        if (!privates->smbpasswd_file) {
                DEBUG(0, ("talloc_strdp() failed for storing smbpasswd location!\n"));
                return NT_STATUS_NO_MEMORY;
@@ -1640,7 +1720,7 @@ static NTSTATUS pdb_init_smbpasswd( struct pdb_methods **pdb_method, const char
        return NT_STATUS_OK;
 }
 
-NTSTATUS pdb_smbpasswd_init(void
+NTSTATUS pdb_smbpasswd_init(TALLOC_CTX *ctx
 {
        return smb_register_passdb(PASSDB_INTERFACE_VERSION, "smbpasswd", pdb_init_smbpasswd);
 }