2 * Unix SMB/Netbios implementation.
3 * Version 1.9. 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
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 2 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, write to the Free Software Foundation, Inc., 675
21 * Mass Ave, Cambridge, MA 02139, USA.
28 smb_passwd is analogous to sam_passwd used everywhere
29 else. However, smb_passwd is limited to the information
30 stored by an smbpasswd entry
35 BOOL smb_userid_set; /* this is actually the unix uid_t */
36 uint32 smb_userid; /* this is actually the unix uid_t */
37 const char *smb_name; /* username string */
39 const unsigned char *smb_passwd; /* Null if no password */
40 const unsigned char *smb_nt_passwd; /* Null if no password */
42 uint16 acct_ctrl; /* account info (ACB_xxxx bit-mask) */
43 time_t pass_last_set_time; /* password last set time */
46 struct smbpasswd_privates
48 /* used for maintain locks on the smbpasswd file */
49 int pw_file_lock_depth;
51 /* Global File pointer */
54 /* formerly static variables */
55 struct smb_passwd pw_buf;
57 unsigned char smbpwd[16];
58 unsigned char smbntpwd[16];
60 /* retrive-once info */
61 const char *smbpasswd_file;
63 BOOL permit_non_unix_accounts;
65 uint32 low_nua_userid;
66 uint32 high_nua_userid;
70 enum pwf_access_type { PWF_READ, PWF_UPDATE, PWF_CREATE };
72 /***************************************************************
73 Lock an fd. Abandon after waitsecs seconds.
74 ****************************************************************/
76 static BOOL pw_file_lock(int fd, int type, int secs, int *plock_depth)
81 if(*plock_depth == 0) {
82 if (!do_file_lock(fd, secs, type)) {
83 DEBUG(10,("pw_file_lock: locking file failed, error = %s.\n",
94 /***************************************************************
95 Unlock an fd. Abandon after waitsecs seconds.
96 ****************************************************************/
98 static BOOL pw_file_unlock(int fd, int *plock_depth)
102 if(*plock_depth == 1)
103 ret = do_file_lock(fd, 5, F_UNLCK);
105 if (*plock_depth > 0)
109 DEBUG(10,("pw_file_unlock: unlocking file failed, error = %s.\n",
115 /**************************************************************
116 Intialize a smb_passwd struct
117 *************************************************************/
119 static void pdb_init_smb(struct smb_passwd *user)
125 user->pass_last_set_time = (time_t)0;
128 /***************************************************************
129 Internal fn to enumerate the smbpasswd list. Returns a void pointer
130 to ensure no modification outside this module. Checks for atomic
131 rename of smbpasswd file on update or create once the lock has
132 been granted to prevent race conditions. JRA.
133 ****************************************************************/
135 static FILE *startsmbfilepwent(const char *pfile, enum pwf_access_type type, int *lock_depth)
138 const char *open_mode = NULL;
140 int lock_type = F_RDLCK;
143 DEBUG(0, ("startsmbfilepwent: No SMB password file set\n"));
158 * Ensure atomic file creation.
163 for(i = 0; i < 5; i++) {
164 if((fd = sys_open(pfile, O_CREAT|O_TRUNC|O_EXCL|O_RDWR, 0600))!=-1)
166 sys_usleep(200); /* Spin, spin... */
169 DEBUG(0,("startsmbfilepwent_internal: too many race conditions creating file %s\n", pfile));
179 for(race_loop = 0; race_loop < 5; race_loop++) {
180 DEBUG(10, ("startsmbfilepwent_internal: opening file %s\n", pfile));
182 if((fp = sys_fopen(pfile, open_mode)) == NULL) {
183 DEBUG(2, ("startsmbfilepwent_internal: unable to open file %s. Error was %s\n", pfile, strerror(errno) ));
187 if (!pw_file_lock(fileno(fp), lock_type, 5, lock_depth)) {
188 DEBUG(0, ("startsmbfilepwent_internal: unable to lock file %s. Error was %s\n", pfile, strerror(errno) ));
194 * Only check for replacement races on update or create.
195 * For read we don't mind if the data is one record out of date.
198 if(type == PWF_READ) {
201 SMB_STRUCT_STAT sbuf1, sbuf2;
204 * Avoid the potential race condition between the open and the lock
205 * by doing a stat on the filename and an fstat on the fd. If the
206 * two inodes differ then someone did a rename between the open and
207 * the lock. Back off and try the open again. Only do this 5 times to
208 * prevent infinate loops. JRA.
211 if (sys_stat(pfile,&sbuf1) != 0) {
212 DEBUG(0, ("startsmbfilepwent_internal: unable to stat file %s. Error was %s\n", pfile, strerror(errno)));
213 pw_file_unlock(fileno(fp), lock_depth);
218 if (sys_fstat(fileno(fp),&sbuf2) != 0) {
219 DEBUG(0, ("startsmbfilepwent_internal: unable to fstat file %s. Error was %s\n", pfile, strerror(errno)));
220 pw_file_unlock(fileno(fp), lock_depth);
225 if( sbuf1.st_ino == sbuf2.st_ino) {
231 * Race occurred - back off and try again...
234 pw_file_unlock(fileno(fp), lock_depth);
240 DEBUG(0, ("startsmbfilepwent_internal: too many race conditions opening file %s\n", pfile));
244 /* Set a buffer to do more efficient reads */
245 setvbuf(fp, (char *)NULL, _IOFBF, 1024);
247 /* Make sure it is only rw by the owner */
248 if(fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1) {
249 DEBUG(0, ("startsmbfilepwent_internal: failed to set 0600 permissions on password file %s. \
250 Error was %s\n.", pfile, strerror(errno) ));
251 pw_file_unlock(fileno(fp), lock_depth);
256 /* We have a lock on the file. */
260 /***************************************************************
261 End enumeration of the smbpasswd list.
262 ****************************************************************/
263 static void endsmbfilepwent(FILE *fp, int *lock_depth)
266 pw_file_unlock(fileno(fp), lock_depth);
268 DEBUG(7, ("endsmbfilepwent_internal: closed password file.\n"));
271 /*************************************************************************
272 Routine to return the next entry in the smbpasswd list.
273 *************************************************************************/
275 static struct smb_passwd *getsmbfilepwent(struct smbpasswd_privates *smbpasswd_state, FILE *fp)
277 /* Static buffers we will return. */
278 struct smb_passwd *pw_buf = &smbpasswd_state->pw_buf;
279 char *user_name = smbpasswd_state->user_name;
280 unsigned char *smbpwd = smbpasswd_state->smbpwd;
281 unsigned char *smbntpwd = smbpasswd_state->smbntpwd;
289 DEBUG(0,("getsmbfilepwent: Bad password file pointer.\n"));
293 pdb_init_smb(pw_buf);
295 pw_buf->acct_ctrl = ACB_NORMAL;
298 * Scan the file, a line at a time and check if the name matches.
303 fgets(linebuf, 256, fp);
309 * Check if the string is terminated with a newline - if not
310 * then we must keep reading and discard until we get one.
312 if ((linebuf_len = strlen(linebuf)) == 0)
315 if (linebuf[linebuf_len - 1] != '\n') {
317 while (!ferror(fp) && !feof(fp)) {
323 linebuf[linebuf_len - 1] = '\0';
325 #ifdef DEBUG_PASSWORD
326 DEBUG(100, ("getsmbfilepwent: got line |%s|\n", linebuf));
328 if ((linebuf[0] == 0) && feof(fp)) {
329 DEBUG(4, ("getsmbfilepwent: end of file reached\n"));
333 * The line we have should be of the form :-
335 * username:uid:32hex bytes:[Account type]:LCT-12345678....other flags presently
340 * username:uid:32hex bytes:32hex bytes:[Account type]:LCT-12345678....ignored....
342 * if Windows NT compatible passwords are also present.
343 * [Account type] is an ascii encoding of the type of account.
344 * LCT-(8 hex digits) is the time_t value of the last change time.
347 if (linebuf[0] == '#' || linebuf[0] == '\0') {
348 DEBUG(6, ("getsmbfilepwent: skipping comment or blank line\n"));
351 p = (unsigned char *) strchr_m(linebuf, ':');
353 DEBUG(0, ("getsmbfilepwent: malformed password entry (no :)\n"));
357 * As 256 is shorter than a pstring we don't need to check
358 * length here - if this ever changes....
360 strncpy(user_name, linebuf, PTR_DIFF(p, linebuf));
361 user_name[PTR_DIFF(p, linebuf)] = '\0';
365 p++; /* Go past ':' */
368 DEBUG(0, ("getsmbfilepwent: uids in the smbpasswd file must not be negative.\n"));
373 DEBUG(0, ("getsmbfilepwent: malformed password entry (uid not number)\n"));
377 uidval = atoi((char *) p);
379 while (*p && isdigit(*p))
383 DEBUG(0, ("getsmbfilepwent: malformed password entry (no : after uid)\n"));
387 pw_buf->smb_name = user_name;
388 pw_buf->smb_userid = uidval;
391 * Now get the password value - this should be 32 hex digits
392 * which are the ascii representations of a 16 byte string.
393 * Get two at a time and put them into the password.
399 if (*p == '*' || *p == 'X') {
400 /* Password deliberately invalid - end here. */
401 DEBUG(10, ("getsmbfilepwent: entry invalidated for user %s\n", user_name));
402 pw_buf->smb_nt_passwd = NULL;
403 pw_buf->smb_passwd = NULL;
404 pw_buf->acct_ctrl |= ACB_DISABLED;
408 if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
409 DEBUG(0, ("getsmbfilepwent: malformed password entry (passwd too short)\n"));
414 DEBUG(0, ("getsmbfilepwent: malformed password entry (no terminating :)\n"));
418 if (!strncasecmp((char *) p, "NO PASSWORD", 11)) {
419 pw_buf->smb_passwd = NULL;
420 pw_buf->acct_ctrl |= ACB_PWNOTREQ;
422 if (!pdb_gethexpwd((char *)p, smbpwd)) {
423 DEBUG(0, ("getsmbfilepwent: Malformed Lanman password entry (non hex chars)\n"));
426 pw_buf->smb_passwd = smbpwd;
430 * Now check if the NT compatible password is
433 pw_buf->smb_nt_passwd = NULL;
435 p += 33; /* Move to the first character of the line after
436 the lanman password. */
437 if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) {
438 if (*p != '*' && *p != 'X') {
439 if(pdb_gethexpwd((char *)p,smbntpwd))
440 pw_buf->smb_nt_passwd = smbntpwd;
442 p += 33; /* Move to the first character of the line after
446 DEBUG(5,("getsmbfilepwent: returning passwd entry for user %s, uid %ld\n",
451 unsigned char *end_p = (unsigned char *)strchr_m((char *)p, ']');
452 pw_buf->acct_ctrl = pdb_decode_acct_ctrl((char*)p);
454 /* Must have some account type set. */
455 if(pw_buf->acct_ctrl == 0)
456 pw_buf->acct_ctrl = ACB_NORMAL;
458 /* Now try and get the last change time. */
463 if(*p && (StrnCaseCmp((char *)p, "LCT-", 4)==0)) {
466 for(i = 0; i < 8; i++) {
467 if(p[i] == '\0' || !isxdigit(p[i]))
472 * p points at 8 characters of hex digits -
473 * read into a time_t as the seconds since
474 * 1970 that the password was last changed.
476 pw_buf->pass_last_set_time = (time_t)strtol((char *)p, NULL, 16);
481 /* 'Old' style file. Fake up based on user name. */
483 * Currently trust accounts are kept in the same
484 * password file as 'normal accounts'. If this changes
485 * we will have to fix this code. JRA.
487 if(pw_buf->smb_name[strlen(pw_buf->smb_name) - 1] == '$') {
488 pw_buf->acct_ctrl &= ~ACB_NORMAL;
489 pw_buf->acct_ctrl |= ACB_WSTRUST;
496 DEBUG(5,("getsmbfilepwent: end of file reached.\n"));
500 /************************************************************************
501 Create a new smbpasswd entry - malloced space returned.
502 *************************************************************************/
504 static char *format_new_smbpasswd_entry(const struct smb_passwd *newpwd)
506 int new_entry_length;
511 new_entry_length = strlen(newpwd->smb_name) + 1 + 15 + 1 + 32 + 1 + 32 + 1 + NEW_PW_FORMAT_SPACE_PADDED_LEN + 1 + 13 + 2;
513 if((new_entry = (char *)malloc( new_entry_length )) == NULL) {
514 DEBUG(0, ("format_new_smbpasswd_entry: Malloc failed adding entry for user %s.\n", newpwd->smb_name ));
518 slprintf(new_entry, new_entry_length - 1, "%s:%u:", newpwd->smb_name, (unsigned)newpwd->smb_userid);
519 p = &new_entry[strlen(new_entry)];
521 if(newpwd->smb_passwd != NULL) {
522 for( i = 0; i < 16; i++) {
523 slprintf((char *)&p[i*2], new_entry_length - (p - new_entry) - 1, "%02X", newpwd->smb_passwd[i]);
527 if(newpwd->acct_ctrl & ACB_PWNOTREQ)
528 safe_strcpy((char *)p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", new_entry_length - 1 - (p - new_entry));
530 safe_strcpy((char *)p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", new_entry_length - 1 - (p - new_entry));
537 if(newpwd->smb_nt_passwd != NULL) {
538 for( i = 0; i < 16; i++) {
539 slprintf((char *)&p[i*2], new_entry_length - 1 - (p - new_entry), "%02X", newpwd->smb_nt_passwd[i]);
542 if(newpwd->acct_ctrl & ACB_PWNOTREQ)
543 safe_strcpy((char *)p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", new_entry_length - 1 - (p - new_entry));
545 safe_strcpy((char *)p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", new_entry_length - 1 - (p - new_entry));
552 /* Add the account encoding and the last change time. */
553 slprintf((char *)p, new_entry_length - 1 - (p - new_entry), "%s:LCT-%08X:\n",
554 pdb_encode_acct_ctrl(newpwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN),
555 (uint32)newpwd->pass_last_set_time);
560 /************************************************************************
561 Routine to add an entry to the smbpasswd file.
562 *************************************************************************/
564 static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, struct smb_passwd *newpwd)
566 const char *pfile = smbpasswd_state->smbpasswd_file;
567 struct smb_passwd *pwd = NULL;
571 size_t new_entry_length;
574 uint32 max_found_uid = 0;
576 /* Open the smbpassword file - for update. */
577 fp = startsmbfilepwent(pfile, PWF_UPDATE, &(smbpasswd_state->pw_file_lock_depth));
579 if (fp == NULL && errno == ENOENT) {
580 /* Try again - create. */
581 fp = startsmbfilepwent(pfile, PWF_CREATE, &(smbpasswd_state->pw_file_lock_depth));
585 DEBUG(0, ("add_smbfilepwd_entry: unable to open file.\n"));
590 * Scan the file, a line at a time and check if the name matches.
593 while ((pwd = getsmbfilepwent(smbpasswd_state, fp)) != NULL)
595 if (strequal(newpwd->smb_name, pwd->smb_name))
597 DEBUG(0, ("add_smbfilepwd_entry: entry with name %s already exists\n", pwd->smb_name));
598 endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
602 /* Look for a free uid for use in non-unix accounts */
603 if (pwd->smb_userid > max_found_uid) {
604 max_found_uid = pwd->smb_userid;
608 /* Ok - entry doesn't exist. We can add it */
610 /* Account not in /etc/passwd hack!!! */
611 if (!newpwd->smb_userid_set) {
612 if (!smbpasswd_state->permit_non_unix_accounts) {
613 DEBUG(0, ("add_smbfilepwd_entry: cannot add account %s without unix identity\n", pwd->smb_name));
614 endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
618 if (max_found_uid < smbpasswd_state->low_nua_userid) {
619 newpwd->smb_userid = smbpasswd_state->low_nua_userid;
620 newpwd->smb_userid_set = True;
621 } else if (max_found_uid >= smbpasswd_state->high_nua_userid) {
622 DEBUG(0, ("add_smbfilepwd_entry: cannot add machine %s, no uids are free! \n", newpwd->smb_name));
623 endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
626 newpwd->smb_userid = max_found_uid + 1;
627 newpwd->smb_userid_set = True;
632 /* Create a new smb passwd entry and set it to the given password. */
634 * The add user write needs to be atomic - so get the fd from
635 * the fp and do a raw write() call.
639 if((offpos = sys_lseek(fd, 0, SEEK_END)) == -1)
641 DEBUG(0, ("add_smbfilepwd_entry(sys_lseek): Failed to add entry for user %s to file %s. \
642 Error was %s\n", newpwd->smb_name, pfile, strerror(errno)));
643 endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
647 if((new_entry = format_new_smbpasswd_entry(newpwd)) == NULL)
649 DEBUG(0, ("add_smbfilepwd_entry(malloc): Failed to add entry for user %s to file %s. \
650 Error was %s\n", newpwd->smb_name, pfile, strerror(errno)));
651 endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
655 new_entry_length = strlen(new_entry);
657 #ifdef DEBUG_PASSWORD
658 DEBUG(100, ("add_smbfilepwd_entry(%d): new_entry_len %d made line |%s|",
659 fd, new_entry_length, new_entry));
662 if ((wr_len = write(fd, new_entry, new_entry_length)) != new_entry_length)
664 DEBUG(0, ("add_smbfilepwd_entry(write): %d Failed to add entry for user %s to file %s. \
665 Error was %s\n", wr_len, newpwd->smb_name, pfile, strerror(errno)));
667 /* Remove the entry we just wrote. */
668 if(sys_ftruncate(fd, offpos) == -1)
670 DEBUG(0, ("add_smbfilepwd_entry: ERROR failed to ftruncate file %s. \
671 Error was %s. Password file may be corrupt ! Please examine by hand !\n",
672 newpwd->smb_name, strerror(errno)));
675 endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
681 endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
685 /************************************************************************
686 Routine to search the smbpasswd file for an entry matching the username.
687 and then modify its password entry. We can't use the startsmbpwent()/
688 getsmbpwent()/endsmbpwent() interfaces here as we depend on looking
689 in the actual file to decide how much room we have to write data.
690 override = False, normal
691 override = True, override XXXXXXXX'd out password or NO PASS
692 ************************************************************************/
694 static BOOL mod_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, const struct smb_passwd* pwd)
696 /* Static buffers we will return. */
697 char * user_name = smbpasswd_state->user_name;
704 unsigned char *p = NULL;
705 size_t linebuf_len = 0;
708 const char *pfile = smbpasswd_state->smbpasswd_file;
709 BOOL found_entry = False;
710 BOOL got_pass_last_set_time = False;
712 SMB_OFF_T pwd_seekpos = 0;
719 DEBUG(0, ("No SMB password file set\n"));
722 DEBUG(10, ("mod_smbfilepwd_entry: opening file %s\n", pfile));
724 fp = sys_fopen(pfile, "r+");
727 DEBUG(0, ("mod_smbfilepwd_entry: unable to open file %s\n", pfile));
730 /* Set a buffer to do more efficient reads */
731 setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf));
735 if (!pw_file_lock(lockfd, F_WRLCK, 5, &(smbpasswd_state->pw_file_lock_depth))) {
736 DEBUG(0, ("mod_smbfilepwd_entry: unable to lock file %s\n", pfile));
741 /* Make sure it is only rw by the owner */
744 /* We have a write lock on the file. */
746 * Scan the file, a line at a time and check if the name matches.
749 pwd_seekpos = sys_ftell(fp);
753 fgets(linebuf, sizeof(linebuf), fp);
755 pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth));
761 * Check if the string is terminated with a newline - if not
762 * then we must keep reading and discard until we get one.
764 linebuf_len = strlen(linebuf);
765 if (linebuf[linebuf_len - 1] != '\n') {
767 while (!ferror(fp) && !feof(fp)) {
774 linebuf[linebuf_len - 1] = '\0';
777 #ifdef DEBUG_PASSWORD
778 DEBUG(100, ("mod_smbfilepwd_entry: got line |%s|\n", linebuf));
781 if ((linebuf[0] == 0) && feof(fp)) {
782 DEBUG(4, ("mod_smbfilepwd_entry: end of file reached\n"));
787 * The line we have should be of the form :-
789 * username:uid:[32hex bytes]:....other flags presently
794 * username:uid:[32hex bytes]:[32hex bytes]:[attributes]:LCT-XXXXXXXX:...ignored.
796 * if Windows NT compatible passwords are also present.
799 if (linebuf[0] == '#' || linebuf[0] == '\0') {
800 DEBUG(6, ("mod_smbfilepwd_entry: skipping comment or blank line\n"));
804 p = (unsigned char *) strchr_m(linebuf, ':');
807 DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no :)\n"));
812 * As 256 is shorter than a pstring we don't need to check
813 * length here - if this ever changes....
815 strncpy(user_name, linebuf, PTR_DIFF(p, linebuf));
816 user_name[PTR_DIFF(p, linebuf)] = '\0';
817 if (strequal(user_name, pwd->smb_name)) {
824 pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth));
829 DEBUG(6, ("mod_smbfilepwd_entry: entry exists\n"));
831 /* User name matches - get uid and password */
832 p++; /* Go past ':' */
835 DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (uid not number)\n"));
836 pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth));
841 while (*p && isdigit(*p))
844 DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no : after uid)\n"));
845 pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth));
851 * Now get the password value - this should be 32 hex digits
852 * which are the ascii representations of a 16 byte string.
853 * Get two at a time and put them into the password.
857 /* Record exact password position */
858 pwd_seekpos += PTR_DIFF(p, linebuf);
860 if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
861 DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (passwd too short)\n"));
862 pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
868 DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no terminating :)\n"));
869 pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
874 /* Now check if the NT compatible password is
876 p += 33; /* Move to the first character of the line after
877 the lanman password. */
878 if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
879 DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (passwd too short)\n"));
880 pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
886 DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no terminating :)\n"));
887 pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
893 * Now check if the account info and the password last
894 * change time is available.
896 p += 33; /* Move to the first character of the line after
902 encode_bits[i++] = *p++;
903 while((linebuf_len > PTR_DIFF(p, linebuf)) && (*p != ']'))
904 encode_bits[i++] = *p++;
906 encode_bits[i++] = ']';
907 encode_bits[i++] = '\0';
909 if(i == NEW_PW_FORMAT_SPACE_PADDED_LEN) {
911 * We are using a new format, space padded
912 * acct ctrl field. Encode the given acct ctrl
915 fstrcpy(encode_bits, pdb_encode_acct_ctrl(pwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN));
917 DEBUG(0,("mod_smbfilepwd_entry: Using old smbpasswd format. This is no longer supported.!\n"));
918 DEBUG(0,("mod_smbfilepwd_entry: No changes made, failing.!\n"));
922 /* Go past the ']' */
923 if(linebuf_len > PTR_DIFF(p, linebuf))
926 if((linebuf_len > PTR_DIFF(p, linebuf)) && (*p == ':')) {
929 /* We should be pointing at the LCT entry. */
930 if((linebuf_len > (PTR_DIFF(p, linebuf) + 13)) && (StrnCaseCmp((char *)p, "LCT-", 4) == 0)) {
933 for(i = 0; i < 8; i++) {
934 if(p[i] == '\0' || !isxdigit(p[i]))
939 * p points at 8 characters of hex digits -
940 * read into a time_t as the seconds since
941 * 1970 that the password was last changed.
943 got_pass_last_set_time = True;
945 } /* *p && StrnCaseCmp() */
949 /* Entry is correctly formed. */
951 /* Create the 32 byte representation of the new p16 */
952 if(pwd->smb_passwd != NULL) {
953 for (i = 0; i < 16; i++) {
954 slprintf(&ascii_p16[i*2], sizeof(fstring) - 1, "%02X", (uchar) pwd->smb_passwd[i]);
957 if(pwd->acct_ctrl & ACB_PWNOTREQ)
958 fstrcpy(ascii_p16, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX");
960 fstrcpy(ascii_p16, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
963 /* Add on the NT md4 hash */
966 if (pwd->smb_nt_passwd != NULL) {
967 for (i = 0; i < 16; i++) {
968 slprintf(&ascii_p16[(i*2)+33], sizeof(fstring) - 1, "%02X", (uchar) pwd->smb_nt_passwd[i]);
971 if(pwd->acct_ctrl & ACB_PWNOTREQ)
972 fstrcpy(&ascii_p16[33], "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX");
974 fstrcpy(&ascii_p16[33], "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
977 ascii_p16[66] = '\0'; /* null-terminate the string so that strlen works */
979 /* Add on the account info bits and the time of last
982 if(got_pass_last_set_time) {
983 slprintf(&ascii_p16[strlen(ascii_p16)],
984 sizeof(ascii_p16)-(strlen(ascii_p16)+1),
986 encode_bits, (uint32)pwd->pass_last_set_time );
987 wr_len = strlen(ascii_p16);
990 #ifdef DEBUG_PASSWORD
991 DEBUG(100,("mod_smbfilepwd_entry: "));
992 dump_data(100, ascii_p16, wr_len);
995 if(wr_len > sizeof(linebuf)) {
996 DEBUG(0, ("mod_smbfilepwd_entry: line to write (%d) is too long.\n", wr_len+1));
997 pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
1003 * Do an atomic write into the file at the position defined by
1007 /* The mod user write needs to be atomic - so get the fd from
1008 the fp and do a raw write() call.
1013 if (sys_lseek(fd, pwd_seekpos - 1, SEEK_SET) != pwd_seekpos - 1) {
1014 DEBUG(0, ("mod_smbfilepwd_entry: seek fail on file %s.\n", pfile));
1015 pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
1020 /* Sanity check - ensure the areas we are writing are framed by ':' */
1021 if (read(fd, linebuf, wr_len+1) != wr_len+1) {
1022 DEBUG(0, ("mod_smbfilepwd_entry: read fail on file %s.\n", pfile));
1023 pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
1028 if ((linebuf[0] != ':') || (linebuf[wr_len] != ':')) {
1029 DEBUG(0, ("mod_smbfilepwd_entry: check on passwd file %s failed.\n", pfile));
1030 pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
1035 if (sys_lseek(fd, pwd_seekpos, SEEK_SET) != pwd_seekpos) {
1036 DEBUG(0, ("mod_smbfilepwd_entry: seek fail on file %s.\n", pfile));
1037 pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
1042 if (write(fd, ascii_p16, wr_len) != wr_len) {
1043 DEBUG(0, ("mod_smbfilepwd_entry: write failed in passwd file %s\n", pfile));
1044 pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
1049 pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
1054 /************************************************************************
1055 Routine to delete an entry in the smbpasswd file by name.
1056 *************************************************************************/
1058 static BOOL del_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, const char *name)
1060 const char *pfile = smbpasswd_state->smbpasswd_file;
1062 struct smb_passwd *pwd = NULL;
1064 FILE *fp_write = NULL;
1065 int pfile2_lockdepth = 0;
1067 slprintf(pfile2, sizeof(pfile2)-1, "%s.%u", pfile, (unsigned)sys_getpid() );
1070 * Open the smbpassword file - for update. It needs to be update
1071 * as we need any other processes to wait until we have replaced
1075 if((fp = startsmbfilepwent(pfile, PWF_UPDATE, &(smbpasswd_state->pw_file_lock_depth))) == NULL) {
1076 DEBUG(0, ("del_smbfilepwd_entry: unable to open file %s.\n", pfile));
1081 * Create the replacement password file.
1083 if((fp_write = startsmbfilepwent(pfile2, PWF_CREATE, &pfile2_lockdepth)) == NULL) {
1084 DEBUG(0, ("del_smbfilepwd_entry: unable to open file %s.\n", pfile));
1085 endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
1090 * Scan the file, a line at a time and check if the name matches.
1093 while ((pwd = getsmbfilepwent(smbpasswd_state, fp)) != NULL) {
1095 size_t new_entry_length;
1097 if (strequal(name, pwd->smb_name)) {
1098 DEBUG(10, ("add_smbfilepwd_entry: found entry with name %s - deleting it.\n", name));
1103 * We need to copy the entry out into the second file.
1106 if((new_entry = format_new_smbpasswd_entry(pwd)) == NULL)
1108 DEBUG(0, ("del_smbfilepwd_entry(malloc): Failed to copy entry for user %s to file %s. \
1109 Error was %s\n", pwd->smb_name, pfile2, strerror(errno)));
1111 endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
1112 endsmbfilepwent(fp_write, &pfile2_lockdepth);
1116 new_entry_length = strlen(new_entry);
1118 if(fwrite(new_entry, 1, new_entry_length, fp_write) != new_entry_length)
1120 DEBUG(0, ("del_smbfilepwd_entry(write): Failed to copy entry for user %s to file %s. \
1121 Error was %s\n", pwd->smb_name, pfile2, strerror(errno)));
1123 endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
1124 endsmbfilepwent(fp_write, &pfile2_lockdepth);
1133 * Ensure pfile2 is flushed before rename.
1136 if(fflush(fp_write) != 0)
1138 DEBUG(0, ("del_smbfilepwd_entry: Failed to flush file %s. Error was %s\n", pfile2, strerror(errno)));
1139 endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
1140 endsmbfilepwent(fp_write,&pfile2_lockdepth);
1145 * Do an atomic rename - then release the locks.
1148 if(rename(pfile2,pfile) != 0) {
1152 endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
1153 endsmbfilepwent(fp_write,&pfile2_lockdepth);
1157 /*********************************************************************
1158 Create a smb_passwd struct from a SAM_ACCOUNT.
1159 We will not allocate any new memory. The smb_passwd struct
1160 should only stay around as long as the SAM_ACCOUNT does.
1161 ********************************************************************/
1162 static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampass)
1166 if (sampass == NULL)
1169 ZERO_STRUCTP(smb_pw);
1171 if (!IS_SAM_UNIX_USER(sampass)) {
1172 smb_pw->smb_userid_set = False;
1173 DEBUG(5,("build_sam_pass: storing user without a UNIX uid or gid. \n"));
1175 smb_pw->smb_userid_set = True;
1176 uid = pdb_get_uid(sampass);
1178 if (uid != pdb_user_rid_to_uid(pdb_get_user_rid(sampass))) {
1179 DEBUG(0,("build_sam_pass: Failing attempt to store user with non-uid based user RID. \n"));
1183 smb_pw->smb_userid=uid;
1186 smb_pw->smb_name=(const char*)pdb_get_username(sampass);
1188 smb_pw->smb_passwd=pdb_get_lanman_passwd(sampass);
1189 smb_pw->smb_nt_passwd=pdb_get_nt_passwd(sampass);
1191 smb_pw->acct_ctrl=pdb_get_acct_ctrl(sampass);
1192 smb_pw->pass_last_set_time=pdb_get_pass_last_set_time(sampass);
1196 * ifdef'out by JFM on 11/29/2001.
1197 * this assertion is no longer valid
1198 * and I don't understand the goal
1199 * and doing the same thing with the group mapping code
1202 * We just have the RID, in which SID is it valid ?
1203 * our domain SID ? well known SID ? local SID ?
1206 if (gid != pdb_group_rid_to_gid(pdb_get_group_rid(sampass))) {
1207 DEBUG(0,("build_sam_pass: Failing attempt to store user with non-gid based primary group RID. \n"));
1208 DEBUG(0,("build_sam_pass: %d %d %d. \n", *gid, pdb_group_rid_to_gid(pdb_get_group_rid(sampass)), pdb_get_group_rid(sampass)));
1216 /*********************************************************************
1217 Create a SAM_ACCOUNT from a smb_passwd struct
1218 ********************************************************************/
1219 static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state, SAM_ACCOUNT *sam_pass, const struct smb_passwd *pw_buf)
1221 struct passwd *pwfile;
1223 if (sam_pass==NULL) {
1224 DEBUG(5,("build_sam_account: SAM_ACCOUNT is NULL\n"));
1228 if ((smbpasswd_state->permit_non_unix_accounts)
1229 && (pw_buf->smb_userid >= smbpasswd_state->low_nua_userid)
1230 && (pw_buf->smb_userid <= smbpasswd_state->high_nua_userid)) {
1232 pdb_set_user_rid(sam_pass, pdb_uid_to_user_rid (pw_buf->smb_userid));
1234 /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here.
1236 This was down the bottom for machines, but it looks pretty good as
1237 a general default for non-unix users. --abartlet 2002-01-08
1239 pdb_set_group_rid (sam_pass, DOMAIN_GROUP_RID_USERS);
1246 /* Verify in system password file...
1247 FIXME!!! This is where we should look up an internal
1248 mapping of allocated uid for machine accounts as well
1250 pwfile = getpwnam_alloc(pw_buf->smb_name);
1251 if (pwfile == NULL) {
1252 DEBUG(0,("build_sam_account: smbpasswd database is corrupt! username %s not in unix passwd database!\n", pw_buf->smb_name));
1256 pdb_set_uid (sam_pass, pwfile->pw_uid);
1257 pdb_set_gid (sam_pass, pwfile->pw_gid);
1259 pdb_set_fullname(sam_pass, pwfile->pw_gecos);
1261 pdb_set_user_rid(sam_pass, pdb_uid_to_user_rid (pwfile->pw_uid));
1263 if (get_group_map_from_gid(pwfile->pw_gid, &map, MAPPING_WITHOUT_PRIV)) {
1264 sid_peek_rid(&map.sid, &grid);
1266 grid=pdb_gid_to_group_rid(pwfile->pw_gid);
1269 pdb_set_group_rid(sam_pass, grid);
1271 /* check if this is a user account or a machine account */
1272 if (pw_buf->smb_name[strlen(pw_buf->smb_name)-1] != '$')
1276 pstrcpy(str, lp_logon_path());
1277 standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str);
1278 pdb_set_profile_path(sam_pass, str, False);
1280 pstrcpy(str, lp_logon_home());
1281 standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str);
1282 pdb_set_homedir(sam_pass, str, False);
1284 pstrcpy(str, lp_logon_drive());
1285 standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str);
1286 pdb_set_dir_drive(sam_pass, str, False);
1288 pstrcpy(str, lp_logon_script());
1289 standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str);
1290 pdb_set_logon_script(sam_pass, str, False);
1293 /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. */
1294 /*pdb_set_group_rid (sam_pass, DOMAIN_GROUP_RID_USERS); */
1297 passwd_free(&pwfile);
1300 pdb_set_username (sam_pass, pw_buf->smb_name);
1301 pdb_set_nt_passwd (sam_pass, pw_buf->smb_nt_passwd);
1302 pdb_set_lanman_passwd (sam_pass, pw_buf->smb_passwd);
1303 pdb_set_acct_ctrl (sam_pass, pw_buf->acct_ctrl);
1304 pdb_set_pass_last_set_time (sam_pass, pw_buf->pass_last_set_time);
1305 pdb_set_pass_can_change_time (sam_pass, pw_buf->pass_last_set_time);
1306 pdb_set_domain (sam_pass, lp_workgroup());
1308 pdb_set_dir_drive (sam_pass, lp_logon_drive(), False);
1311 /* the smbpasswd format doesn't have a must change time field, so
1312 we can't get this right. The best we can do is to set this to
1313 some time in the future. 21 days seems as reasonable as any other value :)
1315 pdb_set_pass_must_change_time (sam_pass, pw_buf->pass_last_set_time + MAX_PASSWORD_AGE);
1320 /*****************************************************************
1321 Functions to be implemented by the new passdb API
1322 ****************************************************************/
1323 static BOOL smbpasswd_setsampwent (struct pdb_context *context, BOOL update)
1325 struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data;
1327 smbpasswd_state->pw_file = startsmbfilepwent(smbpasswd_state->smbpasswd_file,
1328 update ? PWF_UPDATE : PWF_READ,
1329 &(smbpasswd_state->pw_file_lock_depth));
1331 /* did we fail? Should we try to create it? */
1332 if (!smbpasswd_state->pw_file && update && errno == ENOENT)
1335 /* slprintf(msg_str,msg_str_len-1,
1336 "smbpasswd file did not exist - attempting to create it.\n"); */
1337 DEBUG(0,("smbpasswd file did not exist - attempting to create it.\n"));
1338 fp = sys_fopen(smbpasswd_state->smbpasswd_file, "w");
1341 fprintf(fp, "# Samba SMB password file\n");
1345 smbpasswd_state->pw_file = startsmbfilepwent(smbpasswd_state->smbpasswd_file,
1346 update ? PWF_UPDATE : PWF_READ,
1347 &(smbpasswd_state->pw_file_lock_depth));
1350 return (smbpasswd_state->pw_file != NULL);
1353 static void smbpasswd_endsampwent (struct pdb_context *context)
1355 struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data;
1356 endsmbfilepwent(smbpasswd_state->pw_file, &(smbpasswd_state->pw_file_lock_depth));
1359 /*****************************************************************
1360 ****************************************************************/
1361 static BOOL smbpasswd_getsampwent(struct pdb_context *context, SAM_ACCOUNT *user)
1363 struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data;
1364 struct smb_passwd *pw_buf=NULL;
1366 DEBUG(5,("pdb_getsampwent\n"));
1369 DEBUG(5,("pdb_getsampwent (smbpasswd): user is NULL\n"));
1371 smb_panic("NULL pointer passed to getsampwent (smbpasswd)\n");
1378 /* do we have an entry? */
1379 pw_buf = getsmbfilepwent(smbpasswd_state, smbpasswd_state->pw_file);
1383 /* build the SAM_ACCOUNT entry from the smb_passwd struct.
1384 We loop in case the user in the pdb does not exist in
1385 the local system password file */
1386 if (build_sam_account(smbpasswd_state, user, pw_buf))
1390 DEBUG(5,("getsampwent (smbpasswd): done\n"));
1397 /****************************************************************
1398 Search smbpasswd file by iterating over the entries. Do not
1399 call getpwnam() for unix account information until we have found
1401 ***************************************************************/
1402 static BOOL smbpasswd_getsampwnam(struct pdb_context *context, SAM_ACCOUNT *sam_acct, const char *username)
1404 struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data;
1405 struct smb_passwd *smb_pw;
1407 char *domain = NULL;
1411 DEBUG(10, ("getsampwnam (smbpasswd): search by name: %s\n", username));
1414 /* break the username from the domain if we have
1415 been given a string in the form 'DOMAIN\user' */
1416 fstrcpy (name, username);
1417 if ((user=strchr_m(name, '\\')) != NULL) {
1423 /* if a domain was specified and it wasn't ours
1424 then there is no chance of matching */
1425 if ( domain && !StrCaseCmp(domain, lp_workgroup()) )
1428 /* startsmbfilepwent() is used here as we don't want to lookup
1429 the UNIX account in the local system password file until
1431 fp = startsmbfilepwent(smbpasswd_state->smbpasswd_file, PWF_READ, &(smbpasswd_state->pw_file_lock_depth));
1434 DEBUG(0, ("unable to open passdb database.\n"));
1438 /* if we have a domain name, then we should map it to a UNIX
1443 while ( ((smb_pw=getsmbfilepwent(smbpasswd_state, fp)) != NULL)&& (!strequal(smb_pw->smb_name, username)) )
1444 /* do nothing....another loop */ ;
1446 endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
1449 /* did we locate the username in smbpasswd */
1453 DEBUG(10, ("getsampwnam (smbpasswd): found by name: %s\n", smb_pw->smb_name));
1456 DEBUG(10,("getsampwnam (smbpasswd): SAM_ACCOUNT is NULL\n"));
1458 smb_panic("NULL pointer passed to pdb_getsampwnam\n");
1463 /* now build the SAM_ACCOUNT */
1464 if (!build_sam_account(smbpasswd_state, sam_acct, smb_pw))
1472 static BOOL smbpasswd_getsampwrid(struct pdb_context *context, SAM_ACCOUNT *sam_acct,uint32 rid)
1474 struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data;
1475 struct smb_passwd *smb_pw;
1478 DEBUG(10, ("pdb_getsampwrid: search by rid: %d\n", rid));
1480 /* Open the sam password file - not for update. */
1481 fp = startsmbfilepwent(smbpasswd_state->smbpasswd_file, PWF_READ, &(smbpasswd_state->pw_file_lock_depth));
1484 DEBUG(0, ("unable to open passdb database.\n"));
1488 while ( ((smb_pw=getsmbfilepwent(smbpasswd_state, fp)) != NULL) && (pdb_uid_to_user_rid(smb_pw->smb_userid) != rid) )
1491 endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
1494 /* did we locate the username in smbpasswd */
1498 DEBUG(10, ("getsampwrid (smbpasswd): found by name: %s\n", smb_pw->smb_name));
1501 DEBUG(10,("getsampwrid: (smbpasswd) SAM_ACCOUNT is NULL\n"));
1503 smb_panic("NULL pointer passed to pdb_getsampwrid\n");
1508 /* now build the SAM_ACCOUNT */
1509 if (!build_sam_account (smbpasswd_state, sam_acct, smb_pw))
1516 static BOOL smbpasswd_add_sam_account(struct pdb_context *context, const SAM_ACCOUNT *sampass)
1518 struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data;
1519 struct smb_passwd smb_pw;
1521 /* convert the SAM_ACCOUNT */
1522 if (!build_smb_pass(&smb_pw, sampass)) {
1527 if(!add_smbfilepwd_entry(smbpasswd_state, &smb_pw)) {
1534 static BOOL smbpasswd_update_sam_account(struct pdb_context *context, const SAM_ACCOUNT *sampass)
1536 struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data;
1537 struct smb_passwd smb_pw;
1539 /* convert the SAM_ACCOUNT */
1540 if (!build_smb_pass(&smb_pw, sampass))
1543 /* update the entry */
1544 if(!mod_smbfilepwd_entry(smbpasswd_state, &smb_pw))
1550 static BOOL smbpasswd_delete_sam_account (struct pdb_context *context, const SAM_ACCOUNT *sampass)
1552 struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data;
1554 const char *username = pdb_get_username(sampass);
1556 return del_smbfilepwd_entry(smbpasswd_state, username);
1559 static void free_private_data(void **vp)
1561 struct smbpasswd_privates **privates = (struct smbpasswd_privates**)vp;
1563 endsmbfilepwent((*privates)->pw_file, &((*privates)->pw_file_lock_depth));
1566 /* No need to free any further, as it is talloc()ed */
1570 NTSTATUS pdb_init_smbpasswd(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
1573 struct smbpasswd_privates *privates;
1575 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
1579 (*pdb_method)->setsampwent = smbpasswd_setsampwent;
1580 (*pdb_method)->endsampwent = smbpasswd_endsampwent;
1581 (*pdb_method)->getsampwent = smbpasswd_getsampwent;
1582 (*pdb_method)->getsampwnam = smbpasswd_getsampwnam;
1583 (*pdb_method)->getsampwrid = smbpasswd_getsampwrid;
1584 (*pdb_method)->add_sam_account = smbpasswd_add_sam_account;
1585 (*pdb_method)->update_sam_account = smbpasswd_update_sam_account;
1586 (*pdb_method)->delete_sam_account = smbpasswd_delete_sam_account;
1588 /* Setup private data and free function */
1590 privates = talloc_zero(pdb_context->mem_ctx, sizeof(struct smbpasswd_privates));
1593 DEBUG(0, ("talloc() failed for smbpasswd private_data!\n"));
1594 return NT_STATUS_NO_MEMORY;
1597 /* Store some config details */
1600 privates->smbpasswd_file = talloc_strdup(pdb_context->mem_ctx, location);
1602 privates->smbpasswd_file = talloc_strdup(pdb_context->mem_ctx, lp_smb_passwd_file());
1605 if (!privates->smbpasswd_file) {
1606 DEBUG(0, ("talloc_strdp() failed for storing smbpasswd location!\n"));
1607 return NT_STATUS_NO_MEMORY;
1610 (*pdb_method)->private_data = privates;
1613 (*pdb_method)->free_private_data = free_private_data;
1615 return NT_STATUS_OK;
1618 NTSTATUS pdb_init_smbpasswd_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
1621 struct smbpasswd_privates *privates;
1623 if (!NT_STATUS_IS_OK(nt_status = pdb_init_smbpasswd(pdb_context, pdb_method, location))) {
1627 privates = (*pdb_method)->private_data;
1629 privates->permit_non_unix_accounts = True;
1631 if (!lp_non_unix_account_range(&privates->low_nua_userid, &privates->high_nua_userid)) {
1632 DEBUG(0, ("cannot use smbpasswd_nua without 'non unix account range' in smb.conf!\n"));
1633 return NT_STATUS_UNSUCCESSFUL;
1636 return NT_STATUS_OK;