LCOV - code coverage report
Current view: top level - source3/passdb - pdb_smbpasswd.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 51 806 6.3 %
Date: 2024-04-21 15:09:00 Functions: 4 27 14.8 %

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

Generated by: LCOV version 1.14