This commit was manufactured by cvs2svn to create tag
[Samba/gbeck.git] / source / passdb / passdb.c
blobf29a9ff570749853e7c3983fc63aec3642db43ff
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 DOM_SID global_sam_sid;
37 * NOTE. All these functions are abstracted into a structure
38 * that points to the correct function for the selected database. JRA.
40 * NOTE. for the get/mod/add functions, there are two sets of functions.
41 * one supports struct sam_passwd, the other supports struct smb_passwd.
42 * for speed optimisation it is best to support both these sets.
44 * it is, however, optional to support one set but not the other: there
45 * is conversion-capability built in to passdb.c, and run-time error
46 * detection for when neither are supported.
48 * password database writers are recommended to implement the sam_passwd
49 * functions in a first pass, as struct sam_passwd contains more
50 * information, needed by the NT Domain support.
52 * a full example set of derivative functions are listed below. an API
53 * writer is expected to cut/paste these into their module, replace
54 * either one set (struct smb_passwd) or the other (struct sam_passwd)
55 * OR both, and optionally also to write display info routines
56 * (struct sam_disp_info). lkcl
60 static struct passdb_ops *pdb_ops;
62 /***************************************************************
63 Initialize the password db operations.
64 ***************************************************************/
66 BOOL initialize_password_db(void)
68 if (pdb_ops)
70 return True;
73 #ifdef WITH_NISPLUS
74 pdb_ops = nisplus_initialize_password_db();
75 #elif defined(WITH_LDAP)
76 pdb_ops = ldap_initialize_password_db();
77 #else
78 pdb_ops = file_initialize_password_db();
79 #endif
81 return (pdb_ops != NULL);
85 * Functions that return/manipulate a struct smb_passwd.
88 /************************************************************************
89 Utility function to search smb passwd by rid.
90 *************************************************************************/
92 struct smb_passwd *iterate_getsmbpwrid(uint32 user_rid)
94 return iterate_getsmbpwuid(pdb_user_rid_to_uid(user_rid));
97 /************************************************************************
98 Utility function to search smb passwd by uid. use this if your database
99 does not have search facilities.
100 *************************************************************************/
102 struct smb_passwd *iterate_getsmbpwuid(uid_t smb_userid)
104 struct smb_passwd *pwd = NULL;
105 void *fp = NULL;
107 DEBUG(10, ("search by smb_userid: %x\n", (int)smb_userid));
109 /* Open the smb password database - not for update. */
110 fp = startsmbpwent(False);
112 if (fp == NULL)
114 DEBUG(0, ("unable to open smb password database.\n"));
115 return NULL;
118 while ((pwd = getsmbpwent(fp)) != NULL && pwd->smb_userid != smb_userid)
121 if (pwd != NULL)
123 DEBUG(10, ("found by smb_userid: %x\n", (int)smb_userid));
126 endsmbpwent(fp);
127 return pwd;
130 /************************************************************************
131 Utility function to search smb passwd by name. use this if your database
132 does not have search facilities.
133 *************************************************************************/
135 struct smb_passwd *iterate_getsmbpwnam(char *name)
137 struct smb_passwd *pwd = NULL;
138 void *fp = NULL;
140 DEBUG(10, ("search by name: %s\n", name));
142 /* Open the sam password file - not for update. */
143 fp = startsmbpwent(False);
145 if (fp == NULL)
147 DEBUG(0, ("unable to open smb password database.\n"));
148 return NULL;
151 while ((pwd = getsmbpwent(fp)) != NULL && !strequal(pwd->smb_name, name))
154 if (pwd != NULL)
156 DEBUG(10, ("found by name: %s\n", name));
159 endsmbpwent(fp);
160 return pwd;
163 /***************************************************************
164 Start to enumerate the smb or sam passwd list. Returns a void pointer
165 to ensure no modification outside this module.
167 Note that currently it is being assumed that a pointer returned
168 from this function may be used to enumerate struct sam_passwd
169 entries as well as struct smb_passwd entries. This may need
170 to change. JRA.
172 ****************************************************************/
174 void *startsmbpwent(BOOL update)
176 return pdb_ops->startsmbpwent(update);
179 /***************************************************************
180 End enumeration of the smb or sam passwd list.
182 Note that currently it is being assumed that a pointer returned
183 from this function may be used to enumerate struct sam_passwd
184 entries as well as struct smb_passwd entries. This may need
185 to change. JRA.
187 ****************************************************************/
189 void endsmbpwent(void *vp)
191 pdb_ops->endsmbpwent(vp);
194 /*************************************************************************
195 Routine to return the next entry in the smb passwd list.
196 *************************************************************************/
198 struct smb_passwd *getsmbpwent(void *vp)
200 return pdb_ops->getsmbpwent(vp);
203 /************************************************************************
204 Routine to add an entry to the smb passwd file.
205 *************************************************************************/
207 BOOL add_smbpwd_entry(struct smb_passwd *newpwd)
209 return pdb_ops->add_smbpwd_entry(newpwd);
212 /************************************************************************
213 Routine to search the smb passwd file for an entry matching the username.
214 and then modify its password entry. We can't use the startsampwent()/
215 getsampwent()/endsampwent() interfaces here as we depend on looking
216 in the actual file to decide how much room we have to write data.
217 override = False, normal
218 override = True, override XXXXXXXX'd out password or NO PASS
219 ************************************************************************/
221 BOOL mod_smbpwd_entry(struct smb_passwd* pwd, BOOL override)
223 return pdb_ops->mod_smbpwd_entry(pwd, override);
226 /************************************************************************
227 Routine to search smb passwd by name.
228 *************************************************************************/
230 struct smb_passwd *getsmbpwnam(char *name)
232 return pdb_ops->getsmbpwnam(name);
235 /************************************************************************
236 Routine to search smb passwd by user rid.
237 *************************************************************************/
239 struct smb_passwd *getsmbpwrid(uint32 user_rid)
241 return pdb_ops->getsmbpwrid(user_rid);
244 /************************************************************************
245 Routine to search smb passwd by uid.
246 *************************************************************************/
248 struct smb_passwd *getsmbpwuid(uid_t smb_userid)
250 return pdb_ops->getsmbpwuid(smb_userid);
254 * Functions that manupulate a struct sam_passwd.
257 /************************************************************************
258 Utility function to search sam passwd by name. use this if your database
259 does not have search facilities.
260 *************************************************************************/
262 struct sam_passwd *iterate_getsam21pwnam(char *name)
264 struct sam_passwd *pwd = NULL;
265 void *fp = NULL;
267 DEBUG(10, ("search by name: %s\n", name));
269 /* Open the smb password database - not for update. */
270 fp = startsmbpwent(False);
272 if (fp == NULL)
274 DEBUG(0, ("unable to open sam password database.\n"));
275 return NULL;
278 while ((pwd = getsam21pwent(fp)) != NULL && !strequal(pwd->smb_name, name))
280 DEBUG(10, ("iterate: %s 0x%x\n", pwd->smb_name, pwd->user_rid));
283 if (pwd != NULL)
285 DEBUG(10, ("found by name: %s\n", name));
288 endsmbpwent(fp);
289 return pwd;
292 /************************************************************************
293 Utility function to search sam passwd by rid. use this if your database
294 does not have search facilities.
296 search capability by both rid and uid are needed as the rid <-> uid
297 mapping may be non-monotonic.
299 *************************************************************************/
301 struct sam_passwd *iterate_getsam21pwrid(uint32 rid)
303 struct sam_passwd *pwd = NULL;
304 void *fp = NULL;
306 DEBUG(10, ("search by rid: %x\n", rid));
308 /* Open the smb password file - not for update. */
309 fp = startsmbpwent(False);
311 if (fp == NULL)
313 DEBUG(0, ("unable to open sam password database.\n"));
314 return NULL;
317 while ((pwd = getsam21pwent(fp)) != NULL && pwd->user_rid != rid)
319 DEBUG(10, ("iterate: %s 0x%x\n", pwd->smb_name, pwd->user_rid));
322 if (pwd != NULL)
324 DEBUG(10, ("found by user_rid: %x\n", rid));
327 endsmbpwent(fp);
328 return pwd;
331 /************************************************************************
332 Utility function to search sam passwd by uid. use this if your database
333 does not have search facilities.
335 search capability by both rid and uid are needed as the rid <-> uid
336 mapping may be non-monotonic.
338 *************************************************************************/
340 struct sam_passwd *iterate_getsam21pwuid(uid_t uid)
342 struct sam_passwd *pwd = NULL;
343 void *fp = NULL;
345 DEBUG(10, ("search by uid: %x\n", (int)uid));
347 /* Open the smb password file - not for update. */
348 fp = startsmbpwent(False);
350 if (fp == NULL)
352 DEBUG(0, ("unable to open sam password database.\n"));
353 return NULL;
356 while ((pwd = getsam21pwent(fp)) != NULL && pwd->smb_userid != uid)
359 if (pwd != NULL)
361 DEBUG(10, ("found by smb_userid: %x\n", (int)uid));
364 endsmbpwent(fp);
365 return pwd;
368 /*************************************************************************
369 Routine to return a display info structure, by rid
370 *************************************************************************/
371 struct sam_disp_info *getsamdisprid(uint32 rid)
373 return pdb_ops->getsamdisprid(rid);
376 /*************************************************************************
377 Routine to return the next entry in the sam passwd list.
378 *************************************************************************/
380 struct sam_passwd *getsam21pwent(void *vp)
382 return pdb_ops->getsam21pwent(vp);
386 /************************************************************************
387 Routine to search sam passwd by name.
388 *************************************************************************/
390 struct sam_passwd *getsam21pwnam(char *name)
392 return pdb_ops->getsam21pwnam(name);
395 /************************************************************************
396 Routine to search sam passwd by rid.
397 *************************************************************************/
399 struct sam_passwd *getsam21pwrid(uint32 rid)
401 return pdb_ops->getsam21pwrid(rid);
405 /**********************************************************
406 **********************************************************
408 utility routines which are likely to be useful to all password
409 databases
411 **********************************************************
412 **********************************************************/
414 /*************************************************************
415 initialises a struct sam_disp_info.
416 **************************************************************/
418 static void pdb_init_dispinfo(struct sam_disp_info *user)
420 if (user == NULL) return;
421 bzero(user, sizeof(*user));
424 /*************************************************************
425 initialises a struct smb_passwd.
426 **************************************************************/
428 void pdb_init_smb(struct smb_passwd *user)
430 if (user == NULL) return;
431 bzero(user, sizeof(*user));
432 user->pass_last_set_time = (time_t)-1;
435 /*************************************************************
436 initialises a struct sam_passwd.
437 **************************************************************/
438 void pdb_init_sam(struct sam_passwd *user)
440 if (user == NULL) return;
441 bzero(user, sizeof(*user));
442 user->logon_time = (time_t)-1;
443 user->logoff_time = (time_t)-1;
444 user->kickoff_time = (time_t)-1;
445 user->pass_last_set_time = (time_t)-1;
446 user->pass_can_change_time = (time_t)-1;
447 user->pass_must_change_time = (time_t)-1;
450 /*************************************************************************
451 Routine to return the next entry in the sam passwd list.
452 *************************************************************************/
454 struct sam_disp_info *pdb_sam_to_dispinfo(struct sam_passwd *user)
456 static struct sam_disp_info disp_info;
458 if (user == NULL) return NULL;
460 pdb_init_dispinfo(&disp_info);
462 disp_info.smb_name = user->smb_name;
463 disp_info.full_name = user->full_name;
464 disp_info.user_rid = user->user_rid;
466 return &disp_info;
469 /*************************************************************
470 converts a sam_passwd structure to a smb_passwd structure.
471 **************************************************************/
473 struct smb_passwd *pdb_sam_to_smb(struct sam_passwd *user)
475 static struct smb_passwd pw_buf;
477 if (user == NULL) return NULL;
479 pdb_init_smb(&pw_buf);
481 pw_buf.smb_userid = user->smb_userid;
482 pw_buf.smb_name = user->smb_name;
483 pw_buf.smb_passwd = user->smb_passwd;
484 pw_buf.smb_nt_passwd = user->smb_nt_passwd;
485 pw_buf.acct_ctrl = user->acct_ctrl;
486 pw_buf.pass_last_set_time = user->pass_last_set_time;
488 return &pw_buf;
492 /*************************************************************
493 converts a smb_passwd structure to a sam_passwd structure.
494 **************************************************************/
496 struct sam_passwd *pdb_smb_to_sam(struct smb_passwd *user)
498 static struct sam_passwd pw_buf;
500 if (user == NULL) return NULL;
502 pdb_init_sam(&pw_buf);
504 pw_buf.smb_userid = user->smb_userid;
505 pw_buf.smb_name = user->smb_name;
506 pw_buf.smb_passwd = user->smb_passwd;
507 pw_buf.smb_nt_passwd = user->smb_nt_passwd;
508 pw_buf.acct_ctrl = user->acct_ctrl;
509 pw_buf.pass_last_set_time = user->pass_last_set_time;
511 return &pw_buf;
514 /**********************************************************
515 Encode the account control bits into a string.
516 length = length of string to encode into (including terminating
517 null). length *MUST BE MORE THAN 2* !
518 **********************************************************/
520 char *pdb_encode_acct_ctrl(uint16 acct_ctrl, size_t length)
522 static fstring acct_str;
523 size_t i = 0;
525 acct_str[i++] = '[';
527 if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
528 if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
529 if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
530 if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T';
531 if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U';
532 if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M';
533 if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W';
534 if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
535 if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
536 if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X';
537 if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
539 for ( ; i < length - 2 ; i++ ) { acct_str[i] = ' '; }
541 i = length - 2;
542 acct_str[i++] = ']';
543 acct_str[i++] = '\0';
545 return acct_str;
548 /**********************************************************
549 Decode the account control bits from a string.
551 this function breaks coding standards minimum line width of 80 chars.
552 reason: vertical line-up code clarity - all case statements fit into
553 15 lines, which is more important.
554 **********************************************************/
556 uint16 pdb_decode_acct_ctrl(char *p)
558 uint16 acct_ctrl = 0;
559 BOOL finished = False;
562 * Check if the account type bits have been encoded after the
563 * NT password (in the form [NDHTUWSLXI]).
566 if (*p != '[') return 0;
568 for (p++; *p && !finished; p++)
570 switch (*p)
572 case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
573 case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
574 case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
575 case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
576 case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
577 case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
578 case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
579 case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
580 case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
581 case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
582 case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
583 case ' ': { break; }
584 case ':':
585 case '\n':
586 case '\0':
587 case ']':
588 default: { finished = True; }
592 return acct_ctrl;
595 /*******************************************************************
596 gets password-database-format time from a string.
597 ********************************************************************/
599 static time_t get_time_from_string(char *p)
601 int i;
603 for (i = 0; i < 8; i++)
605 if (p[i] == '\0' || !isxdigit((int)(p[i]&0xFF)))
606 break;
608 if (i == 8)
611 * p points at 8 characters of hex digits -
612 * read into a time_t as the seconds since
613 * 1970 that the password was last changed.
615 return (time_t)strtol((char *)p, NULL, 16);
617 return (time_t)-1;
620 /*******************************************************************
621 gets password last set time
622 ********************************************************************/
624 time_t pdb_get_last_set_time(char *p)
626 if (*p && StrnCaseCmp((char *)p, "LCT-", 4))
628 return get_time_from_string(p + 4);
630 return (time_t)-1;
634 /*******************************************************************
635 sets password-database-format time in a string.
636 ********************************************************************/
637 static void set_time_in_string(char *p, int max_len, char *type, time_t t)
639 slprintf(p, max_len, ":%s-%08X:", type, (uint32)t);
642 /*******************************************************************
643 sets logon time
644 ********************************************************************/
645 void pdb_set_logon_time(char *p, int max_len, time_t t)
647 set_time_in_string(p, max_len, "LNT", t);
650 /*******************************************************************
651 sets logoff time
652 ********************************************************************/
653 void pdb_set_logoff_time(char *p, int max_len, time_t t)
655 set_time_in_string(p, max_len, "LOT", t);
658 /*******************************************************************
659 sets kickoff time
660 ********************************************************************/
661 void pdb_set_kickoff_time(char *p, int max_len, time_t t)
663 set_time_in_string(p, max_len, "KOT", t);
666 /*******************************************************************
667 sets password can change time
668 ********************************************************************/
669 void pdb_set_can_change_time(char *p, int max_len, time_t t)
671 set_time_in_string(p, max_len, "CCT", t);
674 /*******************************************************************
675 sets password last set time
676 ********************************************************************/
677 void pdb_set_must_change_time(char *p, int max_len, time_t t)
679 set_time_in_string(p, max_len, "MCT", t);
682 /*******************************************************************
683 sets password last set time
684 ********************************************************************/
685 void pdb_set_last_set_time(char *p, int max_len, time_t t)
687 set_time_in_string(p, max_len, "LCT", t);
691 /*************************************************************
692 Routine to set 32 hex password characters from a 16 byte array.
693 **************************************************************/
694 void pdb_sethexpwd(char *p, char *pwd, uint16 acct_ctrl)
696 if (pwd != NULL)
698 int i;
699 for (i = 0; i < 16; i++)
701 slprintf(&p[i*2], 33, "%02X", pwd[i]);
704 else
706 if (IS_BITS_SET_ALL(acct_ctrl, ACB_PWNOTREQ))
708 safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
710 else
712 safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
716 /*************************************************************
717 Routine to get the 32 hex characters and turn them
718 into a 16 byte array.
719 **************************************************************/
720 BOOL pdb_gethexpwd(char *p, char *pwd)
722 int i;
723 unsigned char lonybble, hinybble;
724 char *hexchars = "0123456789ABCDEF";
725 char *p1, *p2;
727 for (i = 0; i < 32; i += 2)
729 hinybble = toupper(p[i]);
730 lonybble = toupper(p[i + 1]);
732 p1 = strchr(hexchars, hinybble);
733 p2 = strchr(hexchars, lonybble);
735 if (!p1 || !p2)
737 return (False);
740 hinybble = PTR_DIFF(p1, hexchars);
741 lonybble = PTR_DIFF(p2, hexchars);
743 pwd[i / 2] = (hinybble << 4) | lonybble;
745 return (True);
748 /*******************************************************************
749 Group and User RID username mapping function
750 ********************************************************************/
752 BOOL pdb_name_to_rid(char *user_name, uint32 *u_rid, uint32 *g_rid)
754 struct passwd *pw = Get_Pwnam(user_name, False);
756 if (u_rid == NULL || g_rid == NULL || user_name == NULL)
758 return False;
761 if (!pw)
763 DEBUG(1,("Username %s is invalid on this system\n", user_name));
764 return False;
767 if (user_in_list(user_name, lp_domain_guest_users()))
769 *u_rid = DOMAIN_USER_RID_GUEST;
771 else if (user_in_list(user_name, lp_domain_admin_users()))
773 *u_rid = DOMAIN_USER_RID_ADMIN;
775 else
777 /* turn the unix UID into a Domain RID. this is what the posix
778 sub-system does (adds 1000 to the uid) */
779 *u_rid = pdb_uid_to_user_rid(pw->pw_uid);
782 /* absolutely no idea what to do about the unix GID to Domain RID mapping */
783 *g_rid = pdb_gid_to_group_rid(pw->pw_gid);
785 return True;
788 /****************************************************************************
789 Read the machine SID from a file.
790 ****************************************************************************/
792 static BOOL read_sid_from_file(int fd, char *sid_file)
794 fstring fline;
796 memset(fline, '\0', sizeof(fline));
798 if(read(fd, fline, sizeof(fline) -1 ) < 0) {
799 DEBUG(0,("unable to read file %s. Error was %s\n",
800 sid_file, strerror(errno) ));
801 return False;
805 * Convert to the machine SID.
808 fline[sizeof(fline)-1] = '\0';
809 if(!string_to_sid( &global_sam_sid, fline)) {
810 DEBUG(0,("unable to generate machine SID.\n"));
811 return False;
814 return True;
817 /****************************************************************************
818 Generate the global machine sid. Look for the MACHINE.SID file first, if
819 not found then look in smb.conf and use it to create the MACHINE.SID file.
820 ****************************************************************************/
821 BOOL pdb_generate_sam_sid(void)
823 int fd;
824 char *p;
825 pstring sid_file;
826 fstring sid_string;
827 SMB_STRUCT_STAT st;
828 uchar raw_sid_data[12];
830 pstrcpy(sid_file, lp_smb_passwd_file());
831 p = strrchr(sid_file, '/');
832 if(p != NULL) {
833 *++p = '\0';
836 if (!directory_exist(sid_file, NULL)) {
837 if (dos_mkdir(sid_file, 0700) != 0) {
838 DEBUG(0,("can't create private directory %s : %s\n",
839 sid_file, strerror(errno)));
840 return False;
844 pstrcat(sid_file, "MACHINE.SID");
846 if((fd = open(sid_file, O_RDWR | O_CREAT, 0644)) == -1) {
847 DEBUG(0,("unable to open or create file %s. Error was %s\n",
848 sid_file, strerror(errno) ));
849 return False;
853 * Check if the file contains data.
856 if(sys_fstat( fd, &st) < 0) {
857 DEBUG(0,("unable to stat file %s. Error was %s\n",
858 sid_file, strerror(errno) ));
859 close(fd);
860 return False;
863 if(st.st_size > 0) {
865 * We have a valid SID - read it.
867 if(!read_sid_from_file( fd, sid_file)) {
868 DEBUG(0,("unable to read file %s. Error was %s\n",
869 sid_file, strerror(errno) ));
870 close(fd);
871 return False;
873 close(fd);
874 return True;
878 * The file contains no data - we need to generate our
879 * own sid.
884 * Generate the new sid data & turn it into a string.
886 int i;
887 generate_random_buffer( raw_sid_data, 12, True);
889 fstrcpy( sid_string, "S-1-5-21");
890 for( i = 0; i < 3; i++) {
891 fstring tmp_string;
892 slprintf( tmp_string, sizeof(tmp_string) - 1, "-%u", IVAL(raw_sid_data, i*4));
893 fstrcat( sid_string, tmp_string);
897 fstrcat(sid_string, "\n");
900 * Ensure our new SID is valid.
903 if(!string_to_sid( &global_sam_sid, sid_string)) {
904 DEBUG(0,("unable to generate machine SID.\n"));
905 return False;
909 * Do an exclusive blocking lock on the file.
912 if(!do_file_lock( fd, 60, F_WRLCK)) {
913 DEBUG(0,("unable to lock file %s. Error was %s\n",
914 sid_file, strerror(errno) ));
915 close(fd);
916 return False;
920 * At this point we have a blocking lock on the SID
921 * file - check if in the meantime someone else wrote
922 * SID data into the file. If so - they were here first,
923 * use their data.
926 if(sys_fstat( fd, &st) < 0) {
927 DEBUG(0,("unable to stat file %s. Error was %s\n",
928 sid_file, strerror(errno) ));
929 close(fd);
930 return False;
933 if(st.st_size > 0) {
935 * Unlock as soon as possible to reduce
936 * contention on the exclusive lock.
938 do_file_lock( fd, 60, F_UNLCK);
941 * We have a valid SID - read it.
944 if(!read_sid_from_file( fd, sid_file)) {
945 DEBUG(0,("unable to read file %s. Error was %s\n",
946 sid_file, strerror(errno) ));
947 close(fd);
948 return False;
950 close(fd);
951 return True;
955 * The file is still empty and we have an exlusive lock on it.
956 * Write out out SID data into the file.
959 if(fchmod(fd, 0644) < 0) {
960 DEBUG(0,("unable to set correct permissions on file %s. \
961 Error was %s\n", sid_file, strerror(errno) ));
962 close(fd);
963 return False;
966 if(write( fd, sid_string, strlen(sid_string)) != strlen(sid_string)) {
967 DEBUG(0,("unable to write file %s. Error was %s\n",
968 sid_file, strerror(errno) ));
969 close(fd);
970 return False;
974 * Unlock & exit.
977 do_file_lock( fd, 60, F_UNLCK);
978 close(fd);
979 return True;
982 /*******************************************************************
983 converts UNIX uid to an NT User RID.
984 ********************************************************************/
986 uid_t pdb_user_rid_to_uid(uint32 user_rid)
988 return (uid_t)(((user_rid & (~USER_RID_TYPE))- 1000)/RID_MULTIPLIER);
991 /*******************************************************************
992 converts UNIX uid to an NT User RID.
993 ********************************************************************/
995 uint32 pdb_uid_to_user_rid(uid_t uid)
997 return (((((uint32)uid)*RID_MULTIPLIER) + 1000) | USER_RID_TYPE);
1000 /*******************************************************************
1001 converts NT Group RID to a UNIX uid.
1002 ********************************************************************/
1004 uint32 pdb_gid_to_group_rid(gid_t gid)
1006 return (((((uint32)gid)*RID_MULTIPLIER) + 1000) | GROUP_RID_TYPE);
1009 /*******************************************************************
1010 Decides if a RID is a well known RID.
1011 ********************************************************************/
1013 static BOOL pdb_rid_is_well_known(uint32 rid)
1015 return (rid < 1000);
1018 /*******************************************************************
1019 Decides if a RID is a user or group RID.
1020 ********************************************************************/
1022 BOOL pdb_rid_is_user(uint32 rid)
1024 /* lkcl i understand that NT attaches an enumeration to a RID
1025 * such that it can be identified as either a user, group etc
1026 * type. there are 5 such categories, and they are documented.
1028 if(pdb_rid_is_well_known(rid)) {
1030 * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
1031 * and DOMAIN_USER_RID_GUEST.
1033 if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
1034 return True;
1035 } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
1036 return True;
1038 return False;