2 Unix SMB/Netbios implementation.
4 Password and authentication handling
5 Copyright (C) Jeremy Allison 1996-1998
6 Copyright (C) Luke Kenneth Casson Leighton 1996-1998
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 extern int DEBUGLEVEL;
28 * This is set on startup - it defines the SID for this
29 * machine, and therefore the SAM database for which it is
33 extern DOM_SID global_sam_sid;
34 extern pstring global_myname;
35 extern fstring global_myworkgroup;
38 * NOTE. All these functions are abstracted into a structure
39 * that points to the correct function for the selected database. JRA.
41 * NOTE. for the get/mod/add functions, there are two sets of functions.
42 * one supports struct sam_passwd, the other supports struct smb_passwd.
43 * for speed optimisation it is best to support both these sets.
45 * it is, however, optional to support one set but not the other: there
46 * is conversion-capability built in to passdb.c, and run-time error
47 * detection for when neither are supported.
49 * password database writers are recommended to implement the sam_passwd
50 * functions in a first pass, as struct sam_passwd contains more
51 * information, needed by the NT Domain support.
53 * a full example set of derivative functions are listed below. an API
54 * writer is expected to cut/paste these into their module, replace
55 * either one set (struct smb_passwd) or the other (struct sam_passwd)
56 * OR both, and optionally also to write display info routines
57 * (struct sam_disp_info). lkcl
61 static struct passdb_ops *pdb_ops;
63 /***************************************************************
64 Initialize the password db operations.
65 ***************************************************************/
67 BOOL initialize_password_db(void)
75 pdb_ops = nisplus_initialize_password_db();
76 #elif defined(WITH_LDAP)
77 pdb_ops = ldap_initialize_password_db();
79 pdb_ops = file_initialize_password_db();
82 return (pdb_ops != NULL);
86 * Functions that return/manipulate a struct smb_passwd.
89 /************************************************************************
90 Utility function to search smb passwd by rid.
91 *************************************************************************/
93 struct smb_passwd *iterate_getsmbpwrid(uint32 user_rid)
95 return iterate_getsmbpwuid(pdb_user_rid_to_uid(user_rid));
98 /************************************************************************
99 Utility function to search smb passwd by uid. use this if your database
100 does not have search facilities.
101 *************************************************************************/
103 struct smb_passwd *iterate_getsmbpwuid(uid_t smb_userid)
105 struct smb_passwd *pwd = NULL;
108 DEBUG(10, ("search by smb_userid: %x\n", (int)smb_userid));
110 /* Open the smb password database - not for update. */
111 fp = startsmbpwent(False);
115 DEBUG(0, ("unable to open smb password database.\n"));
119 while ((pwd = getsmbpwent(fp)) != NULL && pwd->smb_userid != smb_userid)
124 DEBUG(10, ("found by smb_userid: %x\n", (int)smb_userid));
131 /************************************************************************
132 Utility function to search smb passwd by name. use this if your database
133 does not have search facilities.
134 *************************************************************************/
136 struct smb_passwd *iterate_getsmbpwnam(char *name)
138 struct smb_passwd *pwd = NULL;
141 DEBUG(10, ("search by name: %s\n", name));
143 /* Open the sam password file - not for update. */
144 fp = startsmbpwent(False);
148 DEBUG(0, ("unable to open smb password database.\n"));
152 while ((pwd = getsmbpwent(fp)) != NULL && !strequal(pwd->smb_name, name))
157 DEBUG(10, ("found by name: %s\n", name));
164 /***************************************************************
165 Start to enumerate the smb or sam passwd list. Returns a void pointer
166 to ensure no modification outside this module.
168 Note that currently it is being assumed that a pointer returned
169 from this function may be used to enumerate struct sam_passwd
170 entries as well as struct smb_passwd entries. This may need
173 ****************************************************************/
175 void *startsmbpwent(BOOL update)
177 return pdb_ops->startsmbpwent(update);
180 /***************************************************************
181 End enumeration of the smb or sam passwd list.
183 Note that currently it is being assumed that a pointer returned
184 from this function may be used to enumerate struct sam_passwd
185 entries as well as struct smb_passwd entries. This may need
188 ****************************************************************/
190 void endsmbpwent(void *vp)
192 pdb_ops->endsmbpwent(vp);
195 /*************************************************************************
196 Routine to return the next entry in the smb passwd list.
197 *************************************************************************/
199 struct smb_passwd *getsmbpwent(void *vp)
201 return pdb_ops->getsmbpwent(vp);
204 /************************************************************************
205 Routine to add an entry to the smb passwd file.
206 *************************************************************************/
208 BOOL add_smbpwd_entry(struct smb_passwd *newpwd)
210 return pdb_ops->add_smbpwd_entry(newpwd);
213 /************************************************************************
214 Routine to search the smb passwd file for an entry matching the username.
215 and then modify its password entry. We can't use the startsampwent()/
216 getsampwent()/endsampwent() interfaces here as we depend on looking
217 in the actual file to decide how much room we have to write data.
218 override = False, normal
219 override = True, override XXXXXXXX'd out password or NO PASS
220 ************************************************************************/
222 BOOL mod_smbpwd_entry(struct smb_passwd* pwd, BOOL override)
224 return pdb_ops->mod_smbpwd_entry(pwd, override);
227 /************************************************************************
228 Routine to delete an entry from the smb passwd file.
229 *************************************************************************/
231 BOOL del_smbpwd_entry(const char *name)
233 return pdb_ops->del_smbpwd_entry(name);
236 /************************************************************************
237 Routine to search smb passwd by name.
238 *************************************************************************/
240 struct smb_passwd *getsmbpwnam(char *name)
242 return pdb_ops->getsmbpwnam(name);
245 /************************************************************************
246 Routine to search smb passwd by user rid.
247 *************************************************************************/
249 struct smb_passwd *getsmbpwrid(uint32 user_rid)
251 return pdb_ops->getsmbpwrid(user_rid);
254 /************************************************************************
255 Routine to search smb passwd by uid.
256 *************************************************************************/
258 struct smb_passwd *getsmbpwuid(uid_t smb_userid)
260 return pdb_ops->getsmbpwuid(smb_userid);
264 * Functions that manupulate a struct sam_passwd.
267 /************************************************************************
268 Utility function to search sam passwd by name. use this if your database
269 does not have search facilities.
270 *************************************************************************/
272 struct sam_passwd *iterate_getsam21pwnam(char *name)
274 struct sam_passwd *pwd = NULL;
277 DEBUG(10, ("search by name: %s\n", name));
279 /* Open the smb password database - not for update. */
280 fp = startsmbpwent(False);
284 DEBUG(0, ("unable to open sam password database.\n"));
288 while ((pwd = getsam21pwent(fp)) != NULL && !strequal(pwd->smb_name, name))
290 DEBUG(10, ("iterate: %s 0x%x\n", pwd->smb_name, pwd->user_rid));
295 DEBUG(10, ("found by name: %s\n", name));
302 /************************************************************************
303 Utility function to search sam passwd by rid. use this if your database
304 does not have search facilities.
306 search capability by both rid and uid are needed as the rid <-> uid
307 mapping may be non-monotonic.
309 *************************************************************************/
311 struct sam_passwd *iterate_getsam21pwrid(uint32 rid)
313 struct sam_passwd *pwd = NULL;
316 DEBUG(10, ("search by rid: %x\n", rid));
318 /* Open the smb password file - not for update. */
319 fp = startsmbpwent(False);
323 DEBUG(0, ("unable to open sam password database.\n"));
327 while ((pwd = getsam21pwent(fp)) != NULL && pwd->user_rid != rid)
329 DEBUG(10, ("iterate: %s 0x%x\n", pwd->smb_name, pwd->user_rid));
334 DEBUG(10, ("found by user_rid: %x\n", rid));
341 /************************************************************************
342 Utility function to search sam passwd by uid. use this if your database
343 does not have search facilities.
345 search capability by both rid and uid are needed as the rid <-> uid
346 mapping may be non-monotonic.
348 *************************************************************************/
350 struct sam_passwd *iterate_getsam21pwuid(uid_t uid)
352 struct sam_passwd *pwd = NULL;
355 DEBUG(10, ("search by uid: %x\n", (int)uid));
357 /* Open the smb password file - not for update. */
358 fp = startsmbpwent(False);
362 DEBUG(0, ("unable to open sam password database.\n"));
366 while ((pwd = getsam21pwent(fp)) != NULL && pwd->smb_userid != uid)
371 DEBUG(10, ("found by smb_userid: %x\n", (int)uid));
378 /*************************************************************************
379 Routine to return a display info structure, by rid
380 *************************************************************************/
381 struct sam_disp_info *getsamdisprid(uint32 rid)
383 return pdb_ops->getsamdisprid(rid);
386 /*************************************************************************
387 Routine to return the next entry in the sam passwd list.
388 *************************************************************************/
390 struct sam_passwd *getsam21pwent(void *vp)
392 return pdb_ops->getsam21pwent(vp);
396 /************************************************************************
397 Routine to search sam passwd by name.
398 *************************************************************************/
400 struct sam_passwd *getsam21pwnam(char *name)
402 return pdb_ops->getsam21pwnam(name);
405 /************************************************************************
406 Routine to search sam passwd by rid.
407 *************************************************************************/
409 struct sam_passwd *getsam21pwrid(uint32 rid)
411 return pdb_ops->getsam21pwrid(rid);
415 /**********************************************************
416 **********************************************************
418 utility routines which are likely to be useful to all password
421 **********************************************************
422 **********************************************************/
424 /*************************************************************
425 initialises a struct sam_disp_info.
426 **************************************************************/
428 static void pdb_init_dispinfo(struct sam_disp_info *user)
430 if (user == NULL) return;
431 memset((char *)user, '\0', sizeof(*user));
434 /*************************************************************
435 initialises a struct smb_passwd.
436 **************************************************************/
438 void pdb_init_smb(struct smb_passwd *user)
440 if (user == NULL) return;
441 memset((char *)user, '\0', sizeof(*user));
442 user->pass_last_set_time = (time_t)-1;
445 /*************************************************************
446 initialises a struct sam_passwd.
447 **************************************************************/
448 void pdb_init_sam(struct sam_passwd *user)
450 if (user == NULL) return;
451 memset((char *)user, '\0', sizeof(*user));
452 user->logon_time = (time_t)-1;
453 user->logoff_time = (time_t)-1;
454 user->kickoff_time = (time_t)-1;
455 user->pass_last_set_time = (time_t)-1;
456 user->pass_can_change_time = (time_t)-1;
457 user->pass_must_change_time = (time_t)-1;
460 /*************************************************************************
461 Routine to return the next entry in the sam passwd list.
462 *************************************************************************/
464 struct sam_disp_info *pdb_sam_to_dispinfo(struct sam_passwd *user)
466 static struct sam_disp_info disp_info;
468 if (user == NULL) return NULL;
470 pdb_init_dispinfo(&disp_info);
472 disp_info.smb_name = user->smb_name;
473 disp_info.full_name = user->full_name;
474 disp_info.user_rid = user->user_rid;
479 /*************************************************************
480 converts a sam_passwd structure to a smb_passwd structure.
481 **************************************************************/
483 struct smb_passwd *pdb_sam_to_smb(struct sam_passwd *user)
485 static struct smb_passwd pw_buf;
487 if (user == NULL) return NULL;
489 pdb_init_smb(&pw_buf);
491 pw_buf.smb_userid = user->smb_userid;
492 pw_buf.smb_name = user->smb_name;
493 pw_buf.smb_passwd = user->smb_passwd;
494 pw_buf.smb_nt_passwd = user->smb_nt_passwd;
495 pw_buf.acct_ctrl = user->acct_ctrl;
496 pw_buf.pass_last_set_time = user->pass_last_set_time;
502 /*************************************************************
503 converts a smb_passwd structure to a sam_passwd structure.
504 **************************************************************/
506 struct sam_passwd *pdb_smb_to_sam(struct smb_passwd *user)
508 static struct sam_passwd pw_buf;
510 if (user == NULL) return NULL;
512 pdb_init_sam(&pw_buf);
514 pw_buf.smb_userid = user->smb_userid;
515 pw_buf.smb_name = user->smb_name;
516 pw_buf.smb_passwd = user->smb_passwd;
517 pw_buf.smb_nt_passwd = user->smb_nt_passwd;
518 pw_buf.acct_ctrl = user->acct_ctrl;
519 pw_buf.pass_last_set_time = user->pass_last_set_time;
524 /**********************************************************
525 Encode the account control bits into a string.
526 length = length of string to encode into (including terminating
527 null). length *MUST BE MORE THAN 2* !
528 **********************************************************/
530 char *pdb_encode_acct_ctrl(uint16 acct_ctrl, size_t length)
532 static fstring acct_str;
537 if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
538 if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
539 if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
540 if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T';
541 if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U';
542 if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M';
543 if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W';
544 if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
545 if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
546 if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X';
547 if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
549 for ( ; i < length - 2 ; i++ ) { acct_str[i] = ' '; }
553 acct_str[i++] = '\0';
558 /**********************************************************
559 Decode the account control bits from a string.
561 this function breaks coding standards minimum line width of 80 chars.
562 reason: vertical line-up code clarity - all case statements fit into
563 15 lines, which is more important.
564 **********************************************************/
566 uint16 pdb_decode_acct_ctrl(const char *p)
568 uint16 acct_ctrl = 0;
569 BOOL finished = False;
572 * Check if the account type bits have been encoded after the
573 * NT password (in the form [NDHTUWSLXI]).
576 if (*p != '[') return 0;
578 for (p++; *p && !finished; p++)
582 case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
583 case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
584 case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
585 case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
586 case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
587 case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
588 case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
589 case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
590 case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
591 case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
592 case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
598 default: { finished = True; }
605 /*******************************************************************
606 gets password-database-format time from a string.
607 ********************************************************************/
609 static time_t get_time_from_string(const char *p)
613 for (i = 0; i < 8; i++)
615 if (p[i] == '\0' || !isxdigit((int)(p[i]&0xFF)))
621 * p points at 8 characters of hex digits -
622 * read into a time_t as the seconds since
623 * 1970 that the password was last changed.
625 return (time_t)strtol(p, NULL, 16);
630 /*******************************************************************
631 gets password last set time
632 ********************************************************************/
634 time_t pdb_get_last_set_time(const char *p)
636 if (*p && StrnCaseCmp(p, "LCT-", 4))
638 return get_time_from_string(p + 4);
644 /*******************************************************************
645 sets password-database-format time in a string.
646 ********************************************************************/
647 static void set_time_in_string(char *p, int max_len, char *type, time_t t)
649 slprintf(p, max_len, ":%s-%08X:", type, (uint32)t);
652 /*******************************************************************
654 ********************************************************************/
655 void pdb_set_logon_time(char *p, int max_len, time_t t)
657 set_time_in_string(p, max_len, "LNT", t);
660 /*******************************************************************
662 ********************************************************************/
663 void pdb_set_logoff_time(char *p, int max_len, time_t t)
665 set_time_in_string(p, max_len, "LOT", t);
668 /*******************************************************************
670 ********************************************************************/
671 void pdb_set_kickoff_time(char *p, int max_len, time_t t)
673 set_time_in_string(p, max_len, "KOT", t);
676 /*******************************************************************
677 sets password can change time
678 ********************************************************************/
679 void pdb_set_can_change_time(char *p, int max_len, time_t t)
681 set_time_in_string(p, max_len, "CCT", t);
684 /*******************************************************************
685 sets password last set time
686 ********************************************************************/
687 void pdb_set_must_change_time(char *p, int max_len, time_t t)
689 set_time_in_string(p, max_len, "MCT", t);
692 /*******************************************************************
693 sets password last set time
694 ********************************************************************/
695 void pdb_set_last_set_time(char *p, int max_len, time_t t)
697 set_time_in_string(p, max_len, "LCT", t);
701 /*************************************************************
702 Routine to set 32 hex password characters from a 16 byte array.
703 **************************************************************/
704 void pdb_sethexpwd(char *p, unsigned char *pwd, uint16 acct_ctrl)
709 for (i = 0; i < 16; i++)
711 slprintf(&p[i*2], 3, "%02X", pwd[i]);
716 if (IS_BITS_SET_ALL(acct_ctrl, ACB_PWNOTREQ))
718 safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
722 safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
726 /*************************************************************
727 Routine to get the 32 hex characters and turn them
728 into a 16 byte array.
729 **************************************************************/
730 BOOL pdb_gethexpwd(char *p, unsigned char *pwd)
733 unsigned char lonybble, hinybble;
734 char *hexchars = "0123456789ABCDEF";
737 for (i = 0; i < 32; i += 2)
739 hinybble = toupper(p[i]);
740 lonybble = toupper(p[i + 1]);
742 p1 = strchr(hexchars, hinybble);
743 p2 = strchr(hexchars, lonybble);
750 hinybble = PTR_DIFF(p1, hexchars);
751 lonybble = PTR_DIFF(p2, hexchars);
753 pwd[i / 2] = (hinybble << 4) | lonybble;
758 /*******************************************************************
759 Group and User RID username mapping function
760 ********************************************************************/
762 BOOL pdb_name_to_rid(char *user_name, uint32 *u_rid, uint32 *g_rid)
764 struct passwd *pw = Get_Pwnam(user_name, False);
766 if (u_rid == NULL || g_rid == NULL || user_name == NULL)
773 DEBUG(1,("Username %s is invalid on this system\n", user_name));
777 if (user_in_list(user_name, lp_domain_guest_users()))
779 *u_rid = DOMAIN_USER_RID_GUEST;
781 else if (user_in_list(user_name, lp_domain_admin_users()))
783 *u_rid = DOMAIN_USER_RID_ADMIN;
787 /* turn the unix UID into a Domain RID. this is what the posix
788 sub-system does (adds 1000 to the uid) */
789 *u_rid = pdb_uid_to_user_rid(pw->pw_uid);
792 /* absolutely no idea what to do about the unix GID to Domain RID mapping */
793 *g_rid = pdb_gid_to_group_rid(pw->pw_gid);
798 /****************************************************************************
799 Read the machine SID from a file.
800 ****************************************************************************/
802 static BOOL read_sid_from_file(int fd, char *sid_file)
806 memset(fline, '\0', sizeof(fline));
808 if(read(fd, fline, sizeof(fline) -1 ) < 0) {
809 DEBUG(0,("unable to read file %s. Error was %s\n",
810 sid_file, strerror(errno) ));
815 * Convert to the machine SID.
818 fline[sizeof(fline)-1] = '\0';
819 if(!string_to_sid( &global_sam_sid, fline)) {
820 DEBUG(0,("unable to generate machine SID.\n"));
827 /****************************************************************************
828 Generate the global machine sid. Look for the MACHINE.SID file first, if
829 not found then look in smb.conf and use it to create the MACHINE.SID file.
830 Note this function will be replaced soon. JRA.
831 ****************************************************************************/
833 BOOL pdb_generate_sam_sid(void)
840 BOOL overwrite_bad_sid = False;
842 generate_wellknown_sids();
844 pstrcpy(sid_file, lp_smb_passwd_file());
845 p = strrchr(sid_file, '/');
850 if (!directory_exist(sid_file, NULL)) {
851 if (mkdir(sid_file, 0700) != 0) {
852 DEBUG(0,("can't create private directory %s : %s\n",
853 sid_file, strerror(errno)));
858 pstrcat(sid_file, "MACHINE.SID");
860 if((fd = sys_open(sid_file, O_RDWR | O_CREAT, 0644)) == -1) {
861 DEBUG(0,("unable to open or create file %s. Error was %s\n",
862 sid_file, strerror(errno) ));
867 * Check if the file contains data.
870 if(sys_fstat( fd, &st) < 0) {
871 DEBUG(0,("unable to stat file %s. Error was %s\n",
872 sid_file, strerror(errno) ));
879 * We have a valid SID - read it.
881 if(!read_sid_from_file( fd, sid_file)) {
882 DEBUG(0,("unable to read file %s. Error was %s\n",
883 sid_file, strerror(errno) ));
889 * JRA. Reversed the sense of this test now that I have
890 * actually done this test *personally*. One more reason
891 * to never trust third party information you have not
892 * independently verified.... sigh. JRA.
895 if(global_sam_sid.num_auths > 0 && global_sam_sid.sub_auths[0] == 0x21) {
897 * Fix and re-write...
899 overwrite_bad_sid = True;
900 global_sam_sid.sub_auths[0] = 21;
901 DEBUG(5,("pdb_generate_sam_sid: Old (incorrect) sid id_auth of hex 21 \
902 detected - re-writing to be decimal 21 instead.\n" ));
903 sid_to_string(sid_string, &global_sam_sid);
904 if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) {
905 DEBUG(0,("unable to seek file file %s. Error was %s\n",
906 sid_file, strerror(errno) ));
916 * The file contains no data - we need to generate our
918 * Generate the new sid data & turn it into a string.
921 uchar raw_sid_data[12];
924 memset((char *)&mysid, '\0', sizeof(DOM_SID));
925 mysid.sid_rev_num = 1;
926 mysid.id_auth[5] = 5;
928 mysid.sub_auths[mysid.num_auths++] = 21;
930 generate_random_buffer( raw_sid_data, 12, True);
931 for( i = 0; i < 3; i++)
932 mysid.sub_auths[mysid.num_auths++] = IVAL(raw_sid_data, i*4);
934 sid_to_string(sid_string, &mysid);
937 fstrcat(sid_string, "\n");
940 * Ensure our new SID is valid.
943 if(!string_to_sid( &global_sam_sid, sid_string)) {
944 DEBUG(0,("unable to generate machine SID.\n"));
949 * Do an exclusive blocking lock on the file.
952 if(!do_file_lock( fd, 60, F_WRLCK)) {
953 DEBUG(0,("unable to lock file %s. Error was %s\n",
954 sid_file, strerror(errno) ));
959 if(!overwrite_bad_sid) {
961 * At this point we have a blocking lock on the SID
962 * file - check if in the meantime someone else wrote
963 * SID data into the file. If so - they were here first,
967 if(sys_fstat( fd, &st) < 0) {
968 DEBUG(0,("unable to stat file %s. Error was %s\n",
969 sid_file, strerror(errno) ));
976 * Unlock as soon as possible to reduce
977 * contention on the exclusive lock.
979 do_file_lock( fd, 60, F_UNLCK);
982 * We have a valid SID - read it.
985 if(!read_sid_from_file( fd, sid_file)) {
986 DEBUG(0,("unable to read file %s. Error was %s\n",
987 sid_file, strerror(errno) ));
997 * The file is still empty and we have an exlusive lock on it,
998 * or we're fixing an earlier mistake.
999 * Write out out SID data into the file.
1003 * Use chmod here as some (strange) UNIX's don't
1007 if(chmod(sid_file, 0644) < 0) {
1008 DEBUG(0,("unable to set correct permissions on file %s. \
1009 Error was %s\n", sid_file, strerror(errno) ));
1010 do_file_lock( fd, 60, F_UNLCK);
1015 if(write( fd, sid_string, strlen(sid_string)) != strlen(sid_string)) {
1016 DEBUG(0,("unable to write file %s. Error was %s\n",
1017 sid_file, strerror(errno) ));
1018 do_file_lock( fd, 60, F_UNLCK);
1027 do_file_lock( fd, 60, F_UNLCK);
1031 /*******************************************************************
1032 Converts NT user RID to a UNIX uid.
1033 ********************************************************************/
1035 uid_t pdb_user_rid_to_uid(uint32 user_rid)
1037 return (uid_t)(((user_rid & (~USER_RID_TYPE))- 1000)/RID_MULTIPLIER);
1040 /*******************************************************************
1041 Converts NT user RID to a UNIX gid.
1042 ********************************************************************/
1044 gid_t pdb_user_rid_to_gid(uint32 user_rid)
1046 return (uid_t)(((user_rid & (~GROUP_RID_TYPE))- 1000)/RID_MULTIPLIER);
1049 /*******************************************************************
1050 converts UNIX uid to an NT User RID.
1051 ********************************************************************/
1053 uint32 pdb_uid_to_user_rid(uid_t uid)
1055 return (((((uint32)uid)*RID_MULTIPLIER) + 1000) | USER_RID_TYPE);
1058 /*******************************************************************
1059 converts NT Group RID to a UNIX uid.
1060 ********************************************************************/
1062 uint32 pdb_gid_to_group_rid(gid_t gid)
1064 return (((((uint32)gid)*RID_MULTIPLIER) + 1000) | GROUP_RID_TYPE);
1067 /*******************************************************************
1068 Decides if a RID is a well known RID.
1069 ********************************************************************/
1071 static BOOL pdb_rid_is_well_known(uint32 rid)
1073 return (rid < 1000);
1076 /*******************************************************************
1077 Decides if a RID is a user or group RID.
1078 ********************************************************************/
1080 BOOL pdb_rid_is_user(uint32 rid)
1082 /* lkcl i understand that NT attaches an enumeration to a RID
1083 * such that it can be identified as either a user, group etc
1084 * type. there are 5 such categories, and they are documented.
1086 if(pdb_rid_is_well_known(rid)) {
1088 * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
1089 * and DOMAIN_USER_RID_GUEST.
1091 if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
1093 } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
1099 /*******************************************************************
1100 Convert a rid into a name. Used in the lookup SID rpc.
1101 ********************************************************************/
1103 BOOL lookup_local_rid(uint32 rid, char *name, uint8 *psid_name_use)
1106 BOOL is_user = pdb_rid_is_user(rid);
1108 DEBUG(5,("lookup_local_rid: looking up %s RID %u.\n", is_user ? "user" :
1109 "group", (unsigned int)rid));
1112 if(rid == DOMAIN_USER_RID_ADMIN) {
1113 pstring admin_users;
1114 char *p = admin_users;
1115 pstrcpy( admin_users, lp_domain_admin_users());
1116 if(!next_token(&p, name, NULL, sizeof(fstring)))
1117 fstrcpy(name, "Administrator");
1118 } else if (rid == DOMAIN_USER_RID_GUEST) {
1119 pstring guest_users;
1120 char *p = guest_users;
1121 pstrcpy( guest_users, lp_domain_guest_users());
1122 if(!next_token(&p, name, NULL, sizeof(fstring)))
1123 fstrcpy(name, "Guest");
1125 uid_t uid = pdb_user_rid_to_uid(rid);
1126 struct passwd *pass = sys_getpwuid(uid);
1128 *psid_name_use = SID_NAME_USER;
1130 DEBUG(5,("lookup_local_rid: looking up uid %u %s\n", (unsigned int)uid,
1131 pass ? "succeeded" : "failed" ));
1134 slprintf(name, sizeof(fstring)-1, "unix_user.%u", (unsigned int)uid);
1138 fstrcpy(name, pass->pw_name);
1140 DEBUG(5,("lookup_local_rid: found user %s for rid %u\n", name,
1141 (unsigned int)rid ));
1145 gid_t gid = pdb_user_rid_to_gid(rid);
1146 struct group *gr = getgrgid(gid);
1148 *psid_name_use = SID_NAME_ALIAS;
1150 DEBUG(5,("lookup_local_rid: looking up gid %u %s\n", (unsigned int)gid,
1151 gr ? "succeeded" : "failed" ));
1154 slprintf(name, sizeof(fstring)-1, "unix_group.%u", (unsigned int)gid);
1158 fstrcpy( name, gr->gr_name);
1160 DEBUG(5,("lookup_local_rid: found group %s for rid %u\n", name,
1161 (unsigned int)rid ));
1167 /*******************************************************************
1168 Convert a name into a SID. Used in the lookup name rpc.
1169 ********************************************************************/
1171 BOOL lookup_local_name(char *domain, char *user, DOM_SID *psid, uint8 *psid_name_use)
1173 extern DOM_SID global_sid_World_Domain;
1174 struct passwd *pass = NULL;
1177 sid_copy(&local_sid, &global_sam_sid);
1179 if(!strequal(global_myname, domain) && !strequal(global_myworkgroup, domain))
1183 * Special case for MACHINE\Everyone. Map to the world_sid.
1186 if(strequal(user, "Everyone")) {
1187 sid_copy( psid, &global_sid_World_Domain);
1188 sid_append_rid(psid, 0);
1189 *psid_name_use = SID_NAME_ALIAS;
1193 (void)map_username(user);
1195 if(!(pass = Get_Pwnam(user, False))) {
1197 * Maybe it was a group ?
1199 struct group *grp = getgrnam(user);
1204 sid_append_rid( &local_sid, pdb_gid_to_group_rid(grp->gr_gid));
1205 *psid_name_use = SID_NAME_ALIAS;
1208 sid_append_rid( &local_sid, pdb_uid_to_user_rid(pass->pw_uid));
1209 *psid_name_use = SID_NAME_USER;
1212 sid_copy( psid, &local_sid);
1217 /****************************************************************************
1218 Create a list of SIDS for a user - primary and group.
1219 This is really the wrong way to do this and needs to go via winbind. JRA.
1220 ****************************************************************************/
1222 BOOL setup_user_sids(user_struct *vuser)
1224 extern DOM_SID global_sam_sid;
1226 sid_copy(&vuser->user_sid, &global_sam_sid);
1227 sid_append_rid( &vuser->user_sid, pdb_uid_to_user_rid(vuser->uid));
1229 if (vuser->n_groups != 0) {
1232 vuser->group_sids = (DOM_SID *)malloc(sizeof(DOM_SID) * vuser->n_groups);
1234 if (vuser->group_sids == NULL)
1237 for (i = 0; i < vuser->n_groups; i++) {
1238 sid_copy(&vuser->group_sids[i], &global_sam_sid);
1239 sid_append_rid( &vuser->group_sids[i], pdb_gid_to_group_rid(vuser->groups[i]));