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