Correct PPTP server firewall rules chain.
[tomato/davidwu.git] / release / src / router / samba / source / passdb / passdb.c
blob37e6264fdd30c300bc0b5250fce584ffac179bd9
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 delete an entry from the smb passwd file.
230 *************************************************************************/
232 BOOL del_smbpwd_entry(const char *name)
234 return pdb_ops->del_smbpwd_entry(name);
237 /************************************************************************
238 Routine to search smb passwd by name.
239 *************************************************************************/
241 struct smb_passwd *getsmbpwnam(char *name)
243 return pdb_ops->getsmbpwnam(name);
246 /************************************************************************
247 Routine to search smb passwd by user rid.
248 *************************************************************************/
250 struct smb_passwd *getsmbpwrid(uint32 user_rid)
252 return pdb_ops->getsmbpwrid(user_rid);
255 /************************************************************************
256 Routine to search smb passwd by uid.
257 *************************************************************************/
259 struct smb_passwd *getsmbpwuid(uid_t smb_userid)
261 return pdb_ops->getsmbpwuid(smb_userid);
265 * Functions that manupulate a struct sam_passwd.
268 /************************************************************************
269 Utility function to search sam passwd by name. use this if your database
270 does not have search facilities.
271 *************************************************************************/
273 struct sam_passwd *iterate_getsam21pwnam(char *name)
275 struct sam_passwd *pwd = NULL;
276 void *fp = NULL;
278 DEBUG(10, ("search by name: %s\n", name));
280 /* Open the smb password database - not for update. */
281 fp = startsmbpwent(False);
283 if (fp == NULL)
285 DEBUG(0, ("unable to open sam password database.\n"));
286 return NULL;
289 while ((pwd = getsam21pwent(fp)) != NULL && !strequal(pwd->smb_name, name))
291 DEBUG(10, ("iterate: %s 0x%x\n", pwd->smb_name, pwd->user_rid));
294 if (pwd != NULL)
296 DEBUG(10, ("found by name: %s\n", name));
299 endsmbpwent(fp);
300 return pwd;
303 /************************************************************************
304 Utility function to search sam passwd by rid. use this if your database
305 does not have search facilities.
307 search capability by both rid and uid are needed as the rid <-> uid
308 mapping may be non-monotonic.
310 *************************************************************************/
312 struct sam_passwd *iterate_getsam21pwrid(uint32 rid)
314 struct sam_passwd *pwd = NULL;
315 void *fp = NULL;
317 DEBUG(10, ("search by rid: %x\n", rid));
319 /* Open the smb password file - not for update. */
320 fp = startsmbpwent(False);
322 if (fp == NULL)
324 DEBUG(0, ("unable to open sam password database.\n"));
325 return NULL;
328 while ((pwd = getsam21pwent(fp)) != NULL && pwd->user_rid != rid)
330 DEBUG(10, ("iterate: %s 0x%x\n", pwd->smb_name, pwd->user_rid));
333 if (pwd != NULL)
335 DEBUG(10, ("found by user_rid: %x\n", rid));
338 endsmbpwent(fp);
339 return pwd;
342 /************************************************************************
343 Utility function to search sam passwd by uid. use this if your database
344 does not have search facilities.
346 search capability by both rid and uid are needed as the rid <-> uid
347 mapping may be non-monotonic.
349 *************************************************************************/
351 struct sam_passwd *iterate_getsam21pwuid(uid_t uid)
353 struct sam_passwd *pwd = NULL;
354 void *fp = NULL;
356 DEBUG(10, ("search by uid: %x\n", (int)uid));
358 /* Open the smb password file - not for update. */
359 fp = startsmbpwent(False);
361 if (fp == NULL)
363 DEBUG(0, ("unable to open sam password database.\n"));
364 return NULL;
367 while ((pwd = getsam21pwent(fp)) != NULL && pwd->smb_userid != uid)
370 if (pwd != NULL)
372 DEBUG(10, ("found by smb_userid: %x\n", (int)uid));
375 endsmbpwent(fp);
376 return pwd;
379 /*************************************************************************
380 Routine to return a display info structure, by rid
381 *************************************************************************/
382 struct sam_disp_info *getsamdisprid(uint32 rid)
384 return pdb_ops->getsamdisprid(rid);
387 /*************************************************************************
388 Routine to return the next entry in the sam passwd list.
389 *************************************************************************/
391 struct sam_passwd *getsam21pwent(void *vp)
393 return pdb_ops->getsam21pwent(vp);
397 /************************************************************************
398 Routine to search sam passwd by name.
399 *************************************************************************/
401 struct sam_passwd *getsam21pwnam(char *name)
403 return pdb_ops->getsam21pwnam(name);
406 /************************************************************************
407 Routine to search sam passwd by rid.
408 *************************************************************************/
410 struct sam_passwd *getsam21pwrid(uint32 rid)
412 return pdb_ops->getsam21pwrid(rid);
416 /**********************************************************
417 **********************************************************
419 utility routines which are likely to be useful to all password
420 databases
422 **********************************************************
423 **********************************************************/
425 /*************************************************************
426 initialises a struct sam_disp_info.
427 **************************************************************/
429 static void pdb_init_dispinfo(struct sam_disp_info *user)
431 if (user == NULL) return;
432 memset((char *)user, '\0', sizeof(*user));
435 /*************************************************************
436 initialises a struct smb_passwd.
437 **************************************************************/
439 void pdb_init_smb(struct smb_passwd *user)
441 if (user == NULL) return;
442 memset((char *)user, '\0', sizeof(*user));
443 user->pass_last_set_time = (time_t)-1;
446 /*************************************************************
447 initialises a struct sam_passwd.
448 **************************************************************/
449 void pdb_init_sam(struct sam_passwd *user)
451 if (user == NULL) return;
452 memset((char *)user, '\0', sizeof(*user));
453 user->logon_time = (time_t)-1;
454 user->logoff_time = (time_t)-1;
455 user->kickoff_time = (time_t)-1;
456 user->pass_last_set_time = (time_t)-1;
457 user->pass_can_change_time = (time_t)-1;
458 user->pass_must_change_time = (time_t)-1;
461 /*************************************************************************
462 Routine to return the next entry in the sam passwd list.
463 *************************************************************************/
465 struct sam_disp_info *pdb_sam_to_dispinfo(struct sam_passwd *user)
467 static struct sam_disp_info disp_info;
469 if (user == NULL) return NULL;
471 pdb_init_dispinfo(&disp_info);
473 disp_info.smb_name = user->smb_name;
474 disp_info.full_name = user->full_name;
475 disp_info.user_rid = user->user_rid;
477 return &disp_info;
480 /*************************************************************
481 converts a sam_passwd structure to a smb_passwd structure.
482 **************************************************************/
484 struct smb_passwd *pdb_sam_to_smb(struct sam_passwd *user)
486 static struct smb_passwd pw_buf;
488 if (user == NULL) return NULL;
490 pdb_init_smb(&pw_buf);
492 pw_buf.smb_userid = user->smb_userid;
493 pw_buf.smb_name = user->smb_name;
494 pw_buf.smb_passwd = user->smb_passwd;
495 pw_buf.smb_nt_passwd = user->smb_nt_passwd;
496 pw_buf.acct_ctrl = user->acct_ctrl;
497 pw_buf.pass_last_set_time = user->pass_last_set_time;
499 return &pw_buf;
503 /*************************************************************
504 converts a smb_passwd structure to a sam_passwd structure.
505 **************************************************************/
507 struct sam_passwd *pdb_smb_to_sam(struct smb_passwd *user)
509 static struct sam_passwd pw_buf;
511 if (user == NULL) return NULL;
513 pdb_init_sam(&pw_buf);
515 pw_buf.smb_userid = user->smb_userid;
516 pw_buf.smb_name = user->smb_name;
517 pw_buf.smb_passwd = user->smb_passwd;
518 pw_buf.smb_nt_passwd = user->smb_nt_passwd;
519 pw_buf.acct_ctrl = user->acct_ctrl;
520 pw_buf.pass_last_set_time = user->pass_last_set_time;
522 return &pw_buf;
525 /**********************************************************
526 Encode the account control bits into a string.
527 length = length of string to encode into (including terminating
528 null). length *MUST BE MORE THAN 2* !
529 **********************************************************/
531 char *pdb_encode_acct_ctrl(uint16 acct_ctrl, size_t length)
533 static fstring acct_str;
534 size_t i = 0;
536 acct_str[i++] = '[';
538 if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
539 if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
540 if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
541 if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T';
542 if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U';
543 if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M';
544 if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W';
545 if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
546 if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
547 if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X';
548 if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
550 for ( ; i < length - 2 ; i++ ) { acct_str[i] = ' '; }
552 i = length - 2;
553 acct_str[i++] = ']';
554 acct_str[i++] = '\0';
556 return acct_str;
559 /**********************************************************
560 Decode the account control bits from a string.
562 this function breaks coding standards minimum line width of 80 chars.
563 reason: vertical line-up code clarity - all case statements fit into
564 15 lines, which is more important.
565 **********************************************************/
567 uint16 pdb_decode_acct_ctrl(const char *p)
569 uint16 acct_ctrl = 0;
570 BOOL finished = False;
573 * Check if the account type bits have been encoded after the
574 * NT password (in the form [NDHTUWSLXI]).
577 if (*p != '[') return 0;
579 for (p++; *p && !finished; p++)
581 switch (*p)
583 case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
584 case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
585 case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
586 case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
587 case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
588 case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
589 case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
590 case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
591 case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
592 case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
593 case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
594 case ' ': { break; }
595 case ':':
596 case '\n':
597 case '\0':
598 case ']':
599 default: { finished = True; }
603 return acct_ctrl;
606 /*******************************************************************
607 gets password-database-format time from a string.
608 ********************************************************************/
610 static time_t get_time_from_string(const char *p)
612 int i;
614 for (i = 0; i < 8; i++)
616 if (p[i] == '\0' || !isxdigit((int)(p[i]&0xFF)))
617 break;
619 if (i == 8)
622 * p points at 8 characters of hex digits -
623 * read into a time_t as the seconds since
624 * 1970 that the password was last changed.
626 return (time_t)strtol(p, NULL, 16);
628 return (time_t)-1;
631 /*******************************************************************
632 gets password last set time
633 ********************************************************************/
635 time_t pdb_get_last_set_time(const char *p)
637 if (*p && StrnCaseCmp(p, "LCT-", 4))
639 return get_time_from_string(p + 4);
641 return (time_t)-1;
645 /*******************************************************************
646 sets password-database-format time in a string.
647 ********************************************************************/
648 static void set_time_in_string(char *p, int max_len, char *type, time_t t)
650 slprintf(p, max_len, ":%s-%08X:", type, (uint32)t);
653 /*******************************************************************
654 sets logon time
655 ********************************************************************/
656 void pdb_set_logon_time(char *p, int max_len, time_t t)
658 set_time_in_string(p, max_len, "LNT", t);
661 /*******************************************************************
662 sets logoff time
663 ********************************************************************/
664 void pdb_set_logoff_time(char *p, int max_len, time_t t)
666 set_time_in_string(p, max_len, "LOT", t);
669 /*******************************************************************
670 sets kickoff time
671 ********************************************************************/
672 void pdb_set_kickoff_time(char *p, int max_len, time_t t)
674 set_time_in_string(p, max_len, "KOT", t);
677 /*******************************************************************
678 sets password can change time
679 ********************************************************************/
680 void pdb_set_can_change_time(char *p, int max_len, time_t t)
682 set_time_in_string(p, max_len, "CCT", t);
685 /*******************************************************************
686 sets password last set time
687 ********************************************************************/
688 void pdb_set_must_change_time(char *p, int max_len, time_t t)
690 set_time_in_string(p, max_len, "MCT", t);
693 /*******************************************************************
694 sets password last set time
695 ********************************************************************/
696 void pdb_set_last_set_time(char *p, int max_len, time_t t)
698 set_time_in_string(p, max_len, "LCT", t);
702 /*************************************************************
703 Routine to set 32 hex password characters from a 16 byte array.
704 **************************************************************/
705 void pdb_sethexpwd(char *p, unsigned char *pwd, uint16 acct_ctrl)
707 if (pwd != NULL)
709 int i;
710 for (i = 0; i < 16; i++)
712 slprintf(&p[i*2], 3, "%02X", pwd[i]);
715 else
717 if (IS_BITS_SET_ALL(acct_ctrl, ACB_PWNOTREQ))
719 safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
721 else
723 safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
727 /*************************************************************
728 Routine to get the 32 hex characters and turn them
729 into a 16 byte array.
730 **************************************************************/
731 BOOL pdb_gethexpwd(char *p, unsigned char *pwd)
733 int i;
734 unsigned char lonybble, hinybble;
735 char *hexchars = "0123456789ABCDEF";
736 char *p1, *p2;
738 for (i = 0; i < 32; i += 2)
740 hinybble = toupper(p[i]);
741 lonybble = toupper(p[i + 1]);
743 p1 = strchr(hexchars, hinybble);
744 p2 = strchr(hexchars, lonybble);
746 if (!p1 || !p2)
748 return (False);
751 hinybble = PTR_DIFF(p1, hexchars);
752 lonybble = PTR_DIFF(p2, hexchars);
754 pwd[i / 2] = (hinybble << 4) | lonybble;
756 return (True);
759 /*******************************************************************
760 Group and User RID username mapping function
761 ********************************************************************/
763 BOOL pdb_name_to_rid(char *user_name, uint32 *u_rid, uint32 *g_rid)
765 struct passwd *pw = Get_Pwnam(user_name, False);
767 if (u_rid == NULL || g_rid == NULL || user_name == NULL)
769 return False;
772 if (!pw)
774 DEBUG(1,("Username %s is invalid on this system\n", user_name));
775 return False;
778 if (user_in_list(user_name, lp_domain_guest_users()))
780 *u_rid = DOMAIN_USER_RID_GUEST;
782 else if (user_in_list(user_name, lp_domain_admin_users()))
784 *u_rid = DOMAIN_USER_RID_ADMIN;
786 else
788 /* turn the unix UID into a Domain RID. this is what the posix
789 sub-system does (adds 1000 to the uid) */
790 *u_rid = pdb_uid_to_user_rid(pw->pw_uid);
793 /* absolutely no idea what to do about the unix GID to Domain RID mapping */
794 *g_rid = pdb_gid_to_group_rid(pw->pw_gid);
796 return True;
799 /****************************************************************************
800 Read the machine SID from a file.
801 ****************************************************************************/
803 static BOOL read_sid_from_file(int fd, char *sid_file)
805 fstring fline;
807 memset(fline, '\0', sizeof(fline));
809 if(read(fd, fline, sizeof(fline) -1 ) < 0) {
810 DEBUG(0,("unable to read file %s. Error was %s\n",
811 sid_file, strerror(errno) ));
812 return False;
816 * Convert to the machine SID.
819 fline[sizeof(fline)-1] = '\0';
820 if(!string_to_sid( &global_sam_sid, fline)) {
821 DEBUG(0,("unable to generate machine SID.\n"));
822 return False;
825 return True;
828 /****************************************************************************
829 Generate the global machine sid. Look for the MACHINE.SID file first, if
830 not found then look in smb.conf and use it to create the MACHINE.SID file.
831 ****************************************************************************/
832 BOOL pdb_generate_sam_sid(void)
834 int fd;
835 char *p;
836 pstring sid_file;
837 fstring sid_string;
838 SMB_STRUCT_STAT st;
839 BOOL overwrite_bad_sid = False;
841 generate_wellknown_sids();
843 pstrcpy(sid_file, lp_smb_passwd_file());
844 p = strrchr(sid_file, '/');
845 if(p != NULL) {
846 *++p = '\0';
849 if (!directory_exist(sid_file, NULL)) {
850 if (mkdir(sid_file, 0700) != 0) {
851 DEBUG(0,("can't create private directory %s : %s\n",
852 sid_file, strerror(errno)));
853 return False;
857 pstrcat(sid_file, "MACHINE.SID");
859 if((fd = sys_open(sid_file, O_RDWR | O_CREAT, 0644)) == -1) {
860 DEBUG(0,("unable to open or create file %s. Error was %s\n",
861 sid_file, strerror(errno) ));
862 return False;
866 * Check if the file contains data.
869 if(sys_fstat( fd, &st) < 0) {
870 DEBUG(0,("unable to stat file %s. Error was %s\n",
871 sid_file, strerror(errno) ));
872 close(fd);
873 return False;
876 if(st.st_size > 0) {
878 * We have a valid SID - read it.
880 if(!read_sid_from_file( fd, sid_file)) {
881 DEBUG(0,("unable to read file %s. Error was %s\n",
882 sid_file, strerror(errno) ));
883 close(fd);
884 return False;
888 * JRA. Reversed the sense of this test now that I have
889 * actually done this test *personally*. One more reason
890 * to never trust third party information you have not
891 * independently verified.... sigh. JRA.
894 if(global_sam_sid.num_auths > 0 && global_sam_sid.sub_auths[0] == 0x21) {
896 * Fix and re-write...
898 overwrite_bad_sid = True;
899 global_sam_sid.sub_auths[0] = 21;
900 DEBUG(5,("pdb_generate_sam_sid: Old (incorrect) sid id_auth of hex 21 \
901 detected - re-writing to be decimal 21 instead.\n" ));
902 sid_to_string(sid_string, &global_sam_sid);
903 if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) {
904 DEBUG(0,("unable to seek file file %s. Error was %s\n",
905 sid_file, strerror(errno) ));
906 close(fd);
907 return False;
909 } else {
910 close(fd);
911 return True;
913 } else {
915 * The file contains no data - we need to generate our
916 * own sid.
917 * Generate the new sid data & turn it into a string.
919 int i;
920 uchar raw_sid_data[12];
921 DOM_SID mysid;
923 memset((char *)&mysid, '\0', sizeof(DOM_SID));
924 mysid.sid_rev_num = 1;
925 mysid.id_auth[5] = 5;
926 mysid.num_auths = 0;
927 mysid.sub_auths[mysid.num_auths++] = 21;
929 generate_random_buffer( raw_sid_data, 12, True);
930 for( i = 0; i < 3; i++)
931 mysid.sub_auths[mysid.num_auths++] = IVAL(raw_sid_data, i*4);
933 sid_to_string(sid_string, &mysid);
936 fstrcat(sid_string, "\n");
939 * Ensure our new SID is valid.
942 if(!string_to_sid( &global_sam_sid, sid_string)) {
943 DEBUG(0,("unable to generate machine SID.\n"));
944 return False;
948 * Do an exclusive blocking lock on the file.
951 if(!do_file_lock( fd, 60, F_WRLCK)) {
952 DEBUG(0,("unable to lock file %s. Error was %s\n",
953 sid_file, strerror(errno) ));
954 close(fd);
955 return False;
958 if(!overwrite_bad_sid) {
960 * At this point we have a blocking lock on the SID
961 * file - check if in the meantime someone else wrote
962 * SID data into the file. If so - they were here first,
963 * use their data.
966 if(sys_fstat( fd, &st) < 0) {
967 DEBUG(0,("unable to stat file %s. Error was %s\n",
968 sid_file, strerror(errno) ));
969 close(fd);
970 return False;
973 if(st.st_size > 0) {
975 * Unlock as soon as possible to reduce
976 * contention on the exclusive lock.
978 do_file_lock( fd, 60, F_UNLCK);
981 * We have a valid SID - read it.
984 if(!read_sid_from_file( fd, sid_file)) {
985 DEBUG(0,("unable to read file %s. Error was %s\n",
986 sid_file, strerror(errno) ));
987 close(fd);
988 return False;
990 close(fd);
991 return True;
996 * The file is still empty and we have an exlusive lock on it,
997 * or we're fixing an earlier mistake.
998 * Write out out SID data into the file.
1002 * Use chmod here as some (strange) UNIX's don't
1003 * have fchmod. JRA.
1006 if(chmod(sid_file, 0644) < 0) {
1007 DEBUG(0,("unable to set correct permissions on file %s. \
1008 Error was %s\n", sid_file, strerror(errno) ));
1009 do_file_lock( fd, 60, F_UNLCK);
1010 close(fd);
1011 return False;
1014 if(write( fd, sid_string, strlen(sid_string)) != strlen(sid_string)) {
1015 DEBUG(0,("unable to write file %s. Error was %s\n",
1016 sid_file, strerror(errno) ));
1017 do_file_lock( fd, 60, F_UNLCK);
1018 close(fd);
1019 return False;
1023 * Unlock & exit.
1026 do_file_lock( fd, 60, F_UNLCK);
1027 close(fd);
1028 return True;
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)
1092 return True;
1093 } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
1094 return True;
1096 return False;
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));
1111 if(is_user) {
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");
1124 } else {
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" ));
1133 if(!pass) {
1134 slprintf(name, sizeof(fstring)-1, "unix_user.%u", (unsigned int)uid);
1135 return True;
1138 fstrcpy(name, pass->pw_name);
1140 DEBUG(5,("lookup_local_rid: found user %s for rid %u\n", name,
1141 (unsigned int)rid ));
1144 } else {
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" ));
1153 if(!gr) {
1154 slprintf(name, sizeof(fstring)-1, "unix_group.%u", (unsigned int)gid);
1155 return True;
1158 fstrcpy( name, gr->gr_name);
1160 DEBUG(5,("lookup_local_rid: found group %s for rid %u\n", name,
1161 (unsigned int)rid ));
1164 return True;
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;
1175 DOM_SID local_sid;
1177 sid_copy(&local_sid, &global_sam_sid);
1179 if(!strequal(global_myname, domain) && !strequal(global_myworkgroup, domain))
1180 return False;
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;
1190 return True;
1193 (void)map_username(user);
1195 if(!(pass = Get_Pwnam(user, False))) {
1197 * Maybe it was a group ?
1199 struct group *grp = getgrnam(user);
1201 if(!grp)
1202 return False;
1204 sid_append_rid( &local_sid, pdb_gid_to_group_rid(grp->gr_gid));
1205 *psid_name_use = SID_NAME_ALIAS;
1206 } else {
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);
1214 return True;