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.
26 extern int DEBUGLEVEL;
29 * This is set on startup - it defines the SID for this
33 DOM_SID global_machine_sid;
36 * NOTE. All these functions are abstracted into a structure
37 * that points to the correct function for the selected database. JRA.
39 * NOTE. for the get/mod/add functions, there are two sets of functions.
40 * one supports struct sam_passwd, the other supports struct smb_passwd.
41 * for speed optimisation it is best to support both these sets.
43 * it is, however, optional to support one set but not the other: there
44 * is conversion-capability built in to passdb.c, and run-time error
45 * detection for when neither are supported.
47 * password database writers are recommended to implement the sam_passwd
48 * functions in a first pass, as struct sam_passwd contains more
49 * information, needed by the NT Domain support.
51 * a full example set of derivative functions are listed below. an API
52 * writer is expected to cut/paste these into their module, replace
53 * either one set (struct smb_passwd) or the other (struct sam_passwd)
54 * OR both, and optionally also to write display info routines
55 * (struct sam_disp_info). lkcl
60 static struct smb_passwd *getPDBpwent (void *vp) { return pdb_sam_to_smb(getPDB21pwent(vp)); }
61 static BOOL add_PDBpwd_entry (struct smb_passwd *newpwd) { return add_PDB21pwd_entry(pdb_smb_to_sam(newpwd)); }
62 static BOOL mod_PDBpwd_entry (struct smb_passwd* pwd, BOOL override) { return mod_PDB21pwd_entry(pdb_smb_to_sam(pwd), override); }
63 static struct smb_passwd *getPDBpwnam (char *name) { return pdb_sam_to_smb(getPDB21pwnam(name)); }
64 static struct smb_passwd *getPDBpwuid (uid_t smb_userid) { return pdb_sam_to_smb(getPDB21pwuid(pdb_uid_to_user_rid(smb_userid))); }
66 static struct sam_passwd *getPDB21pwent (void *vp) { return pdb_smb_to_sam(getPDBpwent(vp)); }
67 static BOOL add_PDB21pwd_entry (struct sam_passwd *newpwd) { return add_PDBpwd_entry(pdb_sam_to_smb(newpwd)); }
68 static BOOL mod_PDB21pwd_entry (struct sam_passwd* pwd, BOOL override) { return mod_PDBpwd_entry(pdb_sam_to_smb(pwd), override); }
69 static struct sam_passwd *getPDB21pwnam (char *name) { return pdb_smb_to_sam(getPDBpwnam(name)); }
70 static struct sam_passwd *getPDB21pwrid (uint32 rid) { return pdb_smb_to_sam(getPDBpwuid(pdb_user_rid_to_uid(rid))); }
71 static struct sam_passwd *getPDB21pwuid (uid_t uid) { return pdb_smb_to_sam(getPDBpwuid(uid)); }
73 static struct sam_disp_info *getPDBdispnam (char *name) { return pdb_sam_to_dispinfo(getPDB21pwnam(name)); }
74 static struct sam_disp_info *getPDBdisprid (uint32 rid) { return pdb_sam_to_dispinfo(getPDB21pwrid(rid)); }
75 static struct sam_disp_info *getPDBdispent (void *vp) { return pdb_sam_to_dispinfo(getPDB21pwent(vp)); }
78 static struct passdb_ops *pdb_ops;
80 /***************************************************************
81 Initialize the password db operations.
82 ***************************************************************/
84 BOOL initialize_password_db(void)
92 pdb_ops = nisplus_initialize_password_db();
93 #elif defined(WITH_LDAP)
94 pdb_ops = ldap_initialize_password_db();
96 pdb_ops = file_initialize_password_db();
99 return (pdb_ops != NULL);
103 * Functions that return/manipulate a struct smb_passwd.
106 /************************************************************************
107 Utility function to search smb passwd by uid. use this if your database
108 does not have search facilities.
109 *************************************************************************/
111 struct smb_passwd *iterate_getsmbpwuid(uid_t smb_userid)
113 struct smb_passwd *pwd = NULL;
116 DEBUG(10, ("iterate_getsmbpwuid: search by smb_userid: %x\n", (int)smb_userid));
118 /* Open the smb password database - not for update. */
119 fp = startsmbpwent(False);
123 DEBUG(0, ("iterate_getsmbpwuid: unable to open smb password database.\n"));
127 while ((pwd = getsmbpwent(fp)) != NULL && pwd->smb_userid != smb_userid)
132 DEBUG(10, ("iterate_getsmbpwuid: found by smb_userid: %x\n", (int)smb_userid));
139 /************************************************************************
140 Utility function to search smb passwd by name. use this if your database
141 does not have search facilities.
142 *************************************************************************/
144 struct smb_passwd *iterate_getsmbpwnam(char *name)
146 struct smb_passwd *pwd = NULL;
149 DEBUG(10, ("iterate_getsmbpwnam: search by name: %s\n", name));
151 /* Open the sam password file - not for update. */
152 fp = startsmbpwent(False);
156 DEBUG(0, ("iterate_getsmbpwnam: unable to open smb password database.\n"));
160 while ((pwd = getsmbpwent(fp)) != NULL && !strequal(pwd->smb_name, name))
165 DEBUG(10, ("iterate_getsmbpwnam: found by name: %s\n", name));
172 /***************************************************************
173 Start to enumerate the smb or sam passwd list. Returns a void pointer
174 to ensure no modification outside this module.
176 Note that currently it is being assumed that a pointer returned
177 from this function may be used to enumerate struct sam_passwd
178 entries as well as struct smb_passwd entries. This may need
181 ****************************************************************/
183 void *startsmbpwent(BOOL update)
185 return pdb_ops->startsmbpwent(update);
188 /***************************************************************
189 End enumeration of the smb or sam passwd list.
191 Note that currently it is being assumed that a pointer returned
192 from this function may be used to enumerate struct sam_passwd
193 entries as well as struct smb_passwd entries. This may need
196 ****************************************************************/
198 void endsmbpwent(void *vp)
200 pdb_ops->endsmbpwent(vp);
203 /*************************************************************************
204 Routine to return the next entry in the smb passwd list.
205 *************************************************************************/
207 struct smb_passwd *getsmbpwent(void *vp)
209 return pdb_ops->getsmbpwent(vp);
212 /*************************************************************************
213 Return the current position in the smb passwd list as an unsigned long.
214 This must be treated as an opaque token.
216 Note that currently it is being assumed that a pointer returned
217 from this function may be used to enumerate struct sam_passwd
218 entries as well as struct smb_passwd entries. This may need
221 *************************************************************************/
223 unsigned long getsmbpwpos(void *vp)
225 return pdb_ops->getsmbpwpos(vp);
228 /*************************************************************************
229 Set the current position in the smb passwd list from unsigned long.
230 This must be treated as an opaque token.
232 Note that currently it is being assumed that a pointer returned
233 from this function may be used to enumerate struct sam_passwd
234 entries as well as struct smb_passwd entries. This may need
237 *************************************************************************/
239 BOOL setsmbpwpos(void *vp, unsigned long tok)
241 return pdb_ops->setsmbpwpos(vp, tok);
244 /************************************************************************
245 Routine to add an entry to the smb passwd file.
246 *************************************************************************/
248 BOOL add_smbpwd_entry(struct smb_passwd *newpwd)
250 return pdb_ops->add_smbpwd_entry(newpwd);
253 /************************************************************************
254 Routine to search the smb passwd file for an entry matching the username.
255 and then modify its password entry. We can't use the startsampwent()/
256 getsampwent()/endsampwent() interfaces here as we depend on looking
257 in the actual file to decide how much room we have to write data.
258 override = False, normal
259 override = True, override XXXXXXXX'd out password or NO PASS
260 ************************************************************************/
262 BOOL mod_smbpwd_entry(struct smb_passwd* pwd, BOOL override)
264 return pdb_ops->mod_smbpwd_entry(pwd, override);
267 /************************************************************************
268 Routine to search smb passwd by name.
269 *************************************************************************/
271 struct smb_passwd *getsmbpwnam(char *name)
273 return pdb_ops->getsmbpwnam(name);
276 /************************************************************************
277 Routine to search smb passwd by uid.
278 *************************************************************************/
280 struct smb_passwd *getsmbpwuid(uid_t smb_userid)
282 return pdb_ops->getsmbpwuid(smb_userid);
286 * Functions that manupulate a struct sam_passwd.
289 /************************************************************************
290 Utility function to search sam passwd by name. use this if your database
291 does not have search facilities.
292 *************************************************************************/
294 struct sam_passwd *iterate_getsam21pwnam(char *name)
296 struct sam_passwd *pwd = NULL;
299 DEBUG(10, ("iterate_getsam21pwnam: search by name: %s\n", name));
301 /* Open the smb password database - not for update. */
302 fp = startsmbpwent(False);
306 DEBUG(0, ("iterate_getsam21pwnam: unable to open sam password database.\n"));
310 while ((pwd = getsam21pwent(fp)) != NULL && !strequal(pwd->smb_name, name))
315 DEBUG(10, ("iterate_getsam21pwnam: found by name: %s\n", name));
322 /************************************************************************
323 Utility function to search sam passwd by rid. use this if your database
324 does not have search facilities.
326 search capability by both rid and uid are needed as the rid <-> uid
327 mapping may be non-monotonic.
329 *************************************************************************/
331 struct sam_passwd *iterate_getsam21pwrid(uint32 rid)
333 struct sam_passwd *pwd = NULL;
336 DEBUG(10, ("iterate_getsam21pwrid: search by rid: %x\n", rid));
338 /* Open the smb password file - not for update. */
339 fp = startsmbpwent(False);
343 DEBUG(0, ("iterate_getsam21pwrid: unable to open sam password database.\n"));
347 while ((pwd = getsam21pwent(fp)) != NULL && pwd->user_rid != rid)
352 DEBUG(10, ("iterate_getsam21pwrid: found by user_rid: %x\n", rid));
359 /************************************************************************
360 Utility function to search sam passwd by uid. use this if your database
361 does not have search facilities.
363 search capability by both rid and uid are needed as the rid <-> uid
364 mapping may be non-monotonic.
366 *************************************************************************/
368 struct sam_passwd *iterate_getsam21pwuid(uid_t uid)
370 struct sam_passwd *pwd = NULL;
373 DEBUG(10, ("iterate_getsam21pwuid: search by uid: %x\n", (int)uid));
375 /* Open the smb password file - not for update. */
376 fp = startsmbpwent(False);
380 DEBUG(0, ("iterate_getsam21pwuid: unable to open sam password database.\n"));
384 while ((pwd = getsam21pwent(fp)) != NULL && pwd->smb_userid != uid)
389 DEBUG(10, ("iterate_getsam21pwuid: found by smb_userid: %x\n", (int)uid));
396 /*************************************************************************
397 Routine to return a display info structure, by name
398 *************************************************************************/
399 struct sam_disp_info *getsamdispnam(char *name)
401 return pdb_ops->getsamdispnam(name);
404 /*************************************************************************
405 Routine to return a display info structure, by rid
406 *************************************************************************/
407 struct sam_disp_info *getsamdisprid(uint32 rid)
409 return pdb_ops->getsamdisprid(rid);
412 /*************************************************************************
413 Routine to return the next entry in the sam passwd list.
414 *************************************************************************/
415 struct sam_disp_info *getsamdispent(void *vp)
417 return pdb_ops->getsamdispent(vp);
420 /*************************************************************************
421 Routine to return the next entry in the sam passwd list.
422 *************************************************************************/
424 struct sam_passwd *getsam21pwent(void *vp)
426 return pdb_ops->getsam21pwent(vp);
429 /************************************************************************
430 Routine to add an entry to the sam passwd file.
431 *************************************************************************/
433 BOOL add_sam21pwd_entry(struct sam_passwd *newpwd)
435 return pdb_ops->add_sam21pwd_entry(newpwd);
438 /************************************************************************
439 Routine to search the sam passwd database for an entry matching the username.
440 and then modify its password entry. We can't use the startsampwent()/
441 getsampwent()/endsampwent() interfaces here as we depend on looking
442 in the actual file to decide how much room we have to write data.
443 override = False, normal
444 override = True, override XXXXXXXX'd out password or NO PASS
445 ************************************************************************/
447 BOOL mod_sam21pwd_entry(struct sam_passwd* pwd, BOOL override)
449 return pdb_ops->mod_sam21pwd_entry(pwd, override);
453 /************************************************************************
454 Routine to search sam passwd by name.
455 *************************************************************************/
457 struct sam_passwd *getsam21pwnam(char *name)
459 return pdb_ops->getsam21pwnam(name);
462 /************************************************************************
463 Routine to search sam passwd by rid.
464 *************************************************************************/
466 struct sam_passwd *getsam21pwrid(uint32 rid)
468 return pdb_ops->getsam21pwrid(rid);
471 /************************************************************************
472 Routine to search sam passwd by uid.
473 *************************************************************************/
475 struct sam_passwd *getsam21pwuid(uid_t uid)
477 return pdb_ops->getsam21pwuid(uid);
483 /**********************************************************
484 **********************************************************
486 utility routines which are likely to be useful to all password
489 **********************************************************
490 **********************************************************/
492 /*************************************************************
493 initialises a struct sam_disp_info.
494 **************************************************************/
496 void pdb_init_dispinfo(struct sam_disp_info *user)
498 if (user == NULL) return;
499 bzero(user, sizeof(*user));
502 /*************************************************************
503 initialises a struct smb_passwd.
504 **************************************************************/
506 void pdb_init_smb(struct smb_passwd *user)
508 if (user == NULL) return;
509 bzero(user, sizeof(*user));
510 user->pass_last_set_time = (time_t)-1;
513 /*************************************************************
514 initialises a struct sam_passwd.
515 **************************************************************/
516 void pdb_init_sam(struct sam_passwd *user)
518 if (user == NULL) return;
519 bzero(user, sizeof(*user));
520 user->logon_time = (time_t)-1;
521 user->logoff_time = (time_t)-1;
522 user->kickoff_time = (time_t)-1;
523 user->pass_last_set_time = (time_t)-1;
524 user->pass_can_change_time = (time_t)-1;
525 user->pass_must_change_time = (time_t)-1;
528 /*************************************************************************
529 Routine to return the next entry in the sam passwd list.
530 *************************************************************************/
532 struct sam_disp_info *pdb_sam_to_dispinfo(struct sam_passwd *user)
534 static struct sam_disp_info disp_info;
536 if (user == NULL) return NULL;
538 pdb_init_dispinfo(&disp_info);
540 disp_info.smb_name = user->smb_name;
541 disp_info.full_name = user->full_name;
542 disp_info.user_rid = user->user_rid;
547 /*************************************************************
548 converts a sam_passwd structure to a smb_passwd structure.
549 **************************************************************/
551 struct smb_passwd *pdb_sam_to_smb(struct sam_passwd *user)
553 static struct smb_passwd pw_buf;
555 if (user == NULL) return NULL;
557 pdb_init_smb(&pw_buf);
559 pw_buf.smb_userid = user->smb_userid;
560 pw_buf.smb_name = user->smb_name;
561 pw_buf.smb_passwd = user->smb_passwd;
562 pw_buf.smb_nt_passwd = user->smb_nt_passwd;
563 pw_buf.acct_ctrl = user->acct_ctrl;
564 pw_buf.pass_last_set_time = user->pass_last_set_time;
569 /*************************************************************
570 converts a smb_passwd structure to a sam_passwd structure.
571 **************************************************************/
573 struct sam_passwd *pdb_smb_to_sam(struct smb_passwd *user)
575 static struct sam_passwd pw_buf;
577 if (user == NULL) return NULL;
579 pdb_init_sam(&pw_buf);
581 pw_buf.smb_userid = user->smb_userid;
582 pw_buf.smb_name = user->smb_name;
583 pw_buf.smb_passwd = user->smb_passwd;
584 pw_buf.smb_nt_passwd = user->smb_nt_passwd;
585 pw_buf.acct_ctrl = user->acct_ctrl;
586 pw_buf.pass_last_set_time = user->pass_last_set_time;
592 /*******************************************************************
593 gets password-database-format time from a string.
594 ********************************************************************/
596 static time_t get_time_from_string(char *p)
600 for (i = 0; i < 8; i++)
602 if (p[i] == '\0' || !isxdigit((int)p[i]))
608 * p points at 8 characters of hex digits -
609 * read into a time_t as the seconds since
610 * 1970 that the password was last changed.
612 return (time_t)strtol((char *)p, NULL, 16);
617 /*******************************************************************
618 gets password last set time
619 ********************************************************************/
621 time_t pdb_get_last_set_time(char *p)
623 if (*p && StrnCaseCmp((char *)p, "LCT-", 4))
625 return get_time_from_string(p + 4);
631 /*******************************************************************
632 sets password-database-format time in a string.
633 ********************************************************************/
634 static void set_time_in_string(char *p, int max_len, char *type, time_t t)
636 slprintf(p, max_len, ":%s-%08X:", type, (uint32)t);
639 /*******************************************************************
641 ********************************************************************/
642 void pdb_set_logon_time(char *p, int max_len, time_t t)
644 set_time_in_string(p, max_len, "LNT", t);
647 /*******************************************************************
649 ********************************************************************/
650 void pdb_set_logoff_time(char *p, int max_len, time_t t)
652 set_time_in_string(p, max_len, "LOT", t);
655 /*******************************************************************
657 ********************************************************************/
658 void pdb_set_kickoff_time(char *p, int max_len, time_t t)
660 set_time_in_string(p, max_len, "KOT", t);
663 /*******************************************************************
664 sets password can change time
665 ********************************************************************/
666 void pdb_set_can_change_time(char *p, int max_len, time_t t)
668 set_time_in_string(p, max_len, "CCT", t);
671 /*******************************************************************
672 sets password last set time
673 ********************************************************************/
674 void pdb_set_must_change_time(char *p, int max_len, time_t t)
676 set_time_in_string(p, max_len, "MCT", t);
679 /*******************************************************************
680 sets password last set time
681 ********************************************************************/
682 void pdb_set_last_set_time(char *p, int max_len, time_t t)
684 set_time_in_string(p, max_len, "LCT", t);
687 /**********************************************************
688 Encode the account control bits into a string.
689 **********************************************************/
691 char *pdb_encode_acct_ctrl(uint16 acct_ctrl)
693 static fstring acct_str;
698 if (acct_ctrl & ACB_HOMDIRREQ) *p++ = 'H';
699 if (acct_ctrl & ACB_TEMPDUP ) *p++ = 'T';
700 if (acct_ctrl & ACB_NORMAL ) *p++ = 'U';
701 if (acct_ctrl & ACB_MNS ) *p++ = 'M';
702 if (acct_ctrl & ACB_WSTRUST ) *p++ = 'W';
703 if (acct_ctrl & ACB_SVRTRUST ) *p++ = 'S';
704 if (acct_ctrl & ACB_AUTOLOCK ) *p++ = 'L';
705 if (acct_ctrl & ACB_PWNOEXP ) *p++ = 'X';
706 if (acct_ctrl & ACB_DOMTRUST ) *p++ = 'I';
713 /**********************************************************
714 Decode the account control bits from a string.
716 this function breaks coding standards minimum line width of 80 chars.
717 reason: vertical line-up code clarity - all case statements fit into
718 15 lines, which is more important.
719 **********************************************************/
721 uint16 pdb_decode_acct_ctrl(char *p)
723 uint16 acct_ctrl = 0;
724 BOOL finished = False;
727 * Check if the account type bits have been encoded after the
728 * NT password (in the form [NDHTUWSLXI]).
731 if (*p != '[') return 0;
733 for (p++; *p && !finished; p++)
739 * Hmmm. Don't allow these to be set/read independently
740 * of the actual password fields. We don't want a mismatch.
743 case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
744 case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
746 case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
747 case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
748 case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
749 case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
750 case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
751 case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
752 case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
753 case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
754 case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
760 default: { finished = True; }
767 /*************************************************************
768 Routine to get the 32 hex characters and turn them
769 into a 16 byte array.
770 **************************************************************/
771 BOOL pdb_gethexpwd(char *p, char *pwd)
774 unsigned char lonybble, hinybble;
775 char *hexchars = "0123456789ABCDEF";
778 for (i = 0; i < 32; i += 2)
780 hinybble = toupper(p[i]);
781 lonybble = toupper(p[i + 1]);
783 p1 = strchr(hexchars, hinybble);
784 p2 = strchr(hexchars, lonybble);
791 hinybble = PTR_DIFF(p1, hexchars);
792 lonybble = PTR_DIFF(p2, hexchars);
794 pwd[i / 2] = (hinybble << 4) | lonybble;
799 /*************************************************************
800 Routine to set 32 hex password characters from a 16 byte array.
801 **************************************************************/
802 void pdb_sethexpwd(char *p, char *pwd, uint16 acct_ctrl)
807 for (i = 0; i < 16; i++)
809 slprintf(&p[i*2], 33, "%02X", pwd[i]);
814 if (IS_BITS_SET_ALL(acct_ctrl, ACB_PWNOTREQ))
816 safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
820 safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
825 /*******************************************************************
826 Group and User RID username mapping function
827 ********************************************************************/
829 BOOL pdb_name_to_rid(char *user_name, uint32 *u_rid, uint32 *g_rid)
831 struct passwd *pw = Get_Pwnam(user_name, False);
833 if (u_rid == NULL || g_rid == NULL || user_name == NULL)
840 DEBUG(1,("Username %s is invalid on this system\n", user_name));
844 if (user_in_list(user_name, lp_domain_guest_users()))
846 *u_rid = DOMAIN_USER_RID_GUEST;
848 else if (user_in_list(user_name, lp_domain_admin_users()))
850 *u_rid = DOMAIN_USER_RID_ADMIN;
854 /* turn the unix UID into a Domain RID. this is what the posix
855 sub-system does (adds 1000 to the uid) */
856 *u_rid = pdb_uid_to_user_rid(pw->pw_uid);
859 /* absolutely no idea what to do about the unix GID to Domain RID mapping */
860 *g_rid = pdb_gid_to_group_rid(pw->pw_gid);
865 /****************************************************************************
866 Read the machine SID from a file.
867 ****************************************************************************/
869 static BOOL read_sid_from_file(int fd, char *sid_file)
873 memset(fline, '\0', sizeof(fline));
875 if(read(fd, fline, sizeof(fline) -1 ) < 0) {
876 DEBUG(0,("read_sid_from_file: unable to read file %s. Error was %s\n",
877 sid_file, strerror(errno) ));
882 * Convert to the machine SID.
885 fline[sizeof(fline)-1] = '\0';
886 if(!string_to_sid( &global_machine_sid, fline)) {
887 DEBUG(0,("read_sid_from_file: unable to generate machine SID.\n"));
894 /****************************************************************************
895 Generate the global machine sid. Look for the MACHINE.SID file first, if
896 not found then look in smb.conf and use it to create the MACHINE.SID file.
897 ****************************************************************************/
898 BOOL pdb_generate_machine_sid(void)
905 uchar raw_sid_data[12];
907 pstrcpy(sid_file, lp_smb_passwd_file());
908 p = strrchr(sid_file, '/');
913 if (!directory_exist(sid_file, NULL)) {
914 if (dos_mkdir(sid_file, 0700) != 0) {
915 DEBUG(0,("generate_machine_sid: can't create private directory %s : %s\n",
916 sid_file, strerror(errno)));
921 pstrcat(sid_file, "MACHINE.SID");
923 if((fd = open(sid_file, O_RDWR | O_CREAT, 0644)) == -1) {
924 DEBUG(0,("generate_machine_sid: unable to open or create file %s. Error was %s\n",
925 sid_file, strerror(errno) ));
930 * Check if the file contains data.
933 if(sys_fstat( fd, &st) < 0) {
934 DEBUG(0,("generate_machine_sid: unable to stat file %s. Error was %s\n",
935 sid_file, strerror(errno) ));
942 * We have a valid SID - read it.
944 if(!read_sid_from_file( fd, sid_file)) {
945 DEBUG(0,("generate_machine_sid: unable to read file %s. Error was %s\n",
946 sid_file, strerror(errno) ));
955 * The file contains no data - we may need to generate our
956 * own sid. Try the lp_domain_sid() first.
960 fstrcpy( sid_string, lp_domain_sid());
963 * Generate the new sid data & turn it into a string.
966 generate_random_buffer( raw_sid_data, 12, True);
968 fstrcpy( sid_string, "S-1-5-21");
969 for( i = 0; i < 3; i++) {
971 slprintf( tmp_string, sizeof(tmp_string) - 1, "-%u", IVAL(raw_sid_data, i*4));
972 fstrcat( sid_string, tmp_string);
976 fstrcat(sid_string, "\n");
979 * Ensure our new SID is valid.
982 if(!string_to_sid( &global_machine_sid, sid_string)) {
983 DEBUG(0,("generate_machine_sid: unable to generate machine SID.\n"));
988 * Do an exclusive blocking lock on the file.
991 if(!do_file_lock( fd, 60, F_WRLCK)) {
992 DEBUG(0,("generate_machine_sid: unable to lock file %s. Error was %s\n",
993 sid_file, strerror(errno) ));
999 * At this point we have a blocking lock on the SID
1000 * file - check if in the meantime someone else wrote
1001 * SID data into the file. If so - they were here first,
1005 if(sys_fstat( fd, &st) < 0) {
1006 DEBUG(0,("generate_machine_sid: unable to stat file %s. Error was %s\n",
1007 sid_file, strerror(errno) ));
1012 if(st.st_size > 0) {
1014 * Unlock as soon as possible to reduce
1015 * contention on the exclusive lock.
1017 do_file_lock( fd, 60, F_UNLCK);
1020 * We have a valid SID - read it.
1023 if(!read_sid_from_file( fd, sid_file)) {
1024 DEBUG(0,("generate_machine_sid: unable to read file %s. Error was %s\n",
1025 sid_file, strerror(errno) ));
1034 * The file is still empty and we have an exlusive lock on it.
1035 * Write out out SID data into the file.
1038 if(fchmod(fd, 0644) < 0) {
1039 DEBUG(0,("generate_machine_sid: unable to set correct permissions on file %s. \
1040 Error was %s\n", sid_file, strerror(errno) ));
1045 if(write( fd, sid_string, strlen(sid_string)) != strlen(sid_string)) {
1046 DEBUG(0,("generate_machine_sid: unable to write file %s. Error was %s\n",
1047 sid_file, strerror(errno) ));
1056 do_file_lock( fd, 60, F_UNLCK);
1061 /*******************************************************************
1062 converts NT User RID to a UNIX uid.
1063 ********************************************************************/
1065 uid_t pdb_user_rid_to_uid(uint32 u_rid)
1067 return (uid_t)((u_rid / RID_MULTIPLIER) - 1000);
1070 /*******************************************************************
1071 converts NT Group RID to a UNIX uid.
1072 ********************************************************************/
1074 gid_t pdb_group_rid_to_gid(uint32 g_rid)
1076 return (gid_t)((g_rid / RID_MULTIPLIER) - 1000);
1079 /*******************************************************************
1080 converts UNIX uid to an NT User RID.
1081 ********************************************************************/
1083 uint32 pdb_uid_to_user_rid(uid_t uid)
1085 return (((((uint32)uid)*RID_MULTIPLIER) + 1000) | USER_RID_TYPE);
1088 /*******************************************************************
1089 converts NT Group RID to a UNIX uid.
1090 ********************************************************************/
1092 uint32 pdb_gid_to_group_rid(gid_t gid)
1094 return (((((uint32)gid)*RID_MULTIPLIER) + 1000) | GROUP_RID_TYPE);
1097 /*******************************************************************
1098 Decides if a RID is a well known RID.
1099 ********************************************************************/
1101 BOOL pdb_rid_is_well_known(uint32 rid)
1103 return (rid < 1000);
1106 /*******************************************************************
1107 Decides if a RID is a user or group RID.
1108 ********************************************************************/
1110 BOOL pdb_rid_is_user(uint32 rid)
1112 /* lkcl i understand that NT attaches an enumeration to a RID
1113 * such that it can be identified as either a user, group etc
1114 * type. there are 5 such categories, and they are documented.
1116 if(pdb_rid_is_well_known(rid)) {
1118 * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
1119 * and DOMAIN_USER_RID_GUEST.
1121 if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
1123 } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {