added in some pdb_xxx routines that are needed by nispass.c
[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  gets password-database-format time from a string.
575  ********************************************************************/
576
577 static time_t get_time_from_string(char *p)
578 {
579         int i;
580
581         for (i = 0; i < 8; i++)
582         {
583                 if (p[i] == '\0' || !isxdigit(p[i]))
584                 break;
585         }
586         if (i == 8)
587         {
588                 /*
589                  * p points at 8 characters of hex digits - 
590                  * read into a time_t as the seconds since
591                  * 1970 that the password was last changed.
592                  */
593                 return (time_t)strtol((char *)p, NULL, 16);
594         }
595         return (time_t)-1;
596 }
597
598 /*******************************************************************
599  gets password last set time
600  ********************************************************************/
601
602 time_t pdb_get_last_set_time(char *p)
603 {
604         if (*p && StrnCaseCmp((char *)p, "LCT-", 4))
605         {
606                 return get_time_from_string(p + 4);
607         }
608         return (time_t)-1;
609 }
610
611
612 /*******************************************************************
613  sets password-database-format time in a string.
614  ********************************************************************/
615 static void set_time_in_string(char *p, int max_len, char *type, time_t t)
616 {
617         slprintf(p, max_len, ":%s-%08X:", type, (uint32)t);
618 }
619
620 /*******************************************************************
621  sets logon time
622  ********************************************************************/
623 void pdb_set_logon_time(char *p, int max_len, time_t t)
624 {
625         set_time_in_string(p, max_len, "LNT", t);
626 }
627
628 /*******************************************************************
629  sets logoff time
630  ********************************************************************/
631 void pdb_set_logoff_time(char *p, int max_len, time_t t)
632 {
633         set_time_in_string(p, max_len, "LOT", t);
634 }
635
636 /*******************************************************************
637  sets kickoff time
638  ********************************************************************/
639 void pdb_set_kickoff_time(char *p, int max_len, time_t t)
640 {
641         set_time_in_string(p, max_len, "KOT", t);
642 }
643
644 /*******************************************************************
645  sets password can change time
646  ********************************************************************/
647 void pdb_set_can_change_time(char *p, int max_len, time_t t)
648 {
649         set_time_in_string(p, max_len, "CCT", t);
650 }
651
652 /*******************************************************************
653  sets password last set time
654  ********************************************************************/
655 void pdb_set_must_change_time(char *p, int max_len, time_t t)
656 {
657         set_time_in_string(p, max_len, "MCT", t);
658 }
659
660 /*******************************************************************
661  sets password last set time
662  ********************************************************************/
663 void pdb_set_last_set_time(char *p, int max_len, time_t t)
664 {
665         set_time_in_string(p, max_len, "LCT", t);
666 }
667
668
669 /*************************************************************
670  Routine to set 32 hex password characters from a 16 byte array.
671 **************************************************************/
672 void pdb_sethexpwd(char *p, char *pwd, uint16 acct_ctrl)
673 {
674         if (pwd != NULL)
675         {
676                 int i;
677                 for (i = 0; i < 16; i++)
678                 {
679                         slprintf(&p[i*2], 33, "%02X", pwd[i]);
680                 }
681         }
682         else
683         {
684                 if (IS_BITS_SET_ALL(acct_ctrl, ACB_PWNOTREQ))
685                 {
686                         safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
687                 }
688                 else
689                 {
690                         safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
691                 }
692         }
693 }
694 /*************************************************************
695  Routine to get the 32 hex characters and turn them
696  into a 16 byte array.
697 **************************************************************/
698 BOOL pdb_gethexpwd(char *p, char *pwd)
699 {
700         int i;
701         unsigned char   lonybble, hinybble;
702         char           *hexchars = "0123456789ABCDEF";
703         char           *p1, *p2;
704
705         for (i = 0; i < 32; i += 2)
706         {
707                 hinybble = toupper(p[i]);
708                 lonybble = toupper(p[i + 1]);
709
710                 p1 = strchr(hexchars, hinybble);
711                 p2 = strchr(hexchars, lonybble);
712
713                 if (!p1 || !p2)
714                 {
715                         return (False);
716                 }
717
718                 hinybble = PTR_DIFF(p1, hexchars);
719                 lonybble = PTR_DIFF(p2, hexchars);
720
721                 pwd[i / 2] = (hinybble << 4) | lonybble;
722         }
723         return (True);
724 }
725
726 /*******************************************************************
727  Group and User RID username mapping function
728  ********************************************************************/
729
730 BOOL pdb_name_to_rid(char *user_name, uint32 *u_rid, uint32 *g_rid)
731 {
732     struct passwd *pw = Get_Pwnam(user_name, False);
733
734         if (u_rid == NULL || g_rid == NULL || user_name == NULL)
735         {
736                 return False;
737         }
738
739         if (!pw)
740         {
741                 DEBUG(1,("Username %s is invalid on this system\n", user_name));
742                 return False;
743         }
744
745         if (user_in_list(user_name, lp_domain_guest_users()))
746         {
747                 *u_rid = DOMAIN_USER_RID_GUEST;
748         }
749         else if (user_in_list(user_name, lp_domain_admin_users()))
750         {
751                 *u_rid = DOMAIN_USER_RID_ADMIN;
752         }
753         else
754         {
755                 /* turn the unix UID into a Domain RID.  this is what the posix
756                    sub-system does (adds 1000 to the uid) */
757                 *u_rid = pdb_uid_to_user_rid(pw->pw_uid);
758         }
759
760         /* absolutely no idea what to do about the unix GID to Domain RID mapping */
761         *g_rid = pdb_gid_to_group_rid(pw->pw_gid);
762
763         return True;
764 }
765
766 /****************************************************************************
767  Read the machine SID from a file.
768 ****************************************************************************/
769
770 static BOOL read_sid_from_file(int fd, char *sid_file)
771 {   
772   fstring fline;
773     
774   memset(fline, '\0', sizeof(fline));
775
776   if(read(fd, fline, sizeof(fline) -1 ) < 0) {
777     DEBUG(0,("unable to read file %s. Error was %s\n",
778            sid_file, strerror(errno) ));
779     return False;
780   }
781
782   /*
783    * Convert to the machine SID.
784    */
785
786   fline[sizeof(fline)-1] = '\0';
787   if(!string_to_sid( &global_machine_sid, fline)) {
788     DEBUG(0,("unable to generate machine SID.\n"));
789     return False;
790   }
791
792   return True;
793 }
794
795 /****************************************************************************
796  Generate the global machine sid. Look for the MACHINE.SID file first, if
797  not found then look in smb.conf and use it to create the MACHINE.SID file.
798 ****************************************************************************/
799 BOOL pdb_generate_machine_sid(void)
800 {
801         int fd;
802         char *p;
803         pstring sid_file;
804         fstring sid_string;
805         SMB_STRUCT_STAT st;
806         uchar raw_sid_data[12];
807
808         pstrcpy(sid_file, lp_smb_passwd_file());
809         p = strrchr(sid_file, '/');
810         if(p != NULL) {
811                 *++p = '\0';
812         }
813
814         if (!directory_exist(sid_file, NULL)) {
815                 if (dos_mkdir(sid_file, 0700) != 0) {
816                         DEBUG(0,("can't create private directory %s : %s\n",
817                                  sid_file, strerror(errno)));
818                         return False;
819                 }
820         }
821
822         pstrcat(sid_file, "MACHINE.SID");
823     
824         if((fd = open(sid_file, O_RDWR | O_CREAT, 0644)) == -1) {
825                 DEBUG(0,("unable to open or create file %s. Error was %s\n",
826                          sid_file, strerror(errno) ));
827                 return False;
828         } 
829   
830         /*
831          * Check if the file contains data.
832          */
833         
834         if(sys_fstat( fd, &st) < 0) {
835                 DEBUG(0,("unable to stat file %s. Error was %s\n",
836                          sid_file, strerror(errno) ));
837                 close(fd);
838                 return False;
839         } 
840   
841         if(st.st_size > 0) {
842                 /*
843                  * We have a valid SID - read it.
844                  */
845                 if(!read_sid_from_file( fd, sid_file)) {
846                         DEBUG(0,("unable to read file %s. Error was %s\n",
847                                  sid_file, strerror(errno) ));
848                         close(fd);
849                         return False;
850                 }
851                 close(fd);
852                 return True;
853         } 
854   
855         /*
856          * The file contains no data - we may need to generate our
857          * own sid. Try the lp_domain_sid() first.
858          */
859         
860         if(*lp_domain_sid())
861                 fstrcpy( sid_string, lp_domain_sid());
862         else {
863                 /*
864                  * Generate the new sid data & turn it into a string.
865                  */
866                 int i;
867                 generate_random_buffer( raw_sid_data, 12, True);
868                 
869                 fstrcpy( sid_string, "S-1-5-21");
870                 for( i = 0; i < 3; i++) {
871                         fstring tmp_string;
872                         slprintf( tmp_string, sizeof(tmp_string) - 1, "-%u", IVAL(raw_sid_data, i*4));
873                         fstrcat( sid_string, tmp_string);
874                 }
875         } 
876         
877         fstrcat(sid_string, "\n");
878         
879         /*
880          * Ensure our new SID is valid.
881          */
882         
883         if(!string_to_sid( &global_machine_sid, sid_string)) {
884                 DEBUG(0,("unable to generate machine SID.\n"));
885                 return False;
886         } 
887   
888         /*
889          * Do an exclusive blocking lock on the file.
890          */
891         
892         if(!do_file_lock( fd, 60, F_WRLCK)) {
893                 DEBUG(0,("unable to lock file %s. Error was %s\n",
894                          sid_file, strerror(errno) ));
895                 close(fd);
896                 return False;
897         } 
898   
899         /*
900          * At this point we have a blocking lock on the SID
901          * file - check if in the meantime someone else wrote
902          * SID data into the file. If so - they were here first,
903          * use their data.
904          */
905         
906         if(sys_fstat( fd, &st) < 0) {
907                 DEBUG(0,("unable to stat file %s. Error was %s\n",
908                          sid_file, strerror(errno) ));
909                 close(fd);
910                 return False;
911         } 
912   
913         if(st.st_size > 0) {
914                 /*
915                  * Unlock as soon as possible to reduce
916                  * contention on the exclusive lock.
917                  */ 
918                 do_file_lock( fd, 60, F_UNLCK);
919                 
920                 /*
921                  * We have a valid SID - read it.
922                  */
923                 
924                 if(!read_sid_from_file( fd, sid_file)) {
925                         DEBUG(0,("unable to read file %s. Error was %s\n",
926                                  sid_file, strerror(errno) ));
927                         close(fd);
928                         return False;
929                 }
930                 close(fd);
931                 return True;
932         } 
933         
934         /*
935          * The file is still empty and we have an exlusive lock on it.
936          * Write out out SID data into the file.
937          */
938         
939         if(fchmod(fd, 0644) < 0) {
940                 DEBUG(0,("unable to set correct permissions on file %s. \
941 Error was %s\n", sid_file, strerror(errno) ));
942                 close(fd);
943                 return False;
944         } 
945         
946         if(write( fd, sid_string, strlen(sid_string)) != strlen(sid_string)) {
947                 DEBUG(0,("unable to write file %s. Error was %s\n",
948                          sid_file, strerror(errno) ));
949                 close(fd);
950                 return False;
951         } 
952         
953         /*
954          * Unlock & exit.
955          */
956         
957         do_file_lock( fd, 60, F_UNLCK);
958         close(fd);
959         return True;
960 }   
961
962 /*******************************************************************
963  converts UNIX uid to an NT User RID.
964  ********************************************************************/
965
966 uint32 pdb_uid_to_user_rid(uid_t uid)
967 {
968         return (((((uint32)uid)*RID_MULTIPLIER) + 1000) | USER_RID_TYPE);
969 }
970
971 /*******************************************************************
972  converts NT Group RID to a UNIX uid.
973  ********************************************************************/
974
975 uint32 pdb_gid_to_group_rid(gid_t gid)
976 {
977   return (((((uint32)gid)*RID_MULTIPLIER) + 1000) | GROUP_RID_TYPE);
978 }
979
980 /*******************************************************************
981  Decides if a RID is a well known RID.
982  ********************************************************************/
983
984 static BOOL pdb_rid_is_well_known(uint32 rid)
985 {
986   return (rid < 1000);
987 }
988
989 /*******************************************************************
990  Decides if a RID is a user or group RID.
991  ********************************************************************/
992   
993 BOOL pdb_rid_is_user(uint32 rid)
994 {
995   /* lkcl i understand that NT attaches an enumeration to a RID
996    * such that it can be identified as either a user, group etc
997    * type.  there are 5 such categories, and they are documented.
998    */
999    if(pdb_rid_is_well_known(rid)) {
1000       /*
1001        * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
1002        * and DOMAIN_USER_RID_GUEST.
1003        */
1004      if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
1005        return True;
1006    } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
1007      return True;
1008    }
1009    return False;
1010 }