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.
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)
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
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/>.
24 #include "../librpc/gen_ndr/samr.h"
27 #define DBGC_CLASS DBGC_PASSDB
30 smb_passwd is analogous to sam_passwd used everywhere
31 else. However, smb_passwd is limited to the information
32 stored by an smbpasswd entry
37 uint32 smb_userid
; /* this is actually the unix uid_t */
38 const char *smb_name
; /* username string */
40 const unsigned char *smb_passwd
; /* Null if no password */
41 const unsigned char *smb_nt_passwd
; /* Null if no password */
43 uint16_t acct_ctrl
; /* account info (ACB_xxxx bit-mask) */
44 time_t pass_last_set_time
; /* password last set time */
47 struct smbpasswd_privates
49 /* used for maintain locks on the smbpasswd file */
50 int pw_file_lock_depth
;
52 /* Global File pointer */
55 /* formerly static variables */
56 struct smb_passwd pw_buf
;
58 unsigned char smbpwd
[16];
59 unsigned char smbntpwd
[16];
61 /* retrive-once info */
62 const char *smbpasswd_file
;
65 enum pwf_access_type
{ PWF_READ
, PWF_UPDATE
, PWF_CREATE
};
67 static SIG_ATOMIC_T gotalarm
;
69 /***************************************************************
70 Signal function to tell us we timed out.
71 ****************************************************************/
73 static void gotalarm_sig(int signum
)
78 /***************************************************************
79 Lock or unlock a fd for a known lock type. Abandon after waitsecs
81 ****************************************************************/
83 static bool do_file_lock(int fd
, int waitsecs
, int type
)
85 SMB_STRUCT_FLOCK lock
;
87 void (*oldsig_handler
)(int);
90 oldsig_handler
= CatchSignal(SIGALRM
, gotalarm_sig
);
93 lock
.l_whence
= SEEK_SET
;
99 /* Note we must *NOT* use sys_fcntl here ! JRA */
100 ret
= fcntl(fd
, SMB_F_SETLKW
, &lock
);
102 CatchSignal(SIGALRM
, oldsig_handler
);
104 if (gotalarm
&& ret
== -1) {
105 DEBUG(0, ("do_file_lock: failed to %s file.\n",
106 type
== F_UNLCK
? "unlock" : "lock"));
113 /***************************************************************
114 Lock an fd. Abandon after waitsecs seconds.
115 ****************************************************************/
117 static bool pw_file_lock(int fd
, int type
, int secs
, int *plock_depth
)
123 if(*plock_depth
== 0) {
124 if (!do_file_lock(fd
, secs
, type
)) {
125 DEBUG(10,("pw_file_lock: locking file failed, error = %s.\n",
136 /***************************************************************
137 Unlock an fd. Abandon after waitsecs seconds.
138 ****************************************************************/
140 static bool pw_file_unlock(int fd
, int *plock_depth
)
144 if (fd
== 0 || *plock_depth
== 0) {
148 if(*plock_depth
== 1) {
149 ret
= do_file_lock(fd
, 5, F_UNLCK
);
152 if (*plock_depth
> 0) {
157 DEBUG(10,("pw_file_unlock: unlocking file failed, error = %s.\n",
163 /**************************************************************
164 Intialize a smb_passwd struct
165 *************************************************************/
167 static void pdb_init_smb(struct smb_passwd
*user
)
173 user
->pass_last_set_time
= (time_t)0;
176 /***************************************************************
177 Internal fn to enumerate the smbpasswd list. Returns a void pointer
178 to ensure no modification outside this module. Checks for atomic
179 rename of smbpasswd file on update or create once the lock has
180 been granted to prevent race conditions. JRA.
181 ****************************************************************/
183 static FILE *startsmbfilepwent(const char *pfile
, enum pwf_access_type type
, int *lock_depth
)
186 const char *open_mode
= NULL
;
188 int lock_type
= F_RDLCK
;
191 DEBUG(0, ("startsmbfilepwent: No SMB password file set\n"));
206 * Ensure atomic file creation.
211 for(i
= 0; i
< 5; i
++) {
212 if((fd
= sys_open(pfile
, O_CREAT
|O_TRUNC
|O_EXCL
|O_RDWR
, 0600))!=-1) {
215 sys_usleep(200); /* Spin, spin... */
218 DEBUG(0,("startsmbfilepwent_internal: too many race conditions \
219 creating file %s\n", pfile
));
229 for(race_loop
= 0; race_loop
< 5; race_loop
++) {
230 DEBUG(10, ("startsmbfilepwent_internal: opening file %s\n", pfile
));
232 if((fp
= sys_fopen(pfile
, open_mode
)) == NULL
) {
235 * If smbpasswd file doesn't exist, then create new one. This helps to avoid
236 * confusing error msg when adding user account first time.
238 if (errno
== ENOENT
) {
239 if ((fp
= sys_fopen(pfile
, "a+")) != NULL
) {
240 DEBUG(0, ("startsmbfilepwent_internal: file %s did not \
241 exist. File successfully created.\n", pfile
));
243 DEBUG(0, ("startsmbfilepwent_internal: file %s did not \
244 exist. Couldn't create new one. Error was: %s",
245 pfile
, strerror(errno
)));
249 DEBUG(0, ("startsmbfilepwent_internal: unable to open file %s. \
250 Error was: %s\n", pfile
, strerror(errno
)));
255 if (!pw_file_lock(fileno(fp
), lock_type
, 5, lock_depth
)) {
256 DEBUG(0, ("startsmbfilepwent_internal: unable to lock file %s. \
257 Error was %s\n", pfile
, strerror(errno
) ));
263 * Only check for replacement races on update or create.
264 * For read we don't mind if the data is one record out of date.
267 if(type
== PWF_READ
) {
270 SMB_STRUCT_STAT sbuf1
, sbuf2
;
273 * Avoid the potential race condition between the open and the lock
274 * by doing a stat on the filename and an fstat on the fd. If the
275 * two inodes differ then someone did a rename between the open and
276 * the lock. Back off and try the open again. Only do this 5 times to
277 * prevent infinate loops. JRA.
280 if (sys_stat(pfile
, &sbuf1
, false) != 0) {
281 DEBUG(0, ("startsmbfilepwent_internal: unable to stat file %s. \
282 Error was %s\n", pfile
, strerror(errno
)));
283 pw_file_unlock(fileno(fp
), lock_depth
);
288 if (sys_fstat(fileno(fp
), &sbuf2
, false) != 0) {
289 DEBUG(0, ("startsmbfilepwent_internal: unable to fstat file %s. \
290 Error was %s\n", pfile
, strerror(errno
)));
291 pw_file_unlock(fileno(fp
), lock_depth
);
296 if( sbuf1
.st_ex_ino
== sbuf2
.st_ex_ino
) {
302 * Race occurred - back off and try again...
305 pw_file_unlock(fileno(fp
), lock_depth
);
311 DEBUG(0, ("startsmbfilepwent_internal: too many race conditions opening file %s\n", pfile
));
315 /* Set a buffer to do more efficient reads */
316 setvbuf(fp
, (char *)NULL
, _IOFBF
, 1024);
318 /* Make sure it is only rw by the owner */
320 if(fchmod(fileno(fp
), S_IRUSR
|S_IWUSR
) == -1) {
322 if(chmod(pfile
, S_IRUSR
|S_IWUSR
) == -1) {
324 DEBUG(0, ("startsmbfilepwent_internal: failed to set 0600 permissions on password file %s. \
325 Error was %s\n.", pfile
, strerror(errno
) ));
326 pw_file_unlock(fileno(fp
), lock_depth
);
331 /* We have a lock on the file. */
335 /***************************************************************
336 End enumeration of the smbpasswd list.
337 ****************************************************************/
339 static void endsmbfilepwent(FILE *fp
, int *lock_depth
)
345 pw_file_unlock(fileno(fp
), lock_depth
);
347 DEBUG(7, ("endsmbfilepwent_internal: closed password file.\n"));
350 /*************************************************************************
351 Routine to return the next entry in the smbpasswd list.
352 *************************************************************************/
354 static struct smb_passwd
*getsmbfilepwent(struct smbpasswd_privates
*smbpasswd_state
, FILE *fp
)
356 /* Static buffers we will return. */
357 struct smb_passwd
*pw_buf
= &smbpasswd_state
->pw_buf
;
358 char *user_name
= smbpasswd_state
->user_name
;
359 unsigned char *smbpwd
= smbpasswd_state
->smbpwd
;
360 unsigned char *smbntpwd
= smbpasswd_state
->smbntpwd
;
369 DEBUG(0,("getsmbfilepwent: Bad password file pointer.\n"));
373 pdb_init_smb(pw_buf
);
374 pw_buf
->acct_ctrl
= ACB_NORMAL
;
377 * Scan the file, a line at a time and check if the name matches.
380 while (status
&& !feof(fp
)) {
383 status
= fgets(linebuf
, 256, fp
);
384 if (status
== NULL
&& ferror(fp
)) {
389 * Check if the string is terminated with a newline - if not
390 * then we must keep reading and discard until we get one.
392 if ((linebuf_len
= strlen(linebuf
)) == 0) {
396 if (linebuf
[linebuf_len
- 1] != '\n') {
398 while (!ferror(fp
) && !feof(fp
)) {
405 linebuf
[linebuf_len
- 1] = '\0';
408 #ifdef DEBUG_PASSWORD
409 DEBUG(100, ("getsmbfilepwent: got line |%s|\n", linebuf
));
411 if ((linebuf
[0] == 0) && feof(fp
)) {
412 DEBUG(4, ("getsmbfilepwent: end of file reached\n"));
417 * The line we have should be of the form :-
419 * username:uid:32hex bytes:[Account type]:LCT-12345678....other flags presently
424 * username:uid:32hex bytes:32hex bytes:[Account type]:LCT-12345678....ignored....
426 * if Windows NT compatible passwords are also present.
427 * [Account type] is an ascii encoding of the type of account.
428 * LCT-(8 hex digits) is the time_t value of the last change time.
431 if (linebuf
[0] == '#' || linebuf
[0] == '\0') {
432 DEBUG(6, ("getsmbfilepwent: skipping comment or blank line\n"));
435 p
= (unsigned char *) strchr_m(linebuf
, ':');
437 DEBUG(0, ("getsmbfilepwent: malformed password entry (no :)\n"));
441 strncpy(user_name
, linebuf
, PTR_DIFF(p
, linebuf
));
442 user_name
[PTR_DIFF(p
, linebuf
)] = '\0';
446 p
++; /* Go past ':' */
449 DEBUG(0, ("getsmbfilepwent: user name %s has a negative uid.\n", user_name
));
454 DEBUG(0, ("getsmbfilepwent: malformed password entry for user %s (uid not number)\n",
459 uidval
= atoi((char *) p
);
461 while (*p
&& isdigit(*p
)) {
466 DEBUG(0, ("getsmbfilepwent: malformed password entry for user %s (no : after uid)\n",
471 pw_buf
->smb_name
= user_name
;
472 pw_buf
->smb_userid
= uidval
;
475 * Now get the password value - this should be 32 hex digits
476 * which are the ascii representations of a 16 byte string.
477 * Get two at a time and put them into the password.
483 if (linebuf_len
< (PTR_DIFF(p
, linebuf
) + 33)) {
484 DEBUG(0, ("getsmbfilepwent: malformed password entry for user %s (passwd too short)\n",
490 DEBUG(0, ("getsmbfilepwent: malformed password entry for user %s (no terminating :)\n",
495 if (strnequal((char *) p
, "NO PASSWORD", 11)) {
496 pw_buf
->smb_passwd
= NULL
;
497 pw_buf
->acct_ctrl
|= ACB_PWNOTREQ
;
499 if (*p
== '*' || *p
== 'X') {
500 /* NULL LM password */
501 pw_buf
->smb_passwd
= NULL
;
502 DEBUG(10, ("getsmbfilepwent: LM password for user %s invalidated\n", user_name
));
503 } else if (pdb_gethexpwd((char *)p
, smbpwd
)) {
504 pw_buf
->smb_passwd
= smbpwd
;
506 pw_buf
->smb_passwd
= NULL
;
507 DEBUG(0, ("getsmbfilepwent: Malformed Lanman password entry for user %s \
508 (non hex chars)\n", user_name
));
513 * Now check if the NT compatible password is
516 pw_buf
->smb_nt_passwd
= NULL
;
517 p
+= 33; /* Move to the first character of the line after the lanman password. */
518 if ((linebuf_len
>= (PTR_DIFF(p
, linebuf
) + 33)) && (p
[32] == ':')) {
519 if (*p
!= '*' && *p
!= 'X') {
520 if(pdb_gethexpwd((char *)p
,smbntpwd
)) {
521 pw_buf
->smb_nt_passwd
= smbntpwd
;
524 p
+= 33; /* Move to the first character of the line after the NT password. */
527 DEBUG(5,("getsmbfilepwent: returning passwd entry for user %s, uid %ld\n",
531 unsigned char *end_p
= (unsigned char *)strchr_m((char *)p
, ']');
532 pw_buf
->acct_ctrl
= pdb_decode_acct_ctrl((char*)p
);
534 /* Must have some account type set. */
535 if(pw_buf
->acct_ctrl
== 0) {
536 pw_buf
->acct_ctrl
= ACB_NORMAL
;
539 /* Now try and get the last change time. */
545 if(*p
&& (StrnCaseCmp((char *)p
, "LCT-", 4)==0)) {
548 for(i
= 0; i
< 8; i
++) {
549 if(p
[i
] == '\0' || !isxdigit(p
[i
])) {
555 * p points at 8 characters of hex digits -
556 * read into a time_t as the seconds since
557 * 1970 that the password was last changed.
559 pw_buf
->pass_last_set_time
= (time_t)strtol((char *)p
, NULL
, 16);
564 /* 'Old' style file. Fake up based on user name. */
566 * Currently trust accounts are kept in the same
567 * password file as 'normal accounts'. If this changes
568 * we will have to fix this code. JRA.
570 if(pw_buf
->smb_name
[strlen(pw_buf
->smb_name
) - 1] == '$') {
571 pw_buf
->acct_ctrl
&= ~ACB_NORMAL
;
572 pw_buf
->acct_ctrl
|= ACB_WSTRUST
;
579 DEBUG(5,("getsmbfilepwent: end of file reached.\n"));
583 /************************************************************************
584 Create a new smbpasswd entry - malloced space returned.
585 *************************************************************************/
587 static char *format_new_smbpasswd_entry(const struct smb_passwd
*newpwd
)
589 int new_entry_length
;
593 new_entry_length
= strlen(newpwd
->smb_name
) + 1 + 15 + 1 + 32 + 1 + 32 + 1 +
594 NEW_PW_FORMAT_SPACE_PADDED_LEN
+ 1 + 13 + 2;
596 if((new_entry
= (char *)SMB_MALLOC( new_entry_length
)) == NULL
) {
597 DEBUG(0, ("format_new_smbpasswd_entry: Malloc failed adding entry for user %s.\n",
602 slprintf(new_entry
, new_entry_length
- 1, "%s:%u:", newpwd
->smb_name
, (unsigned)newpwd
->smb_userid
);
604 p
= new_entry
+strlen(new_entry
);
605 pdb_sethexpwd(p
, newpwd
->smb_passwd
, newpwd
->acct_ctrl
);
610 pdb_sethexpwd(p
, newpwd
->smb_nt_passwd
, newpwd
->acct_ctrl
);
615 /* Add the account encoding and the last change time. */
616 slprintf((char *)p
, new_entry_length
- 1 - (p
- new_entry
), "%s:LCT-%08X:\n",
617 pdb_encode_acct_ctrl(newpwd
->acct_ctrl
, NEW_PW_FORMAT_SPACE_PADDED_LEN
),
618 (uint32_t)newpwd
->pass_last_set_time
);
623 /************************************************************************
624 Routine to add an entry to the smbpasswd file.
625 *************************************************************************/
627 static NTSTATUS
add_smbfilepwd_entry(struct smbpasswd_privates
*smbpasswd_state
,
628 struct smb_passwd
*newpwd
)
630 const char *pfile
= smbpasswd_state
->smbpasswd_file
;
631 struct smb_passwd
*pwd
= NULL
;
635 size_t new_entry_length
;
639 /* Open the smbpassword file - for update. */
640 fp
= startsmbfilepwent(pfile
, PWF_UPDATE
, &smbpasswd_state
->pw_file_lock_depth
);
642 if (fp
== NULL
&& errno
== ENOENT
) {
643 /* Try again - create. */
644 fp
= startsmbfilepwent(pfile
, PWF_CREATE
, &smbpasswd_state
->pw_file_lock_depth
);
648 DEBUG(0, ("add_smbfilepwd_entry: unable to open file.\n"));
649 return map_nt_error_from_unix(errno
);
653 * Scan the file, a line at a time and check if the name matches.
656 while ((pwd
= getsmbfilepwent(smbpasswd_state
, fp
)) != NULL
) {
657 if (strequal(newpwd
->smb_name
, pwd
->smb_name
)) {
658 DEBUG(0, ("add_smbfilepwd_entry: entry with name %s already exists\n", pwd
->smb_name
));
659 endsmbfilepwent(fp
, &smbpasswd_state
->pw_file_lock_depth
);
660 return NT_STATUS_USER_EXISTS
;
664 /* Ok - entry doesn't exist. We can add it */
666 /* Create a new smb passwd entry and set it to the given password. */
668 * The add user write needs to be atomic - so get the fd from
669 * the fp and do a raw write() call.
673 if((offpos
= sys_lseek(fd
, 0, SEEK_END
)) == -1) {
674 NTSTATUS result
= map_nt_error_from_unix(errno
);
675 DEBUG(0, ("add_smbfilepwd_entry(sys_lseek): Failed to add entry for user %s to file %s. \
676 Error was %s\n", newpwd
->smb_name
, pfile
, strerror(errno
)));
677 endsmbfilepwent(fp
, &smbpasswd_state
->pw_file_lock_depth
);
681 if((new_entry
= format_new_smbpasswd_entry(newpwd
)) == NULL
) {
682 DEBUG(0, ("add_smbfilepwd_entry(malloc): Failed to add entry for user %s to file %s. \
683 Error was %s\n", newpwd
->smb_name
, pfile
, strerror(errno
)));
684 endsmbfilepwent(fp
, &smbpasswd_state
->pw_file_lock_depth
);
685 return NT_STATUS_NO_MEMORY
;
688 new_entry_length
= strlen(new_entry
);
690 #ifdef DEBUG_PASSWORD
691 DEBUG(100, ("add_smbfilepwd_entry(%d): new_entry_len %d made line |%s|",
692 fd
, (int)new_entry_length
, new_entry
));
695 if ((wr_len
= write(fd
, new_entry
, new_entry_length
)) != new_entry_length
) {
696 NTSTATUS result
= map_nt_error_from_unix(errno
);
697 DEBUG(0, ("add_smbfilepwd_entry(write): %d Failed to add entry for user %s to file %s. \
698 Error was %s\n", wr_len
, newpwd
->smb_name
, pfile
, strerror(errno
)));
700 /* Remove the entry we just wrote. */
701 if(sys_ftruncate(fd
, offpos
) == -1) {
702 DEBUG(0, ("add_smbfilepwd_entry: ERROR failed to ftruncate file %s. \
703 Error was %s. Password file may be corrupt ! Please examine by hand !\n",
704 newpwd
->smb_name
, strerror(errno
)));
707 endsmbfilepwent(fp
, &smbpasswd_state
->pw_file_lock_depth
);
713 endsmbfilepwent(fp
, &smbpasswd_state
->pw_file_lock_depth
);
717 /************************************************************************
718 Routine to search the smbpasswd file for an entry matching the username.
719 and then modify its password entry. We can't use the startsmbpwent()/
720 getsmbpwent()/endsmbpwent() interfaces here as we depend on looking
721 in the actual file to decide how much room we have to write data.
722 override = False, normal
723 override = True, override XXXXXXXX'd out password or NO PASS
724 ************************************************************************/
726 static bool mod_smbfilepwd_entry(struct smbpasswd_privates
*smbpasswd_state
, const struct smb_passwd
* pwd
)
728 /* Static buffers we will return. */
737 unsigned char *p
= NULL
;
738 size_t linebuf_len
= 0;
741 const char *pfile
= smbpasswd_state
->smbpasswd_file
;
742 bool found_entry
= False
;
743 bool got_pass_last_set_time
= False
;
745 SMB_OFF_T pwd_seekpos
= 0;
752 DEBUG(0, ("No SMB password file set\n"));
755 DEBUG(10, ("mod_smbfilepwd_entry: opening file %s\n", pfile
));
757 fp
= sys_fopen(pfile
, "r+");
760 DEBUG(0, ("mod_smbfilepwd_entry: unable to open file %s\n", pfile
));
763 /* Set a buffer to do more efficient reads */
764 setvbuf(fp
, readbuf
, _IOFBF
, sizeof(readbuf
));
768 if (!pw_file_lock(lockfd
, F_WRLCK
, 5, &smbpasswd_state
->pw_file_lock_depth
)) {
769 DEBUG(0, ("mod_smbfilepwd_entry: unable to lock file %s\n", pfile
));
774 /* Make sure it is only rw by the owner */
777 /* We have a write lock on the file. */
779 * Scan the file, a line at a time and check if the name matches.
782 while (status
&& !feof(fp
)) {
783 pwd_seekpos
= sys_ftell(fp
);
787 status
= fgets(linebuf
, sizeof(linebuf
), fp
);
788 if (status
== NULL
&& ferror(fp
)) {
789 pw_file_unlock(lockfd
, &smbpasswd_state
->pw_file_lock_depth
);
795 * Check if the string is terminated with a newline - if not
796 * then we must keep reading and discard until we get one.
798 linebuf_len
= strlen(linebuf
);
799 if (linebuf
[linebuf_len
- 1] != '\n') {
801 while (!ferror(fp
) && !feof(fp
)) {
808 linebuf
[linebuf_len
- 1] = '\0';
811 #ifdef DEBUG_PASSWORD
812 DEBUG(100, ("mod_smbfilepwd_entry: got line |%s|\n", linebuf
));
815 if ((linebuf
[0] == 0) && feof(fp
)) {
816 DEBUG(4, ("mod_smbfilepwd_entry: end of file reached\n"));
821 * The line we have should be of the form :-
823 * username:uid:[32hex bytes]:....other flags presently
828 * username:uid:[32hex bytes]:[32hex bytes]:[attributes]:LCT-XXXXXXXX:...ignored.
830 * if Windows NT compatible passwords are also present.
833 if (linebuf
[0] == '#' || linebuf
[0] == '\0') {
834 DEBUG(6, ("mod_smbfilepwd_entry: skipping comment or blank line\n"));
838 p
= (unsigned char *) strchr_m(linebuf
, ':');
841 DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no :)\n"));
845 strncpy(user_name
, linebuf
, PTR_DIFF(p
, linebuf
));
846 user_name
[PTR_DIFF(p
, linebuf
)] = '\0';
847 if (strequal(user_name
, pwd
->smb_name
)) {
854 pw_file_unlock(lockfd
, &smbpasswd_state
->pw_file_lock_depth
);
857 DEBUG(2, ("Cannot update entry for user %s, as they don't exist in the smbpasswd file!\n",
862 DEBUG(6, ("mod_smbfilepwd_entry: entry exists for user %s\n", pwd
->smb_name
));
864 /* User name matches - get uid and password */
865 p
++; /* Go past ':' */
868 DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry for user %s (uid not number)\n",
870 pw_file_unlock(lockfd
, &smbpasswd_state
->pw_file_lock_depth
);
875 while (*p
&& isdigit(*p
)) {
879 DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry for user %s (no : after uid)\n",
881 pw_file_unlock(lockfd
, &smbpasswd_state
->pw_file_lock_depth
);
887 * Now get the password value - this should be 32 hex digits
888 * which are the ascii representations of a 16 byte string.
889 * Get two at a time and put them into the password.
893 /* Record exact password position */
894 pwd_seekpos
+= PTR_DIFF(p
, linebuf
);
896 if (linebuf_len
< (PTR_DIFF(p
, linebuf
) + 33)) {
897 DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry for user %s (passwd too short)\n",
899 pw_file_unlock(lockfd
,&smbpasswd_state
->pw_file_lock_depth
);
905 DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry for user %s (no terminating :)\n",
907 pw_file_unlock(lockfd
,&smbpasswd_state
->pw_file_lock_depth
);
912 /* Now check if the NT compatible password is available. */
913 p
+= 33; /* Move to the first character of the line after the lanman password. */
914 if (linebuf_len
< (PTR_DIFF(p
, linebuf
) + 33)) {
915 DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry for user %s (passwd too short)\n",
917 pw_file_unlock(lockfd
,&smbpasswd_state
->pw_file_lock_depth
);
923 DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry for user %s (no terminating :)\n",
925 pw_file_unlock(lockfd
,&smbpasswd_state
->pw_file_lock_depth
);
931 * Now check if the account info and the password last
932 * change time is available.
934 p
+= 33; /* Move to the first character of the line after the NT password. */
938 encode_bits
[i
++] = *p
++;
939 while((linebuf_len
> PTR_DIFF(p
, linebuf
)) && (*p
!= ']')) {
940 encode_bits
[i
++] = *p
++;
943 encode_bits
[i
++] = ']';
944 encode_bits
[i
++] = '\0';
946 if(i
== NEW_PW_FORMAT_SPACE_PADDED_LEN
) {
948 * We are using a new format, space padded
949 * acct ctrl field. Encode the given acct ctrl
952 fstrcpy(encode_bits
, pdb_encode_acct_ctrl(pwd
->acct_ctrl
, NEW_PW_FORMAT_SPACE_PADDED_LEN
));
954 DEBUG(0,("mod_smbfilepwd_entry: Using old smbpasswd format for user %s. \
955 This is no longer supported.!\n", pwd
->smb_name
));
956 DEBUG(0,("mod_smbfilepwd_entry: No changes made, failing.!\n"));
957 pw_file_unlock(lockfd
, &smbpasswd_state
->pw_file_lock_depth
);
962 /* Go past the ']' */
963 if(linebuf_len
> PTR_DIFF(p
, linebuf
)) {
967 if((linebuf_len
> PTR_DIFF(p
, linebuf
)) && (*p
== ':')) {
970 /* We should be pointing at the LCT entry. */
971 if((linebuf_len
> (PTR_DIFF(p
, linebuf
) + 13)) && (StrnCaseCmp((char *)p
, "LCT-", 4) == 0)) {
973 for(i
= 0; i
< 8; i
++) {
974 if(p
[i
] == '\0' || !isxdigit(p
[i
])) {
980 * p points at 8 characters of hex digits -
981 * read into a time_t as the seconds since
982 * 1970 that the password was last changed.
984 got_pass_last_set_time
= True
;
986 } /* *p && StrnCaseCmp() */
990 /* Entry is correctly formed. */
992 /* Create the 32 byte representation of the new p16 */
993 pdb_sethexpwd(ascii_p16
, pwd
->smb_passwd
, pwd
->acct_ctrl
);
995 /* Add on the NT md4 hash */
998 pdb_sethexpwd(ascii_p16
+33, pwd
->smb_nt_passwd
, pwd
->acct_ctrl
);
1000 ascii_p16
[66] = '\0'; /* null-terminate the string so that strlen works */
1002 /* Add on the account info bits and the time of last password change. */
1003 if(got_pass_last_set_time
) {
1004 slprintf(&ascii_p16
[strlen(ascii_p16
)],
1005 sizeof(ascii_p16
)-(strlen(ascii_p16
)+1),
1007 encode_bits
, (uint32_t)pwd
->pass_last_set_time
);
1008 wr_len
= strlen(ascii_p16
);
1011 #ifdef DEBUG_PASSWORD
1012 DEBUG(100,("mod_smbfilepwd_entry: "));
1013 dump_data(100, (uint8
*)ascii_p16
, wr_len
);
1016 if(wr_len
> sizeof(linebuf
)) {
1017 DEBUG(0, ("mod_smbfilepwd_entry: line to write (%d) is too long.\n", wr_len
+1));
1018 pw_file_unlock(lockfd
,&smbpasswd_state
->pw_file_lock_depth
);
1024 * Do an atomic write into the file at the position defined by
1028 /* The mod user write needs to be atomic - so get the fd from
1029 the fp and do a raw write() call.
1034 if (sys_lseek(fd
, pwd_seekpos
- 1, SEEK_SET
) != pwd_seekpos
- 1) {
1035 DEBUG(0, ("mod_smbfilepwd_entry: seek fail on file %s.\n", pfile
));
1036 pw_file_unlock(lockfd
,&smbpasswd_state
->pw_file_lock_depth
);
1041 /* Sanity check - ensure the areas we are writing are framed by ':' */
1042 if (read(fd
, linebuf
, wr_len
+1) != wr_len
+1) {
1043 DEBUG(0, ("mod_smbfilepwd_entry: read fail on file %s.\n", pfile
));
1044 pw_file_unlock(lockfd
,&smbpasswd_state
->pw_file_lock_depth
);
1049 if ((linebuf
[0] != ':') || (linebuf
[wr_len
] != ':')) {
1050 DEBUG(0, ("mod_smbfilepwd_entry: check on passwd file %s failed.\n", pfile
));
1051 pw_file_unlock(lockfd
,&smbpasswd_state
->pw_file_lock_depth
);
1056 if (sys_lseek(fd
, pwd_seekpos
, SEEK_SET
) != pwd_seekpos
) {
1057 DEBUG(0, ("mod_smbfilepwd_entry: seek fail on file %s.\n", pfile
));
1058 pw_file_unlock(lockfd
,&smbpasswd_state
->pw_file_lock_depth
);
1063 if (write(fd
, ascii_p16
, wr_len
) != wr_len
) {
1064 DEBUG(0, ("mod_smbfilepwd_entry: write failed in passwd file %s\n", pfile
));
1065 pw_file_unlock(lockfd
,&smbpasswd_state
->pw_file_lock_depth
);
1070 pw_file_unlock(lockfd
,&smbpasswd_state
->pw_file_lock_depth
);
1075 /************************************************************************
1076 Routine to delete an entry in the smbpasswd file by name.
1077 *************************************************************************/
1079 static bool del_smbfilepwd_entry(struct smbpasswd_privates
*smbpasswd_state
, const char *name
)
1081 const char *pfile
= smbpasswd_state
->smbpasswd_file
;
1082 char *pfile2
= NULL
;
1083 struct smb_passwd
*pwd
= NULL
;
1085 FILE *fp_write
= NULL
;
1086 int pfile2_lockdepth
= 0;
1088 pfile2
= talloc_asprintf(talloc_tos(),
1090 pfile
, (unsigned)sys_getpid());
1096 * Open the smbpassword file - for update. It needs to be update
1097 * as we need any other processes to wait until we have replaced
1101 if((fp
= startsmbfilepwent(pfile
, PWF_UPDATE
, &smbpasswd_state
->pw_file_lock_depth
)) == NULL
) {
1102 DEBUG(0, ("del_smbfilepwd_entry: unable to open file %s.\n", pfile
));
1107 * Create the replacement password file.
1109 if((fp_write
= startsmbfilepwent(pfile2
, PWF_CREATE
, &pfile2_lockdepth
)) == NULL
) {
1110 DEBUG(0, ("del_smbfilepwd_entry: unable to open file %s.\n", pfile
));
1111 endsmbfilepwent(fp
, &smbpasswd_state
->pw_file_lock_depth
);
1116 * Scan the file, a line at a time and check if the name matches.
1119 while ((pwd
= getsmbfilepwent(smbpasswd_state
, fp
)) != NULL
) {
1121 size_t new_entry_length
;
1123 if (strequal(name
, pwd
->smb_name
)) {
1124 DEBUG(10, ("del_smbfilepwd_entry: found entry with "
1125 "name %s - deleting it.\n", name
));
1130 * We need to copy the entry out into the second file.
1133 if((new_entry
= format_new_smbpasswd_entry(pwd
)) == NULL
) {
1134 DEBUG(0, ("del_smbfilepwd_entry(malloc): Failed to copy entry for user %s to file %s. \
1135 Error was %s\n", pwd
->smb_name
, pfile2
, strerror(errno
)));
1137 endsmbfilepwent(fp
, &smbpasswd_state
->pw_file_lock_depth
);
1138 endsmbfilepwent(fp_write
, &pfile2_lockdepth
);
1142 new_entry_length
= strlen(new_entry
);
1144 if(fwrite(new_entry
, 1, new_entry_length
, fp_write
) != new_entry_length
) {
1145 DEBUG(0, ("del_smbfilepwd_entry(write): Failed to copy entry for user %s to file %s. \
1146 Error was %s\n", pwd
->smb_name
, pfile2
, strerror(errno
)));
1148 endsmbfilepwent(fp
, &smbpasswd_state
->pw_file_lock_depth
);
1149 endsmbfilepwent(fp_write
, &pfile2_lockdepth
);
1158 * Ensure pfile2 is flushed before rename.
1161 if(fflush(fp_write
) != 0) {
1162 DEBUG(0, ("del_smbfilepwd_entry: Failed to flush file %s. Error was %s\n", pfile2
, strerror(errno
)));
1163 endsmbfilepwent(fp
, &smbpasswd_state
->pw_file_lock_depth
);
1164 endsmbfilepwent(fp_write
,&pfile2_lockdepth
);
1169 * Do an atomic rename - then release the locks.
1172 if(rename(pfile2
,pfile
) != 0) {
1176 endsmbfilepwent(fp
, &smbpasswd_state
->pw_file_lock_depth
);
1177 endsmbfilepwent(fp_write
,&pfile2_lockdepth
);
1181 /*********************************************************************
1182 Create a smb_passwd struct from a struct samu.
1183 We will not allocate any new memory. The smb_passwd struct
1184 should only stay around as long as the struct samu does.
1185 ********************************************************************/
1187 static bool build_smb_pass (struct smb_passwd
*smb_pw
, const struct samu
*sampass
)
1191 if (sampass
== NULL
)
1193 ZERO_STRUCTP(smb_pw
);
1195 if (!IS_SAM_DEFAULT(sampass
, PDB_USERSID
)) {
1196 rid
= pdb_get_user_rid(sampass
);
1198 /* If the user specified a RID, make sure its able to be both stored and retreived */
1199 if (rid
== DOMAIN_RID_GUEST
) {
1200 struct passwd
*passwd
= getpwnam_alloc(NULL
, lp_guestaccount());
1202 DEBUG(0, ("Could not find guest account via getpwnam()! (%s)\n", lp_guestaccount()));
1205 smb_pw
->smb_userid
=passwd
->pw_uid
;
1206 TALLOC_FREE(passwd
);
1207 } else if (algorithmic_pdb_rid_is_user(rid
)) {
1208 smb_pw
->smb_userid
=algorithmic_pdb_user_rid_to_uid(rid
);
1210 DEBUG(0,("build_sam_pass: Failing attempt to store user with non-uid based user RID. \n"));
1215 smb_pw
->smb_name
=(const char*)pdb_get_username(sampass
);
1217 smb_pw
->smb_passwd
=pdb_get_lanman_passwd(sampass
);
1218 smb_pw
->smb_nt_passwd
=pdb_get_nt_passwd(sampass
);
1220 smb_pw
->acct_ctrl
=pdb_get_acct_ctrl(sampass
);
1221 smb_pw
->pass_last_set_time
=pdb_get_pass_last_set_time(sampass
);
1226 /*********************************************************************
1227 Create a struct samu from a smb_passwd struct
1228 ********************************************************************/
1230 static bool build_sam_account(struct smbpasswd_privates
*smbpasswd_state
,
1231 struct samu
*sam_pass
, const struct smb_passwd
*pw_buf
)
1233 struct passwd
*pwfile
;
1236 DEBUG(5,("build_sam_account: struct samu is NULL\n"));
1240 /* verify the user account exists */
1242 if ( !(pwfile
= Get_Pwnam_alloc(NULL
, pw_buf
->smb_name
)) ) {
1243 DEBUG(0,("build_sam_account: smbpasswd database is corrupt! username %s with uid "
1244 "%u is not in unix passwd database!\n", pw_buf
->smb_name
, pw_buf
->smb_userid
));
1248 if ( !NT_STATUS_IS_OK( samu_set_unix(sam_pass
, pwfile
)) )
1251 TALLOC_FREE(pwfile
);
1253 /* set remaining fields */
1255 if (!pdb_set_nt_passwd (sam_pass
, pw_buf
->smb_nt_passwd
, PDB_SET
))
1257 if (!pdb_set_lanman_passwd (sam_pass
, pw_buf
->smb_passwd
, PDB_SET
))
1259 pdb_set_acct_ctrl (sam_pass
, pw_buf
->acct_ctrl
, PDB_SET
);
1260 pdb_set_pass_last_set_time (sam_pass
, pw_buf
->pass_last_set_time
, PDB_SET
);
1261 pdb_set_pass_can_change_time (sam_pass
, pw_buf
->pass_last_set_time
, PDB_SET
);
1266 /*****************************************************************
1267 Functions to be implemented by the new passdb API
1268 ****************************************************************/
1270 /****************************************************************
1271 Search smbpasswd file by iterating over the entries. Do not
1272 call getpwnam() for unix account information until we have found
1274 ***************************************************************/
1276 static NTSTATUS
smbpasswd_getsampwnam(struct pdb_methods
*my_methods
,
1277 struct samu
*sam_acct
, const char *username
)
1279 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
1280 struct smbpasswd_privates
*smbpasswd_state
= (struct smbpasswd_privates
*)my_methods
->private_data
;
1281 struct smb_passwd
*smb_pw
;
1284 DEBUG(10, ("getsampwnam (smbpasswd): search by name: %s\n", username
));
1286 /* startsmbfilepwent() is used here as we don't want to lookup
1287 the UNIX account in the local system password file until
1289 fp
= startsmbfilepwent(smbpasswd_state
->smbpasswd_file
, PWF_READ
, &(smbpasswd_state
->pw_file_lock_depth
));
1292 DEBUG(0, ("Unable to open passdb database.\n"));
1296 while ( ((smb_pw
=getsmbfilepwent(smbpasswd_state
, fp
)) != NULL
)&& (!strequal(smb_pw
->smb_name
, username
)) )
1297 /* do nothing....another loop */ ;
1299 endsmbfilepwent(fp
, &(smbpasswd_state
->pw_file_lock_depth
));
1302 /* did we locate the username in smbpasswd */
1306 DEBUG(10, ("getsampwnam (smbpasswd): found by name: %s\n", smb_pw
->smb_name
));
1309 DEBUG(10,("getsampwnam (smbpasswd): struct samu is NULL\n"));
1313 /* now build the struct samu */
1314 if (!build_sam_account(smbpasswd_state
, sam_acct
, smb_pw
))
1318 return NT_STATUS_OK
;
1321 static NTSTATUS
smbpasswd_getsampwsid(struct pdb_methods
*my_methods
, struct samu
*sam_acct
, const struct dom_sid
*sid
)
1323 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
1324 struct smbpasswd_privates
*smbpasswd_state
= (struct smbpasswd_privates
*)my_methods
->private_data
;
1325 struct smb_passwd
*smb_pw
;
1329 DEBUG(10, ("smbpasswd_getsampwrid: search by sid: %s\n",
1330 sid_string_dbg(sid
)));
1332 if (!sid_peek_check_rid(get_global_sam_sid(), sid
, &rid
))
1333 return NT_STATUS_UNSUCCESSFUL
;
1335 /* More special case 'guest account' hacks... */
1336 if (rid
== DOMAIN_RID_GUEST
) {
1337 const char *guest_account
= lp_guestaccount();
1338 if (!(guest_account
&& *guest_account
)) {
1339 DEBUG(1, ("Guest account not specfied!\n"));
1342 return smbpasswd_getsampwnam(my_methods
, sam_acct
, guest_account
);
1345 /* Open the sam password file - not for update. */
1346 fp
= startsmbfilepwent(smbpasswd_state
->smbpasswd_file
, PWF_READ
, &(smbpasswd_state
->pw_file_lock_depth
));
1349 DEBUG(0, ("Unable to open passdb database.\n"));
1353 while ( ((smb_pw
=getsmbfilepwent(smbpasswd_state
, fp
)) != NULL
) && (algorithmic_pdb_uid_to_user_rid(smb_pw
->smb_userid
) != rid
) )
1356 endsmbfilepwent(fp
, &(smbpasswd_state
->pw_file_lock_depth
));
1359 /* did we locate the username in smbpasswd */
1363 DEBUG(10, ("getsampwrid (smbpasswd): found by name: %s\n", smb_pw
->smb_name
));
1366 DEBUG(10,("getsampwrid: (smbpasswd) struct samu is NULL\n"));
1370 /* now build the struct samu */
1371 if (!build_sam_account (smbpasswd_state
, sam_acct
, smb_pw
))
1374 /* build_sam_account might change the SID on us, if the name was for the guest account */
1375 if (NT_STATUS_IS_OK(nt_status
) && !sid_equal(pdb_get_user_sid(sam_acct
), sid
)) {
1376 DEBUG(1, ("looking for user with sid %s instead returned %s "
1377 "for account %s!?!\n", sid_string_dbg(sid
),
1378 sid_string_dbg(pdb_get_user_sid(sam_acct
)),
1379 pdb_get_username(sam_acct
)));
1380 return NT_STATUS_NO_SUCH_USER
;
1384 return NT_STATUS_OK
;
1387 static NTSTATUS
smbpasswd_add_sam_account(struct pdb_methods
*my_methods
, struct samu
*sampass
)
1389 struct smbpasswd_privates
*smbpasswd_state
= (struct smbpasswd_privates
*)my_methods
->private_data
;
1390 struct smb_passwd smb_pw
;
1392 /* convert the struct samu */
1393 if (!build_smb_pass(&smb_pw
, sampass
)) {
1394 return NT_STATUS_UNSUCCESSFUL
;
1398 return add_smbfilepwd_entry(smbpasswd_state
, &smb_pw
);
1401 static NTSTATUS
smbpasswd_update_sam_account(struct pdb_methods
*my_methods
, struct samu
*sampass
)
1403 struct smbpasswd_privates
*smbpasswd_state
= (struct smbpasswd_privates
*)my_methods
->private_data
;
1404 struct smb_passwd smb_pw
;
1406 /* convert the struct samu */
1407 if (!build_smb_pass(&smb_pw
, sampass
)) {
1408 DEBUG(0, ("smbpasswd_update_sam_account: build_smb_pass failed!\n"));
1409 return NT_STATUS_UNSUCCESSFUL
;
1412 /* update the entry */
1413 if(!mod_smbfilepwd_entry(smbpasswd_state
, &smb_pw
)) {
1414 DEBUG(0, ("smbpasswd_update_sam_account: mod_smbfilepwd_entry failed!\n"));
1415 return NT_STATUS_UNSUCCESSFUL
;
1418 return NT_STATUS_OK
;
1421 static NTSTATUS
smbpasswd_delete_sam_account (struct pdb_methods
*my_methods
, struct samu
*sampass
)
1423 struct smbpasswd_privates
*smbpasswd_state
= (struct smbpasswd_privates
*)my_methods
->private_data
;
1425 const char *username
= pdb_get_username(sampass
);
1427 if (del_smbfilepwd_entry(smbpasswd_state
, username
))
1428 return NT_STATUS_OK
;
1430 return NT_STATUS_UNSUCCESSFUL
;
1433 static NTSTATUS
smbpasswd_rename_sam_account (struct pdb_methods
*my_methods
,
1434 struct samu
*old_acct
,
1435 const char *newname
)
1437 char *rename_script
= NULL
;
1438 struct samu
*new_acct
= NULL
;
1439 bool interim_account
= False
;
1440 TALLOC_CTX
*ctx
= talloc_tos();
1441 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
1443 if (!*(lp_renameuser_script()))
1446 if ( !(new_acct
= samu_new( NULL
)) ) {
1447 return NT_STATUS_NO_MEMORY
;
1450 if ( !pdb_copy_sam_account( new_acct
, old_acct
)
1451 || !pdb_set_username(new_acct
, newname
, PDB_CHANGED
))
1456 ret
= smbpasswd_add_sam_account(my_methods
, new_acct
);
1457 if (!NT_STATUS_IS_OK(ret
))
1460 interim_account
= True
;
1462 /* rename the posix user */
1463 rename_script
= talloc_strdup(ctx
,
1464 lp_renameuser_script());
1465 if (!rename_script
) {
1466 ret
= NT_STATUS_NO_MEMORY
;
1470 if (*rename_script
) {
1473 rename_script
= talloc_string_sub2(ctx
,
1480 if (!rename_script
) {
1481 ret
= NT_STATUS_NO_MEMORY
;
1484 rename_script
= talloc_string_sub2(ctx
,
1487 pdb_get_username(old_acct
),
1491 if (!rename_script
) {
1492 ret
= NT_STATUS_NO_MEMORY
;
1496 rename_ret
= smbrun(rename_script
, NULL
);
1498 DEBUG(rename_ret
? 0 : 3,("Running the command `%s' gave %d\n", rename_script
, rename_ret
));
1500 if (rename_ret
== 0) {
1501 smb_nscd_flush_user_cache();
1510 smbpasswd_delete_sam_account(my_methods
, old_acct
);
1511 interim_account
= False
;
1515 if (interim_account
)
1516 smbpasswd_delete_sam_account(my_methods
, new_acct
);
1519 TALLOC_FREE(new_acct
);
1524 static uint32_t smbpasswd_capabilities(struct pdb_methods
*methods
)
1529 static void free_private_data(void **vp
)
1531 struct smbpasswd_privates
**privates
= (struct smbpasswd_privates
**)vp
;
1533 endsmbfilepwent((*privates
)->pw_file
, &((*privates
)->pw_file_lock_depth
));
1536 /* No need to free any further, as it is talloc()ed */
1539 struct smbpasswd_search_state
{
1540 uint32_t acct_flags
;
1542 struct samr_displayentry
*entries
;
1543 uint32_t num_entries
;
1548 static void smbpasswd_search_end(struct pdb_search
*search
)
1550 struct smbpasswd_search_state
*state
= talloc_get_type_abort(
1551 search
->private_data
, struct smbpasswd_search_state
);
1555 static bool smbpasswd_search_next_entry(struct pdb_search
*search
,
1556 struct samr_displayentry
*entry
)
1558 struct smbpasswd_search_state
*state
= talloc_get_type_abort(
1559 search
->private_data
, struct smbpasswd_search_state
);
1561 if (state
->current
== state
->num_entries
) {
1565 entry
->idx
= state
->entries
[state
->current
].idx
;
1566 entry
->rid
= state
->entries
[state
->current
].rid
;
1567 entry
->acct_flags
= state
->entries
[state
->current
].acct_flags
;
1569 entry
->account_name
= talloc_strdup(
1570 search
, state
->entries
[state
->current
].account_name
);
1571 entry
->fullname
= talloc_strdup(
1572 search
, state
->entries
[state
->current
].fullname
);
1573 entry
->description
= talloc_strdup(
1574 search
, state
->entries
[state
->current
].description
);
1576 if ((entry
->account_name
== NULL
) || (entry
->fullname
== NULL
)
1577 || (entry
->description
== NULL
)) {
1578 DEBUG(0, ("talloc_strdup failed\n"));
1582 state
->current
+= 1;
1586 static bool smbpasswd_search_users(struct pdb_methods
*methods
,
1587 struct pdb_search
*search
,
1588 uint32_t acct_flags
)
1590 struct smbpasswd_privates
*smbpasswd_state
=
1591 (struct smbpasswd_privates
*)methods
->private_data
;
1593 struct smbpasswd_search_state
*search_state
;
1594 struct smb_passwd
*pwd
;
1597 search_state
= talloc_zero(search
, struct smbpasswd_search_state
);
1598 if (search_state
== NULL
) {
1599 DEBUG(0, ("talloc failed\n"));
1602 search_state
->acct_flags
= acct_flags
;
1604 fp
= startsmbfilepwent(smbpasswd_state
->smbpasswd_file
, PWF_READ
,
1605 &smbpasswd_state
->pw_file_lock_depth
);
1608 DEBUG(10, ("Unable to open smbpasswd file.\n"));
1609 TALLOC_FREE(search_state
);
1613 while ((pwd
= getsmbfilepwent(smbpasswd_state
, fp
)) != NULL
) {
1614 struct samr_displayentry entry
;
1617 if ((acct_flags
!= 0)
1618 && ((acct_flags
& pwd
->acct_ctrl
) == 0)) {
1622 user
= samu_new(talloc_tos());
1624 DEBUG(0, ("samu_new failed\n"));
1628 if (!build_sam_account(smbpasswd_state
, user
, pwd
)) {
1629 /* Already got debug msgs... */
1635 entry
.acct_flags
= pdb_get_acct_ctrl(user
);
1636 sid_peek_rid(pdb_get_user_sid(user
), &entry
.rid
);
1637 entry
.account_name
= talloc_strdup(
1638 search_state
, pdb_get_username(user
));
1639 entry
.fullname
= talloc_strdup(
1640 search_state
, pdb_get_fullname(user
));
1641 entry
.description
= talloc_strdup(
1642 search_state
, pdb_get_acct_desc(user
));
1646 if ((entry
.account_name
== NULL
) || (entry
.fullname
== NULL
)
1647 || (entry
.description
== NULL
)) {
1648 DEBUG(0, ("talloc_strdup failed\n"));
1652 ADD_TO_LARGE_ARRAY(search_state
, struct samr_displayentry
,
1653 entry
, &search_state
->entries
,
1654 &search_state
->num_entries
,
1655 &search_state
->array_size
);
1658 endsmbfilepwent(fp
, &(smbpasswd_state
->pw_file_lock_depth
));
1660 search
->private_data
= search_state
;
1661 search
->next_entry
= smbpasswd_search_next_entry
;
1662 search
->search_end
= smbpasswd_search_end
;
1667 static NTSTATUS
pdb_init_smbpasswd( struct pdb_methods
**pdb_method
, const char *location
)
1670 struct smbpasswd_privates
*privates
;
1672 if ( !NT_STATUS_IS_OK(nt_status
= make_pdb_method( pdb_method
)) ) {
1676 (*pdb_method
)->name
= "smbpasswd";
1678 (*pdb_method
)->getsampwnam
= smbpasswd_getsampwnam
;
1679 (*pdb_method
)->getsampwsid
= smbpasswd_getsampwsid
;
1680 (*pdb_method
)->add_sam_account
= smbpasswd_add_sam_account
;
1681 (*pdb_method
)->update_sam_account
= smbpasswd_update_sam_account
;
1682 (*pdb_method
)->delete_sam_account
= smbpasswd_delete_sam_account
;
1683 (*pdb_method
)->rename_sam_account
= smbpasswd_rename_sam_account
;
1684 (*pdb_method
)->search_users
= smbpasswd_search_users
;
1686 (*pdb_method
)->capabilities
= smbpasswd_capabilities
;
1688 /* Setup private data and free function */
1690 if ( !(privates
= TALLOC_ZERO_P( *pdb_method
, struct smbpasswd_privates
)) ) {
1691 DEBUG(0, ("talloc() failed for smbpasswd private_data!\n"));
1692 return NT_STATUS_NO_MEMORY
;
1695 /* Store some config details */
1698 privates
->smbpasswd_file
= talloc_strdup(*pdb_method
, location
);
1700 privates
->smbpasswd_file
= talloc_strdup(*pdb_method
, lp_smb_passwd_file());
1703 if (!privates
->smbpasswd_file
) {
1704 DEBUG(0, ("talloc_strdp() failed for storing smbpasswd location!\n"));
1705 return NT_STATUS_NO_MEMORY
;
1708 (*pdb_method
)->private_data
= privates
;
1710 (*pdb_method
)->free_private_data
= free_private_data
;
1712 return NT_STATUS_OK
;
1715 NTSTATUS
pdb_smbpasswd_init(void)
1717 return smb_register_passdb(PASSDB_INTERFACE_VERSION
, "smbpasswd", pdb_init_smbpasswd
);