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