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