Fix up an embarrsing bug I introduced when I moved the id21/id23 -> SAM_ACCOUNT
[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 = getpwuid_alloc(*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         passwd_free(&pass);
780
781         *name_type = SID_NAME_USER;
782
783         return True;
784 }
785
786 /****************************************************************************
787  Convert a gid to SID - locally.
788 ****************************************************************************/
789
790 DOM_SID *local_gid_to_sid(DOM_SID *psid, gid_t gid)
791 {
792         extern DOM_SID global_sam_sid;
793         GROUP_MAP map;
794
795         sid_copy(psid, &global_sam_sid);
796         
797         if (get_group_map_from_gid(gid, &map, MAPPING_WITHOUT_PRIV)) {
798                 sid_copy(psid, &map.sid);
799         }
800         else {
801                 sid_append_rid(psid, pdb_gid_to_group_rid(gid));
802         }
803
804         return psid;
805 }
806
807 /****************************************************************************
808  Convert a SID to gid - locally.
809 ****************************************************************************/
810
811 BOOL local_sid_to_gid(gid_t *pgid, DOM_SID *psid, enum SID_NAME_USE *name_type)
812 {
813         extern DOM_SID global_sam_sid;
814         DOM_SID dom_sid;
815         uint32 rid;
816         fstring str;
817         struct group *grp;
818         GROUP_MAP map;
819
820         *name_type = SID_NAME_UNKNOWN;
821
822         sid_copy(&dom_sid, psid);
823         sid_split_rid(&dom_sid, &rid);
824
825         /*
826          * We can only convert to a gid if this is our local
827          * Domain SID (ie. we are the controling authority).
828          *
829          * Or in the Builtin SID too. JFM, 11/30/2001
830          */
831
832         if (!sid_equal(&global_sam_sid, &dom_sid))
833                 return False;
834
835         if (pdb_rid_is_user(rid))
836                 return False;
837
838         if (get_group_map_from_sid(*psid, &map, MAPPING_WITHOUT_PRIV)) {
839                 
840                 /* the SID is in the mapping table but not mapped */
841                 if (map.gid==-1)
842                         return False;
843
844                 sid_peek_rid(&map.sid, &rid);
845                 *pgid = rid;
846                 *name_type = map.sid_name_use;
847         } else {
848                 *pgid = pdb_group_rid_to_gid(rid);
849                 *name_type = SID_NAME_ALIAS;
850         }
851
852         /*
853          * Ensure this gid really does exist.
854          */
855
856         if(!(grp = getgrgid(*pgid)))
857                 return False;
858
859         DEBUG(10,("local_sid_to_gid: SID %s -> gid (%u) (%s).\n", sid_to_string( str, psid),
860                 (unsigned int)*pgid, grp->gr_name ));
861
862         return True;
863 }
864
865 /** 
866  * Quick hack to do an easy ucs2 -> mulitbyte conversion 
867  * @return static buffer containing the converted string
868  **/
869
870 static char *pdb_convert(const UNISTR2 *from)
871 {
872         static pstring convert_buffer;
873         *convert_buffer = 0;
874         if (!from) {
875                 return convert_buffer;
876         }
877
878         unistr2_to_ascii(convert_buffer, from, sizeof(pstring));
879         return convert_buffer;
880 }
881
882 /*************************************************************
883  Copies a SAM_USER_INFO_23 to a SAM_ACCOUNT
884  **************************************************************/
885
886 void copy_id23_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_23 *from)
887 {
888
889         if (from == NULL || to == NULL) 
890                 return;
891
892         pdb_set_logon_time(to,nt_time_to_unix(&from->logon_time));
893         pdb_set_logoff_time(to,nt_time_to_unix(&from->logoff_time));
894         pdb_set_kickoff_time(to, nt_time_to_unix(&from->kickoff_time));
895         pdb_set_pass_last_set_time(to, nt_time_to_unix(&from->pass_last_set_time));
896         pdb_set_pass_can_change_time(to, nt_time_to_unix(&from->pass_can_change_time));
897         pdb_set_pass_must_change_time(to, nt_time_to_unix(&from->pass_must_change_time));
898
899         if (from->uni_user_name.buffer)
900                 pdb_set_username(to      , pdb_convert(&from->uni_user_name   ));
901         if (from->uni_full_name.buffer)
902                 pdb_set_fullname(to      , pdb_convert(&from->uni_full_name   ));
903         if (from->uni_home_dir.buffer)
904                 pdb_set_homedir(to       , pdb_convert(&from->uni_home_dir    ), True);
905         if (from->uni_dir_drive.buffer)
906                 pdb_set_dir_drive(to     , pdb_convert(&from->uni_dir_drive   ), True);
907         if (from->uni_logon_script.buffer)
908                 pdb_set_logon_script(to  , pdb_convert(&from->uni_logon_script), True);
909         if (from->uni_profile_path.buffer)
910                 pdb_set_profile_path(to  , pdb_convert(&from->uni_profile_path), True);
911         if (from->uni_acct_desc.buffer)
912                 pdb_set_acct_desc(to     , pdb_convert(&from->uni_acct_desc   ));
913         if (from->uni_workstations.buffer)
914                 pdb_set_workstations(to  , pdb_convert(&from->uni_workstations));
915         if (from->uni_unknown_str.buffer)
916                 pdb_set_unknown_str(to   , pdb_convert(&from->uni_unknown_str ));
917         if (from->uni_munged_dial.buffer)
918                 pdb_set_munged_dial(to   , pdb_convert(&from->uni_munged_dial ));
919
920         if (from->user_rid)
921                 pdb_set_user_rid(to, from->user_rid);
922         if (from->group_rid)
923                 pdb_set_group_rid(to, from->group_rid);
924
925         pdb_set_acct_ctrl(to, from->acb_info);
926         pdb_set_unknown_3(to, from->unknown_3);
927
928         pdb_set_logon_divs(to, from->logon_divs);
929         pdb_set_hours_len(to, from->logon_hrs.len);
930         pdb_set_hours(to, from->logon_hrs.hours);
931
932         pdb_set_unknown_5(to, from->unknown_5);
933         pdb_set_unknown_6(to, from->unknown_6);
934 }
935
936
937 /*************************************************************
938  Copies a sam passwd.
939  **************************************************************/
940
941 void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from)
942 {
943         if (from == NULL || to == NULL) 
944                 return;
945
946         pdb_set_logon_time(to,nt_time_to_unix(&from->logon_time));
947         pdb_set_logoff_time(to,nt_time_to_unix(&from->logoff_time));
948         pdb_set_kickoff_time(to, nt_time_to_unix(&from->kickoff_time));
949         pdb_set_pass_last_set_time(to, nt_time_to_unix(&from->pass_last_set_time));
950         pdb_set_pass_can_change_time(to, nt_time_to_unix(&from->pass_can_change_time));
951         pdb_set_pass_must_change_time(to, nt_time_to_unix(&from->pass_must_change_time));
952
953         if (from->uni_user_name.buffer)
954                 pdb_set_username(to      , pdb_convert(&from->uni_user_name   ));
955         if (from->uni_full_name.buffer)
956                 pdb_set_fullname(to      , pdb_convert(&from->uni_full_name   ));
957         if (from->uni_home_dir.buffer)
958                 pdb_set_homedir(to       , pdb_convert(&from->uni_home_dir    ), True);
959         if (from->uni_dir_drive.buffer)
960                 pdb_set_dir_drive(to     , pdb_convert(&from->uni_dir_drive   ), True);
961         if (from->uni_logon_script.buffer)
962                 pdb_set_logon_script(to  , pdb_convert(&from->uni_logon_script), True);
963         if (from->uni_profile_path.buffer)
964                 pdb_set_profile_path(to  , pdb_convert(&from->uni_profile_path), True);
965         if (from->uni_acct_desc.buffer)
966                 pdb_set_acct_desc(to     , pdb_convert(&from->uni_acct_desc   ));
967         if (from->uni_workstations.buffer)
968                 pdb_set_workstations(to  , pdb_convert(&from->uni_workstations));
969         if (from->uni_unknown_str.buffer)
970                 pdb_set_unknown_str(to   , pdb_convert(&from->uni_unknown_str ));
971         if (from->uni_munged_dial.buffer)
972                 pdb_set_munged_dial(to   , pdb_convert(&from->uni_munged_dial ));
973
974         if (from->user_rid)
975                 pdb_set_user_rid(to, from->user_rid);
976         if (from->group_rid)
977                 pdb_set_group_rid(to, from->group_rid);
978
979         /* FIXME!!  Do we need to copy the passwords here as well?
980            I don't know.  Need to figure this out   --jerry */
981
982         /* Passwords dealt with in caller --abartlet */
983
984         pdb_set_acct_ctrl(to, from->acb_info);
985         pdb_set_unknown_3(to, from->unknown_3);
986
987         pdb_set_logon_divs(to, from->logon_divs);
988         pdb_set_hours_len(to, from->logon_hrs.len);
989         pdb_set_hours(to, from->logon_hrs.hours);
990
991         pdb_set_unknown_5(to, from->unknown_5);
992         pdb_set_unknown_6(to, from->unknown_6);
993 }
994
995
996 /*************************************************************
997  Change a password entry in the local smbpasswd file.
998
999  FIXME!!  The function needs to be abstracted into the
1000  passdb interface or something.  It is currently being called
1001  by _api_samr_create_user() in rpc_server/srv_samr.c,
1002  in SWAT and by smbpasswd/pdbedit.
1003  
1004  --jerry
1005  *************************************************************/
1006
1007 BOOL local_password_change(const char *user_name, int local_flags,
1008                            const char *new_passwd, 
1009                            char *err_str, size_t err_str_len,
1010                            char *msg_str, size_t msg_str_len)
1011 {
1012         struct passwd  *pwd = NULL;
1013         SAM_ACCOUNT     *sam_pass=NULL;
1014
1015         *err_str = '\0';
1016         *msg_str = '\0';
1017
1018         /* Get the smb passwd entry for this user */
1019         pdb_init_sam(&sam_pass);
1020         if(!pdb_getsampwnam(sam_pass, user_name)) {
1021                 pdb_free_sam(&sam_pass);
1022                 
1023                 if (local_flags & LOCAL_ADD_USER) {
1024                         /*
1025                          * Check for a local account - if we're adding only.
1026                          */
1027                         
1028                         if(!(pwd = getpwnam_alloc(user_name))) {
1029                                 slprintf(err_str, err_str_len - 1, "User %s does not \
1030 exist in system password file (usually /etc/passwd). Cannot add \
1031 account without a valid local system user.\n", user_name);
1032                                 return False;
1033                         }
1034                 } else {
1035                         slprintf(err_str, err_str_len-1,"Failed to find entry for user %s.\n", user_name);
1036                         return False;
1037                 }
1038
1039                 if (!NT_STATUS_IS_OK(pdb_init_sam_pw(&sam_pass, pwd))){
1040                         slprintf(err_str, err_str_len-1, "Failed initialise SAM_ACCOUNT for user %s.\n", user_name);
1041                         passwd_free(&pwd);
1042                         return False;
1043                 }
1044                 
1045                 passwd_free(&pwd);
1046         
1047                 if (local_flags & LOCAL_TRUST_ACCOUNT) {
1048                         if (!pdb_set_acct_ctrl(sam_pass, ACB_WSTRUST)) {
1049                                 slprintf(err_str, err_str_len - 1, "Failed to set 'trusted workstation account' flags for user %s.\n", user_name);
1050                                 pdb_free_sam(&sam_pass);
1051                                 return False;
1052                         }
1053                 } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
1054                         if (!pdb_set_acct_ctrl(sam_pass, ACB_DOMTRUST)) {
1055                                 slprintf(err_str, err_str_len - 1, "Failed to set 'domain trust account' flags for user %s.\n", user_name);
1056                                 pdb_free_sam(&sam_pass);
1057                                 return False;
1058                         }
1059                 } else {
1060                         if (!pdb_set_acct_ctrl(sam_pass, ACB_NORMAL)) {
1061                                 slprintf(err_str, err_str_len - 1, "Failed to set 'normal account' flags for user %s.\n", user_name);
1062                                 pdb_free_sam(&sam_pass);
1063                                 return False;
1064                         }
1065                 }
1066
1067         } else {
1068                 /* the entry already existed */
1069                 local_flags &= ~LOCAL_ADD_USER;
1070         }
1071
1072         /*
1073          * We are root - just write the new password
1074          * and the valid last change time.
1075          */
1076
1077         if (local_flags & LOCAL_DISABLE_USER) {
1078                 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_DISABLED)) {
1079                         slprintf(err_str, err_str_len-1, "Failed to set 'disabled' flag for user %s.\n", user_name);
1080                         pdb_free_sam(&sam_pass);
1081                         return False;
1082                 }
1083         } else if (local_flags & LOCAL_ENABLE_USER) {
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         
1091         if (local_flags & LOCAL_SET_NO_PASSWORD) {
1092                 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_PWNOTREQ)) {
1093                         slprintf(err_str, err_str_len-1, "Failed to set 'no password required' flag for user %s.\n", user_name);
1094                         pdb_free_sam(&sam_pass);
1095                         return False;
1096                 }
1097         } else if (local_flags & LOCAL_SET_PASSWORD) {
1098                 /*
1099                  * If we're dealing with setting a completely empty user account
1100                  * ie. One with a password of 'XXXX', but not set disabled (like
1101                  * an account created from scratch) then if the old password was
1102                  * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
1103                  * We remove that as we're giving this user their first password
1104                  * and the decision hasn't really been made to disable them (ie.
1105                  * don't create them disabled). JRA.
1106                  */
1107                 if ((pdb_get_lanman_passwd(sam_pass)==NULL) && (pdb_get_acct_ctrl(sam_pass)&ACB_DISABLED)) {
1108                         if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED))) {
1109                                 slprintf(err_str, err_str_len-1, "Failed to unset 'disabled' flag for user %s.\n", user_name);
1110                                 pdb_free_sam(&sam_pass);
1111                                 return False;
1112                         }
1113                 }
1114                 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_PWNOTREQ))) {
1115                         slprintf(err_str, err_str_len-1, "Failed to unset 'no password required' flag for user %s.\n", user_name);
1116                         pdb_free_sam(&sam_pass);
1117                         return False;
1118                 }
1119                 
1120                 if (!pdb_set_plaintext_passwd (sam_pass, new_passwd)) {
1121                         slprintf(err_str, err_str_len-1, "Failed to set password for user %s.\n", user_name);
1122                         pdb_free_sam(&sam_pass);
1123                         return False;
1124                 }
1125         }       
1126
1127         if (local_flags & LOCAL_ADD_USER) {
1128                 if (pdb_add_sam_account(sam_pass)) {
1129                         slprintf(msg_str, msg_str_len-1, "Added user %s.\n", user_name);
1130                         pdb_free_sam(&sam_pass);
1131                         return True;
1132                 } else {
1133                         slprintf(err_str, err_str_len-1, "Failed to add entry for user %s.\n", user_name);
1134                         pdb_free_sam(&sam_pass);
1135                         return False;
1136                 }
1137         } else if (local_flags & LOCAL_DELETE_USER) {
1138                 if (!pdb_delete_sam_account(user_name)) {
1139                         slprintf(err_str,err_str_len-1, "Failed to delete entry for user %s.\n", user_name);
1140                         pdb_free_sam(&sam_pass);
1141                         return False;
1142                 }
1143                 slprintf(msg_str, msg_str_len-1, "Deleted user %s.\n", user_name);
1144         } else {
1145                 if(!pdb_update_sam_account(sam_pass, True)) {
1146                         slprintf(err_str, err_str_len-1, "Failed to modify entry for user %s.\n", user_name);
1147                         pdb_free_sam(&sam_pass);
1148                         return False;
1149                 }
1150                 if(local_flags & LOCAL_DISABLE_USER)
1151                         slprintf(msg_str, msg_str_len-1, "Disabled user %s.\n", user_name);
1152                 else if (local_flags & LOCAL_ENABLE_USER)
1153                         slprintf(msg_str, msg_str_len-1, "Enabled user %s.\n", user_name);
1154                 else if (local_flags & LOCAL_SET_NO_PASSWORD)
1155                         slprintf(msg_str, msg_str_len-1, "User %s password set to none.\n", user_name);
1156         }
1157
1158         pdb_free_sam(&sam_pass);
1159         return True;
1160 }
1161
1162 /***************************************************************************
1163  Search by uid.  Wrapper around pdb_getsampwnam()
1164  **************************************************************************/
1165
1166 BOOL pdb_getsampwuid (SAM_ACCOUNT* user, uid_t uid)
1167 {
1168         struct passwd   *pw;
1169         fstring         name;
1170
1171         if (user==NULL) {
1172                 DEBUG(0,("pdb_getsampwuid: SAM_ACCOUNT is NULL.\n"));
1173                 return False;
1174         }
1175
1176         /*
1177          * Never trust the uid in the passdb.  Lookup the username first
1178          * and then lokup the user by name in the sam.
1179          */
1180          
1181         if ((pw=getpwuid_alloc(uid)) == NULL)  {
1182                 DEBUG(0,("pdb_getsampwuid: getpwuid(%d) return NULL. User does not exist in Unix accounts!\n", uid));
1183                 return False;
1184         }
1185         
1186         fstrcpy (name, pw->pw_name);
1187
1188         passwd_free(&pw);
1189
1190         return pdb_getsampwnam (user, name);
1191
1192 }
1193