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