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