Fixed a couple of bugs in displaying a UNIX permission as an NT
[Samba/ekacnet.git] / source / passdb / passdb.c
blob9b0e8c21a1503e47e36afafd83df4888b91983a2
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
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.
23 #include "includes.h"
24 #include "nterr.h"
26 extern int DEBUGLEVEL;
29 * This is set on startup - it defines the SID for this
30 * machine, and therefore the SAM database for which it is
31 * responsible.
34 extern DOM_SID global_sam_sid;
35 extern pstring global_myname;
36 extern fstring global_myworkgroup;
39 * NOTE. All these functions are abstracted into a structure
40 * that points to the correct function for the selected database. JRA.
42 * NOTE. for the get/mod/add functions, there are two sets of functions.
43 * one supports struct sam_passwd, the other supports struct smb_passwd.
44 * for speed optimisation it is best to support both these sets.
46 * it is, however, optional to support one set but not the other: there
47 * is conversion-capability built in to passdb.c, and run-time error
48 * detection for when neither are supported.
50 * password database writers are recommended to implement the sam_passwd
51 * functions in a first pass, as struct sam_passwd contains more
52 * information, needed by the NT Domain support.
54 * a full example set of derivative functions are listed below. an API
55 * writer is expected to cut/paste these into their module, replace
56 * either one set (struct smb_passwd) or the other (struct sam_passwd)
57 * OR both, and optionally also to write display info routines
58 * (struct sam_disp_info). lkcl
62 static struct passdb_ops *pdb_ops;
64 /***************************************************************
65 Initialize the password db operations.
66 ***************************************************************/
68 BOOL initialize_password_db(void)
70 if (pdb_ops)
72 return True;
75 #ifdef WITH_NISPLUS
76 pdb_ops = nisplus_initialize_password_db();
77 #elif defined(WITH_LDAP)
78 pdb_ops = ldap_initialize_password_db();
79 #else
80 pdb_ops = file_initialize_password_db();
81 #endif
83 return (pdb_ops != NULL);
87 * Functions that return/manipulate a struct smb_passwd.
90 /************************************************************************
91 Utility function to search smb passwd by rid.
92 *************************************************************************/
94 struct smb_passwd *iterate_getsmbpwrid(uint32 user_rid)
96 return iterate_getsmbpwuid(pdb_user_rid_to_uid(user_rid));
99 /************************************************************************
100 Utility function to search smb passwd by uid. use this if your database
101 does not have search facilities.
102 *************************************************************************/
104 struct smb_passwd *iterate_getsmbpwuid(uid_t smb_userid)
106 struct smb_passwd *pwd = NULL;
107 void *fp = NULL;
109 DEBUG(10, ("search by smb_userid: %x\n", (int)smb_userid));
111 /* Open the smb password database - not for update. */
112 fp = startsmbpwent(False);
114 if (fp == NULL)
116 DEBUG(0, ("unable to open smb password database.\n"));
117 return NULL;
120 while ((pwd = getsmbpwent(fp)) != NULL && pwd->smb_userid != smb_userid)
123 if (pwd != NULL)
125 DEBUG(10, ("found by smb_userid: %x\n", (int)smb_userid));
128 endsmbpwent(fp);
129 return pwd;
132 /************************************************************************
133 Utility function to search smb passwd by name. use this if your database
134 does not have search facilities.
135 *************************************************************************/
137 struct smb_passwd *iterate_getsmbpwnam(char *name)
139 struct smb_passwd *pwd = NULL;
140 void *fp = NULL;
142 DEBUG(10, ("search by name: %s\n", name));
144 /* Open the sam password file - not for update. */
145 fp = startsmbpwent(False);
147 if (fp == NULL)
149 DEBUG(0, ("unable to open smb password database.\n"));
150 return NULL;
153 while ((pwd = getsmbpwent(fp)) != NULL && !strequal(pwd->smb_name, name))
156 if (pwd != NULL)
158 DEBUG(10, ("found by name: %s\n", name));
161 endsmbpwent(fp);
162 return pwd;
165 /***************************************************************
166 Start to enumerate the smb or sam passwd list. Returns a void pointer
167 to ensure no modification outside this module.
169 Note that currently it is being assumed that a pointer returned
170 from this function may be used to enumerate struct sam_passwd
171 entries as well as struct smb_passwd entries. This may need
172 to change. JRA.
174 ****************************************************************/
176 void *startsmbpwent(BOOL update)
178 return pdb_ops->startsmbpwent(update);
181 /***************************************************************
182 End enumeration of the smb or sam passwd list.
184 Note that currently it is being assumed that a pointer returned
185 from this function may be used to enumerate struct sam_passwd
186 entries as well as struct smb_passwd entries. This may need
187 to change. JRA.
189 ****************************************************************/
191 void endsmbpwent(void *vp)
193 pdb_ops->endsmbpwent(vp);
196 /*************************************************************************
197 Routine to return the next entry in the smb passwd list.
198 *************************************************************************/
200 struct smb_passwd *getsmbpwent(void *vp)
202 return pdb_ops->getsmbpwent(vp);
205 /************************************************************************
206 Routine to add an entry to the smb passwd file.
207 *************************************************************************/
209 BOOL add_smbpwd_entry(struct smb_passwd *newpwd)
211 return pdb_ops->add_smbpwd_entry(newpwd);
214 /************************************************************************
215 Routine to search the smb passwd file for an entry matching the username.
216 and then modify its password entry. We can't use the startsampwent()/
217 getsampwent()/endsampwent() interfaces here as we depend on looking
218 in the actual file to decide how much room we have to write data.
219 override = False, normal
220 override = True, override XXXXXXXX'd out password or NO PASS
221 ************************************************************************/
223 BOOL mod_smbpwd_entry(struct smb_passwd* pwd, BOOL override)
225 return pdb_ops->mod_smbpwd_entry(pwd, override);
228 /************************************************************************
229 Routine to search smb passwd by name.
230 *************************************************************************/
232 struct smb_passwd *getsmbpwnam(char *name)
234 return pdb_ops->getsmbpwnam(name);
237 /************************************************************************
238 Routine to search smb passwd by user rid.
239 *************************************************************************/
241 struct smb_passwd *getsmbpwrid(uint32 user_rid)
243 return pdb_ops->getsmbpwrid(user_rid);
246 /************************************************************************
247 Routine to search smb passwd by uid.
248 *************************************************************************/
250 struct smb_passwd *getsmbpwuid(uid_t smb_userid)
252 return pdb_ops->getsmbpwuid(smb_userid);
256 * Functions that manupulate a struct sam_passwd.
259 /************************************************************************
260 Utility function to search sam passwd by name. use this if your database
261 does not have search facilities.
262 *************************************************************************/
264 struct sam_passwd *iterate_getsam21pwnam(char *name)
266 struct sam_passwd *pwd = NULL;
267 void *fp = NULL;
269 DEBUG(10, ("search by name: %s\n", name));
271 /* Open the smb password database - not for update. */
272 fp = startsmbpwent(False);
274 if (fp == NULL)
276 DEBUG(0, ("unable to open sam password database.\n"));
277 return NULL;
280 while ((pwd = getsam21pwent(fp)) != NULL && !strequal(pwd->smb_name, name))
282 DEBUG(10, ("iterate: %s 0x%x\n", pwd->smb_name, pwd->user_rid));
285 if (pwd != NULL)
287 DEBUG(10, ("found by name: %s\n", name));
290 endsmbpwent(fp);
291 return pwd;
294 /************************************************************************
295 Utility function to search sam passwd by rid. use this if your database
296 does not have search facilities.
298 search capability by both rid and uid are needed as the rid <-> uid
299 mapping may be non-monotonic.
301 *************************************************************************/
303 struct sam_passwd *iterate_getsam21pwrid(uint32 rid)
305 struct sam_passwd *pwd = NULL;
306 void *fp = NULL;
308 DEBUG(10, ("search by rid: %x\n", rid));
310 /* Open the smb password file - not for update. */
311 fp = startsmbpwent(False);
313 if (fp == NULL)
315 DEBUG(0, ("unable to open sam password database.\n"));
316 return NULL;
319 while ((pwd = getsam21pwent(fp)) != NULL && pwd->user_rid != rid)
321 DEBUG(10, ("iterate: %s 0x%x\n", pwd->smb_name, pwd->user_rid));
324 if (pwd != NULL)
326 DEBUG(10, ("found by user_rid: %x\n", rid));
329 endsmbpwent(fp);
330 return pwd;
333 /************************************************************************
334 Utility function to search sam passwd by uid. use this if your database
335 does not have search facilities.
337 search capability by both rid and uid are needed as the rid <-> uid
338 mapping may be non-monotonic.
340 *************************************************************************/
342 struct sam_passwd *iterate_getsam21pwuid(uid_t uid)
344 struct sam_passwd *pwd = NULL;
345 void *fp = NULL;
347 DEBUG(10, ("search by uid: %x\n", (int)uid));
349 /* Open the smb password file - not for update. */
350 fp = startsmbpwent(False);
352 if (fp == NULL)
354 DEBUG(0, ("unable to open sam password database.\n"));
355 return NULL;
358 while ((pwd = getsam21pwent(fp)) != NULL && pwd->smb_userid != uid)
361 if (pwd != NULL)
363 DEBUG(10, ("found by smb_userid: %x\n", (int)uid));
366 endsmbpwent(fp);
367 return pwd;
370 /*************************************************************************
371 Routine to return a display info structure, by rid
372 *************************************************************************/
373 struct sam_disp_info *getsamdisprid(uint32 rid)
375 return pdb_ops->getsamdisprid(rid);
378 /*************************************************************************
379 Routine to return the next entry in the sam passwd list.
380 *************************************************************************/
382 struct sam_passwd *getsam21pwent(void *vp)
384 return pdb_ops->getsam21pwent(vp);
388 /************************************************************************
389 Routine to search sam passwd by name.
390 *************************************************************************/
392 struct sam_passwd *getsam21pwnam(char *name)
394 return pdb_ops->getsam21pwnam(name);
397 /************************************************************************
398 Routine to search sam passwd by rid.
399 *************************************************************************/
401 struct sam_passwd *getsam21pwrid(uint32 rid)
403 return pdb_ops->getsam21pwrid(rid);
407 /**********************************************************
408 **********************************************************
410 utility routines which are likely to be useful to all password
411 databases
413 **********************************************************
414 **********************************************************/
416 /*************************************************************
417 initialises a struct sam_disp_info.
418 **************************************************************/
420 static void pdb_init_dispinfo(struct sam_disp_info *user)
422 if (user == NULL) return;
423 memset((char *)user, '\0', sizeof(*user));
426 /*************************************************************
427 initialises a struct smb_passwd.
428 **************************************************************/
430 void pdb_init_smb(struct smb_passwd *user)
432 if (user == NULL) return;
433 memset((char *)user, '\0', sizeof(*user));
434 user->pass_last_set_time = (time_t)-1;
437 /*************************************************************
438 initialises a struct sam_passwd.
439 **************************************************************/
440 void pdb_init_sam(struct sam_passwd *user)
442 if (user == NULL) return;
443 memset((char *)user, '\0', sizeof(*user));
444 user->logon_time = (time_t)-1;
445 user->logoff_time = (time_t)-1;
446 user->kickoff_time = (time_t)-1;
447 user->pass_last_set_time = (time_t)-1;
448 user->pass_can_change_time = (time_t)-1;
449 user->pass_must_change_time = (time_t)-1;
452 /*************************************************************************
453 Routine to return the next entry in the sam passwd list.
454 *************************************************************************/
456 struct sam_disp_info *pdb_sam_to_dispinfo(struct sam_passwd *user)
458 static struct sam_disp_info disp_info;
460 if (user == NULL) return NULL;
462 pdb_init_dispinfo(&disp_info);
464 disp_info.smb_name = user->smb_name;
465 disp_info.full_name = user->full_name;
466 disp_info.user_rid = user->user_rid;
468 return &disp_info;
471 /*************************************************************
472 converts a sam_passwd structure to a smb_passwd structure.
473 **************************************************************/
475 struct smb_passwd *pdb_sam_to_smb(struct sam_passwd *user)
477 static struct smb_passwd pw_buf;
479 if (user == NULL) return NULL;
481 pdb_init_smb(&pw_buf);
483 pw_buf.smb_userid = user->smb_userid;
484 pw_buf.smb_name = user->smb_name;
485 pw_buf.smb_passwd = user->smb_passwd;
486 pw_buf.smb_nt_passwd = user->smb_nt_passwd;
487 pw_buf.acct_ctrl = user->acct_ctrl;
488 pw_buf.pass_last_set_time = user->pass_last_set_time;
490 return &pw_buf;
494 /*************************************************************
495 converts a smb_passwd structure to a sam_passwd structure.
496 **************************************************************/
498 struct sam_passwd *pdb_smb_to_sam(struct smb_passwd *user)
500 static struct sam_passwd pw_buf;
502 if (user == NULL) return NULL;
504 pdb_init_sam(&pw_buf);
506 pw_buf.smb_userid = user->smb_userid;
507 pw_buf.smb_name = user->smb_name;
508 pw_buf.smb_passwd = user->smb_passwd;
509 pw_buf.smb_nt_passwd = user->smb_nt_passwd;
510 pw_buf.acct_ctrl = user->acct_ctrl;
511 pw_buf.pass_last_set_time = user->pass_last_set_time;
513 return &pw_buf;
516 /**********************************************************
517 Encode the account control bits into a string.
518 length = length of string to encode into (including terminating
519 null). length *MUST BE MORE THAN 2* !
520 **********************************************************/
522 char *pdb_encode_acct_ctrl(uint16 acct_ctrl, size_t length)
524 static fstring acct_str;
525 size_t i = 0;
527 acct_str[i++] = '[';
529 if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
530 if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
531 if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
532 if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T';
533 if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U';
534 if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M';
535 if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W';
536 if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
537 if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
538 if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X';
539 if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
541 for ( ; i < length - 2 ; i++ ) { acct_str[i] = ' '; }
543 i = length - 2;
544 acct_str[i++] = ']';
545 acct_str[i++] = '\0';
547 return acct_str;
550 /**********************************************************
551 Decode the account control bits from a string.
553 this function breaks coding standards minimum line width of 80 chars.
554 reason: vertical line-up code clarity - all case statements fit into
555 15 lines, which is more important.
556 **********************************************************/
558 uint16 pdb_decode_acct_ctrl(const char *p)
560 uint16 acct_ctrl = 0;
561 BOOL finished = False;
564 * Check if the account type bits have been encoded after the
565 * NT password (in the form [NDHTUWSLXI]).
568 if (*p != '[') return 0;
570 for (p++; *p && !finished; p++)
572 switch (*p)
574 case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
575 case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
576 case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
577 case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
578 case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
579 case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
580 case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
581 case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
582 case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
583 case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
584 case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
585 case ' ': { break; }
586 case ':':
587 case '\n':
588 case '\0':
589 case ']':
590 default: { finished = True; }
594 return acct_ctrl;
597 /*******************************************************************
598 gets password-database-format time from a string.
599 ********************************************************************/
601 static time_t get_time_from_string(const char *p)
603 int i;
605 for (i = 0; i < 8; i++)
607 if (p[i] == '\0' || !isxdigit((int)(p[i]&0xFF)))
608 break;
610 if (i == 8)
613 * p points at 8 characters of hex digits -
614 * read into a time_t as the seconds since
615 * 1970 that the password was last changed.
617 return (time_t)strtol(p, NULL, 16);
619 return (time_t)-1;
622 /*******************************************************************
623 gets password last set time
624 ********************************************************************/
626 time_t pdb_get_last_set_time(const char *p)
628 if (*p && StrnCaseCmp(p, "LCT-", 4))
630 return get_time_from_string(p + 4);
632 return (time_t)-1;
636 /*******************************************************************
637 sets password-database-format time in a string.
638 ********************************************************************/
639 static void set_time_in_string(char *p, int max_len, char *type, time_t t)
641 slprintf(p, max_len, ":%s-%08X:", type, (uint32)t);
644 /*******************************************************************
645 sets logon time
646 ********************************************************************/
647 void pdb_set_logon_time(char *p, int max_len, time_t t)
649 set_time_in_string(p, max_len, "LNT", t);
652 /*******************************************************************
653 sets logoff time
654 ********************************************************************/
655 void pdb_set_logoff_time(char *p, int max_len, time_t t)
657 set_time_in_string(p, max_len, "LOT", t);
660 /*******************************************************************
661 sets kickoff time
662 ********************************************************************/
663 void pdb_set_kickoff_time(char *p, int max_len, time_t t)
665 set_time_in_string(p, max_len, "KOT", t);
668 /*******************************************************************
669 sets password can change time
670 ********************************************************************/
671 void pdb_set_can_change_time(char *p, int max_len, time_t t)
673 set_time_in_string(p, max_len, "CCT", t);
676 /*******************************************************************
677 sets password last set time
678 ********************************************************************/
679 void pdb_set_must_change_time(char *p, int max_len, time_t t)
681 set_time_in_string(p, max_len, "MCT", t);
684 /*******************************************************************
685 sets password last set time
686 ********************************************************************/
687 void pdb_set_last_set_time(char *p, int max_len, time_t t)
689 set_time_in_string(p, max_len, "LCT", t);
693 /*************************************************************
694 Routine to set 32 hex password characters from a 16 byte array.
695 **************************************************************/
696 void pdb_sethexpwd(char *p, char *pwd, uint16 acct_ctrl)
698 if (pwd != NULL)
700 int i;
701 for (i = 0; i < 16; i++)
703 slprintf(&p[i*2], 33, "%02X", pwd[i]);
706 else
708 if (IS_BITS_SET_ALL(acct_ctrl, ACB_PWNOTREQ))
710 safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
712 else
714 safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
718 /*************************************************************
719 Routine to get the 32 hex characters and turn them
720 into a 16 byte array.
721 **************************************************************/
722 BOOL pdb_gethexpwd(char *p, char *pwd)
724 int i;
725 unsigned char lonybble, hinybble;
726 char *hexchars = "0123456789ABCDEF";
727 char *p1, *p2;
729 for (i = 0; i < 32; i += 2)
731 hinybble = toupper(p[i]);
732 lonybble = toupper(p[i + 1]);
734 p1 = strchr(hexchars, hinybble);
735 p2 = strchr(hexchars, lonybble);
737 if (!p1 || !p2)
739 return (False);
742 hinybble = PTR_DIFF(p1, hexchars);
743 lonybble = PTR_DIFF(p2, hexchars);
745 pwd[i / 2] = (hinybble << 4) | lonybble;
747 return (True);
750 /*******************************************************************
751 Group and User RID username mapping function
752 ********************************************************************/
754 BOOL pdb_name_to_rid(char *user_name, uint32 *u_rid, uint32 *g_rid)
756 struct passwd *pw = Get_Pwnam(user_name, False);
758 if (u_rid == NULL || g_rid == NULL || user_name == NULL)
760 return False;
763 if (!pw)
765 DEBUG(1,("Username %s is invalid on this system\n", user_name));
766 return False;
769 if (user_in_list(user_name, lp_domain_guest_users()))
771 *u_rid = DOMAIN_USER_RID_GUEST;
773 else if (user_in_list(user_name, lp_domain_admin_users()))
775 *u_rid = DOMAIN_USER_RID_ADMIN;
777 else
779 /* turn the unix UID into a Domain RID. this is what the posix
780 sub-system does (adds 1000 to the uid) */
781 *u_rid = pdb_uid_to_user_rid(pw->pw_uid);
784 /* absolutely no idea what to do about the unix GID to Domain RID mapping */
785 *g_rid = pdb_gid_to_group_rid(pw->pw_gid);
787 return True;
790 /****************************************************************************
791 Read the machine SID from a file.
792 ****************************************************************************/
794 static BOOL read_sid_from_file(int fd, char *sid_file)
796 fstring fline;
798 memset(fline, '\0', sizeof(fline));
800 if(read(fd, fline, sizeof(fline) -1 ) < 0) {
801 DEBUG(0,("unable to read file %s. Error was %s\n",
802 sid_file, strerror(errno) ));
803 return False;
807 * Convert to the machine SID.
810 fline[sizeof(fline)-1] = '\0';
811 if(!string_to_sid( &global_sam_sid, fline)) {
812 DEBUG(0,("unable to generate machine SID.\n"));
813 return False;
816 return True;
819 /****************************************************************************
820 Generate the global machine sid. Look for the MACHINE.SID file first, if
821 not found then look in smb.conf and use it to create the MACHINE.SID file.
822 ****************************************************************************/
823 BOOL pdb_generate_sam_sid(void)
825 int fd;
826 char *p;
827 pstring sid_file;
828 fstring sid_string;
829 SMB_STRUCT_STAT st;
830 BOOL overwrite_bad_sid = False;
832 generate_wellknown_sids();
834 pstrcpy(sid_file, lp_smb_passwd_file());
835 p = strrchr(sid_file, '/');
836 if(p != NULL) {
837 *++p = '\0';
840 if (!directory_exist(sid_file, NULL)) {
841 if (mkdir(sid_file, 0700) != 0) {
842 DEBUG(0,("can't create private directory %s : %s\n",
843 sid_file, strerror(errno)));
844 return False;
848 pstrcat(sid_file, "MACHINE.SID");
850 if((fd = sys_open(sid_file, O_RDWR | O_CREAT, 0644)) == -1) {
851 DEBUG(0,("unable to open or create file %s. Error was %s\n",
852 sid_file, strerror(errno) ));
853 return False;
857 * Check if the file contains data.
860 if(sys_fstat( fd, &st) < 0) {
861 DEBUG(0,("unable to stat file %s. Error was %s\n",
862 sid_file, strerror(errno) ));
863 close(fd);
864 return False;
867 if(st.st_size > 0) {
869 * We have a valid SID - read it.
871 if(!read_sid_from_file( fd, sid_file)) {
872 DEBUG(0,("unable to read file %s. Error was %s\n",
873 sid_file, strerror(errno) ));
874 close(fd);
875 return False;
879 * JRA. Reversed the sense of this test now that I have
880 * actually done this test *personally*. One more reason
881 * to never trust third party information you have not
882 * independently verified.... sigh. JRA.
885 if(global_sam_sid.num_auths > 0 && global_sam_sid.sub_auths[0] == 0x21) {
887 * Fix and re-write...
889 overwrite_bad_sid = True;
890 global_sam_sid.sub_auths[0] = 21;
891 DEBUG(5,("pdb_generate_sam_sid: Old (incorrect) sid id_auth of hex 21 \
892 detected - re-writing to be decimal 21 instead.\n" ));
893 sid_to_string(sid_string, &global_sam_sid);
894 if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) {
895 DEBUG(0,("unable to seek file file %s. Error was %s\n",
896 sid_file, strerror(errno) ));
897 close(fd);
898 return False;
900 } else {
901 close(fd);
902 return True;
904 } else {
906 * The file contains no data - we need to generate our
907 * own sid.
908 * Generate the new sid data & turn it into a string.
910 int i;
911 uchar raw_sid_data[12];
912 DOM_SID mysid;
914 memset((char *)&mysid, '\0', sizeof(DOM_SID));
915 mysid.sid_rev_num = 1;
916 mysid.id_auth[5] = 5;
917 mysid.num_auths = 0;
918 mysid.sub_auths[mysid.num_auths++] = 21;
920 generate_random_buffer( raw_sid_data, 12, True);
921 for( i = 0; i < 3; i++)
922 mysid.sub_auths[mysid.num_auths++] = IVAL(raw_sid_data, i*4);
924 sid_to_string(sid_string, &mysid);
927 fstrcat(sid_string, "\n");
930 * Ensure our new SID is valid.
933 if(!string_to_sid( &global_sam_sid, sid_string)) {
934 DEBUG(0,("unable to generate machine SID.\n"));
935 return False;
939 * Do an exclusive blocking lock on the file.
942 if(!do_file_lock( fd, 60, F_WRLCK)) {
943 DEBUG(0,("unable to lock file %s. Error was %s\n",
944 sid_file, strerror(errno) ));
945 close(fd);
946 return False;
949 if(!overwrite_bad_sid) {
951 * At this point we have a blocking lock on the SID
952 * file - check if in the meantime someone else wrote
953 * SID data into the file. If so - they were here first,
954 * use their data.
957 if(sys_fstat( fd, &st) < 0) {
958 DEBUG(0,("unable to stat file %s. Error was %s\n",
959 sid_file, strerror(errno) ));
960 close(fd);
961 return False;
964 if(st.st_size > 0) {
966 * Unlock as soon as possible to reduce
967 * contention on the exclusive lock.
969 do_file_lock( fd, 60, F_UNLCK);
972 * We have a valid SID - read it.
975 if(!read_sid_from_file( fd, sid_file)) {
976 DEBUG(0,("unable to read file %s. Error was %s\n",
977 sid_file, strerror(errno) ));
978 close(fd);
979 return False;
981 close(fd);
982 return True;
987 * The file is still empty and we have an exlusive lock on it,
988 * or we're fixing an earlier mistake.
989 * Write out out SID data into the file.
993 * Use chmod here as some (strange) UNIX's don't
994 * have fchmod. JRA.
997 if(chmod(sid_file, 0644) < 0) {
998 DEBUG(0,("unable to set correct permissions on file %s. \
999 Error was %s\n", sid_file, strerror(errno) ));
1000 do_file_lock( fd, 60, F_UNLCK);
1001 close(fd);
1002 return False;
1005 if(write( fd, sid_string, strlen(sid_string)) != strlen(sid_string)) {
1006 DEBUG(0,("unable to write file %s. Error was %s\n",
1007 sid_file, strerror(errno) ));
1008 do_file_lock( fd, 60, F_UNLCK);
1009 close(fd);
1010 return False;
1014 * Unlock & exit.
1017 do_file_lock( fd, 60, F_UNLCK);
1018 close(fd);
1019 return True;
1022 /*******************************************************************
1023 Converts NT user RID to a UNIX uid.
1024 ********************************************************************/
1026 uid_t pdb_user_rid_to_uid(uint32 user_rid)
1028 return (uid_t)(((user_rid & (~USER_RID_TYPE))- 1000)/RID_MULTIPLIER);
1031 /*******************************************************************
1032 Converts NT user RID to a UNIX gid.
1033 ********************************************************************/
1035 gid_t pdb_user_rid_to_gid(uint32 user_rid)
1037 return (uid_t)(((user_rid & (~GROUP_RID_TYPE))- 1000)/RID_MULTIPLIER);
1040 /*******************************************************************
1041 converts UNIX uid to an NT User RID.
1042 ********************************************************************/
1044 uint32 pdb_uid_to_user_rid(uid_t uid)
1046 return (((((uint32)uid)*RID_MULTIPLIER) + 1000) | USER_RID_TYPE);
1049 /*******************************************************************
1050 converts NT Group RID to a UNIX uid.
1051 ********************************************************************/
1053 uint32 pdb_gid_to_group_rid(gid_t gid)
1055 return (((((uint32)gid)*RID_MULTIPLIER) + 1000) | GROUP_RID_TYPE);
1058 /*******************************************************************
1059 Decides if a RID is a well known RID.
1060 ********************************************************************/
1062 static BOOL pdb_rid_is_well_known(uint32 rid)
1064 return (rid < 1000);
1067 /*******************************************************************
1068 Decides if a RID is a user or group RID.
1069 ********************************************************************/
1071 BOOL pdb_rid_is_user(uint32 rid)
1073 /* lkcl i understand that NT attaches an enumeration to a RID
1074 * such that it can be identified as either a user, group etc
1075 * type. there are 5 such categories, and they are documented.
1077 if(pdb_rid_is_well_known(rid)) {
1079 * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
1080 * and DOMAIN_USER_RID_GUEST.
1082 if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
1083 return True;
1084 } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
1085 return True;
1087 return False;
1090 /*******************************************************************
1091 Convert a rid into a name. Used in the lookup SID rpc.
1092 ********************************************************************/
1094 BOOL lookup_local_rid(uint32 rid, char *name, uint8 *psid_name_use)
1097 BOOL is_user = pdb_rid_is_user(rid);
1099 DEBUG(5,("lookup_local_rid: looking up %s RID %u.\n", is_user ? "user" :
1100 "group", (unsigned int)rid));
1102 if(is_user) {
1103 if(rid == DOMAIN_USER_RID_ADMIN) {
1104 pstring admin_users;
1105 char *p = admin_users;
1106 pstrcpy( admin_users, lp_domain_admin_users());
1107 if(!next_token(&p, name, NULL, sizeof(fstring)))
1108 fstrcpy(name, "Administrator");
1109 } else if (rid == DOMAIN_USER_RID_GUEST) {
1110 pstring guest_users;
1111 char *p = guest_users;
1112 pstrcpy( guest_users, lp_domain_guest_users());
1113 if(!next_token(&p, name, NULL, sizeof(fstring)))
1114 fstrcpy(name, "Guest");
1115 } else {
1116 uid_t uid = pdb_user_rid_to_uid(rid);
1117 struct passwd *pass = getpwuid(uid);
1119 *psid_name_use = SID_NAME_USER;
1121 DEBUG(5,("lookup_local_rid: looking up uid %u %s\n", (unsigned int)uid,
1122 pass ? "succeeded" : "failed" ));
1124 if(!pass) {
1125 slprintf(name, sizeof(fstring)-1, "unix_user.%u", (unsigned int)uid);
1126 return True;
1129 fstrcpy(name, pass->pw_name);
1131 DEBUG(5,("lookup_local_rid: found user %s for rid %u\n", name,
1132 (unsigned int)rid ));
1135 } else {
1136 gid_t gid = pdb_user_rid_to_gid(rid);
1137 struct group *gr = getgrgid(gid);
1139 *psid_name_use = SID_NAME_ALIAS;
1141 DEBUG(5,("lookup_local_rid: looking up gid %u %s\n", (unsigned int)gid,
1142 gr ? "succeeded" : "failed" ));
1144 if(!gr) {
1145 slprintf(name, sizeof(fstring)-1, "unix_group.%u", (unsigned int)gid);
1146 return True;
1149 fstrcpy( name, gr->gr_name);
1151 DEBUG(5,("lookup_local_rid: found group %s for rid %u\n", name,
1152 (unsigned int)rid ));
1155 return True;
1158 /*******************************************************************
1159 Convert a name into a SID. Used in the lookup name rpc.
1160 ********************************************************************/
1162 BOOL lookup_local_name(char *domain, char *user, DOM_SID *psid, uint8 *psid_name_use)
1164 extern DOM_SID global_sid_World_Domain;
1165 struct passwd *pass = NULL;
1166 DOM_SID local_sid;
1168 sid_copy(&local_sid, &global_sam_sid);
1170 if(!strequal(global_myname, domain) && !strequal(global_myworkgroup, domain))
1171 return False;
1174 * Special case for MACHINE\Everyone. Map to the world_sid.
1177 if(strequal(user, "Everyone")) {
1178 sid_copy( psid, &global_sid_World_Domain);
1179 sid_append_rid(psid, 0);
1180 *psid_name_use = SID_NAME_ALIAS;
1181 return True;
1184 (void)map_username(user);
1186 if(!(pass = Get_Pwnam(user, False))) {
1188 * Maybe it was a group ?
1190 struct group *grp = getgrnam(user);
1192 if(!grp)
1193 return False;
1195 sid_append_rid( &local_sid, pdb_gid_to_group_rid(grp->gr_gid));
1196 *psid_name_use = SID_NAME_ALIAS;
1197 } else {
1199 sid_append_rid( &local_sid, pdb_uid_to_user_rid(pass->pw_uid));
1200 *psid_name_use = SID_NAME_USER;
1203 sid_copy( psid, &local_sid);
1205 return True;