12c6e1ca4ede73c7505ec59482e571c5fd538d5b
[tprouty/samba.git] / source / 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
25 extern int DEBUGLEVEL;
26
27 /*
28  * This is set on startup - it defines the SID for this
29  * machine, and therefore the SAM database for which it is
30  * responsible.
31  */
32
33 extern DOM_SID global_sam_sid;
34 extern pstring global_myname;
35 extern fstring global_myworkgroup;
36
37 /*
38  * NOTE. All these functions are abstracted into a structure
39  * that points to the correct function for the selected database. JRA.
40  *
41  * NOTE.  for the get/mod/add functions, there are two sets of functions.
42  * one supports struct sam_passwd, the other supports struct smb_passwd.
43  * for speed optimisation it is best to support both these sets.
44  * 
45  * it is, however, optional to support one set but not the other: there
46  * is conversion-capability built in to passdb.c, and run-time error
47  * detection for when neither are supported.
48  * 
49  * password database writers are recommended to implement the sam_passwd
50  * functions in a first pass, as struct sam_passwd contains more
51  * information, needed by the NT Domain support.
52  * 
53  * a full example set of derivative functions are listed below.  an API
54  * writer is expected to cut/paste these into their module, replace
55  * either one set (struct smb_passwd) or the other (struct sam_passwd)
56  * OR both, and optionally also to write display info routines
57  * (struct sam_disp_info).  lkcl
58  *
59  */
60
61 static struct passdb_ops *pdb_ops;
62
63 /***************************************************************
64  Initialize the password db operations.
65 ***************************************************************/
66
67 BOOL initialize_password_db(void)
68 {
69   if (pdb_ops)
70   {
71     return True;
72   }
73
74 #ifdef WITH_NISPLUS
75   pdb_ops =  nisplus_initialize_password_db();
76 #elif defined(WITH_LDAP)
77   pdb_ops = ldap_initialize_password_db();
78 #else 
79   pdb_ops = file_initialize_password_db();
80 #endif 
81
82   return (pdb_ops != NULL);
83 }
84
85 /*
86  * Functions that return/manipulate a struct smb_passwd.
87  */
88
89 /************************************************************************
90  Utility function to search smb passwd by rid.  
91 *************************************************************************/
92
93 struct smb_passwd *iterate_getsmbpwrid(uint32 user_rid)
94 {
95         return iterate_getsmbpwuid(pdb_user_rid_to_uid(user_rid));
96 }
97
98 /************************************************************************
99  Utility function to search smb passwd by uid.  use this if your database
100  does not have search facilities.
101 *************************************************************************/
102
103 struct smb_passwd *iterate_getsmbpwuid(uid_t smb_userid)
104 {
105         struct smb_passwd *pwd = NULL;
106         void *fp = NULL;
107
108         DEBUG(10, ("search by smb_userid: %x\n", (int)smb_userid));
109
110         /* Open the smb password database - not for update. */
111         fp = startsmbpwent(False);
112
113         if (fp == NULL)
114         {
115                 DEBUG(0, ("unable to open smb password database.\n"));
116                 return NULL;
117         }
118
119         while ((pwd = getsmbpwent(fp)) != NULL && pwd->smb_userid != smb_userid)
120       ;
121
122         if (pwd != NULL)
123         {
124                 DEBUG(10, ("found by smb_userid: %x\n", (int)smb_userid));
125         }
126
127         endsmbpwent(fp);
128         return pwd;
129 }
130
131 /************************************************************************
132  Utility function to search smb passwd by name.  use this if your database
133  does not have search facilities.
134 *************************************************************************/
135
136 struct smb_passwd *iterate_getsmbpwnam(char *name)
137 {
138         struct smb_passwd *pwd = NULL;
139         void *fp = NULL;
140
141         DEBUG(10, ("search by name: %s\n", name));
142
143         /* Open the sam password file - not for update. */
144         fp = startsmbpwent(False);
145
146         if (fp == NULL)
147         {
148                 DEBUG(0, ("unable to open smb password database.\n"));
149                 return NULL;
150         }
151
152         while ((pwd = getsmbpwent(fp)) != NULL && !strequal(pwd->smb_name, name))
153       ;
154
155         if (pwd != NULL)
156         {
157                 DEBUG(10, ("found by name: %s\n", name));
158         }
159
160         endsmbpwent(fp);
161         return pwd;
162 }
163
164 /***************************************************************
165  Start to enumerate the smb or sam passwd list. Returns a void pointer
166  to ensure no modification outside this module.
167
168  Note that currently it is being assumed that a pointer returned
169  from this function may be used to enumerate struct sam_passwd
170  entries as well as struct smb_passwd entries. This may need
171  to change. JRA.
172
173 ****************************************************************/
174
175 void *startsmbpwent(BOOL update)
176 {
177   return pdb_ops->startsmbpwent(update);
178 }
179
180 /***************************************************************
181  End enumeration of the smb or sam passwd list.
182
183  Note that currently it is being assumed that a pointer returned
184  from this function may be used to enumerate struct sam_passwd
185  entries as well as struct smb_passwd entries. This may need
186  to change. JRA.
187
188 ****************************************************************/
189
190 void endsmbpwent(void *vp)
191 {
192   pdb_ops->endsmbpwent(vp);
193 }
194
195 /*************************************************************************
196  Routine to return the next entry in the smb passwd list.
197  *************************************************************************/
198
199 struct smb_passwd *getsmbpwent(void *vp)
200 {
201         return pdb_ops->getsmbpwent(vp);
202 }
203
204 /************************************************************************
205  Routine to add an entry to the smb passwd file.
206 *************************************************************************/
207
208 BOOL add_smbpwd_entry(struct smb_passwd *newpwd)
209 {
210         return pdb_ops->add_smbpwd_entry(newpwd);
211 }
212
213 /************************************************************************
214  Routine to search the smb passwd file for an entry matching the username.
215  and then modify its password entry. We can't use the startsampwent()/
216  getsampwent()/endsampwent() interfaces here as we depend on looking
217  in the actual file to decide how much room we have to write data.
218  override = False, normal
219  override = True, override XXXXXXXX'd out password or NO PASS
220 ************************************************************************/
221
222 BOOL mod_smbpwd_entry(struct smb_passwd* pwd, BOOL override)
223 {
224         return pdb_ops->mod_smbpwd_entry(pwd, override);
225 }
226
227 /************************************************************************
228  Routine to delete an entry from the smb passwd file.
229 *************************************************************************/
230
231 BOOL del_smbpwd_entry(const char *name)
232 {
233         return pdb_ops->del_smbpwd_entry(name);
234 }
235
236 /************************************************************************
237  Routine to search smb passwd by name.
238 *************************************************************************/
239
240 struct smb_passwd *getsmbpwnam(char *name)
241 {
242         return pdb_ops->getsmbpwnam(name);
243 }
244
245 /************************************************************************
246  Routine to search smb passwd by user rid.
247 *************************************************************************/
248
249 struct smb_passwd *getsmbpwrid(uint32 user_rid)
250 {
251         return pdb_ops->getsmbpwrid(user_rid);
252 }
253
254 /************************************************************************
255  Routine to search smb passwd by uid.
256 *************************************************************************/
257
258 struct smb_passwd *getsmbpwuid(uid_t smb_userid)
259 {
260         return pdb_ops->getsmbpwuid(smb_userid);
261 }
262
263 /*
264  * Functions that manupulate a struct sam_passwd.
265  */
266
267 /************************************************************************
268  Utility function to search sam passwd by name.  use this if your database
269  does not have search facilities.
270 *************************************************************************/
271
272 struct sam_passwd *iterate_getsam21pwnam(char *name)
273 {
274         struct sam_passwd *pwd = NULL;
275         void *fp = NULL;
276
277         DEBUG(10, ("search by name: %s\n", name));
278
279         /* Open the smb password database - not for update. */
280         fp = startsmbpwent(False);
281
282         if (fp == NULL)
283         {
284                 DEBUG(0, ("unable to open sam password database.\n"));
285                 return NULL;
286         }
287
288         while ((pwd = getsam21pwent(fp)) != NULL && !strequal(pwd->smb_name, name))
289         {
290                 DEBUG(10, ("iterate: %s 0x%x\n", pwd->smb_name, pwd->user_rid));
291         }
292
293         if (pwd != NULL)
294         {
295                 DEBUG(10, ("found by name: %s\n", name));
296         }
297
298         endsmbpwent(fp);
299         return pwd;
300 }
301
302 /************************************************************************
303  Utility function to search sam passwd by rid.  use this if your database
304  does not have search facilities.
305
306  search capability by both rid and uid are needed as the rid <-> uid
307  mapping may be non-monotonic.  
308
309 *************************************************************************/
310
311 struct sam_passwd *iterate_getsam21pwrid(uint32 rid)
312 {
313         struct sam_passwd *pwd = NULL;
314         void *fp = NULL;
315
316         DEBUG(10, ("search by rid: %x\n", rid));
317
318         /* Open the smb password file - not for update. */
319         fp = startsmbpwent(False);
320
321         if (fp == NULL)
322         {
323                 DEBUG(0, ("unable to open sam password database.\n"));
324                 return NULL;
325         }
326
327         while ((pwd = getsam21pwent(fp)) != NULL && pwd->user_rid != rid)
328         {
329                 DEBUG(10, ("iterate: %s 0x%x\n", pwd->smb_name, pwd->user_rid));
330         }
331
332         if (pwd != NULL)
333         {
334                 DEBUG(10, ("found by user_rid: %x\n", rid));
335         }
336
337         endsmbpwent(fp);
338         return pwd;
339 }
340
341 /************************************************************************
342  Utility function to search sam passwd by uid.  use this if your database
343  does not have search facilities.
344
345  search capability by both rid and uid are needed as the rid <-> uid
346  mapping may be non-monotonic.  
347
348 *************************************************************************/
349
350 struct sam_passwd *iterate_getsam21pwuid(uid_t uid)
351 {
352         struct sam_passwd *pwd = NULL;
353         void *fp = NULL;
354
355         DEBUG(10, ("search by uid: %x\n", (int)uid));
356
357         /* Open the smb password file - not for update. */
358         fp = startsmbpwent(False);
359
360         if (fp == NULL)
361         {
362                 DEBUG(0, ("unable to open sam password database.\n"));
363                 return NULL;
364         }
365
366         while ((pwd = getsam21pwent(fp)) != NULL && pwd->smb_userid != uid)
367       ;
368
369         if (pwd != NULL)
370         {
371                 DEBUG(10, ("found by smb_userid: %x\n", (int)uid));
372         }
373
374         endsmbpwent(fp);
375         return pwd;
376 }
377
378 /*************************************************************************
379  Routine to return a display info structure, by rid
380  *************************************************************************/
381 struct sam_disp_info *getsamdisprid(uint32 rid)
382 {
383         return pdb_ops->getsamdisprid(rid);
384 }
385
386 /*************************************************************************
387  Routine to return the next entry in the sam passwd list.
388  *************************************************************************/
389
390 struct sam_passwd *getsam21pwent(void *vp)
391 {
392         return pdb_ops->getsam21pwent(vp);
393 }
394
395
396 /************************************************************************
397  Routine to search sam passwd by name.
398 *************************************************************************/
399
400 struct sam_passwd *getsam21pwnam(char *name)
401 {
402         return pdb_ops->getsam21pwnam(name);
403 }
404
405 /************************************************************************
406  Routine to search sam passwd by rid.  
407 *************************************************************************/
408
409 struct sam_passwd *getsam21pwrid(uint32 rid)
410 {
411         return pdb_ops->getsam21pwrid(rid);
412 }
413
414
415 /**********************************************************
416  **********************************************************
417
418  utility routines which are likely to be useful to all password
419  databases
420
421  **********************************************************
422  **********************************************************/
423
424 /*************************************************************
425  initialises a struct sam_disp_info.
426  **************************************************************/
427
428 static void pdb_init_dispinfo(struct sam_disp_info *user)
429 {
430         if (user == NULL) return;
431         memset((char *)user, '\0', sizeof(*user));
432 }
433
434 /*************************************************************
435  initialises a struct smb_passwd.
436  **************************************************************/
437
438 void pdb_init_smb(struct smb_passwd *user)
439 {
440         if (user == NULL) return;
441         memset((char *)user, '\0', sizeof(*user));
442         user->pass_last_set_time    = (time_t)-1;
443 }
444
445 /*************************************************************
446  initialises a struct sam_passwd.
447  **************************************************************/
448 void pdb_init_sam(struct sam_passwd *user)
449 {
450         if (user == NULL) return;
451         memset((char *)user, '\0', sizeof(*user));
452         user->logon_time            = (time_t)-1;
453         user->logoff_time           = (time_t)-1;
454         user->kickoff_time          = (time_t)-1;
455         user->pass_last_set_time    = (time_t)-1;
456         user->pass_can_change_time  = (time_t)-1;
457         user->pass_must_change_time = (time_t)-1;
458 }
459
460 /*************************************************************************
461  Routine to return the next entry in the sam passwd list.
462  *************************************************************************/
463
464 struct sam_disp_info *pdb_sam_to_dispinfo(struct sam_passwd *user)
465 {
466         static struct sam_disp_info disp_info;
467
468         if (user == NULL) return NULL;
469
470         pdb_init_dispinfo(&disp_info);
471
472         disp_info.smb_name  = user->smb_name;
473         disp_info.full_name = user->full_name;
474         disp_info.user_rid  = user->user_rid;
475
476         return &disp_info;
477 }
478
479 /*************************************************************
480  converts a sam_passwd structure to a smb_passwd structure.
481  **************************************************************/
482
483 struct smb_passwd *pdb_sam_to_smb(struct sam_passwd *user)
484 {
485         static struct smb_passwd pw_buf;
486
487         if (user == NULL) return NULL;
488
489         pdb_init_smb(&pw_buf);
490
491         pw_buf.smb_userid         = user->smb_userid;
492         pw_buf.smb_name           = user->smb_name;
493         pw_buf.smb_passwd         = user->smb_passwd;
494         pw_buf.smb_nt_passwd      = user->smb_nt_passwd;
495         pw_buf.acct_ctrl          = user->acct_ctrl;
496         pw_buf.pass_last_set_time = user->pass_last_set_time;
497
498         return &pw_buf;
499 }
500
501
502 /*************************************************************
503  converts a smb_passwd structure to a sam_passwd structure.
504  **************************************************************/
505
506 struct sam_passwd *pdb_smb_to_sam(struct smb_passwd *user)
507 {
508         static struct sam_passwd pw_buf;
509
510         if (user == NULL) return NULL;
511
512         pdb_init_sam(&pw_buf);
513
514         pw_buf.smb_userid         = user->smb_userid;
515         pw_buf.smb_name           = user->smb_name;
516         pw_buf.smb_passwd         = user->smb_passwd;
517         pw_buf.smb_nt_passwd      = user->smb_nt_passwd;
518         pw_buf.acct_ctrl          = user->acct_ctrl;
519         pw_buf.pass_last_set_time = user->pass_last_set_time;
520
521         return &pw_buf;
522 }
523
524 /**********************************************************
525  Encode the account control bits into a string.
526  length = length of string to encode into (including terminating
527  null). length *MUST BE MORE THAN 2* !
528  **********************************************************/
529
530 char *pdb_encode_acct_ctrl(uint16 acct_ctrl, size_t length)
531 {
532   static fstring acct_str;
533   size_t i = 0;
534
535   acct_str[i++] = '[';
536
537   if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
538   if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
539   if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
540   if (acct_ctrl & ACB_TEMPDUP  ) acct_str[i++] = 'T'; 
541   if (acct_ctrl & ACB_NORMAL   ) acct_str[i++] = 'U';
542   if (acct_ctrl & ACB_MNS      ) acct_str[i++] = 'M';
543   if (acct_ctrl & ACB_WSTRUST  ) acct_str[i++] = 'W';
544   if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
545   if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
546   if (acct_ctrl & ACB_PWNOEXP  ) acct_str[i++] = 'X';
547   if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
548
549   for ( ; i < length - 2 ; i++ ) { acct_str[i] = ' '; }
550
551   i = length - 2;
552   acct_str[i++] = ']';
553   acct_str[i++] = '\0';
554
555   return acct_str;
556 }     
557
558 /**********************************************************
559  Decode the account control bits from a string.
560
561  this function breaks coding standards minimum line width of 80 chars.
562  reason: vertical line-up code clarity - all case statements fit into
563  15 lines, which is more important.
564  **********************************************************/
565
566 uint16 pdb_decode_acct_ctrl(const char *p)
567 {
568         uint16 acct_ctrl = 0;
569         BOOL finished = False;
570
571         /*
572          * Check if the account type bits have been encoded after the
573          * NT password (in the form [NDHTUWSLXI]).
574          */
575
576         if (*p != '[') return 0;
577
578         for (p++; *p && !finished; p++)
579         {
580                 switch (*p)
581                 {
582                         case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
583                         case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
584                         case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
585                         case 'T': { acct_ctrl |= ACB_TEMPDUP  ; break; /* 'T'emp account. */ } 
586                         case 'U': { acct_ctrl |= ACB_NORMAL   ; break; /* 'U'ser account (normal). */ } 
587                         case 'M': { acct_ctrl |= ACB_MNS      ; break; /* 'M'NS logon user account. What is this ? */ } 
588                         case 'W': { acct_ctrl |= ACB_WSTRUST  ; break; /* 'W'orkstation account. */ } 
589                         case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ } 
590                         case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ } 
591                         case 'X': { acct_ctrl |= ACB_PWNOEXP  ; break; /* No 'X'piry on password */ } 
592                         case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
593             case ' ': { break; }
594                         case ':':
595                         case '\n':
596                         case '\0': 
597                         case ']':
598                         default:  { finished = True; }
599                 }
600         }
601
602         return acct_ctrl;
603 }
604
605 /*******************************************************************
606  gets password-database-format time from a string.
607  ********************************************************************/
608
609 static time_t get_time_from_string(const char *p)
610 {
611         int i;
612
613         for (i = 0; i < 8; i++)
614         {
615                 if (p[i] == '\0' || !isxdigit((int)(p[i]&0xFF)))
616                 break;
617         }
618         if (i == 8)
619         {
620                 /*
621                  * p points at 8 characters of hex digits - 
622                  * read into a time_t as the seconds since
623                  * 1970 that the password was last changed.
624                  */
625                 return (time_t)strtol(p, NULL, 16);
626         }
627         return (time_t)-1;
628 }
629
630 /*******************************************************************
631  gets password last set time
632  ********************************************************************/
633
634 time_t pdb_get_last_set_time(const char *p)
635 {
636         if (*p && StrnCaseCmp(p, "LCT-", 4))
637         {
638                 return get_time_from_string(p + 4);
639         }
640         return (time_t)-1;
641 }
642
643
644 /*******************************************************************
645  sets password-database-format time in a string.
646  ********************************************************************/
647 static void set_time_in_string(char *p, int max_len, char *type, time_t t)
648 {
649         slprintf(p, max_len, ":%s-%08X:", type, (uint32)t);
650 }
651
652 /*******************************************************************
653  sets logon time
654  ********************************************************************/
655 void pdb_set_logon_time(char *p, int max_len, time_t t)
656 {
657         set_time_in_string(p, max_len, "LNT", t);
658 }
659
660 /*******************************************************************
661  sets logoff time
662  ********************************************************************/
663 void pdb_set_logoff_time(char *p, int max_len, time_t t)
664 {
665         set_time_in_string(p, max_len, "LOT", t);
666 }
667
668 /*******************************************************************
669  sets kickoff time
670  ********************************************************************/
671 void pdb_set_kickoff_time(char *p, int max_len, time_t t)
672 {
673         set_time_in_string(p, max_len, "KOT", t);
674 }
675
676 /*******************************************************************
677  sets password can change time
678  ********************************************************************/
679 void pdb_set_can_change_time(char *p, int max_len, time_t t)
680 {
681         set_time_in_string(p, max_len, "CCT", t);
682 }
683
684 /*******************************************************************
685  sets password last set time
686  ********************************************************************/
687 void pdb_set_must_change_time(char *p, int max_len, time_t t)
688 {
689         set_time_in_string(p, max_len, "MCT", t);
690 }
691
692 /*******************************************************************
693  sets password last set time
694  ********************************************************************/
695 void pdb_set_last_set_time(char *p, int max_len, time_t t)
696 {
697         set_time_in_string(p, max_len, "LCT", t);
698 }
699
700
701 /*************************************************************
702  Routine to set 32 hex password characters from a 16 byte array.
703 **************************************************************/
704 void pdb_sethexpwd(char *p, unsigned char *pwd, uint16 acct_ctrl)
705 {
706         if (pwd != NULL)
707         {
708                 int i;
709                 for (i = 0; i < 16; i++)
710                 {
711                         slprintf(&p[i*2], 3, "%02X", pwd[i]);
712                 }
713         }
714         else
715         {
716                 if (IS_BITS_SET_ALL(acct_ctrl, ACB_PWNOTREQ))
717                 {
718                         safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
719                 }
720                 else
721                 {
722                         safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
723                 }
724         }
725 }
726 /*************************************************************
727  Routine to get the 32 hex characters and turn them
728  into a 16 byte array.
729 **************************************************************/
730 BOOL pdb_gethexpwd(char *p, unsigned char *pwd)
731 {
732         int i;
733         unsigned char   lonybble, hinybble;
734         char           *hexchars = "0123456789ABCDEF";
735         char           *p1, *p2;
736
737         for (i = 0; i < 32; i += 2)
738         {
739                 hinybble = toupper(p[i]);
740                 lonybble = toupper(p[i + 1]);
741
742                 p1 = strchr(hexchars, hinybble);
743                 p2 = strchr(hexchars, lonybble);
744
745                 if (!p1 || !p2)
746                 {
747                         return (False);
748                 }
749
750                 hinybble = PTR_DIFF(p1, hexchars);
751                 lonybble = PTR_DIFF(p2, hexchars);
752
753                 pwd[i / 2] = (hinybble << 4) | lonybble;
754         }
755         return (True);
756 }
757
758 /*******************************************************************
759  Group and User RID username mapping function
760  ********************************************************************/
761
762 BOOL pdb_name_to_rid(char *user_name, uint32 *u_rid, uint32 *g_rid)
763 {
764     struct passwd *pw = Get_Pwnam(user_name, False);
765
766         if (u_rid == NULL || g_rid == NULL || user_name == NULL)
767         {
768                 return False;
769         }
770
771         if (!pw)
772         {
773                 DEBUG(1,("Username %s is invalid on this system\n", user_name));
774                 return False;
775         }
776
777         if (user_in_list(user_name, lp_domain_guest_users()))
778         {
779                 *u_rid = DOMAIN_USER_RID_GUEST;
780         }
781         else if (user_in_list(user_name, lp_domain_admin_users()))
782         {
783                 *u_rid = DOMAIN_USER_RID_ADMIN;
784         }
785         else
786         {
787                 /* turn the unix UID into a Domain RID.  this is what the posix
788                    sub-system does (adds 1000 to the uid) */
789                 *u_rid = pdb_uid_to_user_rid(pw->pw_uid);
790         }
791
792         /* absolutely no idea what to do about the unix GID to Domain RID mapping */
793         *g_rid = pdb_gid_to_group_rid(pw->pw_gid);
794
795         return True;
796 }
797
798 /****************************************************************************
799  Read the machine SID from a file.
800 ****************************************************************************/
801
802 static BOOL read_sid_from_file(int fd, char *sid_file)
803 {
804   fstring fline;
805
806   memset(fline, '\0', sizeof(fline));
807
808   if(read(fd, fline, sizeof(fline) -1 ) < 0) {
809     DEBUG(0,("unable to read file %s. Error was %s\n",
810            sid_file, strerror(errno) ));
811     return False;
812   }
813
814   /*
815    * Convert to the machine SID.
816    */
817
818   fline[sizeof(fline)-1] = '\0';
819   if(!string_to_sid( &global_sam_sid, fline)) {
820     DEBUG(0,("unable to generate machine SID.\n"));
821     return False;
822   }
823
824   return True;
825 }
826
827 /****************************************************************************
828  Generate the global machine sid. Look for the MACHINE.SID file first, if
829  not found then look in smb.conf and use it to create the MACHINE.SID file.
830  Note this function will be replaced soon. JRA.
831 ****************************************************************************/
832
833 BOOL pdb_generate_sam_sid(void)
834 {
835         int fd;
836         char *p;
837         pstring sid_file;
838         fstring sid_string;
839         SMB_STRUCT_STAT st;
840         BOOL overwrite_bad_sid = False;
841
842         generate_wellknown_sids();
843
844         pstrcpy(sid_file, lp_smb_passwd_file());
845         p = strrchr(sid_file, '/');
846         if(p != NULL) {
847                 *++p = '\0';
848         }
849
850         if (!directory_exist(sid_file, NULL)) {
851                 if (mkdir(sid_file, 0700) != 0) {
852                         DEBUG(0,("can't create private directory %s : %s\n",
853                                  sid_file, strerror(errno)));
854                         return False;
855                 }
856         }
857
858         pstrcat(sid_file, "MACHINE.SID");
859     
860         if((fd = sys_open(sid_file, O_RDWR | O_CREAT, 0644)) == -1) {
861                 DEBUG(0,("unable to open or create file %s. Error was %s\n",
862                          sid_file, strerror(errno) ));
863                 return False;
864         } 
865   
866         /*
867          * Check if the file contains data.
868          */
869         
870         if(sys_fstat( fd, &st) < 0) {
871                 DEBUG(0,("unable to stat file %s. Error was %s\n",
872                          sid_file, strerror(errno) ));
873                 close(fd);
874                 return False;
875         } 
876   
877         if(st.st_size > 0) {
878                 /*
879                  * We have a valid SID - read it.
880                  */
881                 if(!read_sid_from_file( fd, sid_file)) {
882                         DEBUG(0,("unable to read file %s. Error was %s\n",
883                                  sid_file, strerror(errno) ));
884                         close(fd);
885                         return False;
886                 }
887
888                 /*
889                  * JRA. Reversed the sense of this test now that I have
890                  * actually done this test *personally*. One more reason
891                  * to never trust third party information you have not
892                  * independently verified.... sigh. JRA.
893                  */
894
895                 if(global_sam_sid.num_auths > 0 && global_sam_sid.sub_auths[0] == 0x21) {
896                         /*
897                          * Fix and re-write...
898                          */
899                         overwrite_bad_sid = True;
900                         global_sam_sid.sub_auths[0] = 21;
901                         DEBUG(5,("pdb_generate_sam_sid: Old (incorrect) sid id_auth of hex 21 \
902 detected - re-writing to be decimal 21 instead.\n" ));
903                         sid_to_string(sid_string, &global_sam_sid);
904                         if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) {
905                                 DEBUG(0,("unable to seek file file %s. Error was %s\n",
906                                          sid_file, strerror(errno) ));
907                                 close(fd);
908                                 return False;
909                         }
910                 } else {
911                         close(fd);
912                         return True;
913                 }
914         } else {
915                 /*
916                  * The file contains no data - we need to generate our
917                  * own sid.
918                  * Generate the new sid data & turn it into a string.
919                  */
920                 int i;
921                 uchar raw_sid_data[12];
922                 DOM_SID mysid;
923
924                 memset((char *)&mysid, '\0', sizeof(DOM_SID));
925                 mysid.sid_rev_num = 1;
926                 mysid.id_auth[5] = 5;
927                 mysid.num_auths = 0;
928                 mysid.sub_auths[mysid.num_auths++] = 21;
929
930                 generate_random_buffer( raw_sid_data, 12, True);
931                 for( i = 0; i < 3; i++)
932                         mysid.sub_auths[mysid.num_auths++] = IVAL(raw_sid_data, i*4);
933
934                 sid_to_string(sid_string, &mysid);
935         } 
936         
937         fstrcat(sid_string, "\n");
938         
939         /*
940          * Ensure our new SID is valid.
941          */
942         
943         if(!string_to_sid( &global_sam_sid, sid_string)) {
944                 DEBUG(0,("unable to generate machine SID.\n"));
945                 return False;
946         } 
947   
948         /*
949          * Do an exclusive blocking lock on the file.
950          */
951         
952         if(!do_file_lock( fd, 60, F_WRLCK)) {
953                 DEBUG(0,("unable to lock file %s. Error was %s\n",
954                          sid_file, strerror(errno) ));
955                 close(fd);
956                 return False;
957         } 
958  
959         if(!overwrite_bad_sid) {
960                 /*
961                  * At this point we have a blocking lock on the SID
962                  * file - check if in the meantime someone else wrote
963                  * SID data into the file. If so - they were here first,
964                  * use their data.
965                  */
966         
967                 if(sys_fstat( fd, &st) < 0) {
968                         DEBUG(0,("unable to stat file %s. Error was %s\n",
969                                  sid_file, strerror(errno) ));
970                         close(fd);
971                         return False;
972                 } 
973   
974                 if(st.st_size > 0) {
975                         /*
976                          * Unlock as soon as possible to reduce
977                          * contention on the exclusive lock.
978                          */ 
979                         do_file_lock( fd, 60, F_UNLCK);
980                 
981                         /*
982                          * We have a valid SID - read it.
983                          */
984                 
985                         if(!read_sid_from_file( fd, sid_file)) {
986                                 DEBUG(0,("unable to read file %s. Error was %s\n",
987                                          sid_file, strerror(errno) ));
988                                 close(fd);
989                                 return False;
990                         }
991                         close(fd);
992                         return True;
993                 } 
994         }
995         
996         /*
997          * The file is still empty and we have an exlusive lock on it,
998          * or we're fixing an earlier mistake.
999          * Write out out SID data into the file.
1000          */
1001
1002         /*
1003          * Use chmod here as some (strange) UNIX's don't
1004          * have fchmod. JRA.
1005          */     
1006
1007         if(chmod(sid_file, 0644) < 0) {
1008                 DEBUG(0,("unable to set correct permissions on file %s. \
1009 Error was %s\n", sid_file, strerror(errno) ));
1010                 do_file_lock( fd, 60, F_UNLCK);
1011                 close(fd);
1012                 return False;
1013         } 
1014         
1015         if(write( fd, sid_string, strlen(sid_string)) != strlen(sid_string)) {
1016                 DEBUG(0,("unable to write file %s. Error was %s\n",
1017                          sid_file, strerror(errno) ));
1018                 do_file_lock( fd, 60, F_UNLCK);
1019                 close(fd);
1020                 return False;
1021         } 
1022         
1023         /*
1024          * Unlock & exit.
1025          */
1026         
1027         do_file_lock( fd, 60, F_UNLCK);
1028         close(fd);
1029         return True;
1030 }   
1031 /*******************************************************************
1032  Converts NT user RID to a UNIX uid.
1033  ********************************************************************/
1034
1035 uid_t pdb_user_rid_to_uid(uint32 user_rid)
1036 {
1037         return (uid_t)(((user_rid & (~USER_RID_TYPE))- 1000)/RID_MULTIPLIER);
1038 }
1039
1040 /*******************************************************************
1041  Converts NT user RID to a UNIX gid.
1042  ********************************************************************/
1043
1044 gid_t pdb_user_rid_to_gid(uint32 user_rid)
1045 {
1046         return (uid_t)(((user_rid & (~GROUP_RID_TYPE))- 1000)/RID_MULTIPLIER);
1047 }
1048
1049 /*******************************************************************
1050  converts UNIX uid to an NT User RID.
1051  ********************************************************************/
1052
1053 uint32 pdb_uid_to_user_rid(uid_t uid)
1054 {
1055         return (((((uint32)uid)*RID_MULTIPLIER) + 1000) | USER_RID_TYPE);
1056 }
1057
1058 /*******************************************************************
1059  converts NT Group RID to a UNIX uid.
1060  ********************************************************************/
1061
1062 uint32 pdb_gid_to_group_rid(gid_t gid)
1063 {
1064   return (((((uint32)gid)*RID_MULTIPLIER) + 1000) | GROUP_RID_TYPE);
1065 }
1066
1067 /*******************************************************************
1068  Decides if a RID is a well known RID.
1069  ********************************************************************/
1070
1071 static BOOL pdb_rid_is_well_known(uint32 rid)
1072 {
1073   return (rid < 1000);
1074 }
1075
1076 /*******************************************************************
1077  Decides if a RID is a user or group RID.
1078  ********************************************************************/
1079   
1080 BOOL pdb_rid_is_user(uint32 rid)
1081 {
1082   /* lkcl i understand that NT attaches an enumeration to a RID
1083    * such that it can be identified as either a user, group etc
1084    * type.  there are 5 such categories, and they are documented.
1085    */
1086    if(pdb_rid_is_well_known(rid)) {
1087       /*
1088        * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
1089        * and DOMAIN_USER_RID_GUEST.
1090        */
1091      if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
1092        return True;
1093    } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
1094      return True;
1095    }
1096    return False;
1097 }
1098
1099 /*******************************************************************
1100  Convert a rid into a name. Used in the lookup SID rpc.
1101  ********************************************************************/
1102
1103 BOOL lookup_local_rid(uint32 rid, char *name, uint8 *psid_name_use)
1104 {
1105
1106         BOOL is_user = pdb_rid_is_user(rid);
1107
1108         DEBUG(5,("lookup_local_rid: looking up %s RID %u.\n", is_user ? "user" :
1109                         "group", (unsigned int)rid));
1110
1111         if(is_user) {
1112                 if(rid == DOMAIN_USER_RID_ADMIN) {
1113                         pstring admin_users;
1114                         char *p = admin_users;
1115                         pstrcpy( admin_users, lp_domain_admin_users());
1116                         if(!next_token(&p, name, NULL, sizeof(fstring)))
1117                                 fstrcpy(name, "Administrator");
1118                 } else if (rid == DOMAIN_USER_RID_GUEST) {
1119                         pstring guest_users;
1120                         char *p = guest_users;
1121                         pstrcpy( guest_users, lp_domain_guest_users());
1122                         if(!next_token(&p, name, NULL, sizeof(fstring)))
1123                                 fstrcpy(name, "Guest");
1124                 } else {
1125                         uid_t uid = pdb_user_rid_to_uid(rid);
1126                         struct passwd *pass = sys_getpwuid(uid);
1127
1128                         *psid_name_use = SID_NAME_USER;
1129
1130                         DEBUG(5,("lookup_local_rid: looking up uid %u %s\n", (unsigned int)uid,
1131                                 pass ? "succeeded" : "failed" ));
1132
1133                         if(!pass) {
1134                                 slprintf(name, sizeof(fstring)-1, "unix_user.%u", (unsigned int)uid);
1135                                 return True;
1136                         }
1137
1138                         fstrcpy(name, pass->pw_name);
1139
1140                         DEBUG(5,("lookup_local_rid: found user %s for rid %u\n", name,
1141                                 (unsigned int)rid ));
1142                 }
1143
1144         } else {
1145                 gid_t gid = pdb_user_rid_to_gid(rid);
1146                 struct group *gr = getgrgid(gid);
1147
1148                 *psid_name_use = SID_NAME_ALIAS;
1149
1150                 DEBUG(5,("lookup_local_rid: looking up gid %u %s\n", (unsigned int)gid,
1151                         gr ? "succeeded" : "failed" ));
1152
1153                 if(!gr) {
1154                         slprintf(name, sizeof(fstring)-1, "unix_group.%u", (unsigned int)gid);
1155                         return True;
1156                 }
1157
1158                 fstrcpy( name, gr->gr_name);
1159
1160                 DEBUG(5,("lookup_local_rid: found group %s for rid %u\n", name,
1161                         (unsigned int)rid ));
1162         }
1163
1164         return True;
1165 }
1166
1167 /*******************************************************************
1168  Convert a name into a SID. Used in the lookup name rpc.
1169  ********************************************************************/
1170
1171 BOOL lookup_local_name(char *domain, char *user, DOM_SID *psid, uint8 *psid_name_use)
1172 {
1173         extern DOM_SID global_sid_World_Domain;
1174         struct passwd *pass = NULL;
1175         DOM_SID local_sid;
1176
1177         sid_copy(&local_sid, &global_sam_sid);
1178
1179         if(!strequal(global_myname, domain) && !strequal(global_myworkgroup, domain))
1180                 return False;
1181
1182         /*
1183          * Special case for MACHINE\Everyone. Map to the world_sid.
1184          */
1185
1186         if(strequal(user, "Everyone")) {
1187                 sid_copy( psid, &global_sid_World_Domain);
1188                 sid_append_rid(psid, 0);
1189                 *psid_name_use = SID_NAME_ALIAS;
1190                 return True;
1191         }
1192
1193         (void)map_username(user);
1194
1195         if(!(pass = Get_Pwnam(user, False))) {
1196                 /*
1197                  * Maybe it was a group ?
1198                  */
1199                 struct group *grp = getgrnam(user);
1200
1201                 if(!grp)
1202                         return False;
1203
1204                 sid_append_rid( &local_sid, pdb_gid_to_group_rid(grp->gr_gid));
1205                 *psid_name_use = SID_NAME_ALIAS;
1206         } else {
1207
1208                 sid_append_rid( &local_sid, pdb_uid_to_user_rid(pass->pw_uid));
1209                 *psid_name_use = SID_NAME_USER;
1210         }
1211
1212         sid_copy( psid, &local_sid);
1213
1214         return True;
1215 }
1216
1217 /****************************************************************************
1218  Create a list of SIDS for a user - primary and group.
1219  This is really the wrong way to do this and needs to go via winbind. JRA.
1220 ****************************************************************************/
1221
1222 BOOL setup_user_sids(user_struct *vuser)
1223 {
1224     extern DOM_SID global_sam_sid;
1225
1226         sid_copy(&vuser->user_sid, &global_sam_sid);
1227         sid_append_rid( &vuser->user_sid, pdb_uid_to_user_rid(vuser->uid));
1228
1229         if (vuser->n_groups != 0) {
1230                 int i;
1231
1232                 vuser->group_sids = (DOM_SID *)malloc(sizeof(DOM_SID) * vuser->n_groups);
1233
1234                 if (vuser->group_sids == NULL)
1235                         return False;
1236
1237                 for (i = 0; i < vuser->n_groups; i++) {
1238                         sid_copy(&vuser->group_sids[i], &global_sam_sid);
1239                         sid_append_rid( &vuser->group_sids[i], pdb_gid_to_group_rid(vuser->groups[i]));
1240                 }
1241         }
1242
1243         return True;
1244 }