15b2e8ed50803152d2dccac4d50a422918bfcc27
[samba.git] / source3 / passdb / passdb.c
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
7       
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.
12    
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.
17    
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.
21 */
22
23 #include "includes.h"
24 #include "nterr.h"
25
26 extern int DEBUGLEVEL;
27
28 /*
29  * This is set on startup - it defines the SID for this
30  * machine.
31  */
32
33 DOM_SID global_machine_sid;
34
35 /*
36  * NOTE. All these functions are abstracted into a structure
37  * that points to the correct function for the selected database. JRA.
38  *
39  * NOTE.  for the get/mod/add functions, there are two sets of functions.
40  * one supports struct sam_passwd, the other supports struct smb_passwd.
41  * for speed optimisation it is best to support both these sets.
42  * 
43  * it is, however, optional to support one set but not the other: there
44  * is conversion-capability built in to passdb.c, and run-time error
45  * detection for when neither are supported.
46  * 
47  * password database writers are recommended to implement the sam_passwd
48  * functions in a first pass, as struct sam_passwd contains more
49  * information, needed by the NT Domain support.
50  * 
51  * a full example set of derivative functions are listed below.  an API
52  * writer is expected to cut/paste these into their module, replace
53  * either one set (struct smb_passwd) or the other (struct sam_passwd)
54  * OR both, and optionally also to write display info routines
55  * (struct sam_disp_info).  lkcl
56  *
57  */
58
59 #if 0
60 static struct smb_passwd    *getPDBpwent        (void *vp)                              { return pdb_sam_to_smb(getPDB21pwent(vp)); } 
61 static BOOL                  add_PDBpwd_entry   (struct smb_passwd *newpwd)             { return add_PDB21pwd_entry(pdb_smb_to_sam(newpwd)); } 
62 static BOOL                  mod_PDBpwd_entry   (struct smb_passwd* pwd, BOOL override) { return mod_PDB21pwd_entry(pdb_smb_to_sam(pwd), override); } 
63 static struct smb_passwd    *getPDBpwnam        (char *name)                            { return pdb_sam_to_smb(getPDB21pwnam(name)); } 
64 static struct smb_passwd    *getPDBpwuid        (uid_t smb_userid)                      { return pdb_sam_to_smb(getPDB21pwuid(pdb_uid_to_user_rid(smb_userid))); } 
65
66 static struct sam_passwd    *getPDB21pwent      (void *vp)                              { return pdb_smb_to_sam(getPDBpwent(vp)); } 
67 static BOOL                  add_PDB21pwd_entry (struct sam_passwd *newpwd)             { return add_PDBpwd_entry(pdb_sam_to_smb(newpwd)); } 
68 static BOOL                  mod_PDB21pwd_entry (struct sam_passwd* pwd, BOOL override) { return mod_PDBpwd_entry(pdb_sam_to_smb(pwd), override); } 
69 static struct sam_passwd    *getPDB21pwnam      (char *name)                            { return pdb_smb_to_sam(getPDBpwnam(name)); } 
70 static struct sam_passwd    *getPDB21pwrid      (uint32 rid)                            { return pdb_smb_to_sam(getPDBpwuid(pdb_user_rid_to_uid(rid))); } 
71 static struct sam_passwd    *getPDB21pwuid      (uid_t uid)                             { return pdb_smb_to_sam(getPDBpwuid(uid)); } 
72
73 static struct sam_disp_info *getPDBdispnam      (char *name)                            { return pdb_sam_to_dispinfo(getPDB21pwnam(name)); } 
74 static struct sam_disp_info *getPDBdisprid      (uint32 rid)                            { return pdb_sam_to_dispinfo(getPDB21pwrid(rid)); } 
75 static struct sam_disp_info *getPDBdispent      (void *vp)                              { return pdb_sam_to_dispinfo(getPDB21pwent(vp)); } 
76 #endif /* 0 */
77
78 static struct passdb_ops *pdb_ops;
79
80 /***************************************************************
81  Initialize the password db operations.
82 ***************************************************************/
83
84 BOOL initialize_password_db(void)
85 {
86   if (pdb_ops)
87   {
88     return True;
89   }
90
91 #ifdef WITH_NISPLUS
92   pdb_ops =  nisplus_initialize_password_db();
93 #elif defined(WITH_LDAP)
94   pdb_ops = ldap_initialize_password_db();
95 #else 
96   pdb_ops = file_initialize_password_db();
97 #endif 
98
99   return (pdb_ops != NULL);
100 }
101
102 /*
103  * Functions that return/manipulate a struct smb_passwd.
104  */
105
106 /************************************************************************
107  Utility function to search smb passwd by uid.  use this if your database
108  does not have search facilities.
109 *************************************************************************/
110
111 struct smb_passwd *iterate_getsmbpwuid(uid_t smb_userid)
112 {
113         struct smb_passwd *pwd = NULL;
114         void *fp = NULL;
115
116         DEBUG(10, ("search by smb_userid: %x\n", (int)smb_userid));
117
118         /* Open the smb password database - not for update. */
119         fp = startsmbpwent(False);
120
121         if (fp == NULL)
122         {
123                 DEBUG(0, ("unable to open smb password database.\n"));
124                 return NULL;
125         }
126
127         while ((pwd = getsmbpwent(fp)) != NULL && pwd->smb_userid != smb_userid)
128       ;
129
130         if (pwd != NULL)
131         {
132                 DEBUG(10, ("found by smb_userid: %x\n", (int)smb_userid));
133         }
134
135         endsmbpwent(fp);
136         return pwd;
137 }
138
139 /************************************************************************
140  Utility function to search smb passwd by name.  use this if your database
141  does not have search facilities.
142 *************************************************************************/
143
144 struct smb_passwd *iterate_getsmbpwnam(char *name)
145 {
146         struct smb_passwd *pwd = NULL;
147         void *fp = NULL;
148
149         DEBUG(10, ("search by name: %s\n", name));
150
151         /* Open the sam password file - not for update. */
152         fp = startsmbpwent(False);
153
154         if (fp == NULL)
155         {
156                 DEBUG(0, ("unable to open smb password database.\n"));
157                 return NULL;
158         }
159
160         while ((pwd = getsmbpwent(fp)) != NULL && !strequal(pwd->smb_name, name))
161       ;
162
163         if (pwd != NULL)
164         {
165                 DEBUG(10, ("found by name: %s\n", name));
166         }
167
168         endsmbpwent(fp);
169         return pwd;
170 }
171
172 /***************************************************************
173  Start to enumerate the smb or sam passwd list. Returns a void pointer
174  to ensure no modification outside this module.
175
176  Note that currently it is being assumed that a pointer returned
177  from this function may be used to enumerate struct sam_passwd
178  entries as well as struct smb_passwd entries. This may need
179  to change. JRA.
180
181 ****************************************************************/
182
183 void *startsmbpwent(BOOL update)
184 {
185   return pdb_ops->startsmbpwent(update);
186 }
187
188 /***************************************************************
189  End enumeration of the smb or sam passwd list.
190
191  Note that currently it is being assumed that a pointer returned
192  from this function may be used to enumerate struct sam_passwd
193  entries as well as struct smb_passwd entries. This may need
194  to change. JRA.
195
196 ****************************************************************/
197
198 void endsmbpwent(void *vp)
199 {
200   pdb_ops->endsmbpwent(vp);
201 }
202
203 /*************************************************************************
204  Routine to return the next entry in the smb passwd list.
205  *************************************************************************/
206
207 struct smb_passwd *getsmbpwent(void *vp)
208 {
209         return pdb_ops->getsmbpwent(vp);
210 }
211
212 /************************************************************************
213  Routine to add an entry to the smb passwd file.
214 *************************************************************************/
215
216 BOOL add_smbpwd_entry(struct smb_passwd *newpwd)
217 {
218         return pdb_ops->add_smbpwd_entry(newpwd);
219 }
220
221 /************************************************************************
222  Routine to search the smb passwd file for an entry matching the username.
223  and then modify its password entry. We can't use the startsampwent()/
224  getsampwent()/endsampwent() interfaces here as we depend on looking
225  in the actual file to decide how much room we have to write data.
226  override = False, normal
227  override = True, override XXXXXXXX'd out password or NO PASS
228 ************************************************************************/
229
230 BOOL mod_smbpwd_entry(struct smb_passwd* pwd, BOOL override)
231 {
232         return pdb_ops->mod_smbpwd_entry(pwd, override);
233 }
234
235 /************************************************************************
236  Routine to search smb passwd by name.
237 *************************************************************************/
238
239 struct smb_passwd *getsmbpwnam(char *name)
240 {
241         return pdb_ops->getsmbpwnam(name);
242 }
243
244 /************************************************************************
245  Routine to search smb passwd by uid.
246 *************************************************************************/
247
248 struct smb_passwd *getsmbpwuid(uid_t smb_userid)
249 {
250         return pdb_ops->getsmbpwuid(smb_userid);
251 }
252
253 /*
254  * Functions that manupulate a struct sam_passwd.
255  */
256
257 /************************************************************************
258  Utility function to search sam passwd by name.  use this if your database
259  does not have search facilities.
260 *************************************************************************/
261
262 struct sam_passwd *iterate_getsam21pwnam(char *name)
263 {
264         struct sam_passwd *pwd = NULL;
265         void *fp = NULL;
266
267         DEBUG(10, ("search by name: %s\n", name));
268
269         /* Open the smb password database - not for update. */
270         fp = startsmbpwent(False);
271
272         if (fp == NULL)
273         {
274                 DEBUG(0, ("unable to open sam password database.\n"));
275                 return NULL;
276         }
277
278         while ((pwd = getsam21pwent(fp)) != NULL && !strequal(pwd->smb_name, name))
279         {
280                 DEBUG(10, ("iterate: %s 0x%x\n", pwd->smb_name, pwd->user_rid));
281         }
282
283         if (pwd != NULL)
284         {
285                 DEBUG(10, ("found by name: %s\n", name));
286         }
287
288         endsmbpwent(fp);
289         return pwd;
290 }
291
292 /************************************************************************
293  Utility function to search sam passwd by rid.  use this if your database
294  does not have search facilities.
295
296  search capability by both rid and uid are needed as the rid <-> uid
297  mapping may be non-monotonic.  
298
299 *************************************************************************/
300
301 struct sam_passwd *iterate_getsam21pwrid(uint32 rid)
302 {
303         struct sam_passwd *pwd = NULL;
304         void *fp = NULL;
305
306         DEBUG(10, ("search by rid: %x\n", rid));
307
308         /* Open the smb password file - not for update. */
309         fp = startsmbpwent(False);
310
311         if (fp == NULL)
312         {
313                 DEBUG(0, ("unable to open sam password database.\n"));
314                 return NULL;
315         }
316
317         while ((pwd = getsam21pwent(fp)) != NULL && pwd->user_rid != rid)
318         {
319                 DEBUG(10, ("iterate: %s 0x%x\n", pwd->smb_name, pwd->user_rid));
320         }
321
322         if (pwd != NULL)
323         {
324                 DEBUG(10, ("found by user_rid: %x\n", rid));
325         }
326
327         endsmbpwent(fp);
328         return pwd;
329 }
330
331 /************************************************************************
332  Utility function to search sam passwd by uid.  use this if your database
333  does not have search facilities.
334
335  search capability by both rid and uid are needed as the rid <-> uid
336  mapping may be non-monotonic.  
337
338 *************************************************************************/
339
340 struct sam_passwd *iterate_getsam21pwuid(uid_t uid)
341 {
342         struct sam_passwd *pwd = NULL;
343         void *fp = NULL;
344
345         DEBUG(10, ("search by uid: %x\n", (int)uid));
346
347         /* Open the smb password file - not for update. */
348         fp = startsmbpwent(False);
349
350         if (fp == NULL)
351         {
352                 DEBUG(0, ("unable to open sam password database.\n"));
353                 return NULL;
354         }
355
356         while ((pwd = getsam21pwent(fp)) != NULL && pwd->smb_userid != uid)
357       ;
358
359         if (pwd != NULL)
360         {
361                 DEBUG(10, ("found by smb_userid: %x\n", (int)uid));
362         }
363
364         endsmbpwent(fp);
365         return pwd;
366 }
367
368 /*************************************************************************
369  Routine to return a display info structure, by rid
370  *************************************************************************/
371 struct sam_disp_info *getsamdisprid(uint32 rid)
372 {
373         return pdb_ops->getsamdisprid(rid);
374 }
375
376 /*************************************************************************
377  Routine to return the next entry in the sam passwd list.
378  *************************************************************************/
379
380 struct sam_passwd *getsam21pwent(void *vp)
381 {
382         return pdb_ops->getsam21pwent(vp);
383 }
384
385
386 /************************************************************************
387  Routine to search sam passwd by name.
388 *************************************************************************/
389
390 struct sam_passwd *getsam21pwnam(char *name)
391 {
392         return pdb_ops->getsam21pwnam(name);
393 }
394
395 /************************************************************************
396  Routine to search sam passwd by rid.  
397 *************************************************************************/
398
399 struct sam_passwd *getsam21pwrid(uint32 rid)
400 {
401         return pdb_ops->getsam21pwrid(rid);
402 }
403
404
405 /**********************************************************
406  **********************************************************
407
408  utility routines which are likely to be useful to all password
409  databases
410
411  **********************************************************
412  **********************************************************/
413
414 /*************************************************************
415  initialises a struct sam_disp_info.
416  **************************************************************/
417
418 static void pdb_init_dispinfo(struct sam_disp_info *user)
419 {
420         if (user == NULL) return;
421         bzero(user, sizeof(*user));
422 }
423
424 /*************************************************************
425  initialises a struct smb_passwd.
426  **************************************************************/
427
428 void pdb_init_smb(struct smb_passwd *user)
429 {
430         if (user == NULL) return;
431         bzero(user, sizeof(*user));
432         user->pass_last_set_time    = (time_t)-1;
433 }
434
435 /*************************************************************
436  initialises a struct sam_passwd.
437  **************************************************************/
438 void pdb_init_sam(struct sam_passwd *user)
439 {
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;
448 }
449
450 /*************************************************************************
451  Routine to return the next entry in the sam passwd list.
452  *************************************************************************/
453
454 struct sam_disp_info *pdb_sam_to_dispinfo(struct sam_passwd *user)
455 {
456         static struct sam_disp_info disp_info;
457
458         if (user == NULL) return NULL;
459
460         pdb_init_dispinfo(&disp_info);
461
462         disp_info.smb_name  = user->smb_name;
463         disp_info.full_name = user->full_name;
464         disp_info.user_rid  = user->user_rid;
465
466         return &disp_info;
467 }
468
469 /*************************************************************
470  converts a sam_passwd structure to a smb_passwd structure.
471  **************************************************************/
472
473 struct smb_passwd *pdb_sam_to_smb(struct sam_passwd *user)
474 {
475         static struct smb_passwd pw_buf;
476
477         if (user == NULL) return NULL;
478
479         pdb_init_smb(&pw_buf);
480
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;
487
488         return &pw_buf;
489 }
490
491
492 /**********************************************************
493  Encode the account control bits into a string.
494  length = length of string to encode into (including terminating
495  null). length *MUST BE MORE THAN 2* !
496  **********************************************************/
497
498 char *pdb_encode_acct_ctrl(uint16 acct_ctrl, size_t length)
499 {
500   static fstring acct_str;
501   size_t i = 0;
502
503   acct_str[i++] = '[';
504
505   if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
506   if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
507   if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
508   if (acct_ctrl & ACB_TEMPDUP  ) acct_str[i++] = 'T'; 
509   if (acct_ctrl & ACB_NORMAL   ) acct_str[i++] = 'U';
510   if (acct_ctrl & ACB_MNS      ) acct_str[i++] = 'M';
511   if (acct_ctrl & ACB_WSTRUST  ) acct_str[i++] = 'W';
512   if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
513   if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
514   if (acct_ctrl & ACB_PWNOEXP  ) acct_str[i++] = 'X';
515   if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
516
517   for ( ; i < length - 2 ; i++ ) { acct_str[i] = ' '; }
518
519   i = length - 2;
520   acct_str[i++] = ']';
521   acct_str[i++] = '\0';
522
523   return acct_str;
524 }     
525
526 /**********************************************************
527  Decode the account control bits from a string.
528
529  this function breaks coding standards minimum line width of 80 chars.
530  reason: vertical line-up code clarity - all case statements fit into
531  15 lines, which is more important.
532  **********************************************************/
533
534 uint16 pdb_decode_acct_ctrl(char *p)
535 {
536         uint16 acct_ctrl = 0;
537         BOOL finished = False;
538
539         /*
540          * Check if the account type bits have been encoded after the
541          * NT password (in the form [NDHTUWSLXI]).
542          */
543
544         if (*p != '[') return 0;
545
546         for (p++; *p && !finished; p++)
547         {
548                 switch (*p)
549                 {
550                         case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
551                         case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
552                         case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
553                         case 'T': { acct_ctrl |= ACB_TEMPDUP  ; break; /* 'T'emp account. */ } 
554                         case 'U': { acct_ctrl |= ACB_NORMAL   ; break; /* 'U'ser account (normal). */ } 
555                         case 'M': { acct_ctrl |= ACB_MNS      ; break; /* 'M'NS logon user account. What is this ? */ } 
556                         case 'W': { acct_ctrl |= ACB_WSTRUST  ; break; /* 'W'orkstation account. */ } 
557                         case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ } 
558                         case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ } 
559                         case 'X': { acct_ctrl |= ACB_PWNOEXP  ; break; /* No 'X'piry on password */ } 
560                         case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
561             case ' ': { break; }
562                         case ':':
563                         case '\n':
564                         case '\0': 
565                         case ']':
566                         default:  { finished = True; }
567                 }
568         }
569
570         return acct_ctrl;
571 }
572
573 /*************************************************************
574  Routine to get the 32 hex characters and turn them
575  into a 16 byte array.
576 **************************************************************/
577 BOOL pdb_gethexpwd(char *p, char *pwd)
578 {
579         int i;
580         unsigned char   lonybble, hinybble;
581         char           *hexchars = "0123456789ABCDEF";
582         char           *p1, *p2;
583
584         for (i = 0; i < 32; i += 2)
585         {
586                 hinybble = toupper(p[i]);
587                 lonybble = toupper(p[i + 1]);
588
589                 p1 = strchr(hexchars, hinybble);
590                 p2 = strchr(hexchars, lonybble);
591
592                 if (!p1 || !p2)
593                 {
594                         return (False);
595                 }
596
597                 hinybble = PTR_DIFF(p1, hexchars);
598                 lonybble = PTR_DIFF(p2, hexchars);
599
600                 pwd[i / 2] = (hinybble << 4) | lonybble;
601         }
602         return (True);
603 }
604
605 /*******************************************************************
606  Group and User RID username mapping function
607  ********************************************************************/
608
609 BOOL pdb_name_to_rid(char *user_name, uint32 *u_rid, uint32 *g_rid)
610 {
611     struct passwd *pw = Get_Pwnam(user_name, False);
612
613         if (u_rid == NULL || g_rid == NULL || user_name == NULL)
614         {
615                 return False;
616         }
617
618         if (!pw)
619         {
620                 DEBUG(1,("Username %s is invalid on this system\n", user_name));
621                 return False;
622         }
623
624         if (user_in_list(user_name, lp_domain_guest_users()))
625         {
626                 *u_rid = DOMAIN_USER_RID_GUEST;
627         }
628         else if (user_in_list(user_name, lp_domain_admin_users()))
629         {
630                 *u_rid = DOMAIN_USER_RID_ADMIN;
631         }
632         else
633         {
634                 /* turn the unix UID into a Domain RID.  this is what the posix
635                    sub-system does (adds 1000 to the uid) */
636                 *u_rid = pdb_uid_to_user_rid(pw->pw_uid);
637         }
638
639         /* absolutely no idea what to do about the unix GID to Domain RID mapping */
640         *g_rid = pdb_gid_to_group_rid(pw->pw_gid);
641
642         return True;
643 }
644
645 /****************************************************************************
646  Read the machine SID from a file.
647 ****************************************************************************/
648
649 static BOOL read_sid_from_file(int fd, char *sid_file)
650 {   
651   fstring fline;
652     
653   memset(fline, '\0', sizeof(fline));
654
655   if(read(fd, fline, sizeof(fline) -1 ) < 0) {
656     DEBUG(0,("unable to read file %s. Error was %s\n",
657            sid_file, strerror(errno) ));
658     return False;
659   }
660
661   /*
662    * Convert to the machine SID.
663    */
664
665   fline[sizeof(fline)-1] = '\0';
666   if(!string_to_sid( &global_machine_sid, fline)) {
667     DEBUG(0,("unable to generate machine SID.\n"));
668     return False;
669   }
670
671   return True;
672 }
673
674 /****************************************************************************
675  Generate the global machine sid. Look for the MACHINE.SID file first, if
676  not found then look in smb.conf and use it to create the MACHINE.SID file.
677 ****************************************************************************/
678 BOOL pdb_generate_machine_sid(void)
679 {
680         int fd;
681         char *p;
682         pstring sid_file;
683         fstring sid_string;
684         SMB_STRUCT_STAT st;
685         uchar raw_sid_data[12];
686
687         pstrcpy(sid_file, lp_smb_passwd_file());
688         p = strrchr(sid_file, '/');
689         if(p != NULL) {
690                 *++p = '\0';
691         }
692
693         if (!directory_exist(sid_file, NULL)) {
694                 if (dos_mkdir(sid_file, 0700) != 0) {
695                         DEBUG(0,("can't create private directory %s : %s\n",
696                                  sid_file, strerror(errno)));
697                         return False;
698                 }
699         }
700
701         pstrcat(sid_file, "MACHINE.SID");
702     
703         if((fd = open(sid_file, O_RDWR | O_CREAT, 0644)) == -1) {
704                 DEBUG(0,("unable to open or create file %s. Error was %s\n",
705                          sid_file, strerror(errno) ));
706                 return False;
707         } 
708   
709         /*
710          * Check if the file contains data.
711          */
712         
713         if(sys_fstat( fd, &st) < 0) {
714                 DEBUG(0,("unable to stat file %s. Error was %s\n",
715                          sid_file, strerror(errno) ));
716                 close(fd);
717                 return False;
718         } 
719   
720         if(st.st_size > 0) {
721                 /*
722                  * We have a valid SID - read it.
723                  */
724                 if(!read_sid_from_file( fd, sid_file)) {
725                         DEBUG(0,("unable to read file %s. Error was %s\n",
726                                  sid_file, strerror(errno) ));
727                         close(fd);
728                         return False;
729                 }
730                 close(fd);
731                 return True;
732         } 
733   
734         /*
735          * The file contains no data - we may need to generate our
736          * own sid. Try the lp_domain_sid() first.
737          */
738         
739         if(*lp_domain_sid())
740                 fstrcpy( sid_string, lp_domain_sid());
741         else {
742                 /*
743                  * Generate the new sid data & turn it into a string.
744                  */
745                 int i;
746                 generate_random_buffer( raw_sid_data, 12, True);
747                 
748                 fstrcpy( sid_string, "S-1-5-21");
749                 for( i = 0; i < 3; i++) {
750                         fstring tmp_string;
751                         slprintf( tmp_string, sizeof(tmp_string) - 1, "-%u", IVAL(raw_sid_data, i*4));
752                         fstrcat( sid_string, tmp_string);
753                 }
754         } 
755         
756         fstrcat(sid_string, "\n");
757         
758         /*
759          * Ensure our new SID is valid.
760          */
761         
762         if(!string_to_sid( &global_machine_sid, sid_string)) {
763                 DEBUG(0,("unable to generate machine SID.\n"));
764                 return False;
765         } 
766   
767         /*
768          * Do an exclusive blocking lock on the file.
769          */
770         
771         if(!do_file_lock( fd, 60, F_WRLCK)) {
772                 DEBUG(0,("unable to lock file %s. Error was %s\n",
773                          sid_file, strerror(errno) ));
774                 close(fd);
775                 return False;
776         } 
777   
778         /*
779          * At this point we have a blocking lock on the SID
780          * file - check if in the meantime someone else wrote
781          * SID data into the file. If so - they were here first,
782          * use their data.
783          */
784         
785         if(sys_fstat( fd, &st) < 0) {
786                 DEBUG(0,("unable to stat file %s. Error was %s\n",
787                          sid_file, strerror(errno) ));
788                 close(fd);
789                 return False;
790         } 
791   
792         if(st.st_size > 0) {
793                 /*
794                  * Unlock as soon as possible to reduce
795                  * contention on the exclusive lock.
796                  */ 
797                 do_file_lock( fd, 60, F_UNLCK);
798                 
799                 /*
800                  * We have a valid SID - read it.
801                  */
802                 
803                 if(!read_sid_from_file( fd, sid_file)) {
804                         DEBUG(0,("unable to read file %s. Error was %s\n",
805                                  sid_file, strerror(errno) ));
806                         close(fd);
807                         return False;
808                 }
809                 close(fd);
810                 return True;
811         } 
812         
813         /*
814          * The file is still empty and we have an exlusive lock on it.
815          * Write out out SID data into the file.
816          */
817         
818         if(fchmod(fd, 0644) < 0) {
819                 DEBUG(0,("unable to set correct permissions on file %s. \
820 Error was %s\n", sid_file, strerror(errno) ));
821                 close(fd);
822                 return False;
823         } 
824         
825         if(write( fd, sid_string, strlen(sid_string)) != strlen(sid_string)) {
826                 DEBUG(0,("unable to write file %s. Error was %s\n",
827                          sid_file, strerror(errno) ));
828                 close(fd);
829                 return False;
830         } 
831         
832         /*
833          * Unlock & exit.
834          */
835         
836         do_file_lock( fd, 60, F_UNLCK);
837         close(fd);
838         return True;
839 }   
840
841 /*******************************************************************
842  converts UNIX uid to an NT User RID.
843  ********************************************************************/
844
845 uint32 pdb_uid_to_user_rid(uid_t uid)
846 {
847         return (((((uint32)uid)*RID_MULTIPLIER) + 1000) | USER_RID_TYPE);
848 }
849
850 /*******************************************************************
851  converts NT Group RID to a UNIX uid.
852  ********************************************************************/
853
854 uint32 pdb_gid_to_group_rid(gid_t gid)
855 {
856   return (((((uint32)gid)*RID_MULTIPLIER) + 1000) | GROUP_RID_TYPE);
857 }
858
859 /*******************************************************************
860  Decides if a RID is a well known RID.
861  ********************************************************************/
862
863 static BOOL pdb_rid_is_well_known(uint32 rid)
864 {
865   return (rid < 1000);
866 }
867
868 /*******************************************************************
869  Decides if a RID is a user or group RID.
870  ********************************************************************/
871   
872 BOOL pdb_rid_is_user(uint32 rid)
873 {
874   /* lkcl i understand that NT attaches an enumeration to a RID
875    * such that it can be identified as either a user, group etc
876    * type.  there are 5 such categories, and they are documented.
877    */
878    if(pdb_rid_is_well_known(rid)) {
879       /*
880        * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
881        * and DOMAIN_USER_RID_GUEST.
882        */
883      if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
884        return True;
885    } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
886      return True;
887    }
888    return False;
889 }