loadparm.c: Added machine password timeout parameter - set to 7 days be default.
[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 rid.  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
596 /*******************************************************************
597  gets password-database-format time from a string.
598  ********************************************************************/
599
600 static time_t get_time_from_string(char *p)
601 {
602         int i;
603
604         for (i = 0; i < 8; i++)
605         {
606                 if (p[i] == '\0' || !isxdigit(p[i]))
607                 break;
608         }
609         if (i == 8)
610         {
611                 /*
612                  * p points at 8 characters of hex digits - 
613                  * read into a time_t as the seconds since
614                  * 1970 that the password was last changed.
615                  */
616                 return (time_t)strtol((char *)p, NULL, 16);
617         }
618         return (time_t)-1;
619 }
620
621 /*******************************************************************
622  gets password last set time
623  ********************************************************************/
624
625 time_t pdb_get_last_set_time(char *p)
626 {
627         if (*p && StrnCaseCmp((char *)p, "LCT-", 4))
628         {
629                 return get_time_from_string(p + 4);
630         }
631         return (time_t)-1;
632 }
633
634
635 /*******************************************************************
636  sets password-database-format time in a string.
637  ********************************************************************/
638 static void set_time_in_string(char *p, int max_len, char *type, time_t t)
639 {
640         slprintf(p, max_len, ":%s-%08X:", type, (uint32)t);
641 }
642
643 /*******************************************************************
644  sets logon time
645  ********************************************************************/
646 void pdb_set_logon_time(char *p, int max_len, time_t t)
647 {
648         set_time_in_string(p, max_len, "LNT", t);
649 }
650
651 /*******************************************************************
652  sets logoff time
653  ********************************************************************/
654 void pdb_set_logoff_time(char *p, int max_len, time_t t)
655 {
656         set_time_in_string(p, max_len, "LOT", t);
657 }
658
659 /*******************************************************************
660  sets kickoff time
661  ********************************************************************/
662 void pdb_set_kickoff_time(char *p, int max_len, time_t t)
663 {
664         set_time_in_string(p, max_len, "KOT", t);
665 }
666
667 /*******************************************************************
668  sets password can change time
669  ********************************************************************/
670 void pdb_set_can_change_time(char *p, int max_len, time_t t)
671 {
672         set_time_in_string(p, max_len, "CCT", t);
673 }
674
675 /*******************************************************************
676  sets password last set time
677  ********************************************************************/
678 void pdb_set_must_change_time(char *p, int max_len, time_t t)
679 {
680         set_time_in_string(p, max_len, "MCT", t);
681 }
682
683 /*******************************************************************
684  sets password last set time
685  ********************************************************************/
686 void pdb_set_last_set_time(char *p, int max_len, time_t t)
687 {
688         set_time_in_string(p, max_len, "LCT", t);
689 }
690
691 /**********************************************************
692  Encode the account control bits into a string.
693  **********************************************************/
694
695 char *pdb_encode_acct_ctrl(uint16 acct_ctrl)
696 {
697   static fstring acct_str;
698   char *p = acct_str;
699  
700   *p++ = '[';
701
702   if (acct_ctrl & ACB_HOMDIRREQ) *p++ = 'H';
703   if (acct_ctrl & ACB_TEMPDUP  ) *p++ = 'T'; 
704   if (acct_ctrl & ACB_NORMAL   ) *p++ = 'U';
705   if (acct_ctrl & ACB_MNS      ) *p++ = 'M';
706   if (acct_ctrl & ACB_WSTRUST  ) *p++ = 'W';
707   if (acct_ctrl & ACB_SVRTRUST ) *p++ = 'S';
708   if (acct_ctrl & ACB_AUTOLOCK ) *p++ = 'L';
709   if (acct_ctrl & ACB_PWNOEXP  ) *p++ = 'X';
710   if (acct_ctrl & ACB_DOMTRUST ) *p++ = 'I';
711       
712   *p++ = ']';
713   *p = '\0';
714   return acct_str;
715 }     
716
717 /**********************************************************
718  Decode the account control bits from a string.
719
720  this function breaks coding standards minimum line width of 80 chars.
721  reason: vertical line-up code clarity - all case statements fit into
722  15 lines, which is more important.
723  **********************************************************/
724
725 uint16 pdb_decode_acct_ctrl(char *p)
726 {
727         uint16 acct_ctrl = 0;
728         BOOL finished = False;
729
730         /*
731          * Check if the account type bits have been encoded after the
732          * NT password (in the form [NDHTUWSLXI]).
733          */
734
735         if (*p != '[') return 0;
736
737         for (p++; *p && !finished; p++)
738         {
739                 switch (*p)
740                 {
741 #if 0
742                         /*
743                          * Hmmm. Don't allow these to be set/read independently
744                          * of the actual password fields. We don't want a mismatch.
745                          * JRA.
746                          */
747                         case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
748                         case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
749 #endif 
750                         case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
751                         case 'T': { acct_ctrl |= ACB_TEMPDUP  ; break; /* 'T'emp account. */ } 
752                         case 'U': { acct_ctrl |= ACB_NORMAL   ; break; /* 'U'ser account (normal). */ } 
753                         case 'M': { acct_ctrl |= ACB_MNS      ; break; /* 'M'NS logon user account. What is this ? */ } 
754                         case 'W': { acct_ctrl |= ACB_WSTRUST  ; break; /* 'W'orkstation account. */ } 
755                         case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ } 
756                         case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ } 
757                         case 'X': { acct_ctrl |= ACB_PWNOEXP  ; break; /* No 'X'piry on password */ } 
758                         case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
759
760                         case ':':
761                         case '\n':
762                         case '\0': 
763                         case ']':
764                         default:  { finished = True; }
765                 }
766         }
767
768         return acct_ctrl;
769 }
770
771 /*************************************************************
772  Routine to get the 32 hex characters and turn them
773  into a 16 byte array.
774 **************************************************************/
775 BOOL pdb_gethexpwd(char *p, char *pwd)
776 {
777         int i;
778         unsigned char   lonybble, hinybble;
779         char           *hexchars = "0123456789ABCDEF";
780         char           *p1, *p2;
781
782         for (i = 0; i < 32; i += 2)
783         {
784                 hinybble = toupper(p[i]);
785                 lonybble = toupper(p[i + 1]);
786
787                 p1 = strchr(hexchars, hinybble);
788                 p2 = strchr(hexchars, lonybble);
789
790                 if (!p1 || !p2)
791                 {
792                         return (False);
793                 }
794
795                 hinybble = PTR_DIFF(p1, hexchars);
796                 lonybble = PTR_DIFF(p2, hexchars);
797
798                 pwd[i / 2] = (hinybble << 4) | lonybble;
799         }
800         return (True);
801 }
802
803 /*************************************************************
804  Routine to set 32 hex password characters from a 16 byte array.
805 **************************************************************/
806 void pdb_sethexpwd(char *p, char *pwd, uint16 acct_ctrl)
807 {
808         if (pwd != NULL)
809         {
810                 int i;
811                 for (i = 0; i < 16; i++)
812                 {
813                         slprintf(&p[i*2], 33, "%02X", pwd[i]);
814                 }
815         }
816         else
817         {
818                 if (IS_BITS_SET_ALL(acct_ctrl, ACB_PWNOTREQ))
819                 {
820                         safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
821                 }
822                 else
823                 {
824                         safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
825                 }
826         }
827 }
828
829 /*******************************************************************
830  Group and User RID username mapping function
831  ********************************************************************/
832
833 BOOL pdb_name_to_rid(char *user_name, uint32 *u_rid, uint32 *g_rid)
834 {
835     struct passwd *pw = Get_Pwnam(user_name, False);
836
837         if (u_rid == NULL || g_rid == NULL || user_name == NULL)
838         {
839                 return False;
840         }
841
842     if (!pw)
843         {
844       DEBUG(1,("Username %s is invalid on this system\n", user_name));
845       return False;
846     }
847
848         if (user_in_list(user_name, lp_domain_guest_users()))
849         {
850                 *u_rid = DOMAIN_USER_RID_GUEST;
851         }
852         else if (user_in_list(user_name, lp_domain_admin_users()))
853         {
854                 *u_rid = DOMAIN_USER_RID_ADMIN;
855         }
856         else
857         {
858                 /* turn the unix UID into a Domain RID.  this is what the posix
859                    sub-system does (adds 1000 to the uid) */
860                 *u_rid = pdb_uid_to_user_rid(pw->pw_uid);
861         }
862
863         /* absolutely no idea what to do about the unix GID to Domain RID mapping */
864         *g_rid = pdb_gid_to_group_rid(pw->pw_gid);
865
866         return True;
867 }
868
869 /****************************************************************************
870  Read the machine SID from a file.
871 ****************************************************************************/
872
873 static BOOL read_sid_from_file(int fd, char *sid_file)
874 {   
875   fstring fline;
876     
877   if(read(fd, fline, sizeof(fline) -1 ) < 0) {
878     DEBUG(0,("read_sid_from_file: unable to read file %s. Error was %s\n",
879            sid_file, strerror(errno) ));
880     return False;
881   }
882
883   /*
884    * Convert to the machine SID.
885    */
886
887   fline[sizeof(fline)-1] = '\0';
888   if(!string_to_sid( &global_machine_sid, fline)) {
889     DEBUG(0,("read_sid_from_file: unable to generate machine SID.\n"));
890     return False;
891   }
892
893   return True;
894 }
895
896 /****************************************************************************
897  Generate the global machine sid. Look for the MACHINE.SID file first, if
898  not found then look in smb.conf and use it to create the MACHINE.SID file.
899 ****************************************************************************/
900
901 BOOL pdb_generate_machine_sid(void)
902 {
903   int fd;
904   char *p;
905   pstring sid_file;
906   fstring sid_string;
907   struct stat st;
908   uchar raw_sid_data[12];
909
910   pstrcpy(sid_file, lp_smb_passwd_file());
911   p = strrchr(sid_file, '/');
912   if(p != NULL)
913     *++p = '\0';
914     
915   pstrcat(sid_file, "MACHINE.SID");
916     
917   if((fd = open( sid_file, O_RDWR | O_CREAT, 0644)) < 0 ) {
918     DEBUG(0,("generate_machine_sid: unable to open or create file %s. Error was %s\n",
919              sid_file, strerror(errno) ));
920     return False;
921   } 
922   
923   /*
924    * Check if the file contains data.
925    */
926     
927   if(fstat( fd, &st) < 0) {
928     DEBUG(0,("generate_machine_sid: unable to stat file %s. Error was %s\n",
929              sid_file, strerror(errno) ));
930     close(fd);
931     return False;
932   } 
933   
934   if(st.st_size > 0) {
935     /*
936      * We have a valid SID - read it.
937      */
938     if(!read_sid_from_file( fd, sid_file)) {
939       DEBUG(0,("generate_machine_sid: unable to read file %s. Error was %s\n",
940              sid_file, strerror(errno) ));
941       close(fd);
942       return False;
943     }
944     close(fd);
945     return True;
946   } 
947   
948   /*
949    * The file contains no data - we may need to generate our
950    * own sid. Try the lp_domain_sid() first.
951    */
952     
953   if(*lp_domain_sid())
954     fstrcpy( sid_string, lp_domain_sid());
955   else {
956     /*
957      * Generate the new sid data & turn it into a string.
958      */
959     int i;
960     generate_random_buffer( raw_sid_data, 12, True);
961     
962     fstrcpy( sid_string, "S-1-5-21");
963     for( i = 0; i < 3; i++) {
964       fstring tmp_string;
965       slprintf( tmp_string, sizeof(tmp_string) - 1, "-%u", IVAL(raw_sid_data, i*4));
966       fstrcat( sid_string, tmp_string);
967     }
968   } 
969   
970   fstrcat(sid_string, "\n");
971     
972   /*
973    * Ensure our new SID is valid.
974    */
975     
976   if(!string_to_sid( &global_machine_sid, sid_string)) {
977     DEBUG(0,("generate_machine_sid: unable to generate machine SID.\n"));
978     return False;
979   } 
980   
981   /*
982    * Do an exclusive blocking lock on the file.
983    */
984     
985   if(!do_file_lock( fd, 60, F_WRLCK)) {
986     DEBUG(0,("generate_machine_sid: unable to lock file %s. Error was %s\n",
987              sid_file, strerror(errno) ));
988     close(fd);
989     return False;
990   } 
991   
992   /*
993    * At this point we have a blocking lock on the SID
994    * file - check if in the meantime someone else wrote
995    * SID data into the file. If so - they were here first,
996    * use their data.
997    */
998     
999   if(fstat( fd, &st) < 0) {
1000     DEBUG(0,("generate_machine_sid: unable to stat file %s. Error was %s\n",
1001              sid_file, strerror(errno) ));
1002     close(fd);
1003     return False;
1004   } 
1005   
1006   if(st.st_size > 0) {
1007     /*
1008      * Unlock as soon as possible to reduce
1009      * contention on the exclusive lock.
1010      */ 
1011     do_file_lock( fd, 60, F_UNLCK);
1012     
1013     /*
1014      * We have a valid SID - read it.
1015      */
1016     
1017     if(!read_sid_from_file( fd, sid_file)) {
1018       DEBUG(0,("generate_machine_sid: unable to read file %s. Error was %s\n",
1019              sid_file, strerror(errno) ));
1020       close(fd);
1021       return False;
1022     }
1023     close(fd);
1024     return True;
1025   } 
1026     
1027   /*
1028    * The file is still empty and we have an exlusive lock on it.
1029    * Write out out SID data into the file.
1030    */
1031     
1032   if(fchmod(fd, 0644) < 0) {
1033     DEBUG(0,("generate_machine_sid: unable to set correct permissions on file %s. \
1034 Error was %s\n", sid_file, strerror(errno) ));
1035     close(fd);
1036     return False;
1037   } 
1038   
1039   if(write( fd, sid_string, strlen(sid_string)) != strlen(sid_string)) {
1040     DEBUG(0,("generate_machine_sid: unable to write file %s. Error was %s\n",
1041           sid_file, strerror(errno) ));
1042     close(fd);
1043     return False;
1044   } 
1045   
1046   /*
1047    * Unlock & exit.
1048    */
1049     
1050   do_file_lock( fd, 60, F_UNLCK);
1051   close(fd);
1052   return True;
1053 }   
1054
1055 /*******************************************************************
1056  converts NT User RID to a UNIX uid.
1057  ********************************************************************/
1058
1059 uid_t pdb_user_rid_to_uid(uint32 u_rid)
1060 {
1061         return (uid_t)(u_rid - 1000);
1062 }
1063
1064 /*******************************************************************
1065  converts NT Group RID to a UNIX uid.
1066  ********************************************************************/
1067
1068 gid_t pdb_group_rid_to_gid(uint32 g_rid)
1069 {
1070         return (gid_t)(g_rid - 1000);
1071 }
1072
1073 /*******************************************************************
1074  converts UNIX uid to an NT User RID.
1075  ********************************************************************/
1076
1077 uint32 pdb_uid_to_user_rid(uid_t uid)
1078 {
1079         return (uint32)(uid + 1000);
1080 }
1081
1082 /*******************************************************************
1083  converts NT Group RID to a UNIX uid.
1084  ********************************************************************/
1085
1086 uint32 pdb_gid_to_group_rid(gid_t gid)
1087 {
1088         return (uint32)(gid + 1000);
1089 }
1090
1091 /*******************************************************************
1092  Decides if a RID is a user or group RID.
1093  ********************************************************************/
1094   
1095 BOOL pdb_rid_is_user(uint32 rid)
1096 {
1097   /* Punt for now - we need to look at the encoding here. JRA. */
1098   /* lkcl i understand that NT attaches an enumeration to a RID
1099    * such that it can be identified as either a user, group etc
1100    * type.  there are 5 such categories, and they are documented.
1101    */
1102   return True;
1103 }