LCOV - code coverage report
Current view: top level - source3/passdb - pdb_smbpasswd.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 44 748 5.9 %
Date: 2021-09-23 10:06:22 Functions: 4 28 14.3 %

          Line data    Source code
       1             : /*
       2             :  * Unix SMB/CIFS implementation. 
       3             :  * SMB parameters and setup
       4             :  * Copyright (C) Andrew Tridgell       1992-1998 
       5             :  * Modified by Jeremy Allison          1995.
       6             :  * Modified by Gerald (Jerry) Carter   2000-2001,2003
       7             :  * Modified by Andrew Bartlett         2002.
       8             :  * 
       9             :  * This program is free software; you can redistribute it and/or modify it under
      10             :  * the terms of the GNU General Public License as published by the Free
      11             :  * Software Foundation; either version 3 of the License, or (at your option)
      12             :  * any later version.
      13             :  * 
      14             :  * This program is distributed in the hope that it will be useful, but WITHOUT
      15             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      16             :  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
      17             :  * more details.
      18             :  * 
      19             :  * You should have received a copy of the GNU General Public License along with
      20             :  * this program; if not, see <http://www.gnu.org/licenses/>.
      21             :  */
      22             : 
      23             : #include "includes.h"
      24             : #include "passdb.h"
      25             : #include "system/passwd.h"
      26             : #include "system/filesys.h"
      27             : #include "../librpc/gen_ndr/samr.h"
      28             : #include "../libcli/security/security.h"
      29             : #include "passdb/pdb_smbpasswd.h"
      30             : #include "lib/util/string_wrappers.h"
      31             : 
      32             : #undef DBGC_CLASS
      33             : #define DBGC_CLASS DBGC_PASSDB
      34             : 
      35             : /* 
      36             :    smb_passwd is analogous to sam_passwd used everywhere
      37             :    else.  However, smb_passwd is limited to the information
      38             :    stored by an smbpasswd entry 
      39             :  */
      40             : 
      41             : struct smb_passwd
      42             : {
      43             :         uint32_t smb_userid;      /* this is actually the unix uid_t */
      44             :         const char *smb_name;     /* username string */
      45             : 
      46             :         const unsigned char *smb_passwd;    /* Null if no password */
      47             :         const unsigned char *smb_nt_passwd; /* Null if no password */
      48             : 
      49             :         uint16_t acct_ctrl;             /* account info (ACB_xxxx bit-mask) */
      50             :         time_t pass_last_set_time;    /* password last set time */
      51             : };
      52             : 
      53             : struct smbpasswd_privates
      54             : {
      55             :         /* used for maintain locks on the smbpasswd file */
      56             :         int     pw_file_lock_depth;
      57             : 
      58             :         /* Global File pointer */
      59             :         FILE    *pw_file;
      60             : 
      61             :         /* formerly static variables */
      62             :         struct smb_passwd pw_buf;
      63             :         fstring user_name;
      64             :         unsigned char smbpwd[16];
      65             :         unsigned char smbntpwd[16];
      66             : 
      67             :         /* retrieve-once info */
      68             :         const char *smbpasswd_file;
      69             : };
      70             : 
      71             : enum pwf_access_type { PWF_READ, PWF_UPDATE, PWF_CREATE };
      72             : 
      73             : static SIG_ATOMIC_T gotalarm;
      74             : 
      75             : /***************************************************************
      76             :  Signal function to tell us we timed out.
      77             : ****************************************************************/
      78             : 
      79           0 : static void gotalarm_sig(int signum)
      80             : {
      81           0 :         gotalarm = 1;
      82           0 : }
      83             : 
      84             : /***************************************************************
      85             :  Lock or unlock a fd for a known lock type. Abandon after waitsecs 
      86             :  seconds.
      87             : ****************************************************************/
      88             : 
      89           0 : static bool do_file_lock(int fd, int waitsecs, int type)
      90             : {
      91             :         struct flock lock;
      92             :         int             ret;
      93             :         void (*oldsig_handler)(int);
      94             : 
      95           0 :         gotalarm = 0;
      96           0 :         oldsig_handler = CatchSignal(SIGALRM, gotalarm_sig);
      97             : 
      98           0 :         lock.l_type = type;
      99           0 :         lock.l_whence = SEEK_SET;
     100           0 :         lock.l_start = 0;
     101           0 :         lock.l_len = 1;
     102           0 :         lock.l_pid = 0;
     103             : 
     104           0 :         alarm(waitsecs);
     105             :         /* Note we must *NOT* use sys_fcntl here ! JRA */
     106           0 :         ret = fcntl(fd, F_SETLKW, &lock);
     107           0 :         alarm(0);
     108           0 :         CatchSignal(SIGALRM, oldsig_handler);
     109             : 
     110           0 :         if (gotalarm && ret == -1) {
     111           0 :                 DEBUG(0, ("do_file_lock: failed to %s file.\n",
     112             :                         type == F_UNLCK ? "unlock" : "lock"));
     113           0 :                 return False;
     114             :         }
     115             : 
     116           0 :         return (ret == 0);
     117             : }
     118             : 
     119             : /***************************************************************
     120             :  Lock an fd. Abandon after waitsecs seconds.
     121             : ****************************************************************/
     122             : 
     123           0 : static bool pw_file_lock(int fd, int type, int secs, int *plock_depth)
     124             : {
     125           0 :         if (fd < 0) {
     126           0 :                 return False;
     127             :         }
     128             : 
     129           0 :         if(*plock_depth == 0) {
     130           0 :                 if (!do_file_lock(fd, secs, type)) {
     131           0 :                         DEBUG(10,("pw_file_lock: locking file failed, error = %s.\n",
     132             :                                 strerror(errno)));
     133           0 :                         return False;
     134             :                 }
     135             :         }
     136             : 
     137           0 :         (*plock_depth)++;
     138             : 
     139           0 :         return True;
     140             : }
     141             : 
     142             : /***************************************************************
     143             :  Unlock an fd. Abandon after waitsecs seconds.
     144             : ****************************************************************/
     145             : 
     146           0 : static bool pw_file_unlock(int fd, int *plock_depth)
     147             : {
     148           0 :         bool ret=True;
     149             : 
     150           0 :         if (fd == 0 || *plock_depth == 0) {
     151           0 :                 return True;
     152             :         }
     153             : 
     154           0 :         if(*plock_depth == 1) {
     155           0 :                 ret = do_file_lock(fd, 5, F_UNLCK);
     156             :         }
     157             : 
     158           0 :         if (*plock_depth > 0) {
     159           0 :                 (*plock_depth)--;
     160             :         }
     161             : 
     162           0 :         if(!ret) {
     163           0 :                 DEBUG(10,("pw_file_unlock: unlocking file failed, error = %s.\n",
     164             :                         strerror(errno)));
     165             :         }
     166           0 :         return ret;
     167             : }
     168             : 
     169             : /**************************************************************
     170             :  Intialize a smb_passwd struct
     171             :  *************************************************************/
     172             : 
     173           0 : static void pdb_init_smb(struct smb_passwd *user)
     174             : {
     175           0 :         if (user == NULL) 
     176           0 :                 return;
     177           0 :         ZERO_STRUCTP (user);
     178             : 
     179           0 :         user->pass_last_set_time = (time_t)0;
     180             : }
     181             : 
     182             : /***************************************************************
     183             :  Internal fn to enumerate the smbpasswd list. Returns a void pointer
     184             :  to ensure no modification outside this module. Checks for atomic
     185             :  rename of smbpasswd file on update or create once the lock has
     186             :  been granted to prevent race conditions. JRA.
     187             : ****************************************************************/
     188             : 
     189           3 : static FILE *startsmbfilepwent(const char *pfile, enum pwf_access_type type, int *lock_depth)
     190             : {
     191           3 :         FILE *fp = NULL;
     192           3 :         const char *open_mode = NULL;
     193           3 :         int race_loop = 0;
     194           3 :         int lock_type = F_RDLCK;
     195             : 
     196           3 :         if (!*pfile) {
     197           0 :                 DEBUG(0, ("startsmbfilepwent: No SMB password file set\n"));
     198           0 :                 return (NULL);
     199             :         }
     200             : 
     201           3 :         switch(type) {
     202           0 :                 case PWF_READ:
     203           0 :                         open_mode = "rb";
     204           0 :                         lock_type = F_RDLCK;
     205           0 :                         break;
     206           0 :                 case PWF_UPDATE:
     207           0 :                         open_mode = "r+b";
     208           0 :                         lock_type = F_WRLCK;
     209           0 :                         break;
     210           0 :                 case PWF_CREATE:
     211             :                         /*
     212             :                          * Ensure atomic file creation.
     213             :                          */
     214             :                         {
     215           0 :                                 int i, fd = -1;
     216             : 
     217           0 :                                 for(i = 0; i < 5; i++) {
     218           0 :                                         if((fd = open(pfile, O_CREAT|O_TRUNC|O_EXCL|O_RDWR, 0600))!=-1) {
     219           0 :                                                 break;
     220             :                                         }
     221           0 :                                         usleep(200); /* Spin, spin... */
     222             :                                 }
     223           0 :                                 if(fd == -1) {
     224           0 :                                         DEBUG(0,("startsmbfilepwent_internal: too many race conditions \
     225             : creating file %s\n", pfile));
     226           0 :                                         return NULL;
     227             :                                 }
     228           0 :                                 close(fd);
     229           0 :                                 open_mode = "r+b";
     230           0 :                                 lock_type = F_WRLCK;
     231           0 :                                 break;
     232             :                         }
     233           0 :                 default:
     234           0 :                         DEBUG(10, ("Invalid open mode: %d\n", type));
     235           0 :                         return NULL;
     236             :         }
     237             : 
     238           6 :         for(race_loop = 0; race_loop < 5; race_loop++) {
     239           3 :                 DEBUG(10, ("startsmbfilepwent_internal: opening file %s\n", pfile));
     240             : 
     241           3 :                 if((fp = fopen(pfile, open_mode)) == NULL) {
     242             : 
     243             :                         /*
     244             :                          * If smbpasswd file doesn't exist, then create new one. This helps to avoid
     245             :                          * confusing error msg when adding user account first time.
     246             :                          */
     247           3 :                         if (errno == ENOENT) {
     248           3 :                                 if ((fp = fopen(pfile, "a+")) != NULL) {
     249           0 :                                         DEBUG(0, ("startsmbfilepwent_internal: file %s did not \
     250             : exist. File successfully created.\n", pfile));
     251             :                                 } else {
     252           3 :                                         DEBUG(0, ("startsmbfilepwent_internal: file %s did not \
     253             : exist. Couldn't create new one. Error was: %s",
     254             :                                         pfile, strerror(errno)));
     255           0 :                                         return NULL;
     256             :                                 }
     257             :                         } else {
     258           0 :                                 DEBUG(0, ("startsmbfilepwent_internal: unable to open file %s. \
     259             : Error was: %s\n", pfile, strerror(errno)));
     260           0 :                                 return NULL;
     261             :                         }
     262             :                 }
     263             : 
     264           0 :                 if (!pw_file_lock(fileno(fp), lock_type, 5, lock_depth)) {
     265           0 :                         DEBUG(0, ("startsmbfilepwent_internal: unable to lock file %s. \
     266             : Error was %s\n", pfile, strerror(errno) ));
     267           0 :                         fclose(fp);
     268           0 :                         return NULL;
     269             :                 }
     270             : 
     271             :                 /*
     272             :                  * Only check for replacement races on update or create.
     273             :                  * For read we don't mind if the data is one record out of date.
     274             :                  */
     275             : 
     276           0 :                 if(type == PWF_READ) {
     277           0 :                         break;
     278             :                 } else {
     279             :                         SMB_STRUCT_STAT sbuf1, sbuf2;
     280             : 
     281             :                         /*
     282             :                          * Avoid the potential race condition between the open and the lock
     283             :                          * by doing a stat on the filename and an fstat on the fd. If the
     284             :                          * two inodes differ then someone did a rename between the open and
     285             :                          * the lock. Back off and try the open again. Only do this 5 times to
     286             :                          * prevent infinate loops. JRA.
     287             :                          */
     288             : 
     289           0 :                         if (sys_stat(pfile, &sbuf1, false) != 0) {
     290           0 :                                 DEBUG(0, ("startsmbfilepwent_internal: unable to stat file %s. \
     291             : Error was %s\n", pfile, strerror(errno)));
     292           0 :                                 pw_file_unlock(fileno(fp), lock_depth);
     293           0 :                                 fclose(fp);
     294           0 :                                 return NULL;
     295             :                         }
     296             : 
     297           0 :                         if (sys_fstat(fileno(fp), &sbuf2, false) != 0) {
     298           0 :                                 DEBUG(0, ("startsmbfilepwent_internal: unable to fstat file %s. \
     299             : Error was %s\n", pfile, strerror(errno)));
     300           0 :                                 pw_file_unlock(fileno(fp), lock_depth);
     301           0 :                                 fclose(fp);
     302           0 :                                 return NULL;
     303             :                         }
     304             : 
     305           0 :                         if( sbuf1.st_ex_ino == sbuf2.st_ex_ino) {
     306             :                                 /* No race. */
     307           0 :                                 break;
     308             :                         }
     309             : 
     310             :                         /*
     311             :                          * Race occurred - back off and try again...
     312             :                          */
     313             : 
     314           0 :                         pw_file_unlock(fileno(fp), lock_depth);
     315           0 :                         fclose(fp);
     316             :                 }
     317             :         }
     318             : 
     319           0 :         if(race_loop == 5) {
     320           0 :                 DEBUG(0, ("startsmbfilepwent_internal: too many race conditions opening file %s\n", pfile));
     321           0 :                 return NULL;
     322             :         }
     323             : 
     324             :         /* Set a buffer to do more efficient reads */
     325           0 :         setvbuf(fp, (char *)NULL, _IOFBF, 1024);
     326             : 
     327             :         /* Make sure it is only rw by the owner */
     328             : #ifdef HAVE_FCHMOD
     329           0 :         if(fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1) {
     330             : #else
     331             :         if(chmod(pfile, S_IRUSR|S_IWUSR) == -1) {
     332             : #endif
     333           0 :                 DEBUG(0, ("startsmbfilepwent_internal: failed to set 0600 permissions on password file %s. \
     334             : Error was %s\n.", pfile, strerror(errno) ));
     335           0 :                 pw_file_unlock(fileno(fp), lock_depth);
     336           0 :                 fclose(fp);
     337           0 :                 return NULL;
     338             :         }
     339             : 
     340             :         /* We have a lock on the file. */
     341           0 :         return fp;
     342             : }
     343             : 
     344             : /***************************************************************
     345             :  End enumeration of the smbpasswd list.
     346             : ****************************************************************/
     347             : 
     348           0 : static void endsmbfilepwent(FILE *fp, int *lock_depth)
     349             : {
     350           0 :         if (!fp) {
     351           0 :                 return;
     352             :         }
     353             : 
     354           0 :         pw_file_unlock(fileno(fp), lock_depth);
     355           0 :         fclose(fp);
     356           0 :         DEBUG(7, ("endsmbfilepwent_internal: closed password file.\n"));
     357             : }
     358             : 
     359             : /*************************************************************************
     360             :  Routine to return the next entry in the smbpasswd list.
     361             :  *************************************************************************/
     362             : 
     363           0 : static struct smb_passwd *getsmbfilepwent(struct smbpasswd_privates *smbpasswd_state, FILE *fp)
     364             : {
     365             :         /* Static buffers we will return. */
     366           0 :         struct smb_passwd *pw_buf = &smbpasswd_state->pw_buf;
     367           0 :         char  *user_name = smbpasswd_state->user_name;
     368           0 :         unsigned char *smbpwd = smbpasswd_state->smbpwd;
     369           0 :         unsigned char *smbntpwd = smbpasswd_state->smbntpwd;
     370             :         char linebuf[256];
     371             :         unsigned char *p;
     372             :         long uidval;
     373             :         size_t linebuf_len;
     374             :         char *status;
     375             : 
     376           0 :         if(fp == NULL) {
     377           0 :                 DEBUG(0,("getsmbfilepwent: Bad password file pointer.\n"));
     378           0 :                 return NULL;
     379             :         }
     380             : 
     381           0 :         pdb_init_smb(pw_buf);
     382           0 :         pw_buf->acct_ctrl = ACB_NORMAL;  
     383             : 
     384             :         /*
     385             :          * Scan the file, a line at a time and check if the name matches.
     386             :          */
     387           0 :         status = linebuf;
     388           0 :         while (status && !feof(fp)) {
     389           0 :                 linebuf[0] = '\0';
     390             : 
     391           0 :                 status = fgets(linebuf, 256, fp);
     392           0 :                 if (status == NULL && ferror(fp)) {
     393           0 :                         return NULL;
     394             :                 }
     395             : 
     396             :                 /*
     397             :                  * Check if the string is terminated with a newline - if not
     398             :                  * then we must keep reading and discard until we get one.
     399             :                  */
     400           0 :                 if ((linebuf_len = strlen(linebuf)) == 0) {
     401           0 :                         continue;
     402             :                 }
     403             : 
     404           0 :                 if (linebuf[linebuf_len - 1] != '\n') {
     405           0 :                         while (!ferror(fp) && !feof(fp)) {
     406             :                                 int c;
     407           0 :                                 c = fgetc(fp);
     408           0 :                                 if (c == '\n') {
     409           0 :                                         break;
     410             :                                 }
     411             :                         }
     412             :                 } else {
     413           0 :                         linebuf[linebuf_len - 1] = '\0';
     414             :                 }
     415             : 
     416             : #ifdef DEBUG_PASSWORD
     417           0 :                 DEBUG(100, ("getsmbfilepwent: got line |%s|\n", linebuf));
     418             : #endif
     419           0 :                 if ((linebuf[0] == 0) && feof(fp)) {
     420           0 :                         DEBUG(4, ("getsmbfilepwent: end of file reached\n"));
     421           0 :                         break;
     422             :                 }
     423             : 
     424             :                 /*
     425             :                  * The line we have should be of the form :-
     426             :                  * 
     427             :                  * username:uid:32hex bytes:[Account type]:LCT-12345678....other flags presently
     428             :                  * ignored....
     429             :                  * 
     430             :                  * or,
     431             :                  *
     432             :                  * username:uid:32hex bytes:32hex bytes:[Account type]:LCT-12345678....ignored....
     433             :                  *
     434             :                  * if Windows NT compatible passwords are also present.
     435             :                  * [Account type] is an ascii encoding of the type of account.
     436             :                  * LCT-(8 hex digits) is the time_t value of the last change time.
     437             :                  */
     438             : 
     439           0 :                 if (linebuf[0] == '#' || linebuf[0] == '\0') {
     440           0 :                         DEBUG(6, ("getsmbfilepwent: skipping comment or blank line\n"));
     441           0 :                         continue;
     442             :                 }
     443           0 :                 p = (unsigned char *) strchr_m(linebuf, ':');
     444           0 :                 if (p == NULL) {
     445           0 :                         DEBUG(0, ("getsmbfilepwent: malformed password entry (no :)\n"));
     446           0 :                         continue;
     447             :                 }
     448             : 
     449           0 :                 strncpy(user_name, linebuf, PTR_DIFF(p, linebuf));
     450           0 :                 user_name[PTR_DIFF(p, linebuf)] = '\0';
     451             : 
     452             :                 /* Get smb uid. */
     453             : 
     454           0 :                 p++; /* Go past ':' */
     455             : 
     456           0 :                 if(*p == '-') {
     457           0 :                         DEBUG(0, ("getsmbfilepwent: user name %s has a negative uid.\n", user_name));
     458           0 :                         continue;
     459             :                 }
     460             : 
     461           0 :                 if (!isdigit(*p)) {
     462           0 :                         DEBUG(0, ("getsmbfilepwent: malformed password entry for user %s (uid not number)\n",
     463             :                                 user_name));
     464           0 :                         continue;
     465             :                 }
     466             : 
     467           0 :                 uidval = atoi((char *) p);
     468             : 
     469           0 :                 while (*p && isdigit(*p)) {
     470           0 :                         p++;
     471             :                 }
     472             : 
     473           0 :                 if (*p != ':') {
     474           0 :                         DEBUG(0, ("getsmbfilepwent: malformed password entry for user %s (no : after uid)\n",
     475             :                                 user_name));
     476           0 :                         continue;
     477             :                 }
     478             : 
     479           0 :                 pw_buf->smb_name = user_name;
     480           0 :                 pw_buf->smb_userid = uidval;
     481             : 
     482             :                 /*
     483             :                  * Now get the password value - this should be 32 hex digits
     484             :                  * which are the ascii representations of a 16 byte string.
     485             :                  * Get two at a time and put them into the password.
     486             :                  */
     487             : 
     488             :                 /* Skip the ':' */
     489           0 :                 p++;
     490             : 
     491           0 :                 if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
     492           0 :                         DEBUG(0, ("getsmbfilepwent: malformed password entry for user %s (passwd too short)\n",
     493             :                                 user_name ));
     494           0 :                         continue;
     495             :                 }
     496             : 
     497           0 :                 if (p[32] != ':') {
     498           0 :                         DEBUG(0, ("getsmbfilepwent: malformed password entry for user %s (no terminating :)\n",
     499             :                                 user_name));
     500           0 :                         continue;
     501             :                 }
     502             : 
     503           0 :                 if (strnequal((char *) p, "NO PASSWORD", 11)) {
     504           0 :                         pw_buf->smb_passwd = NULL;
     505           0 :                         pw_buf->acct_ctrl |= ACB_PWNOTREQ;
     506             :                 } else {
     507           0 :                         if (*p == '*' || *p == 'X') {
     508             :                                 /* NULL LM password */
     509           0 :                                 pw_buf->smb_passwd = NULL;
     510           0 :                                 DEBUG(10, ("getsmbfilepwent: LM password for user %s invalidated\n", user_name));
     511           0 :                         } else if (pdb_gethexpwd((char *)p, smbpwd)) {
     512           0 :                                 pw_buf->smb_passwd = smbpwd;
     513             :                         } else {
     514           0 :                                 pw_buf->smb_passwd = NULL;
     515           0 :                                 DEBUG(0, ("getsmbfilepwent: Malformed Lanman password entry for user %s \
     516             : (non hex chars)\n", user_name));
     517             :                         }
     518             :                 }
     519             : 
     520             :                 /* 
     521             :                  * Now check if the NT compatible password is
     522             :                  * available.
     523             :                  */
     524           0 :                 pw_buf->smb_nt_passwd = NULL;
     525           0 :                 p += 33; /* Move to the first character of the line after the lanman password. */
     526           0 :                 if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) {
     527           0 :                         if (*p != '*' && *p != 'X') {
     528           0 :                                 if(pdb_gethexpwd((char *)p,smbntpwd)) {
     529           0 :                                         pw_buf->smb_nt_passwd = smbntpwd;
     530             :                                 }
     531             :                         }
     532           0 :                         p += 33; /* Move to the first character of the line after the NT password. */
     533             :                 }
     534             : 
     535           0 :                 DEBUG(5,("getsmbfilepwent: returning passwd entry for user %s, uid %ld\n",
     536             :                         user_name, uidval));
     537             : 
     538           0 :                 if (*p == '[') {
     539           0 :                         unsigned char *end_p = (unsigned char *)strchr_m((char *)p, ']');
     540           0 :                         pw_buf->acct_ctrl = pdb_decode_acct_ctrl((char*)p);
     541             : 
     542             :                         /* Must have some account type set. */
     543           0 :                         if(pw_buf->acct_ctrl == 0) {
     544           0 :                                 pw_buf->acct_ctrl = ACB_NORMAL;
     545             :                         }
     546             : 
     547             :                         /* Now try and get the last change time. */
     548           0 :                         if(end_p) {
     549           0 :                                 p = end_p + 1;
     550             :                         }
     551           0 :                         if(*p == ':') {
     552           0 :                                 p++;
     553           0 :                                 if(*p && (strncasecmp_m((char *)p, "LCT-", 4)==0)) {
     554             :                                         int i;
     555           0 :                                         p += 4;
     556           0 :                                         for(i = 0; i < 8; i++) {
     557           0 :                                                 if(p[i] == '\0' || !isxdigit(p[i])) {
     558             :                                                         break;
     559             :                                                 }
     560             :                                         }
     561           0 :                                         if(i == 8) {
     562             :                                                 /*
     563             :                                                  * p points at 8 characters of hex digits - 
     564             :                                                  * read into a time_t as the seconds since
     565             :                                                  * 1970 that the password was last changed.
     566             :                                                  */
     567           0 :                                                 pw_buf->pass_last_set_time = (time_t)strtol((char *)p, NULL, 16);
     568             :                                         }
     569             :                                 }
     570             :                         }
     571             :                 } else {
     572             :                         /* 'Old' style file. Fake up based on user name. */
     573             :                         /*
     574             :                          * Currently trust accounts are kept in the same
     575             :                          * password file as 'normal accounts'. If this changes
     576             :                          * we will have to fix this code. JRA.
     577             :                          */
     578           0 :                         if(pw_buf->smb_name[strlen(pw_buf->smb_name) - 1] == '$') {
     579           0 :                                 pw_buf->acct_ctrl &= ~ACB_NORMAL;
     580           0 :                                 pw_buf->acct_ctrl |= ACB_WSTRUST;
     581             :                         }
     582             :                 }
     583             : 
     584           0 :                 return pw_buf;
     585             :         }
     586             : 
     587           0 :         DEBUG(5,("getsmbfilepwent: end of file reached.\n"));
     588           0 :         return NULL;
     589             : }
     590             : 
     591             : /************************************************************************
     592             :  Create a new smbpasswd entry - malloced space returned.
     593             : *************************************************************************/
     594             : 
     595           0 : static char *format_new_smbpasswd_entry(const struct smb_passwd *newpwd)
     596             : {
     597             :         int new_entry_length;
     598             :         char *new_entry;
     599             :         char *p;
     600             : 
     601           0 :         new_entry_length = strlen(newpwd->smb_name) + 1 + 15 + 1 + 32 + 1 + 32 + 1 + 
     602           0 :                                 NEW_PW_FORMAT_SPACE_PADDED_LEN + 1 + 13 + 2;
     603             : 
     604           0 :         if((new_entry = (char *)SMB_MALLOC( new_entry_length )) == NULL) {
     605           0 :                 DEBUG(0, ("format_new_smbpasswd_entry: Malloc failed adding entry for user %s.\n",
     606             :                         newpwd->smb_name ));
     607           0 :                 return NULL;
     608             :         }
     609             : 
     610           0 :         slprintf(new_entry, new_entry_length - 1, "%s:%u:", newpwd->smb_name, (unsigned)newpwd->smb_userid);
     611             : 
     612           0 :         p = new_entry+strlen(new_entry);
     613           0 :         pdb_sethexpwd(p, newpwd->smb_passwd, newpwd->acct_ctrl);
     614           0 :         p+=strlen(p);
     615           0 :         *p = ':';
     616           0 :         p++;
     617             : 
     618           0 :         pdb_sethexpwd(p, newpwd->smb_nt_passwd, newpwd->acct_ctrl);
     619           0 :         p+=strlen(p);
     620           0 :         *p = ':';
     621           0 :         p++;
     622             : 
     623             :         /* Add the account encoding and the last change time. */
     624           0 :         slprintf((char *)p, new_entry_length - 1 - (p - new_entry),  "%s:LCT-%08X:\n",
     625           0 :                 pdb_encode_acct_ctrl(newpwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN),
     626           0 :                 (uint32_t)newpwd->pass_last_set_time);
     627             : 
     628           0 :         return new_entry;
     629             : }
     630             : 
     631             : /************************************************************************
     632             :  Routine to add an entry to the smbpasswd file.
     633             : *************************************************************************/
     634             : 
     635           0 : static NTSTATUS add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state,
     636             :                                      struct smb_passwd *newpwd)
     637             : {
     638           0 :         const char *pfile = smbpasswd_state->smbpasswd_file;
     639           0 :         struct smb_passwd *pwd = NULL;
     640           0 :         FILE *fp = NULL;
     641             :         int wr_len;
     642             :         int fd;
     643             :         size_t new_entry_length;
     644             :         char *new_entry;
     645             :         off_t offpos;
     646             :  
     647             :         /* Open the smbpassword file - for update. */
     648           0 :         fp = startsmbfilepwent(pfile, PWF_UPDATE, &smbpasswd_state->pw_file_lock_depth);
     649             : 
     650           0 :         if (fp == NULL && errno == ENOENT) {
     651             :                 /* Try again - create. */
     652           0 :                 fp = startsmbfilepwent(pfile, PWF_CREATE, &smbpasswd_state->pw_file_lock_depth);
     653             :         }
     654             : 
     655           0 :         if (fp == NULL) {
     656           0 :                 DEBUG(0, ("add_smbfilepwd_entry: unable to open file.\n"));
     657           0 :                 return map_nt_error_from_unix(errno);
     658             :         }
     659             : 
     660             :         /*
     661             :          * Scan the file, a line at a time and check if the name matches.
     662             :          */
     663             : 
     664           0 :         while ((pwd = getsmbfilepwent(smbpasswd_state, fp)) != NULL) {
     665           0 :                 if (strequal(newpwd->smb_name, pwd->smb_name)) {
     666           0 :                         DEBUG(0, ("add_smbfilepwd_entry: entry with name %s already exists\n", pwd->smb_name));
     667           0 :                         endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
     668           0 :                         return NT_STATUS_USER_EXISTS;
     669             :                 }
     670             :         }
     671             : 
     672             :         /* Ok - entry doesn't exist. We can add it */
     673             : 
     674             :         /* Create a new smb passwd entry and set it to the given password. */
     675             :         /* 
     676             :          * The add user write needs to be atomic - so get the fd from 
     677             :          * the fp and do a raw write() call.
     678             :          */
     679           0 :         fd = fileno(fp);
     680             : 
     681           0 :         if((offpos = lseek(fd, 0, SEEK_END)) == -1) {
     682           0 :                 NTSTATUS result = map_nt_error_from_unix(errno);
     683           0 :                 DEBUG(0, ("add_smbfilepwd_entry(lseek): Failed to add entry for user %s to file %s. \
     684             : Error was %s\n", newpwd->smb_name, pfile, strerror(errno)));
     685           0 :                 endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
     686           0 :                 return result;
     687             :         }
     688             : 
     689           0 :         if((new_entry = format_new_smbpasswd_entry(newpwd)) == NULL) {
     690           0 :                 DEBUG(0, ("add_smbfilepwd_entry(malloc): Failed to add entry for user %s to file %s. \
     691             : Error was %s\n", newpwd->smb_name, pfile, strerror(errno)));
     692           0 :                 endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
     693           0 :                 return NT_STATUS_NO_MEMORY;
     694             :         }
     695             : 
     696           0 :         new_entry_length = strlen(new_entry);
     697             : 
     698             : #ifdef DEBUG_PASSWORD
     699           0 :         DEBUG(100, ("add_smbfilepwd_entry(%d): new_entry_len %d made line |%s|", 
     700             :                         fd, (int)new_entry_length, new_entry));
     701             : #endif
     702             : 
     703           0 :         if ((wr_len = write(fd, new_entry, new_entry_length)) != new_entry_length) {
     704           0 :                 NTSTATUS result = map_nt_error_from_unix(errno);
     705           0 :                 DEBUG(0, ("add_smbfilepwd_entry(write): %d Failed to add entry for user %s to file %s. \
     706             : Error was %s\n", wr_len, newpwd->smb_name, pfile, strerror(errno)));
     707             : 
     708             :                 /* Remove the entry we just wrote. */
     709           0 :                 if(ftruncate(fd, offpos) == -1) {
     710           0 :                         DEBUG(0, ("add_smbfilepwd_entry: ERROR failed to ftruncate file %s. \
     711             : Error was %s. Password file may be corrupt ! Please examine by hand !\n", 
     712             :                                 newpwd->smb_name, strerror(errno)));
     713             :                 }
     714             : 
     715           0 :                 endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
     716           0 :                 free(new_entry);
     717           0 :                 return result;
     718             :         }
     719             : 
     720           0 :         free(new_entry);
     721           0 :         endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
     722           0 :         return NT_STATUS_OK;
     723             : }
     724             : 
     725             : /************************************************************************
     726             :  Routine to search the smbpasswd file for an entry matching the username.
     727             :  and then modify its password entry. We can't use the startsmbpwent()/
     728             :  getsmbpwent()/endsmbpwent() interfaces here as we depend on looking
     729             :  in the actual file to decide how much room we have to write data.
     730             :  override = False, normal
     731             :  override = True, override XXXXXXXX'd out password or NO PASS
     732             : ************************************************************************/
     733             : 
     734           0 : static bool mod_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, const struct smb_passwd* pwd)
     735             : {
     736             :         /* Static buffers we will return. */
     737             :         fstring user_name;
     738             : 
     739             :         char *status;
     740             : #define LINEBUF_SIZE 255
     741             :         char linebuf[LINEBUF_SIZE + 1];
     742             :         char readbuf[1024];
     743             :         char ascii_p16[FSTRING_LEN + 20];
     744             :         fstring encode_bits;
     745           0 :         unsigned char *p = NULL;
     746           0 :         size_t linebuf_len = 0;
     747             :         FILE *fp;
     748             :         int lockfd;
     749           0 :         const char *pfile = smbpasswd_state->smbpasswd_file;
     750           0 :         bool found_entry = False;
     751           0 :         bool got_pass_last_set_time = False;
     752             : 
     753           0 :         off_t pwd_seekpos = 0;
     754             : 
     755             :         int i;
     756             :         int wr_len;
     757             :         int fd;
     758             : 
     759           0 :         if (!*pfile) {
     760           0 :                 DEBUG(0, ("No SMB password file set\n"));
     761           0 :                 return False;
     762             :         }
     763           0 :         DEBUG(10, ("mod_smbfilepwd_entry: opening file %s\n", pfile));
     764             : 
     765           0 :         fp = fopen(pfile, "r+");
     766             : 
     767           0 :         if (fp == NULL) {
     768           0 :                 DEBUG(0, ("mod_smbfilepwd_entry: unable to open file %s\n", pfile));
     769           0 :                 return False;
     770             :         }
     771             :         /* Set a buffer to do more efficient reads */
     772           0 :         setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf));
     773             : 
     774           0 :         lockfd = fileno(fp);
     775             : 
     776           0 :         if (!pw_file_lock(lockfd, F_WRLCK, 5, &smbpasswd_state->pw_file_lock_depth)) {
     777           0 :                 DEBUG(0, ("mod_smbfilepwd_entry: unable to lock file %s\n", pfile));
     778           0 :                 fclose(fp);
     779           0 :                 return False;
     780             :         }
     781             : 
     782             :         /* Make sure it is only rw by the owner */
     783           0 :         chmod(pfile, 0600);
     784             : 
     785             :         /* We have a write lock on the file. */
     786             :         /*
     787             :          * Scan the file, a line at a time and check if the name matches.
     788             :          */
     789           0 :         status = linebuf;
     790           0 :         while (status && !feof(fp)) {
     791           0 :                 pwd_seekpos = ftell(fp);
     792             : 
     793           0 :                 linebuf[0] = '\0';
     794             : 
     795           0 :                 status = fgets(linebuf, LINEBUF_SIZE, fp);
     796           0 :                 if (status == NULL && ferror(fp)) {
     797           0 :                         pw_file_unlock(lockfd, &smbpasswd_state->pw_file_lock_depth);
     798           0 :                         fclose(fp);
     799           0 :                         return False;
     800             :                 }
     801             : 
     802             :                 /*
     803             :                  * Check if the string is terminated with a newline - if not
     804             :                  * then we must keep reading and discard until we get one.
     805             :                  */
     806           0 :                 linebuf_len = strlen(linebuf);
     807           0 :                 if (linebuf[linebuf_len - 1] != '\n') {
     808           0 :                         while (!ferror(fp) && !feof(fp)) {
     809             :                                 int c;
     810           0 :                                 c = fgetc(fp);
     811           0 :                                 if (c == '\n') {
     812           0 :                                         break;
     813             :                                 }
     814             :                         }
     815             :                 } else {
     816           0 :                         linebuf[linebuf_len - 1] = '\0';
     817             :                 }
     818             : 
     819             : #ifdef DEBUG_PASSWORD
     820           0 :                 DEBUG(100, ("mod_smbfilepwd_entry: got line |%s|\n", linebuf));
     821             : #endif
     822             : 
     823           0 :                 if ((linebuf[0] == 0) && feof(fp)) {
     824           0 :                         DEBUG(4, ("mod_smbfilepwd_entry: end of file reached\n"));
     825           0 :                         break;
     826             :                 }
     827             : 
     828             :                 /*
     829             :                  * The line we have should be of the form :-
     830             :                  * 
     831             :                  * username:uid:[32hex bytes]:....other flags presently
     832             :                  * ignored....
     833             :                  * 
     834             :                  * or,
     835             :                  *
     836             :                  * username:uid:[32hex bytes]:[32hex bytes]:[attributes]:LCT-XXXXXXXX:...ignored.
     837             :                  *
     838             :                  * if Windows NT compatible passwords are also present.
     839             :                  */
     840             : 
     841           0 :                 if (linebuf[0] == '#' || linebuf[0] == '\0') {
     842           0 :                         DEBUG(6, ("mod_smbfilepwd_entry: skipping comment or blank line\n"));
     843           0 :                         continue;
     844             :                 }
     845             : 
     846           0 :                 p = (unsigned char *) strchr_m(linebuf, ':');
     847             : 
     848           0 :                 if (p == NULL) {
     849           0 :                         DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no :)\n"));
     850           0 :                         continue;
     851             :                 }
     852             : 
     853           0 :                 strncpy(user_name, linebuf, PTR_DIFF(p, linebuf));
     854           0 :                 user_name[PTR_DIFF(p, linebuf)] = '\0';
     855           0 :                 if (strequal(user_name, pwd->smb_name)) {
     856           0 :                         found_entry = True;
     857           0 :                         break;
     858             :                 }
     859             :         }
     860             : 
     861           0 :         if (!found_entry) {
     862           0 :                 pw_file_unlock(lockfd, &smbpasswd_state->pw_file_lock_depth);
     863           0 :                 fclose(fp);
     864             : 
     865           0 :                 DEBUG(2, ("Cannot update entry for user %s, as they don't exist in the smbpasswd file!\n",
     866             :                         pwd->smb_name));
     867           0 :                 return False;
     868             :         }
     869             : 
     870           0 :         DEBUG(6, ("mod_smbfilepwd_entry: entry exists for user %s\n", pwd->smb_name));
     871             : 
     872             :         /* User name matches - get uid and password */
     873           0 :         p++; /* Go past ':' */
     874             : 
     875           0 :         if (!isdigit(*p)) {
     876           0 :                 DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry for user %s (uid not number)\n",
     877             :                         pwd->smb_name));
     878           0 :                 pw_file_unlock(lockfd, &smbpasswd_state->pw_file_lock_depth);
     879           0 :                 fclose(fp);
     880           0 :                 return False;
     881             :         }
     882             : 
     883           0 :         while (*p && isdigit(*p)) {
     884           0 :                 p++;
     885             :         }
     886           0 :         if (*p != ':') {
     887           0 :                 DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry for user %s (no : after uid)\n",
     888             :                         pwd->smb_name));
     889           0 :                 pw_file_unlock(lockfd, &smbpasswd_state->pw_file_lock_depth);
     890           0 :                 fclose(fp);
     891           0 :                 return False;
     892             :         }
     893             : 
     894             :         /*
     895             :          * Now get the password value - this should be 32 hex digits
     896             :          * which are the ascii representations of a 16 byte string.
     897             :          * Get two at a time and put them into the password.
     898             :          */
     899           0 :         p++;
     900             : 
     901             :         /* Record exact password position */
     902           0 :         pwd_seekpos += PTR_DIFF(p, linebuf);
     903             : 
     904           0 :         if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
     905           0 :                 DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry for user %s (passwd too short)\n",
     906             :                         pwd->smb_name));
     907           0 :                 pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
     908           0 :                 fclose(fp);
     909           0 :                 return (False);
     910             :         }
     911             : 
     912           0 :         if (p[32] != ':') {
     913           0 :                 DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry for user %s (no terminating :)\n",
     914             :                         pwd->smb_name));
     915           0 :                 pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
     916           0 :                 fclose(fp);
     917           0 :                 return False;
     918             :         }
     919             : 
     920             :         /* Now check if the NT compatible password is available. */
     921           0 :         p += 33; /* Move to the first character of the line after the lanman password. */
     922           0 :         if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
     923           0 :                 DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry for user %s (passwd too short)\n",
     924             :                         pwd->smb_name));
     925           0 :                 pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
     926           0 :                 fclose(fp);
     927           0 :                 return (False);
     928             :         }
     929             : 
     930           0 :         if (p[32] != ':') {
     931           0 :                 DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry for user %s (no terminating :)\n",
     932             :                         pwd->smb_name));
     933           0 :                 pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
     934           0 :                 fclose(fp);
     935           0 :                 return False;
     936             :         }
     937             : 
     938             :         /* 
     939             :          * Now check if the account info and the password last
     940             :          * change time is available.
     941             :          */
     942           0 :         p += 33; /* Move to the first character of the line after the NT password. */
     943             : 
     944           0 :         if (*p == '[') {
     945           0 :                 i = 0;
     946           0 :                 encode_bits[i++] = *p++;
     947           0 :                 while((linebuf_len > PTR_DIFF(p, linebuf)) && (*p != ']')) {
     948           0 :                         encode_bits[i++] = *p++;
     949             :                 }
     950             : 
     951           0 :                 encode_bits[i++] = ']';
     952           0 :                 encode_bits[i++] = '\0';
     953             : 
     954           0 :                 if(i == NEW_PW_FORMAT_SPACE_PADDED_LEN) {
     955             :                         /*
     956             :                          * We are using a new format, space padded
     957             :                          * acct ctrl field. Encode the given acct ctrl
     958             :                          * bits into it.
     959             :                          */
     960           0 :                         fstrcpy(encode_bits, pdb_encode_acct_ctrl(pwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN));
     961             :                 } else {
     962           0 :                         DEBUG(0,("mod_smbfilepwd_entry:  Using old smbpasswd format for user %s. \
     963             : This is no longer supported.!\n", pwd->smb_name));
     964           0 :                         DEBUG(0,("mod_smbfilepwd_entry:  No changes made, failing.!\n"));
     965           0 :                         pw_file_unlock(lockfd, &smbpasswd_state->pw_file_lock_depth);
     966           0 :                         fclose(fp);
     967           0 :                         return False;
     968             :                 }
     969             : 
     970             :                 /* Go past the ']' */
     971           0 :                 if(linebuf_len > PTR_DIFF(p, linebuf)) {
     972           0 :                         p++;
     973             :                 }
     974             : 
     975           0 :                 if((linebuf_len > PTR_DIFF(p, linebuf)) && (*p == ':')) {
     976           0 :                         p++;
     977             : 
     978             :                         /* We should be pointing at the LCT entry. */
     979           0 :                         if((linebuf_len > (PTR_DIFF(p, linebuf) + 13)) && (strncasecmp_m((char *)p, "LCT-", 4) == 0)) {
     980           0 :                                 p += 4;
     981           0 :                                 for(i = 0; i < 8; i++) {
     982           0 :                                         if(p[i] == '\0' || !isxdigit(p[i])) {
     983             :                                                 break;
     984             :                                         }
     985             :                                 }
     986           0 :                                 if(i == 8) {
     987             :                                         /*
     988             :                                          * p points at 8 characters of hex digits -
     989             :                                          * read into a time_t as the seconds since
     990             :                                          * 1970 that the password was last changed.
     991             :                                          */
     992           0 :                                         got_pass_last_set_time = True;
     993             :                                 } /* i == 8 */
     994             :                         } /* *p && strncasecmp_m() */
     995             :                 } /* p == ':' */
     996             :         } /* p == '[' */
     997             : 
     998             :         /* Entry is correctly formed. */
     999             : 
    1000             :         /* Create the 32 byte representation of the new p16 */
    1001           0 :         pdb_sethexpwd(ascii_p16, pwd->smb_passwd, pwd->acct_ctrl);
    1002             : 
    1003             :         /* Add on the NT md4 hash */
    1004           0 :         ascii_p16[32] = ':';
    1005           0 :         wr_len = 66;
    1006           0 :         pdb_sethexpwd(ascii_p16+33, pwd->smb_nt_passwd, pwd->acct_ctrl);
    1007           0 :         ascii_p16[65] = ':';
    1008           0 :         ascii_p16[66] = '\0'; /* null-terminate the string so that strlen works */
    1009             : 
    1010             :         /* Add on the account info bits and the time of last password change. */
    1011           0 :         if(got_pass_last_set_time) {
    1012           0 :                 slprintf(&ascii_p16[strlen(ascii_p16)], 
    1013           0 :                         sizeof(ascii_p16)-(strlen(ascii_p16)+1),
    1014             :                         "%s:LCT-%08X:", 
    1015           0 :                         encode_bits, (uint32_t)pwd->pass_last_set_time );
    1016           0 :                 wr_len = strlen(ascii_p16);
    1017             :         }
    1018             : 
    1019             : #ifdef DEBUG_PASSWORD
    1020           0 :         DEBUG(100,("mod_smbfilepwd_entry: "));
    1021           0 :         dump_data(100, (uint8_t *)ascii_p16, wr_len);
    1022             : #endif
    1023             : 
    1024           0 :         if(wr_len > LINEBUF_SIZE) {
    1025           0 :                 DEBUG(0, ("mod_smbfilepwd_entry: line to write (%d) is too long.\n", wr_len+1));
    1026           0 :                 pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
    1027           0 :                 fclose(fp);
    1028           0 :                 return (False);
    1029             :         }
    1030             : 
    1031             :         /*
    1032             :          * Do an atomic write into the file at the position defined by
    1033             :          * seekpos.
    1034             :          */
    1035             : 
    1036             :         /* The mod user write needs to be atomic - so get the fd from 
    1037             :                 the fp and do a raw write() call.
    1038             :          */
    1039             : 
    1040           0 :         fd = fileno(fp);
    1041             : 
    1042           0 :         if (lseek(fd, pwd_seekpos - 1, SEEK_SET) != pwd_seekpos - 1) {
    1043           0 :                 DEBUG(0, ("mod_smbfilepwd_entry: seek fail on file %s.\n", pfile));
    1044           0 :                 pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
    1045           0 :                 fclose(fp);
    1046           0 :                 return False;
    1047             :         }
    1048             : 
    1049             :         /* Sanity check - ensure the areas we are writing are framed by ':' */
    1050           0 :         if (read(fd, linebuf, wr_len+1) != wr_len+1) {
    1051           0 :                 DEBUG(0, ("mod_smbfilepwd_entry: read fail on file %s.\n", pfile));
    1052           0 :                 pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
    1053           0 :                 fclose(fp);
    1054           0 :                 return False;
    1055             :         }
    1056             : 
    1057           0 :         if ((linebuf[0] != ':') || (linebuf[wr_len] != ':'))    {
    1058           0 :                 DEBUG(0, ("mod_smbfilepwd_entry: check on passwd file %s failed.\n", pfile));
    1059           0 :                 pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
    1060           0 :                 fclose(fp);
    1061           0 :                 return False;
    1062             :         }
    1063             :  
    1064           0 :         if (lseek(fd, pwd_seekpos, SEEK_SET) != pwd_seekpos) {
    1065           0 :                 DEBUG(0, ("mod_smbfilepwd_entry: seek fail on file %s.\n", pfile));
    1066           0 :                 pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
    1067           0 :                 fclose(fp);
    1068           0 :                 return False;
    1069             :         }
    1070             : 
    1071           0 :         if (write(fd, ascii_p16, wr_len) != wr_len) {
    1072           0 :                 DEBUG(0, ("mod_smbfilepwd_entry: write failed in passwd file %s\n", pfile));
    1073           0 :                 pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
    1074           0 :                 fclose(fp);
    1075           0 :                 return False;
    1076             :         }
    1077             : 
    1078           0 :         pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
    1079           0 :         fclose(fp);
    1080           0 :         return True;
    1081             : }
    1082             : 
    1083             : /************************************************************************
    1084             :  Routine to delete an entry in the smbpasswd file by name.
    1085             : *************************************************************************/
    1086             : 
    1087           0 : static bool del_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, const char *name)
    1088             : {
    1089           0 :         const char *pfile = smbpasswd_state->smbpasswd_file;
    1090           0 :         char *pfile2 = NULL;
    1091           0 :         struct smb_passwd *pwd = NULL;
    1092           0 :         FILE *fp = NULL;
    1093           0 :         FILE *fp_write = NULL;
    1094           0 :         int pfile2_lockdepth = 0;
    1095             : 
    1096           0 :         pfile2 = talloc_asprintf(talloc_tos(),
    1097             :                         "%s.%u",
    1098           0 :                         pfile, (unsigned)getpid());
    1099           0 :         if (!pfile2) {
    1100           0 :                 return false;
    1101             :         }
    1102             : 
    1103             :         /*
    1104             :          * Open the smbpassword file - for update. It needs to be update
    1105             :          * as we need any other processes to wait until we have replaced
    1106             :          * it.
    1107             :          */
    1108             : 
    1109           0 :         if((fp = startsmbfilepwent(pfile, PWF_UPDATE, &smbpasswd_state->pw_file_lock_depth)) == NULL) {
    1110           0 :                 DEBUG(0, ("del_smbfilepwd_entry: unable to open file %s.\n", pfile));
    1111           0 :                 return False;
    1112             :         }
    1113             : 
    1114             :         /*
    1115             :          * Create the replacement password file.
    1116             :          */
    1117           0 :         if((fp_write = startsmbfilepwent(pfile2, PWF_CREATE, &pfile2_lockdepth)) == NULL) {
    1118           0 :                 DEBUG(0, ("del_smbfilepwd_entry: unable to open file %s.\n", pfile));
    1119           0 :                 endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
    1120           0 :                 return False;
    1121             :         }
    1122             : 
    1123             :         /*
    1124             :          * Scan the file, a line at a time and check if the name matches.
    1125             :          */
    1126             : 
    1127           0 :         while ((pwd = getsmbfilepwent(smbpasswd_state, fp)) != NULL) {
    1128             :                 char *new_entry;
    1129             :                 size_t new_entry_length;
    1130             : 
    1131           0 :                 if (strequal(name, pwd->smb_name)) {
    1132           0 :                         DEBUG(10, ("del_smbfilepwd_entry: found entry with "
    1133             :                                    "name %s - deleting it.\n", name));
    1134           0 :                         continue;
    1135             :                 }
    1136             : 
    1137             :                 /*
    1138             :                  * We need to copy the entry out into the second file.
    1139             :                  */
    1140             : 
    1141           0 :                 if((new_entry = format_new_smbpasswd_entry(pwd)) == NULL) {
    1142           0 :                         DEBUG(0, ("del_smbfilepwd_entry(malloc): Failed to copy entry for user %s to file %s. \
    1143             : Error was %s\n", pwd->smb_name, pfile2, strerror(errno)));
    1144           0 :                         unlink(pfile2);
    1145           0 :                         endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
    1146           0 :                         endsmbfilepwent(fp_write, &pfile2_lockdepth);
    1147           0 :                         return False;
    1148             :                 }
    1149             : 
    1150           0 :                 new_entry_length = strlen(new_entry);
    1151             : 
    1152           0 :                 if(fwrite(new_entry, 1, new_entry_length, fp_write) != new_entry_length) {
    1153           0 :                         DEBUG(0, ("del_smbfilepwd_entry(write): Failed to copy entry for user %s to file %s. \
    1154             : Error was %s\n", pwd->smb_name, pfile2, strerror(errno)));
    1155           0 :                         unlink(pfile2);
    1156           0 :                         endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
    1157           0 :                         endsmbfilepwent(fp_write, &pfile2_lockdepth);
    1158           0 :                         free(new_entry);
    1159           0 :                         return False;
    1160             :                 }
    1161             : 
    1162           0 :                 free(new_entry);
    1163             :         }
    1164             : 
    1165             :         /*
    1166             :          * Ensure pfile2 is flushed before rename.
    1167             :          */
    1168             : 
    1169           0 :         if(fflush(fp_write) != 0) {
    1170           0 :                 DEBUG(0, ("del_smbfilepwd_entry: Failed to flush file %s. Error was %s\n", pfile2, strerror(errno)));
    1171           0 :                 endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
    1172           0 :                 endsmbfilepwent(fp_write,&pfile2_lockdepth);
    1173           0 :                 return False;
    1174             :         }
    1175             : 
    1176             :         /*
    1177             :          * Do an atomic rename - then release the locks.
    1178             :          */
    1179             : 
    1180           0 :         if(rename(pfile2,pfile) != 0) {
    1181           0 :                 unlink(pfile2);
    1182             :         }
    1183             : 
    1184           0 :         endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
    1185           0 :         endsmbfilepwent(fp_write,&pfile2_lockdepth);
    1186           0 :         return True;
    1187             : }
    1188             : 
    1189             : /*********************************************************************
    1190             :  Create a smb_passwd struct from a struct samu.
    1191             :  We will not allocate any new memory.  The smb_passwd struct
    1192             :  should only stay around as long as the struct samu does.
    1193             :  ********************************************************************/
    1194             : 
    1195           0 : static bool build_smb_pass (struct smb_passwd *smb_pw, const struct samu *sampass)
    1196             : {
    1197             :         uint32_t rid;
    1198             : 
    1199           0 :         if (sampass == NULL) 
    1200           0 :                 return False;
    1201           0 :         ZERO_STRUCTP(smb_pw);
    1202             : 
    1203           0 :         if (!IS_SAM_DEFAULT(sampass, PDB_USERSID)) {
    1204           0 :                 rid = pdb_get_user_rid(sampass);
    1205             : 
    1206             :                 /* If the user specified a RID, make sure its able to be both stored and retreived */
    1207           0 :                 if (rid == DOMAIN_RID_GUEST) {
    1208           0 :                         struct passwd *passwd = Get_Pwnam_alloc(NULL, lp_guest_account());
    1209           0 :                         if (!passwd) {
    1210           0 :                                 DEBUG(0, ("Could not find guest account via Get_Pwnam_alloc()! (%s)\n", lp_guest_account()));
    1211           0 :                                 return False;
    1212             :                         }
    1213           0 :                         smb_pw->smb_userid=passwd->pw_uid;
    1214           0 :                         TALLOC_FREE(passwd);
    1215           0 :                 } else if (algorithmic_pdb_rid_is_user(rid)) {
    1216           0 :                         smb_pw->smb_userid=algorithmic_pdb_user_rid_to_uid(rid);
    1217             :                 } else {
    1218           0 :                         DEBUG(0,("build_sam_pass: Failing attempt to store user with non-uid based user RID. \n"));
    1219           0 :                         return False;
    1220             :                 }
    1221             :         }
    1222             : 
    1223           0 :         smb_pw->smb_name=(const char*)pdb_get_username(sampass);
    1224             : 
    1225           0 :         smb_pw->smb_passwd=pdb_get_lanman_passwd(sampass);
    1226           0 :         smb_pw->smb_nt_passwd=pdb_get_nt_passwd(sampass);
    1227             : 
    1228           0 :         smb_pw->acct_ctrl=pdb_get_acct_ctrl(sampass);
    1229           0 :         smb_pw->pass_last_set_time=pdb_get_pass_last_set_time(sampass);
    1230             : 
    1231           0 :         return True;
    1232             : }       
    1233             : 
    1234             : /*********************************************************************
    1235             :  Create a struct samu from a smb_passwd struct
    1236             :  ********************************************************************/
    1237             : 
    1238           0 : static bool build_sam_account(struct smbpasswd_privates *smbpasswd_state, 
    1239             :                               struct samu *sam_pass, const struct smb_passwd *pw_buf)
    1240             : {
    1241             :         struct passwd *pwfile;
    1242             : 
    1243           0 :         if ( !sam_pass ) {
    1244           0 :                 DEBUG(5,("build_sam_account: struct samu is NULL\n"));
    1245           0 :                 return False;
    1246             :         }
    1247             : 
    1248             :         /* verify the user account exists */
    1249             : 
    1250           0 :         if ( !(pwfile = Get_Pwnam_alloc(NULL, pw_buf->smb_name )) ) {
    1251           0 :                 DEBUG(0,("build_sam_account: smbpasswd database is corrupt!  username %s with uid "
    1252             :                 "%u is not in unix passwd database!\n", pw_buf->smb_name, pw_buf->smb_userid));
    1253           0 :                         return False;
    1254             :         }
    1255             : 
    1256           0 :         if ( !NT_STATUS_IS_OK( samu_set_unix(sam_pass, pwfile )) )
    1257           0 :                 return False;
    1258             : 
    1259           0 :         TALLOC_FREE(pwfile);
    1260             : 
    1261             :         /* set remaining fields */
    1262             : 
    1263           0 :         if (!pdb_set_nt_passwd (sam_pass, pw_buf->smb_nt_passwd, PDB_SET))
    1264           0 :                 return False;
    1265           0 :         if (!pdb_set_lanman_passwd (sam_pass, pw_buf->smb_passwd, PDB_SET))
    1266           0 :                 return False;
    1267           0 :         pdb_set_acct_ctrl (sam_pass, pw_buf->acct_ctrl, PDB_SET);
    1268           0 :         pdb_set_pass_last_set_time (sam_pass, pw_buf->pass_last_set_time, PDB_SET);
    1269           0 :         pdb_set_pass_can_change_time (sam_pass, pw_buf->pass_last_set_time, PDB_SET);
    1270             : 
    1271           0 :         return True;
    1272             : }
    1273             : 
    1274             : /*****************************************************************
    1275             :  Functions to be implemented by the new passdb API 
    1276             :  ****************************************************************/
    1277             : 
    1278             : /****************************************************************
    1279             :  Search smbpasswd file by iterating over the entries.  Do not
    1280             :  call getpwnam() for unix account information until we have found
    1281             :  the correct entry
    1282             :  ***************************************************************/
    1283             : 
    1284           0 : static NTSTATUS smbpasswd_getsampwnam(struct pdb_methods *my_methods, 
    1285             :                                   struct samu *sam_acct, const char *username)
    1286             : {
    1287           0 :         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
    1288           0 :         struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
    1289             :         struct smb_passwd *smb_pw;
    1290           0 :         FILE *fp = NULL;
    1291             : 
    1292           0 :         DEBUG(10, ("getsampwnam (smbpasswd): search by name: %s\n", username));
    1293             : 
    1294             :         /* startsmbfilepwent() is used here as we don't want to lookup
    1295             :            the UNIX account in the local system password file until
    1296             :            we have a match.  */
    1297           0 :         fp = startsmbfilepwent(smbpasswd_state->smbpasswd_file, PWF_READ, &(smbpasswd_state->pw_file_lock_depth));
    1298             : 
    1299           0 :         if (fp == NULL) {
    1300           0 :                 DEBUG(0, ("Unable to open passdb database.\n"));
    1301           0 :                 return nt_status;
    1302             :         }
    1303             : 
    1304           0 :         while ( ((smb_pw=getsmbfilepwent(smbpasswd_state, fp)) != NULL)&& (!strequal(smb_pw->smb_name, username)) )
    1305             :                 /* do nothing....another loop */ ;
    1306             : 
    1307           0 :         endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
    1308             : 
    1309             : 
    1310             :         /* did we locate the username in smbpasswd  */
    1311           0 :         if (smb_pw == NULL)
    1312           0 :                 return nt_status;
    1313             : 
    1314           0 :         DEBUG(10, ("getsampwnam (smbpasswd): found by name: %s\n", smb_pw->smb_name));
    1315             : 
    1316           0 :         if (!sam_acct) {
    1317           0 :                 DEBUG(10,("getsampwnam (smbpasswd): struct samu is NULL\n"));
    1318           0 :                 return nt_status;
    1319             :         }
    1320             : 
    1321             :         /* now build the struct samu */
    1322           0 :         if (!build_sam_account(smbpasswd_state, sam_acct, smb_pw))
    1323           0 :                 return nt_status;
    1324             : 
    1325             :         /* success */
    1326           0 :         return NT_STATUS_OK;
    1327             : }
    1328             : 
    1329           3 : static NTSTATUS smbpasswd_getsampwsid(struct pdb_methods *my_methods, struct samu *sam_acct, const struct dom_sid *sid)
    1330             : {
    1331           3 :         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
    1332           3 :         struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
    1333             :         struct smb_passwd *smb_pw;
    1334             :         struct dom_sid_buf buf;
    1335           3 :         FILE *fp = NULL;
    1336             :         uint32_t rid;
    1337             : 
    1338           3 :         DEBUG(10, ("smbpasswd_getsampwrid: search by sid: %s\n",
    1339             :                    dom_sid_str_buf(sid, &buf)));
    1340             : 
    1341           3 :         if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid))
    1342           0 :                 return NT_STATUS_UNSUCCESSFUL;
    1343             : 
    1344             :         /* More special case 'guest account' hacks... */
    1345           3 :         if (rid == DOMAIN_RID_GUEST) {
    1346           0 :                 const char *guest_account = lp_guest_account();
    1347           0 :                 if (!(guest_account && *guest_account)) {
    1348           0 :                         DEBUG(1, ("Guest account not specified!\n"));
    1349           0 :                         return nt_status;
    1350             :                 }
    1351           0 :                 return smbpasswd_getsampwnam(my_methods, sam_acct, guest_account);
    1352             :         }
    1353             : 
    1354             :         /* Open the sam password file - not for update. */
    1355           3 :         fp = startsmbfilepwent(smbpasswd_state->smbpasswd_file, PWF_READ, &(smbpasswd_state->pw_file_lock_depth));
    1356             : 
    1357           3 :         if (fp == NULL) {
    1358           3 :                 DEBUG(0, ("Unable to open passdb database.\n"));
    1359           3 :                 return nt_status;
    1360             :         }
    1361             : 
    1362           0 :         while ( ((smb_pw=getsmbfilepwent(smbpasswd_state, fp)) != NULL) && (algorithmic_pdb_uid_to_user_rid(smb_pw->smb_userid) != rid) )
    1363             :                 /* do nothing */ ;
    1364             : 
    1365           0 :         endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
    1366             : 
    1367             : 
    1368             :         /* did we locate the username in smbpasswd  */
    1369           0 :         if (smb_pw == NULL)
    1370           0 :                 return nt_status;
    1371             : 
    1372           0 :         DEBUG(10, ("getsampwrid (smbpasswd): found by name: %s\n", smb_pw->smb_name));
    1373             : 
    1374           0 :         if (!sam_acct) {
    1375           0 :                 DEBUG(10,("getsampwrid: (smbpasswd) struct samu is NULL\n"));
    1376           0 :                 return nt_status;
    1377             :         }
    1378             : 
    1379             :         /* now build the struct samu */
    1380           0 :         if (!build_sam_account (smbpasswd_state, sam_acct, smb_pw))
    1381           0 :                 return nt_status;
    1382             : 
    1383             :         /* build_sam_account might change the SID on us, if the name was for the guest account */
    1384           0 :         if (NT_STATUS_IS_OK(nt_status) && !dom_sid_equal(pdb_get_user_sid(sam_acct), sid)) {
    1385             :                 struct dom_sid_buf buf1, buf2;
    1386           0 :                 DEBUG(1, ("looking for user with sid %s instead returned %s "
    1387             :                           "for account %s!?!\n",
    1388             :                           dom_sid_str_buf(sid, &buf1),
    1389             :                           dom_sid_str_buf(pdb_get_user_sid(sam_acct), &buf2),
    1390             :                           pdb_get_username(sam_acct)));
    1391           0 :                 return NT_STATUS_NO_SUCH_USER;
    1392             :         }
    1393             : 
    1394             :         /* success */
    1395           0 :         return NT_STATUS_OK;
    1396             : }
    1397             : 
    1398           0 : static NTSTATUS smbpasswd_add_sam_account(struct pdb_methods *my_methods, struct samu *sampass)
    1399             : {
    1400           0 :         struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
    1401             :         struct smb_passwd smb_pw;
    1402             : 
    1403             :         /* convert the struct samu */
    1404           0 :         if (!build_smb_pass(&smb_pw, sampass)) {
    1405           0 :                 return NT_STATUS_UNSUCCESSFUL;
    1406             :         }
    1407             : 
    1408             :         /* add the entry */
    1409           0 :         return add_smbfilepwd_entry(smbpasswd_state, &smb_pw);
    1410             : }
    1411             : 
    1412           0 : static NTSTATUS smbpasswd_update_sam_account(struct pdb_methods *my_methods, struct samu *sampass)
    1413             : {
    1414           0 :         struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
    1415             :         struct smb_passwd smb_pw;
    1416             : 
    1417             :         /* convert the struct samu */
    1418           0 :         if (!build_smb_pass(&smb_pw, sampass)) {
    1419           0 :                 DEBUG(0, ("smbpasswd_update_sam_account: build_smb_pass failed!\n"));
    1420           0 :                 return NT_STATUS_UNSUCCESSFUL;
    1421             :         }
    1422             : 
    1423             :         /* update the entry */
    1424           0 :         if(!mod_smbfilepwd_entry(smbpasswd_state, &smb_pw)) {
    1425           0 :                 DEBUG(0, ("smbpasswd_update_sam_account: mod_smbfilepwd_entry failed!\n"));
    1426           0 :                 return NT_STATUS_UNSUCCESSFUL;
    1427             :         }
    1428             : 
    1429           0 :         return NT_STATUS_OK;
    1430             : }
    1431             : 
    1432           0 : static NTSTATUS smbpasswd_delete_sam_account (struct pdb_methods *my_methods, struct samu *sampass)
    1433             : {
    1434           0 :         struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
    1435             : 
    1436           0 :         const char *username = pdb_get_username(sampass);
    1437             : 
    1438           0 :         if (del_smbfilepwd_entry(smbpasswd_state, username))
    1439           0 :                 return NT_STATUS_OK;
    1440             : 
    1441           0 :         return NT_STATUS_UNSUCCESSFUL;
    1442             : }
    1443             : 
    1444           0 : static NTSTATUS smbpasswd_rename_sam_account (struct pdb_methods *my_methods, 
    1445             :                                               struct samu *old_acct,
    1446             :                                               const char *newname)
    1447             : {
    1448           0 :         const struct loadparm_substitution *lp_sub =
    1449           0 :                 loadparm_s3_global_substitution();
    1450           0 :         char *rename_script = NULL;
    1451           0 :         struct samu *new_acct = NULL;
    1452           0 :         bool interim_account = False;
    1453           0 :         TALLOC_CTX *ctx = talloc_tos();
    1454           0 :         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
    1455             : 
    1456           0 :         if (!*(lp_rename_user_script(talloc_tos(), lp_sub)))
    1457           0 :                 goto done;
    1458             : 
    1459           0 :         if ( !(new_acct = samu_new( NULL )) ) {
    1460           0 :                 return NT_STATUS_NO_MEMORY;
    1461             :         }
    1462             : 
    1463           0 :         if ( !pdb_copy_sam_account( new_acct, old_acct ) 
    1464           0 :                 || !pdb_set_username(new_acct, newname, PDB_CHANGED)) 
    1465             :         {
    1466           0 :                 goto done;
    1467             :         }
    1468             : 
    1469           0 :         ret = smbpasswd_add_sam_account(my_methods, new_acct);
    1470           0 :         if (!NT_STATUS_IS_OK(ret))
    1471           0 :                 goto done;
    1472             : 
    1473           0 :         interim_account = True;
    1474             : 
    1475             :         /* rename the posix user */
    1476           0 :         rename_script = lp_rename_user_script(ctx, lp_sub);
    1477           0 :         if (!rename_script) {
    1478           0 :                 ret = NT_STATUS_NO_MEMORY;
    1479           0 :                 goto done;
    1480             :         }
    1481             : 
    1482           0 :         if (*rename_script) {
    1483             :                 int rename_ret;
    1484             : 
    1485           0 :                 rename_script = talloc_string_sub2(ctx,
    1486             :                                         rename_script,
    1487             :                                         "%unew",
    1488             :                                         newname,
    1489             :                                         true,
    1490             :                                         false,
    1491             :                                         true);
    1492           0 :                 if (!rename_script) {
    1493           0 :                         ret = NT_STATUS_NO_MEMORY;
    1494           0 :                         goto done;
    1495             :                 }
    1496           0 :                 rename_script = talloc_string_sub2(ctx,
    1497             :                                         rename_script,
    1498             :                                         "%uold",
    1499             :                                         pdb_get_username(old_acct),
    1500             :                                         true,
    1501             :                                         false,
    1502             :                                         true);
    1503           0 :                 if (!rename_script) {
    1504           0 :                         ret = NT_STATUS_NO_MEMORY;
    1505           0 :                         goto done;
    1506             :                 }
    1507             : 
    1508           0 :                 rename_ret = smbrun(rename_script, NULL, NULL);
    1509             : 
    1510           0 :                 DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n", rename_script, rename_ret));
    1511             : 
    1512           0 :                 if (rename_ret == 0) {
    1513           0 :                         smb_nscd_flush_user_cache();
    1514             :                 }
    1515             : 
    1516           0 :                 if (rename_ret)
    1517           0 :                         goto done;
    1518             :         } else {
    1519           0 :                 goto done;
    1520             :         }
    1521             : 
    1522           0 :         smbpasswd_delete_sam_account(my_methods, old_acct);
    1523           0 :         interim_account = False;
    1524             : 
    1525           0 : done:
    1526             :         /* cleanup */
    1527           0 :         if (interim_account)
    1528           0 :                 smbpasswd_delete_sam_account(my_methods, new_acct);
    1529             : 
    1530           0 :         if (new_acct)
    1531           0 :                 TALLOC_FREE(new_acct);
    1532             : 
    1533           0 :         return (ret);   
    1534             : }
    1535             : 
    1536           0 : static uint32_t smbpasswd_capabilities(struct pdb_methods *methods)
    1537             : {
    1538           0 :         return 0;
    1539             : }
    1540             : 
    1541           0 : static void free_private_data(void **vp) 
    1542             : {
    1543           0 :         struct smbpasswd_privates **privates = (struct smbpasswd_privates**)vp;
    1544             : 
    1545           0 :         endsmbfilepwent((*privates)->pw_file, &((*privates)->pw_file_lock_depth));
    1546             : 
    1547           0 :         *privates = NULL;
    1548             :         /* No need to free any further, as it is talloc()ed */
    1549           0 : }
    1550             : 
    1551             : struct smbpasswd_search_state {
    1552             :         uint32_t acct_flags;
    1553             : 
    1554             :         struct samr_displayentry *entries;
    1555             :         uint32_t num_entries;
    1556             :         ssize_t array_size;
    1557             :         uint32_t current;
    1558             : };
    1559             : 
    1560           0 : static void smbpasswd_search_end(struct pdb_search *search)
    1561             : {
    1562           0 :         struct smbpasswd_search_state *state = talloc_get_type_abort(
    1563             :                 search->private_data, struct smbpasswd_search_state);
    1564           0 :         TALLOC_FREE(state);
    1565           0 : }
    1566             : 
    1567           0 : static bool smbpasswd_search_next_entry(struct pdb_search *search,
    1568             :                                         struct samr_displayentry *entry)
    1569             : {
    1570           0 :         struct smbpasswd_search_state *state = talloc_get_type_abort(
    1571             :                 search->private_data, struct smbpasswd_search_state);
    1572             : 
    1573           0 :         if (state->current == state->num_entries) {
    1574           0 :                 return false;
    1575             :         }
    1576             : 
    1577           0 :         entry->idx = state->entries[state->current].idx;
    1578           0 :         entry->rid = state->entries[state->current].rid;
    1579           0 :         entry->acct_flags = state->entries[state->current].acct_flags;
    1580             : 
    1581           0 :         entry->account_name = talloc_strdup(
    1582           0 :                 search, state->entries[state->current].account_name);
    1583           0 :         entry->fullname = talloc_strdup(
    1584           0 :                 search, state->entries[state->current].fullname);
    1585           0 :         entry->description = talloc_strdup(
    1586           0 :                 search, state->entries[state->current].description);
    1587             : 
    1588           0 :         if ((entry->account_name == NULL) || (entry->fullname == NULL)
    1589           0 :             || (entry->description == NULL)) {
    1590           0 :                 DEBUG(0, ("talloc_strdup failed\n"));
    1591           0 :                 return false;
    1592             :         }
    1593             : 
    1594           0 :         state->current += 1;
    1595           0 :         return true;
    1596             : }
    1597             : 
    1598           0 : static bool smbpasswd_search_users(struct pdb_methods *methods,
    1599             :                                    struct pdb_search *search,
    1600             :                                    uint32_t acct_flags)
    1601             : {
    1602           0 :         struct smbpasswd_privates *smbpasswd_state =
    1603             :                 (struct smbpasswd_privates*)methods->private_data;
    1604             : 
    1605             :         struct smbpasswd_search_state *search_state;
    1606             :         struct smb_passwd *pwd;
    1607             :         FILE *fp;
    1608             : 
    1609           0 :         search_state = talloc_zero(search, struct smbpasswd_search_state);
    1610           0 :         if (search_state == NULL) {
    1611           0 :                 DEBUG(0, ("talloc failed\n"));
    1612           0 :                 return false;
    1613             :         }
    1614           0 :         search_state->acct_flags = acct_flags;
    1615             : 
    1616           0 :         fp = startsmbfilepwent(smbpasswd_state->smbpasswd_file, PWF_READ,
    1617             :                                &smbpasswd_state->pw_file_lock_depth);
    1618             : 
    1619           0 :         if (fp == NULL) {
    1620           0 :                 DEBUG(10, ("Unable to open smbpasswd file.\n"));
    1621           0 :                 TALLOC_FREE(search_state);
    1622           0 :                 return false;
    1623             :         }
    1624             : 
    1625           0 :         while ((pwd = getsmbfilepwent(smbpasswd_state, fp)) != NULL) {
    1626             :                 struct samr_displayentry entry;
    1627             :                 struct samu *user;
    1628             : 
    1629           0 :                 if ((acct_flags != 0)
    1630           0 :                     && ((acct_flags & pwd->acct_ctrl) == 0)) {
    1631           0 :                         continue;
    1632             :                 }
    1633             : 
    1634           0 :                 user = samu_new(talloc_tos());
    1635           0 :                 if (user == NULL) {
    1636           0 :                         DEBUG(0, ("samu_new failed\n"));
    1637           0 :                         break;
    1638             :                 }
    1639             : 
    1640           0 :                 if (!build_sam_account(smbpasswd_state, user, pwd)) {
    1641             :                         /* Already got debug msgs... */
    1642           0 :                         break;
    1643             :                 }
    1644             : 
    1645           0 :                 ZERO_STRUCT(entry);
    1646             : 
    1647           0 :                 entry.acct_flags = pdb_get_acct_ctrl(user);
    1648           0 :                 sid_peek_rid(pdb_get_user_sid(user), &entry.rid);
    1649           0 :                 entry.account_name = talloc_strdup(
    1650             :                         search_state, pdb_get_username(user));
    1651           0 :                 entry.fullname = talloc_strdup(
    1652             :                         search_state, pdb_get_fullname(user));
    1653           0 :                 entry.description = talloc_strdup(
    1654             :                         search_state, pdb_get_acct_desc(user));
    1655             : 
    1656           0 :                 TALLOC_FREE(user);
    1657             : 
    1658           0 :                 if ((entry.account_name == NULL) || (entry.fullname == NULL)
    1659           0 :                     || (entry.description == NULL)) {
    1660           0 :                         DEBUG(0, ("talloc_strdup failed\n"));
    1661           0 :                         break;
    1662             :                 }
    1663             : 
    1664           0 :                 ADD_TO_LARGE_ARRAY(search_state, struct samr_displayentry,
    1665             :                                    entry, &search_state->entries,
    1666             :                                    &search_state->num_entries,
    1667             :                                    &search_state->array_size);
    1668             :         }
    1669             : 
    1670           0 :         endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
    1671             : 
    1672           0 :         search->private_data = search_state;
    1673           0 :         search->next_entry = smbpasswd_search_next_entry;
    1674           0 :         search->search_end = smbpasswd_search_end;
    1675             : 
    1676           0 :         return true;
    1677             : }
    1678             : 
    1679           2 : static NTSTATUS pdb_init_smbpasswd( struct pdb_methods **pdb_method, const char *location )
    1680             : {
    1681             :         NTSTATUS nt_status;
    1682             :         struct smbpasswd_privates *privates;
    1683             : 
    1684           2 :         if ( !NT_STATUS_IS_OK(nt_status = make_pdb_method( pdb_method )) ) {
    1685           0 :                 return nt_status;
    1686             :         }
    1687             : 
    1688           2 :         (*pdb_method)->name = "smbpasswd";
    1689             : 
    1690           2 :         (*pdb_method)->getsampwnam = smbpasswd_getsampwnam;
    1691           2 :         (*pdb_method)->getsampwsid = smbpasswd_getsampwsid;
    1692           2 :         (*pdb_method)->add_sam_account = smbpasswd_add_sam_account;
    1693           2 :         (*pdb_method)->update_sam_account = smbpasswd_update_sam_account;
    1694           2 :         (*pdb_method)->delete_sam_account = smbpasswd_delete_sam_account;
    1695           2 :         (*pdb_method)->rename_sam_account = smbpasswd_rename_sam_account;
    1696           2 :         (*pdb_method)->search_users = smbpasswd_search_users;
    1697             : 
    1698           2 :         (*pdb_method)->capabilities = smbpasswd_capabilities;
    1699             : 
    1700             :         /* Setup private data and free function */
    1701             : 
    1702           2 :         if ( !(privates = talloc_zero( *pdb_method, struct smbpasswd_privates )) ) {
    1703           0 :                 DEBUG(0, ("talloc() failed for smbpasswd private_data!\n"));
    1704           0 :                 return NT_STATUS_NO_MEMORY;
    1705             :         }
    1706             : 
    1707             :         /* Store some config details */
    1708             : 
    1709           2 :         if (location) {
    1710           2 :                 privates->smbpasswd_file = talloc_strdup(*pdb_method, location);
    1711             :         } else {
    1712           0 :                 privates->smbpasswd_file = talloc_strdup(*pdb_method, lp_smb_passwd_file());
    1713             :         }
    1714             : 
    1715           2 :         if (!privates->smbpasswd_file) {
    1716           0 :                 DEBUG(0, ("talloc_strdp() failed for storing smbpasswd location!\n"));
    1717           0 :                 return NT_STATUS_NO_MEMORY;
    1718             :         }
    1719             : 
    1720           2 :         (*pdb_method)->private_data = privates;
    1721             : 
    1722           2 :         (*pdb_method)->free_private_data = free_private_data;
    1723             : 
    1724           2 :         return NT_STATUS_OK;
    1725             : }
    1726             : 
    1727        1011 : NTSTATUS pdb_smbpasswd_init(TALLOC_CTX *ctx) 
    1728             : {
    1729        1011 :         return smb_register_passdb(PASSDB_INTERFACE_VERSION, "smbpasswd", pdb_init_smbpasswd);
    1730             : }

Generated by: LCOV version 1.13