Commit the auth associated changes I missed from the last commit.
[ira/wip.git] / source3 / passdb / passdb.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 3.0
4    Password and authentication handling
5    Copyright (C) Jeremy Allison                 1996-2001
6    Copyright (C) Luke Kenneth Casson Leighton   1996-1998
7    Copyright (C) Gerald (Jerry) Carter          2000-2001
8    Copyright (C) Andrew Bartlett                2001-2002
9       
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
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
35 struct passdb_ops *pdb_ops;
36
37 #if 0   /* JERRY */
38 static void* pdb_handle = NULL;
39 #endif
40
41 /***************************************************************
42  Initialize the password db operations.
43 ***************************************************************/
44
45 BOOL initialize_password_db(BOOL reload)
46 {       
47         /* 
48          * This function is unfinished right now, so just 
49          * ignore the details and always return True.  It 
50          * is here only as a placeholder          --jerry 
51          */
52         return True;
53         
54 }
55
56
57 /************************************************************
58  Fill the SAM_ACCOUNT with default values.
59  ***********************************************************/
60
61 static void pdb_fill_default_sam(SAM_ACCOUNT *user)
62 {
63         ZERO_STRUCT(user->private); /* Don't touch the talloc context */
64
65         /* Don't change these timestamp settings without a good reason.
66            They are important for NT member server compatibility. */
67
68         user->private.init_flag             = FLAG_SAM_UNINIT;
69         user->private.uid = user->private.gid       = -1;
70
71         user->private.logon_time            = (time_t)0;
72         user->private.pass_last_set_time    = (time_t)0;
73         user->private.pass_can_change_time  = (time_t)0;
74         user->private.logoff_time           = 
75         user->private.kickoff_time          = 
76         user->private.pass_must_change_time = get_time_t_max();
77         user->private.unknown_3 = 0x00ffffff;   /* don't know */
78         user->private.logon_divs = 168;         /* hours per week */
79         user->private.hours_len = 21;           /* 21 times 8 bits = 168 */
80         memset(user->private.hours, 0xff, user->private.hours_len); /* available at all hours */
81         user->private.unknown_5 = 0x00000000; /* don't know */
82         user->private.unknown_6 = 0x000004ec; /* don't know */
83
84         /* Some parts of samba strlen their pdb_get...() returns, 
85            so this keeps the interface unchanged for now. */
86            
87         user->private.username = "";
88         user->private.domain = "";
89         user->private.nt_username = "";
90         user->private.full_name = "";
91         user->private.home_dir = "";
92         user->private.logon_script = "";
93         user->private.profile_path = "";
94         user->private.acct_desc = "";
95         user->private.workstations = "";
96         user->private.unknown_str = "";
97         user->private.munged_dial = "";
98 }       
99
100 static void destroy_pdb_talloc(SAM_ACCOUNT **user) 
101 {
102         if (*user) {
103                 talloc_destroy((*user)->mem_ctx);
104                 *user = NULL;
105         }
106 }
107
108
109 /**********************************************************************
110  Alloc memory and initialises a struct sam_passwd on supplied mem_ctx.
111 ***********************************************************************/
112
113 NTSTATUS pdb_init_sam_talloc(TALLOC_CTX *mem_ctx, SAM_ACCOUNT **user)
114 {
115         if (*user != NULL) {
116                 DEBUG(0,("pdb_init_sam: SAM_ACCOUNT was non NULL\n"));
117 #if 0
118                 smb_panic("NULL pointer passed to pdb_init_sam\n");
119 #endif
120                 return NT_STATUS_UNSUCCESSFUL;
121         }
122
123         if (!mem_ctx) {
124                 DEBUG(0,("pdb_init_sam_talloc: mem_ctx was NULL!\n"));
125                 return NT_STATUS_UNSUCCESSFUL;
126         }
127
128         *user=(SAM_ACCOUNT *)talloc(mem_ctx, sizeof(SAM_ACCOUNT));
129
130         if (*user==NULL) {
131                 DEBUG(0,("pdb_init_sam: error while allocating memory\n"));
132                 return NT_STATUS_NO_MEMORY;
133         }
134
135         (*user)->mem_ctx = mem_ctx;
136
137         (*user)->free_fn = NULL;
138
139         pdb_fill_default_sam(*user);
140         
141         return NT_STATUS_OK;
142 }
143
144
145 /*************************************************************
146  Alloc memory and initialises a struct sam_passwd.
147  ************************************************************/
148
149 NTSTATUS pdb_init_sam(SAM_ACCOUNT **user)
150 {
151         TALLOC_CTX *mem_ctx;
152         NTSTATUS nt_status;
153         
154         mem_ctx = talloc_init_named("passdb internal SAM_ACCOUNT allocation");
155
156         if (!mem_ctx) {
157                 DEBUG(0,("pdb_init_sam: error while doing talloc_init()\n"));
158                 return NT_STATUS_NO_MEMORY;
159         }
160
161         if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_talloc(mem_ctx, user))) {
162                 talloc_destroy(mem_ctx);
163                 return nt_status;
164         }
165         
166         (*user)->free_fn = destroy_pdb_talloc;
167
168         return NT_STATUS_OK;
169 }
170
171
172 /*************************************************************
173  Initialises a struct sam_passwd with sane values.
174  ************************************************************/
175
176 NTSTATUS pdb_init_sam_pw(SAM_ACCOUNT **new_sam_acct, const struct passwd *pwd)
177 {
178         pstring str;
179         GROUP_MAP map;
180         uint32 rid;
181         NTSTATUS nt_status;
182
183         if (!pwd) {
184                 new_sam_acct = NULL;
185                 return NT_STATUS_UNSUCCESSFUL;
186         }
187
188         if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(new_sam_acct))) {
189                 new_sam_acct = NULL;
190                 return nt_status;
191         }
192
193         pdb_set_username(*new_sam_acct, pwd->pw_name);
194         pdb_set_fullname(*new_sam_acct, pwd->pw_gecos);
195
196         pdb_set_uid(*new_sam_acct, pwd->pw_uid);
197         pdb_set_gid(*new_sam_acct, pwd->pw_gid);
198         
199         pdb_set_user_rid(*new_sam_acct, pdb_uid_to_user_rid(pwd->pw_uid));
200
201         /* call the mapping code here */
202         if(get_group_map_from_gid(pwd->pw_gid, &map, MAPPING_WITHOUT_PRIV)) {
203                 sid_peek_rid(&map.sid, &rid);
204         } 
205         else {
206                 rid=pdb_gid_to_group_rid(pwd->pw_gid);
207         }
208                 
209         pdb_set_group_rid(*new_sam_acct, rid);
210
211         pstrcpy(str, lp_logon_path());
212         standard_sub_advanced(-1, pwd->pw_name, "", pwd->pw_gid, pwd->pw_name, str);
213         pdb_set_profile_path(*new_sam_acct, str, False);
214         
215         pstrcpy(str, lp_logon_home());
216         standard_sub_advanced(-1, pwd->pw_name, "", pwd->pw_gid, pwd->pw_name, str);
217         pdb_set_homedir(*new_sam_acct, str, False);
218         
219         pstrcpy(str, lp_logon_drive());
220         standard_sub_advanced(-1, pwd->pw_name, "", pwd->pw_gid, pwd->pw_name, str);
221         pdb_set_dir_drive(*new_sam_acct, str, False);
222
223         pstrcpy(str, lp_logon_script());
224         standard_sub_advanced(-1, pwd->pw_name, "", pwd->pw_gid, pwd->pw_name, str);
225         pdb_set_logon_script(*new_sam_acct, str, False);
226         
227         return NT_STATUS_OK;
228 }
229
230
231 /**
232  * Free the contets of the SAM_ACCOUNT, but not the structure.
233  *
234  * Also wipes the LM and NT hashes from memory.
235  *
236  * @param user SAM_ACCOUNT to free members of.
237  **/
238
239 static void pdb_free_sam_contents(SAM_ACCOUNT *user)
240 {
241         /* As we start mallocing more strings this is where  
242            we should free them. */
243
244         data_blob_clear_free(&(user->private.lm_pw));
245         data_blob_clear_free(&(user->private.nt_pw));
246 }
247
248
249 /************************************************************
250  Reset the SAM_ACCOUNT and free the NT/LM hashes.
251  ***********************************************************/
252
253 NTSTATUS pdb_reset_sam(SAM_ACCOUNT *user)
254 {
255         if (user == NULL) {
256                 DEBUG(0,("pdb_reset_sam: SAM_ACCOUNT was NULL\n"));
257 #if 0
258                 smb_panic("NULL pointer passed to pdb_free_sam\n");
259 #endif
260                 return NT_STATUS_UNSUCCESSFUL;
261         }
262         
263         pdb_free_sam_contents(user);
264
265         pdb_fill_default_sam(user);
266
267         return NT_STATUS_OK;
268 }
269
270
271 /************************************************************
272  Free the SAM_ACCOUNT and the member pointers.
273  ***********************************************************/
274
275 NTSTATUS pdb_free_sam(SAM_ACCOUNT **user)
276 {
277         if (*user == NULL) {
278                 DEBUG(0,("pdb_free_sam: SAM_ACCOUNT was NULL\n"));
279 #if 0
280                 smb_panic("NULL pointer passed to pdb_free_sam\n");
281 #endif
282                 return NT_STATUS_UNSUCCESSFUL;
283         }
284
285         pdb_free_sam_contents(*user);
286         
287         if ((*user)->free_fn) {
288                 (*user)->free_fn(user);
289         }
290
291         return NT_STATUS_OK;    
292 }
293
294
295 /**********************************************************
296  Encode the account control bits into a string.
297  length = length of string to encode into (including terminating
298  null). length *MUST BE MORE THAN 2* !
299  **********************************************************/
300
301 char *pdb_encode_acct_ctrl(uint16 acct_ctrl, size_t length)
302 {
303         static fstring acct_str;
304         size_t i = 0;
305
306         acct_str[i++] = '[';
307
308         if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
309         if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
310         if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
311         if (acct_ctrl & ACB_TEMPDUP  ) acct_str[i++] = 'T'; 
312         if (acct_ctrl & ACB_NORMAL   ) acct_str[i++] = 'U';
313         if (acct_ctrl & ACB_MNS      ) acct_str[i++] = 'M';
314         if (acct_ctrl & ACB_WSTRUST  ) acct_str[i++] = 'W';
315         if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
316         if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
317         if (acct_ctrl & ACB_PWNOEXP  ) acct_str[i++] = 'X';
318         if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
319
320         for ( ; i < length - 2 ; i++ )
321                 acct_str[i] = ' ';
322
323         i = length - 2;
324         acct_str[i++] = ']';
325         acct_str[i++] = '\0';
326
327         return acct_str;
328 }     
329
330 /**********************************************************
331  Decode the account control bits from a string.
332  **********************************************************/
333
334 uint16 pdb_decode_acct_ctrl(const char *p)
335 {
336         uint16 acct_ctrl = 0;
337         BOOL finished = False;
338
339         /*
340          * Check if the account type bits have been encoded after the
341          * NT password (in the form [NDHTUWSLXI]).
342          */
343
344         if (*p != '[')
345                 return 0;
346
347         for (p++; *p && !finished; p++) {
348                 switch (*p) {
349                         case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
350                         case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
351                         case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
352                         case 'T': { acct_ctrl |= ACB_TEMPDUP  ; break; /* 'T'emp account. */ } 
353                         case 'U': { acct_ctrl |= ACB_NORMAL   ; break; /* 'U'ser account (normal). */ } 
354                         case 'M': { acct_ctrl |= ACB_MNS      ; break; /* 'M'NS logon user account. What is this ? */ } 
355                         case 'W': { acct_ctrl |= ACB_WSTRUST  ; break; /* 'W'orkstation account. */ } 
356                         case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ } 
357                         case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ } 
358                         case 'X': { acct_ctrl |= ACB_PWNOEXP  ; break; /* No 'X'piry on password */ } 
359                         case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
360             case ' ': { break; }
361                         case ':':
362                         case '\n':
363                         case '\0': 
364                         case ']':
365                         default:  { finished = True; }
366                 }
367         }
368
369         return acct_ctrl;
370 }
371
372 /*************************************************************
373  Routine to set 32 hex password characters from a 16 byte array.
374 **************************************************************/
375
376 void pdb_sethexpwd(char *p, const unsigned char *pwd, uint16 acct_ctrl)
377 {
378         if (pwd != NULL) {
379                 int i;
380                 for (i = 0; i < 16; i++)
381                         slprintf(&p[i*2], 3, "%02X", pwd[i]);
382         } else {
383                 if (acct_ctrl & ACB_PWNOTREQ)
384                         safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
385                 else
386                         safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
387         }
388 }
389
390 /*************************************************************
391  Routine to get the 32 hex characters and turn them
392  into a 16 byte array.
393 **************************************************************/
394
395 BOOL pdb_gethexpwd(const char *p, unsigned char *pwd)
396 {
397         int i;
398         unsigned char   lonybble, hinybble;
399         char           *hexchars = "0123456789ABCDEF";
400         char           *p1, *p2;
401         
402         if (!p)
403                 return (False);
404         
405         for (i = 0; i < 32; i += 2) {
406                 hinybble = toupper(p[i]);
407                 lonybble = toupper(p[i + 1]);
408
409                 p1 = strchr(hexchars, hinybble);
410                 p2 = strchr(hexchars, lonybble);
411
412                 if (!p1 || !p2)
413                         return (False);
414
415                 hinybble = PTR_DIFF(p1, hexchars);
416                 lonybble = PTR_DIFF(p2, hexchars);
417
418                 pwd[i / 2] = (hinybble << 4) | lonybble;
419         }
420         return (True);
421 }
422
423 /*******************************************************************
424  Group and User RID username mapping function
425  ********************************************************************/
426
427 BOOL pdb_name_to_rid(const char *user_name, uint32 *u_rid, uint32 *g_rid)
428 {
429         GROUP_MAP map;
430         struct passwd *pw = Get_Pwnam(user_name);
431
432         if (u_rid == NULL || g_rid == NULL || user_name == NULL)
433                 return False;
434
435         if (!pw) {
436                 DEBUG(1,("Username %s is invalid on this system\n", user_name));
437                 return False;
438         }
439
440         /* turn the unix UID into a Domain RID.  this is what the posix
441            sub-system does (adds 1000 to the uid) */
442         *u_rid = pdb_uid_to_user_rid(pw->pw_uid);
443
444         /* absolutely no idea what to do about the unix GID to Domain RID mapping */
445         /* map it ! */
446         if (get_group_map_from_gid(pw->pw_gid, &map, MAPPING_WITHOUT_PRIV)) {
447                 sid_peek_rid(&map.sid, g_rid);
448         } else 
449                 *g_rid = pdb_gid_to_group_rid(pw->pw_gid);
450
451         return True;
452 }
453
454 /*******************************************************************
455  Converts NT user RID to a UNIX uid.
456  ********************************************************************/
457
458 uid_t pdb_user_rid_to_uid(uint32 user_rid)
459 {
460         return (uid_t)(((user_rid & (~USER_RID_TYPE))- 1000)/RID_MULTIPLIER);
461 }
462
463
464 /*******************************************************************
465  Converts NT group RID to a UNIX gid.
466  ********************************************************************/
467
468 gid_t pdb_group_rid_to_gid(uint32 group_rid)
469 {
470         return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- 1000)/RID_MULTIPLIER);
471 }
472
473 /*******************************************************************
474  converts UNIX uid to an NT User RID.
475  ********************************************************************/
476
477 uint32 pdb_uid_to_user_rid(uid_t uid)
478 {
479         return (((((uint32)uid)*RID_MULTIPLIER) + 1000) | USER_RID_TYPE);
480 }
481
482 /*******************************************************************
483  converts NT Group RID to a UNIX uid.
484  
485  warning: you must not call that function only
486  you must do a call to the group mapping first.
487  there is not anymore a direct link between the gid and the rid.
488  ********************************************************************/
489
490 uint32 pdb_gid_to_group_rid(gid_t gid)
491 {
492   return (((((uint32)gid)*RID_MULTIPLIER) + 1000) | GROUP_RID_TYPE);
493 }
494
495 /*******************************************************************
496  Decides if a RID is a well known RID.
497  ********************************************************************/
498
499 static BOOL pdb_rid_is_well_known(uint32 rid)
500 {
501   return (rid < 1000);
502 }
503
504 /*******************************************************************
505  Decides if a RID is a user or group RID.
506  ********************************************************************/
507
508 BOOL pdb_rid_is_user(uint32 rid)
509 {
510   /* lkcl i understand that NT attaches an enumeration to a RID
511    * such that it can be identified as either a user, group etc
512    * type.  there are 5 such categories, and they are documented.
513    */
514    if(pdb_rid_is_well_known(rid)) {
515       /*
516        * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
517        * and DOMAIN_USER_RID_GUEST.
518        */
519      if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
520        return True;
521    } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
522      return True;
523    }
524    return False;
525 }
526
527 /*******************************************************************
528  Convert a rid into a name. Used in the lookup SID rpc.
529  ********************************************************************/
530
531 BOOL local_lookup_sid(DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use)
532 {
533         uint32 rid;
534         BOOL is_user;
535
536         sid_peek_rid(sid, &rid);
537         is_user = pdb_rid_is_user(rid);
538         *psid_name_use = SID_NAME_UNKNOWN;
539
540         DEBUG(5,("local_lookup_sid: looking up %s RID %u.\n", is_user ? "user" :
541                         "group", (unsigned int)rid));
542
543         if(is_user) {
544                 if(rid == DOMAIN_USER_RID_ADMIN) {
545                         pstring admin_users;
546                         char *p = admin_users;
547                         *psid_name_use = SID_NAME_USER;
548                         if(!next_token(&p, name, NULL, sizeof(fstring)))
549                                 fstrcpy(name, "Administrator");
550                 } else if (rid == DOMAIN_USER_RID_GUEST) {
551                         pstring guest_users;
552                         char *p = guest_users;
553                         *psid_name_use = SID_NAME_USER;
554                         if(!next_token(&p, name, NULL, sizeof(fstring)))
555                                 fstrcpy(name, "Guest");
556                 } else {
557                         uid_t uid;
558                         struct passwd *pass;
559                         
560                         /*
561                          * Don't try to convert the rid to a name if 
562                          * running in appliance mode
563                          */
564                         if (lp_hide_local_users())
565                                 return False;
566                         
567                         uid = pdb_user_rid_to_uid(rid);
568                         pass = sys_getpwuid(uid);
569
570                         *psid_name_use = SID_NAME_USER;
571
572                         DEBUG(5,("local_lookup_sid: looking up uid %u %s\n", (unsigned int)uid,
573                                 pass ? "succeeded" : "failed" ));
574
575                         if(!pass) {
576                                 slprintf(name, sizeof(fstring)-1, "unix_user.%u", (unsigned int)uid);
577                                 return True;
578                         }
579
580                         fstrcpy(name, pass->pw_name);
581
582                         DEBUG(5,("local_lookup_sid: found user %s for rid %u\n", name,
583                                 (unsigned int)rid ));
584                 }
585
586         } else {
587                 gid_t gid;
588                 struct group *gr; 
589                 GROUP_MAP map;
590                 
591                 /* 
592                  * Don't try to convert the rid to a name if running
593                  * in appliance mode
594                  */
595                 
596                 if (lp_hide_local_users()) 
597                         return False;
598
599                 /* check if it's a mapped group */
600                 if (get_group_map_from_sid(*sid, &map, MAPPING_WITHOUT_PRIV)) {
601                         if (map.gid!=-1) {
602                                 DEBUG(5,("local_lookup_sid: mapped group %s to gid %u\n", map.nt_name, (unsigned int)map.gid));
603                                 fstrcpy(name, map.nt_name);
604                                 *psid_name_use = map.sid_name_use;
605                                 return True;
606                         }
607                 }
608                 
609                 gid = pdb_group_rid_to_gid(rid);
610                 gr = getgrgid(gid);
611
612                 *psid_name_use = SID_NAME_ALIAS;
613
614                 DEBUG(5,("local_lookup_sid: looking up gid %u %s\n", (unsigned int)gid,
615                         gr ? "succeeded" : "failed" ));
616
617                 if(!gr) {
618                         slprintf(name, sizeof(fstring)-1, "unix_group.%u", (unsigned int)gid);
619                         return False;
620                 }
621
622                 fstrcpy( name, gr->gr_name);
623
624                 DEBUG(5,("local_lookup_sid: found group %s for rid %u\n", name,
625                         (unsigned int)rid ));
626         }
627
628         return True;
629 }
630
631 /*******************************************************************
632  Convert a name into a SID. Used in the lookup name rpc.
633  ********************************************************************/
634
635 BOOL local_lookup_name(const char *c_domain, const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psid_name_use)
636 {
637         extern DOM_SID global_sid_World_Domain;
638         struct passwd *pass = NULL;
639         DOM_SID local_sid;
640         fstring user;
641         fstring domain;
642
643         *psid_name_use = SID_NAME_UNKNOWN;
644
645         /*
646          * domain and user may be quoted const strings, and map_username and
647          * friends can modify them. Make a modifiable copy. JRA.
648          */
649
650         fstrcpy(domain, c_domain);
651         fstrcpy(user, c_user);
652
653         sid_copy(&local_sid, &global_sam_sid);
654
655         /*
656          * Special case for MACHINE\Everyone. Map to the world_sid.
657          */
658
659         if(strequal(user, "Everyone")) {
660                 sid_copy( psid, &global_sid_World_Domain);
661                 sid_append_rid(psid, 0);
662                 *psid_name_use = SID_NAME_ALIAS;
663                 return True;
664         }
665
666         /* 
667          * Don't lookup local unix users if running in appliance mode
668          */
669         if (lp_hide_local_users()) 
670                 return False;
671
672         (void)map_username(user);
673
674         if((pass = Get_Pwnam(user))) {
675                 sid_append_rid( &local_sid, pdb_uid_to_user_rid(pass->pw_uid));
676                 *psid_name_use = SID_NAME_USER;
677         } else {
678                 /*
679                  * Maybe it was a group ?
680                  */
681                 struct group *grp;
682                 GROUP_MAP map;
683                 
684                 /* check if it's a mapped group */
685                 if (get_group_map_from_ntname(user, &map, MAPPING_WITHOUT_PRIV)) {
686                         if (map.gid!=-1) {
687                                 /* yes it's a mapped group to a valid unix group */
688                                 sid_copy(&local_sid, &map.sid);
689                                 *psid_name_use = map.sid_name_use;
690                         }
691                         else
692                                 /* it's a correct name but not mapped so it points to nothing*/
693                                 return False;
694                 } else {
695                         /* it's not a mapped group */
696                         grp = getgrnam(user);
697                         if(!grp)
698                                 return False;
699
700                         /* 
701                          *check if it's mapped, if it is reply it doesn't exist
702                          *
703                          * that's to prevent this case:
704                          *
705                          * unix group ug is mapped to nt group ng
706                          * someone does a lookup on ug
707                          * we must not reply as it doesn't "exist" anymore
708                          * for NT. For NT only ng exists.
709                          * JFM, 30/11/2001
710                          */
711                         
712                         if(get_group_map_from_gid(grp->gr_gid, &map, MAPPING_WITHOUT_PRIV)){
713                                 return False;
714                         }
715
716                         sid_append_rid( &local_sid, pdb_gid_to_group_rid(grp->gr_gid));
717                         *psid_name_use = SID_NAME_ALIAS;
718                 }
719         }
720
721         sid_copy( psid, &local_sid);
722
723         return True;
724 }
725
726 /****************************************************************************
727  Convert a uid to SID - locally.
728 ****************************************************************************/
729
730 DOM_SID *local_uid_to_sid(DOM_SID *psid, uid_t uid)
731 {
732         extern DOM_SID global_sam_sid;
733
734         sid_copy(psid, &global_sam_sid);
735         sid_append_rid(psid, pdb_uid_to_user_rid(uid));
736
737         return psid;
738 }
739
740 /****************************************************************************
741  Convert a SID to uid - locally.
742 ****************************************************************************/
743
744 BOOL local_sid_to_uid(uid_t *puid, DOM_SID *psid, enum SID_NAME_USE *name_type)
745 {
746         extern DOM_SID global_sam_sid;
747
748         DOM_SID dom_sid;
749         uint32 rid;
750         fstring str;
751         struct passwd *pass;
752
753         *name_type = SID_NAME_UNKNOWN;
754
755         sid_copy(&dom_sid, psid);
756         sid_split_rid(&dom_sid, &rid);
757
758         if (!pdb_rid_is_user(rid))
759                 return False;
760
761         /*
762          * We can only convert to a uid if this is our local
763          * Domain SID (ie. we are the controling authority).
764          */
765         if (!sid_equal(&global_sam_sid, &dom_sid))
766                 return False;
767
768         *puid = pdb_user_rid_to_uid(rid);
769
770         /*
771          * Ensure this uid really does exist.
772          */
773         if(!(pass = sys_getpwuid(*puid)))
774                 return False;
775
776         DEBUG(10,("local_sid_to_uid: SID %s -> uid (%u) (%s).\n", sid_to_string( str, psid),
777                 (unsigned int)*puid, pass->pw_name ));
778
779         *name_type = SID_NAME_USER;
780
781         return True;
782 }
783
784 /****************************************************************************
785  Convert a gid to SID - locally.
786 ****************************************************************************/
787
788 DOM_SID *local_gid_to_sid(DOM_SID *psid, gid_t gid)
789 {
790         extern DOM_SID global_sam_sid;
791         GROUP_MAP map;
792
793         sid_copy(psid, &global_sam_sid);
794         
795         if (get_group_map_from_gid(gid, &map, MAPPING_WITHOUT_PRIV)) {
796                 sid_copy(psid, &map.sid);
797         }
798         else {
799                 sid_append_rid(psid, pdb_gid_to_group_rid(gid));
800         }
801
802         return psid;
803 }
804
805 /****************************************************************************
806  Convert a SID to gid - locally.
807 ****************************************************************************/
808
809 BOOL local_sid_to_gid(gid_t *pgid, DOM_SID *psid, enum SID_NAME_USE *name_type)
810 {
811         extern DOM_SID global_sam_sid;
812         DOM_SID dom_sid;
813         uint32 rid;
814         fstring str;
815         struct group *grp;
816         GROUP_MAP map;
817
818         *name_type = SID_NAME_UNKNOWN;
819
820         sid_copy(&dom_sid, psid);
821         sid_split_rid(&dom_sid, &rid);
822
823         /*
824          * We can only convert to a gid if this is our local
825          * Domain SID (ie. we are the controling authority).
826          *
827          * Or in the Builtin SID too. JFM, 11/30/2001
828          */
829
830         if (!sid_equal(&global_sam_sid, &dom_sid))
831                 return False;
832
833         if (pdb_rid_is_user(rid))
834                 return False;
835
836         if (get_group_map_from_sid(*psid, &map, MAPPING_WITHOUT_PRIV)) {
837                 
838                 /* the SID is in the mapping table but not mapped */
839                 if (map.gid==-1)
840                         return False;
841
842                 sid_peek_rid(&map.sid, &rid);
843                 *pgid = rid;
844                 *name_type = map.sid_name_use;
845         } else {
846                 *pgid = pdb_group_rid_to_gid(rid);
847                 *name_type = SID_NAME_ALIAS;
848         }
849
850         /*
851          * Ensure this gid really does exist.
852          */
853
854         if(!(grp = getgrgid(*pgid)))
855                 return False;
856
857         DEBUG(10,("local_sid_to_gid: SID %s -> gid (%u) (%s).\n", sid_to_string( str, psid),
858                 (unsigned int)*pgid, grp->gr_name ));
859
860         return True;
861 }
862
863 /** 
864  * Quick hack to do an easy ucs2 -> mulitbyte conversion 
865  * @return static buffer containing the converted string
866  **/
867
868 static char *pdb_convert(const UNISTR2 *from)
869 {
870         static pstring convert_buffer;
871         *convert_buffer = 0;
872         if (!from) {
873                 return convert_buffer;
874         }
875
876         unistr2_to_ascii(convert_buffer, from, sizeof(pstring));
877         return convert_buffer;
878 }
879
880 /*************************************************************
881  Copies a SAM_USER_INFO_23 to a SAM_ACCOUNT
882  **************************************************************/
883
884 void copy_id23_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_23 *from)
885 {
886
887         if (from == NULL || to == NULL) 
888                 return;
889
890         pdb_set_logon_time(to,nt_time_to_unix(&from->logon_time));
891         pdb_set_logoff_time(to,nt_time_to_unix(&from->logoff_time));
892         pdb_set_kickoff_time(to, nt_time_to_unix(&from->kickoff_time));
893         pdb_set_pass_last_set_time(to, nt_time_to_unix(&from->pass_last_set_time));
894         pdb_set_pass_can_change_time(to, nt_time_to_unix(&from->pass_can_change_time));
895         pdb_set_pass_must_change_time(to, nt_time_to_unix(&from->pass_must_change_time));
896
897         pdb_set_username(to      , pdb_convert(&from->uni_user_name   ));
898         pdb_set_fullname(to      , pdb_convert(&from->uni_full_name   ));
899         pdb_set_homedir(to       , pdb_convert(&from->uni_home_dir    ), True);
900         pdb_set_dir_drive(to     , pdb_convert(&from->uni_dir_drive   ), True);
901         pdb_set_logon_script(to  , pdb_convert(&from->uni_logon_script), True);
902         pdb_set_profile_path(to  , pdb_convert(&from->uni_profile_path), True);
903         pdb_set_acct_desc(to     , pdb_convert(&from->uni_acct_desc   ));
904         pdb_set_workstations(to  , pdb_convert(&from->uni_workstations));
905         pdb_set_unknown_str(to   , pdb_convert(&from->uni_unknown_str ));
906         pdb_set_munged_dial(to   , pdb_convert(&from->uni_munged_dial ));
907
908         if (from->user_rid)
909                 pdb_set_user_rid(to, from->user_rid);
910         if (from->group_rid)
911                 pdb_set_group_rid(to, from->group_rid);
912
913         pdb_set_acct_ctrl(to, from->acb_info);
914         pdb_set_unknown_3(to, from->unknown_3);
915
916         pdb_set_logon_divs(to, from->logon_divs);
917         pdb_set_hours_len(to, from->logon_hrs.len);
918         pdb_set_hours(to, from->logon_hrs.hours);
919
920         pdb_set_unknown_5(to, from->unknown_5);
921         pdb_set_unknown_6(to, from->unknown_6);
922 }
923
924
925 /*************************************************************
926  Copies a sam passwd.
927  **************************************************************/
928
929 void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from)
930 {
931         if (from == NULL || to == NULL) 
932                 return;
933
934         pdb_set_logon_time(to,nt_time_to_unix(&from->logon_time));
935         pdb_set_logoff_time(to,nt_time_to_unix(&from->logoff_time));
936         pdb_set_kickoff_time(to, nt_time_to_unix(&from->kickoff_time));
937         pdb_set_pass_last_set_time(to, nt_time_to_unix(&from->pass_last_set_time));
938         pdb_set_pass_can_change_time(to, nt_time_to_unix(&from->pass_can_change_time));
939         pdb_set_pass_must_change_time(to, nt_time_to_unix(&from->pass_must_change_time));
940
941         pdb_set_username(to      , pdb_convert(&from->uni_user_name   ));
942         pdb_set_fullname(to      , pdb_convert(&from->uni_full_name   ));
943         pdb_set_homedir(to       , pdb_convert(&from->uni_home_dir    ), True);
944         pdb_set_dir_drive(to     , pdb_convert(&from->uni_dir_drive   ), True);
945         pdb_set_logon_script(to  , pdb_convert(&from->uni_logon_script), True);
946         pdb_set_profile_path(to  , pdb_convert(&from->uni_profile_path), True);
947         pdb_set_acct_desc(to     , pdb_convert(&from->uni_acct_desc   ));
948         pdb_set_workstations(to  , pdb_convert(&from->uni_workstations));
949         pdb_set_unknown_str(to   , pdb_convert(&from->uni_unknown_str ));
950         pdb_set_munged_dial(to   , pdb_convert(&from->uni_munged_dial ));
951
952         if (from->user_rid)
953                 pdb_set_user_rid(to, from->user_rid);
954         if (from->group_rid)
955                 pdb_set_group_rid(to, from->group_rid);
956
957         /* FIXME!!  Do we need to copy the passwords here as well?
958            I don't know.  Need to figure this out   --jerry */
959
960         /* Passwords dealt with in caller --abartlet */
961
962         pdb_set_acct_ctrl(to, from->acb_info);
963         pdb_set_unknown_3(to, from->unknown_3);
964
965         pdb_set_logon_divs(to, from->logon_divs);
966         pdb_set_hours_len(to, from->logon_hrs.len);
967         pdb_set_hours(to, from->logon_hrs.hours);
968
969         pdb_set_unknown_5(to, from->unknown_5);
970         pdb_set_unknown_6(to, from->unknown_6);
971 }
972
973
974 /*************************************************************
975  Change a password entry in the local smbpasswd file.
976
977  FIXME!!  The function needs to be abstracted into the
978  passdb interface or something.  It is currently being called
979  by _api_samr_create_user() in rpc_server/srv_samr.c,
980  in SWAT and by smbpasswd/pdbedit.
981  
982  --jerry
983  *************************************************************/
984
985 BOOL local_password_change(const char *user_name, int local_flags,
986                            const char *new_passwd, 
987                            char *err_str, size_t err_str_len,
988                            char *msg_str, size_t msg_str_len)
989 {
990         struct passwd  *pwd = NULL;
991         SAM_ACCOUNT     *sam_pass=NULL;
992
993         *err_str = '\0';
994         *msg_str = '\0';
995
996         /* Get the smb passwd entry for this user */
997         pdb_init_sam(&sam_pass);
998         if(!pdb_getsampwnam(sam_pass, user_name)) {
999                 pdb_free_sam(&sam_pass);
1000                 
1001                 if (local_flags & LOCAL_ADD_USER) {
1002                         /*
1003                          * Check for a local account - if we're adding only.
1004                          */
1005                         
1006                         if(!(pwd = sys_getpwnam(user_name))) {
1007                                 slprintf(err_str, err_str_len - 1, "User %s does not \
1008 exist in system password file (usually /etc/passwd). Cannot add \
1009 account without a valid local system user.\n", user_name);
1010                                 return False;
1011                         }
1012                 } else {
1013                         slprintf(err_str, err_str_len-1,"Failed to find entry for user %s.\n", user_name);
1014                         return False;
1015                 }
1016
1017                 if (!NT_STATUS_IS_OK(pdb_init_sam_pw(&sam_pass, pwd))){
1018                         slprintf(err_str, err_str_len-1, "Failed initialise SAM_ACCOUNT for user %s.\n", user_name);
1019                         return False;
1020                 }
1021
1022         
1023                 if (local_flags & LOCAL_TRUST_ACCOUNT) {
1024                         if (!pdb_set_acct_ctrl(sam_pass, ACB_WSTRUST)) {
1025                                 slprintf(err_str, err_str_len - 1, "Failed to set 'trusted workstation account' flags for user %s.\n", user_name);
1026                                 pdb_free_sam(&sam_pass);
1027                                 return False;
1028                         }
1029                 } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
1030                         if (!pdb_set_acct_ctrl(sam_pass, ACB_DOMTRUST)) {
1031                                 slprintf(err_str, err_str_len - 1, "Failed to set 'domain trust account' flags for user %s.\n", user_name);
1032                                 pdb_free_sam(&sam_pass);
1033                                 return False;
1034                         }
1035                 } else {
1036                         if (!pdb_set_acct_ctrl(sam_pass, ACB_NORMAL)) {
1037                                 slprintf(err_str, err_str_len - 1, "Failed to set 'normal account' flags for user %s.\n", user_name);
1038                                 pdb_free_sam(&sam_pass);
1039                                 return False;
1040                         }
1041                 }
1042
1043         } else {
1044                 /* the entry already existed */
1045                 local_flags &= ~LOCAL_ADD_USER;
1046         }
1047
1048         /*
1049          * We are root - just write the new password
1050          * and the valid last change time.
1051          */
1052
1053         if (local_flags & LOCAL_DISABLE_USER) {
1054                 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_DISABLED)) {
1055                         slprintf(err_str, err_str_len-1, "Failed to set 'disabled' flag for user %s.\n", user_name);
1056                         pdb_free_sam(&sam_pass);
1057                         return False;
1058                 }
1059         } else if (local_flags & LOCAL_ENABLE_USER) {
1060                 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED))) {
1061                         slprintf(err_str, err_str_len-1, "Failed to unset 'disabled' flag for user %s.\n", user_name);
1062                         pdb_free_sam(&sam_pass);
1063                         return False;
1064                 }
1065         }
1066         
1067         if (local_flags & LOCAL_SET_NO_PASSWORD) {
1068                 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_PWNOTREQ)) {
1069                         slprintf(err_str, err_str_len-1, "Failed to set 'no password required' flag for user %s.\n", user_name);
1070                         pdb_free_sam(&sam_pass);
1071                         return False;
1072                 }
1073         } else if (local_flags & LOCAL_SET_PASSWORD) {
1074                 /*
1075                  * If we're dealing with setting a completely empty user account
1076                  * ie. One with a password of 'XXXX', but not set disabled (like
1077                  * an account created from scratch) then if the old password was
1078                  * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
1079                  * We remove that as we're giving this user their first password
1080                  * and the decision hasn't really been made to disable them (ie.
1081                  * don't create them disabled). JRA.
1082                  */
1083                 if ((pdb_get_lanman_passwd(sam_pass)==NULL) && (pdb_get_acct_ctrl(sam_pass)&ACB_DISABLED)) {
1084                         if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED))) {
1085                                 slprintf(err_str, err_str_len-1, "Failed to unset 'disabled' flag for user %s.\n", user_name);
1086                                 pdb_free_sam(&sam_pass);
1087                                 return False;
1088                         }
1089                 }
1090                 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_PWNOTREQ))) {
1091                         slprintf(err_str, err_str_len-1, "Failed to unset 'no password required' flag for user %s.\n", user_name);
1092                         pdb_free_sam(&sam_pass);
1093                         return False;
1094                 }
1095                 
1096                 if (!pdb_set_plaintext_passwd (sam_pass, new_passwd)) {
1097                         slprintf(err_str, err_str_len-1, "Failed to set password for user %s.\n", user_name);
1098                         pdb_free_sam(&sam_pass);
1099                         return False;
1100                 }
1101         }       
1102
1103         if (local_flags & LOCAL_ADD_USER) {
1104                 if (pdb_add_sam_account(sam_pass)) {
1105                         slprintf(msg_str, msg_str_len-1, "Added user %s.\n", user_name);
1106                         pdb_free_sam(&sam_pass);
1107                         return True;
1108                 } else {
1109                         slprintf(err_str, err_str_len-1, "Failed to add entry for user %s.\n", user_name);
1110                         pdb_free_sam(&sam_pass);
1111                         return False;
1112                 }
1113         } else if (local_flags & LOCAL_DELETE_USER) {
1114                 if (!pdb_delete_sam_account(user_name)) {
1115                         slprintf(err_str,err_str_len-1, "Failed to delete entry for user %s.\n", user_name);
1116                         pdb_free_sam(&sam_pass);
1117                         return False;
1118                 }
1119                 slprintf(msg_str, msg_str_len-1, "Deleted user %s.\n", user_name);
1120         } else {
1121                 if(!pdb_update_sam_account(sam_pass, True)) {
1122                         slprintf(err_str, err_str_len-1, "Failed to modify entry for user %s.\n", user_name);
1123                         pdb_free_sam(&sam_pass);
1124                         return False;
1125                 }
1126                 if(local_flags & LOCAL_DISABLE_USER)
1127                         slprintf(msg_str, msg_str_len-1, "Disabled user %s.\n", user_name);
1128                 else if (local_flags & LOCAL_ENABLE_USER)
1129                         slprintf(msg_str, msg_str_len-1, "Enabled user %s.\n", user_name);
1130                 else if (local_flags & LOCAL_SET_NO_PASSWORD)
1131                         slprintf(msg_str, msg_str_len-1, "User %s password set to none.\n", user_name);
1132         }
1133
1134         pdb_free_sam(&sam_pass);
1135         return True;
1136 }
1137
1138 /***************************************************************************
1139  Search by uid.  Wrapper around pdb_getsampwnam()
1140  **************************************************************************/
1141
1142 BOOL pdb_getsampwuid (SAM_ACCOUNT* user, uid_t uid)
1143 {
1144         struct passwd   *pw;
1145         fstring         name;
1146
1147         if (user==NULL) {
1148                 DEBUG(0,("pdb_getsampwuid: SAM_ACCOUNT is NULL.\n"));
1149                 return False;
1150         }
1151
1152         /*
1153          * Never trust the uid in the passdb.  Lookup the username first
1154          * and then lokup the user by name in the sam.
1155          */
1156          
1157         if ((pw=sys_getpwuid(uid)) == NULL)  {
1158                 DEBUG(0,("pdb_getsampwuid: getpwuid(%d) return NULL. User does not exist in Unix accounts!\n", uid));
1159                 return False;
1160         }
1161         
1162         fstrcpy (name, pw->pw_name);
1163
1164         return pdb_getsampwnam (user, name);
1165
1166 }
1167