*id_to_*id call reshape to return NTSTATUS errors
[ira/wip.git] / source3 / lib / domain_namemap.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Groupname handling
5    Copyright (C) Jeremy Allison 1998.
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 /* 
23  * UNIX gid and Local or Domain SID resolution.  This module resolves
24  * only those entries in the map files, it is *NOT* responsible for
25  * resolving UNIX groups not listed: that is an entirely different
26  * matter, altogether...
27  */
28
29 /*
30  *
31  *
32
33  format of the file is:
34
35  unixname       NT Group name
36  unixname       Domain Admins (well-known Domain Group)
37  unixname       DOMAIN_NAME\NT Group name
38  unixname       OTHER_DOMAIN_NAME\NT Group name
39  unixname       DOMAIN_NAME\Domain Admins (well-known Domain Group)
40  ....
41
42  if the DOMAIN_NAME\ component is left off, then your own domain is assumed.
43
44  *
45  *
46  */
47
48
49 #include "includes.h"
50 extern int DEBUGLEVEL;
51
52 extern fstring global_myworkgroup;
53 extern DOM_SID global_member_sid;
54 extern fstring global_sam_name;
55 extern DOM_SID global_sam_sid;
56 extern DOM_SID global_sid_S_1_5_20;
57
58 /*******************************************************************
59  converts UNIX uid to an NT User RID. NOTE: IS SOMETHING SPECIFIC TO SAMBA
60  ********************************************************************/
61 static uid_t pwdb_user_rid_to_uid(uint32 user_rid)
62 {
63         return ((user_rid & (~RID_TYPE_USER))- 1000)/RID_MULTIPLIER;
64 }
65
66 /*******************************************************************
67  converts NT Group RID to a UNIX uid. NOTE: IS SOMETHING SPECIFIC TO SAMBA
68  ********************************************************************/
69 static uint32 pwdb_group_rid_to_gid(uint32 group_rid)
70 {
71         return ((group_rid & (~RID_TYPE_GROUP))- 1000)/RID_MULTIPLIER;
72 }
73
74 /*******************************************************************
75  converts NT Alias RID to a UNIX uid. NOTE: IS SOMETHING SPECIFIC TO SAMBA
76  ********************************************************************/
77 static uint32 pwdb_alias_rid_to_gid(uint32 alias_rid)
78 {
79         return ((alias_rid & (~RID_TYPE_ALIAS))- 1000)/RID_MULTIPLIER;
80 }
81
82 /*******************************************************************
83  converts NT Group RID to a UNIX uid. NOTE: IS SOMETHING SPECIFIC TO SAMBA
84  ********************************************************************/
85 static uint32 pwdb_gid_to_group_rid(uint32 gid)
86 {
87         uint32 grp_rid = ((((gid)*RID_MULTIPLIER) + 1000) | RID_TYPE_GROUP);
88         return grp_rid;
89 }
90
91 /******************************************************************
92  converts UNIX gid to an NT Alias RID. NOTE: IS SOMETHING SPECIFIC TO SAMBA
93  ********************************************************************/
94 static uint32 pwdb_gid_to_alias_rid(uint32 gid)
95 {
96         uint32 alias_rid = ((((gid)*RID_MULTIPLIER) + 1000) | RID_TYPE_ALIAS);
97         return alias_rid;
98 }
99
100 /*******************************************************************
101  converts UNIX uid to an NT User RID. NOTE: IS SOMETHING SPECIFIC TO SAMBA
102  ********************************************************************/
103 static uint32 pwdb_uid_to_user_rid(uint32 uid)
104 {
105         uint32 user_rid = ((((uid)*RID_MULTIPLIER) + 1000) | RID_TYPE_USER);
106         return user_rid;
107 }
108
109 /******************************************************************
110  converts SID + SID_NAME_USE type to a UNIX id.  the Domain SID is,
111  and can only be, our own SID.
112  ********************************************************************/
113 static BOOL pwdb_sam_sid_to_unixid(DOM_SID *sid, uint8 type, uint32 *id)
114 {
115         DOM_SID tmp_sid;
116         uint32 rid;
117
118         sid_copy(&tmp_sid, sid);
119         sid_split_rid(&tmp_sid, &rid);
120         if (!sid_equal(&global_sam_sid, &tmp_sid))
121         {
122                 return False;
123         }
124
125         switch (type)
126         {
127                 case SID_NAME_USER:
128                 {
129                         *id = pwdb_user_rid_to_uid(rid);
130                         return True;
131                 }
132                 case SID_NAME_ALIAS:
133                 {
134                         *id = pwdb_alias_rid_to_gid(rid);
135                         return True;
136                 }
137                 case SID_NAME_DOM_GRP:
138                 case SID_NAME_WKN_GRP:
139                 {
140                         *id = pwdb_group_rid_to_gid(rid);
141                         return True;
142                 }
143         }
144         return False;
145 }
146
147 /******************************************************************
148  converts UNIX gid + SID_NAME_USE type to a SID.  the Domain SID is,
149  and can only be, our own SID.
150  ********************************************************************/
151 static BOOL pwdb_unixid_to_sam_sid(uint32 id, uint8 type, DOM_SID *sid)
152 {
153         sid_copy(sid, &global_sam_sid);
154         switch (type)
155         {
156                 case SID_NAME_USER:
157                 {
158                         sid_append_rid(sid, pwdb_uid_to_user_rid(id));
159                         return True;
160                 }
161                 case SID_NAME_ALIAS:
162                 {
163                         sid_append_rid(sid, pwdb_gid_to_alias_rid(id));
164                         return True;
165                 }
166                 case SID_NAME_DOM_GRP:
167                 case SID_NAME_WKN_GRP:
168                 {
169                         sid_append_rid(sid, pwdb_gid_to_group_rid(id));
170                         return True;
171                 }
172         }
173         return False;
174 }
175
176 /*******************************************************************
177  Decides if a RID is a well known RID.
178  ********************************************************************/
179 static BOOL pwdb_rid_is_well_known(uint32 rid)
180 {
181         return (rid < 1000);
182 }
183
184 /*******************************************************************
185  determines a rid's type.  NOTE: THIS IS SOMETHING SPECIFIC TO SAMBA
186  ********************************************************************/
187 static uint32 pwdb_rid_type(uint32 rid)
188 {
189         /* lkcl i understand that NT attaches an enumeration to a RID
190          * such that it can be identified as either a user, group etc
191          * type: SID_ENUM_TYPE.
192          */
193         if (pwdb_rid_is_well_known(rid))
194         {
195                 /*
196                  * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
197                  * and DOMAIN_USER_RID_GUEST.
198                  */
199                 if (rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
200                 {
201                         return RID_TYPE_USER;
202                 }
203                 if (DOMAIN_GROUP_RID_ADMINS <= rid && rid <= DOMAIN_GROUP_RID_GUESTS)
204                 {
205                         return RID_TYPE_GROUP;
206                 }
207                 if (BUILTIN_ALIAS_RID_ADMINS <= rid && rid <= BUILTIN_ALIAS_RID_REPLICATOR)
208                 {
209                         return RID_TYPE_ALIAS;
210                 }
211         }
212         return (rid & RID_TYPE_MASK);
213 }
214
215 /*******************************************************************
216  checks whether rid is a user rid.  NOTE: THIS IS SOMETHING SPECIFIC TO SAMBA
217  ********************************************************************/
218 BOOL pwdb_rid_is_user(uint32 rid)
219 {
220         return pwdb_rid_type(rid) == RID_TYPE_USER;
221 }
222
223 /**************************************************************************
224  Groupname map functionality. The code loads a groupname map file and
225  (currently) loads it into a linked list. This is slow and memory
226  hungry, but can be changed into a more efficient storage format
227  if the demands on it become excessive.
228 ***************************************************************************/
229
230 typedef struct name_map
231 {
232         ubi_slNode next;
233         DOM_NAME_MAP grp;
234
235 } name_map_entry;
236
237 static ubi_slList groupname_map_list;
238 static ubi_slList aliasname_map_list;
239 static ubi_slList ntusrname_map_list;
240
241 static void delete_name_entry(name_map_entry *gmep)
242 {
243         if (gmep->grp.nt_name)
244         {
245                 free(gmep->grp.nt_name);
246         }
247         if (gmep->grp.nt_domain)
248         {
249                 free(gmep->grp.nt_domain);
250         }
251         if (gmep->grp.unix_name)
252         {
253                 free(gmep->grp.unix_name);
254         }
255         free((char*)gmep);
256 }
257
258 /**************************************************************************
259  Delete all the entries in the name map list.
260 ***************************************************************************/
261
262 static void delete_map_list(ubi_slList *map_list)
263 {
264         name_map_entry *gmep;
265
266         while ((gmep = (name_map_entry *)ubi_slRemHead(map_list )) != NULL)
267         {
268                 delete_name_entry(gmep);
269         }
270 }
271
272
273 /**************************************************************************
274  makes a group sid out of a domain sid and a _unix_ gid.
275 ***************************************************************************/
276 static BOOL make_mydomain_sid(DOM_NAME_MAP *grp, DOM_MAP_TYPE type)
277 {
278         int ret = False;
279         fstring sid_str;
280
281         if (!map_domain_name_to_sid(&grp->sid, &(grp->nt_domain)))
282         {
283                 DEBUG(0,("make_mydomain_sid: unknown domain %s\n",
284                           grp->nt_domain));
285                 return False;
286         }
287
288         if (sid_equal(&grp->sid, &global_sid_S_1_5_20))
289         {
290                 /*
291                  * only builtin aliases are recognised in S-1-5-20
292                  */
293                 DEBUG(10,("make_mydomain_sid: group %s in builtin domain\n",
294                            grp->nt_name));
295
296                 if (lookup_builtin_alias_name(grp->nt_name, "BUILTIN", &grp->sid, &grp->type) != 0x0)
297                 {
298                         DEBUG(0,("unix group %s mapped to an unrecognised BUILTIN domain name %s\n",
299                                   grp->unix_name, grp->nt_name));
300                         return False;
301                 }
302                 ret = True;
303         }
304         else if (lookup_wk_user_name(grp->nt_name, grp->nt_domain, &grp->sid, &grp->type) == 0x0)
305         {
306                 if (type != DOM_MAP_USER)
307                 {
308                         DEBUG(0,("well-known NT user %s\\%s listed in wrong map file\n",
309                                   grp->nt_domain, grp->nt_name));
310                         return False;
311                 }
312                 ret = True;
313         }
314         else if (lookup_wk_group_name(grp->nt_name, grp->nt_domain, &grp->sid, &grp->type) == 0x0)
315         {
316                 if (type != DOM_MAP_DOMAIN)
317                 {
318                         DEBUG(0,("well-known NT group %s\\%s listed in wrong map file\n",
319                                   grp->nt_domain, grp->nt_name));
320                         return False;
321                 }
322                 ret = True;
323         }
324         else
325         {
326                 switch (type)
327                 {
328                         case DOM_MAP_USER:
329                         {
330                                 grp->type = SID_NAME_USER;
331                                 break;
332                         }
333                         case DOM_MAP_DOMAIN:
334                         {
335                                 grp->type = SID_NAME_DOM_GRP;
336                                 break;
337                         }
338                         case DOM_MAP_LOCAL:
339                         {
340                                 grp->type = SID_NAME_ALIAS;
341                                 break;
342                         }
343                 }
344
345                 ret = pwdb_unixid_to_sam_sid(grp->unix_id, grp->type, &grp->sid);
346         }
347
348         sid_to_string(sid_str, &grp->sid);
349         DEBUG(10,("nt name %s\\%s gid %d mapped to %s\n",
350                    grp->nt_domain, grp->nt_name, grp->unix_id, sid_str));
351         return ret;
352 }
353
354 /**************************************************************************
355  makes a group sid out of an nt domain, nt group name or a unix group name.
356 ***************************************************************************/
357 static BOOL unix_name_to_nt_name_info(DOM_NAME_MAP *map, DOM_MAP_TYPE type)
358 {
359         /*
360          * Attempt to get the unix gid_t for this name.
361          */
362
363         DEBUG(5,("unix_name_to_nt_name_info: unix_name:%s\n", map->unix_name));
364
365         if (type == DOM_MAP_USER)
366         {
367                 const struct passwd *pwptr = Get_Pwnam(map->unix_name, False);
368                 if (pwptr == NULL)
369                 {
370                         DEBUG(0,("unix_name_to_nt_name_info: Get_Pwnam for user %s\
371 failed. Error was %s.\n", map->unix_name, strerror(errno) ));
372                         return False;
373                 }
374
375                 map->unix_id = (uint32)pwptr->pw_uid;
376         }
377         else
378         {
379                 struct group *gptr = getgrnam(map->unix_name);
380                 if (gptr == NULL)
381                 {
382                         DEBUG(0,("unix_name_to_nt_name_info: getgrnam for group %s\
383 failed. Error was %s.\n", map->unix_name, strerror(errno) ));
384                         return False;
385                 }
386
387                 map->unix_id = (uint32)gptr->gr_gid;
388         }
389
390         DEBUG(5,("unix_name_to_nt_name_info: unix gid:%d\n", map->unix_id));
391
392         /*
393          * Now map the name to an NT SID+RID.
394          */
395
396         if (map->nt_domain != NULL && !strequal(map->nt_domain, global_sam_name))
397         {
398                 /* Must add client-call lookup code here, to 
399                  * resolve remote domain's sid and the group's rid,
400                  * in that domain.
401                  *
402                  * NOTE: it is _incorrect_ to put code here that assumes
403                  * we are responsible for lookups for foriegn domains' RIDs.
404                  *
405                  * for foriegn domains for which we are *NOT* the PDC, all
406                  * we can be responsible for is the unix gid_t to which
407                  * the foriegn SID+rid maps to, on this _local_ machine.  
408                  * we *CANNOT* make any short-cuts or assumptions about
409                  * RIDs in a foriegn domain.
410                  */
411
412                 if (!map_domain_name_to_sid(&map->sid, &(map->nt_domain)))
413                 {
414                         DEBUG(0,("unix_name_to_nt_name_info: no known sid for %s\n",
415                                   map->nt_domain));
416                         return False;
417                 }
418         }
419
420         return make_mydomain_sid(map, type);
421 }
422
423 static BOOL make_name_entry(name_map_entry **new_ep,
424                 char *nt_domain, char *nt_group, char *unix_group,
425                 DOM_MAP_TYPE type)
426 {
427         /*
428          * Create the list entry and add it onto the list.
429          */
430
431         DEBUG(5,("make_name_entry:%s,%s,%s\n", nt_domain, nt_group, unix_group));
432
433         (*new_ep) = (name_map_entry *)malloc(sizeof(name_map_entry));
434         if ((*new_ep) == NULL)
435         {
436                 DEBUG(0,("make_name_entry: malloc fail for name_map_entry.\n"));
437                 return False;
438         } 
439
440         ZERO_STRUCTP(*new_ep);
441
442         (*new_ep)->grp.nt_name   = strdup(nt_group  );
443         (*new_ep)->grp.nt_domain = strdup(nt_domain );
444         (*new_ep)->grp.unix_name = strdup(unix_group);
445
446         if ((*new_ep)->grp.nt_name   == NULL ||
447             (*new_ep)->grp.unix_name == NULL)
448         {
449                 DEBUG(0,("make_name_entry: malloc fail for names in name_map_entry.\n"));
450                 delete_name_entry((*new_ep));
451                 return False;
452         }
453
454         /*
455          * look up the group names, make the Group-SID and unix gid
456          */
457  
458         if (!unix_name_to_nt_name_info(&(*new_ep)->grp, type))
459         {
460                 delete_name_entry((*new_ep));
461                 return False;
462         }
463
464         return True;
465 }
466
467 /**************************************************************************
468  Load a name map file. Sets last accessed timestamp.
469 ***************************************************************************/
470 static ubi_slList *load_name_map(DOM_MAP_TYPE type)
471 {
472         static time_t groupmap_file_last_modified = (time_t)0;
473         static time_t aliasmap_file_last_modified = (time_t)0;
474         static time_t ntusrmap_file_last_modified  = (time_t)0;
475         static BOOL initialised_group = False;
476         static BOOL initialised_alias = False;
477         static BOOL initialised_ntusr  = False;
478         char *groupname_map_file = lp_groupname_map();
479         char *aliasname_map_file = lp_aliasname_map();
480         char *ntusrname_map_file = lp_ntusrname_map();
481
482         FILE *fp;
483         char *s;
484         pstring buf;
485         name_map_entry *new_ep;
486
487         time_t *file_last_modified = NULL;
488         int    *initialised = NULL;
489         char   *map_file = NULL;
490         ubi_slList *map_list = NULL;
491
492         switch (type)
493         {
494                 case DOM_MAP_DOMAIN:
495                 {
496                         file_last_modified = &groupmap_file_last_modified;
497                         initialised        = &initialised_group;
498                         map_file           = groupname_map_file;
499                         map_list           = &groupname_map_list;
500
501                         break;
502                 }
503                 case DOM_MAP_LOCAL:
504                 {
505                         file_last_modified = &aliasmap_file_last_modified;
506                         initialised        = &initialised_alias;
507                         map_file           = aliasname_map_file;
508                         map_list           = &aliasname_map_list;
509
510                         break;
511                 }
512                 case DOM_MAP_USER:
513                 {
514                         file_last_modified = &ntusrmap_file_last_modified;
515                         initialised        = &initialised_ntusr;
516                         map_file           = ntusrname_map_file;
517                         map_list           = &ntusrname_map_list;
518
519                         break;
520                 }
521         }
522
523         if (!(*initialised))
524         {
525                 DEBUG(10,("initialising map %s\n", map_file));
526                 ubi_slInitList(map_list);
527                 (*initialised) = True;
528         }
529
530         if (!*map_file)
531         {
532                 return map_list;
533         }
534
535         /*
536          * Load the file.
537          */
538
539         fp = open_file_if_modified(map_file, "r", file_last_modified);
540         if (!fp)
541         {
542                 return map_list;
543         }
544
545         /*
546          * Throw away any previous list.
547          */
548         delete_map_list(map_list);
549
550         DEBUG(4,("load_name_map: Scanning name map %s\n",map_file));
551
552         while ((s = fgets_slash(buf, sizeof(buf), fp)) != NULL)
553         {
554                 pstring unixname;
555                 pstring nt_name;
556                 fstring nt_domain;
557                 fstring ntname;
558                 char *p;
559
560                 DEBUG(10,("Read line |%s|\n", s));
561
562                 memset(nt_name, 0, sizeof(nt_name));
563
564                 if (!*s || strchr("#;",*s))
565                         continue;
566
567                 if (!next_token(&s,unixname, "\t\n\r=", sizeof(unixname)))
568                         continue;
569
570                 if (!next_token(&s,nt_name, "\t\n\r=", sizeof(nt_name)))
571                         continue;
572
573                 trim_string(unixname, " ", " ");
574                 trim_string(nt_name, " ", " ");
575
576                 if (!*nt_name)
577                         continue;
578
579                 if (!*unixname)
580                         continue;
581
582                 p = strchr(nt_name, '\\');
583
584                 if (p == NULL)
585                 {
586                         memset(nt_domain, 0, sizeof(nt_domain));
587                         fstrcpy(ntname, nt_name);
588                 }
589                 else
590                 {
591                         *p = 0;
592                         p++;
593                         fstrcpy(nt_domain, nt_name);
594                         fstrcpy(ntname , p);
595                 }
596
597                 if (make_name_entry(&new_ep, nt_domain, ntname, unixname, type))
598                 {
599                         ubi_slAddTail(map_list, (ubi_slNode *)new_ep);
600                         DEBUG(5,("unixname = %s, ntname = %s\\%s type = %d\n",
601                                   new_ep->grp.unix_name,
602                                   new_ep->grp.nt_domain,
603                                   new_ep->grp.nt_name,
604                                   new_ep->grp.type));
605                 }
606         }
607
608         DEBUG(10,("load_name_map: Added %ld entries to name map.\n",
609                    ubi_slCount(map_list)));
610
611         fclose(fp);
612
613         return map_list;
614 }
615
616 static void copy_grp_map_entry(DOM_NAME_MAP *grp, const DOM_NAME_MAP *from)
617 {
618         sid_copy(&grp->sid, &from->sid);
619         grp->unix_id   = from->unix_id;
620         grp->nt_name   = from->nt_name;
621         grp->nt_domain = from->nt_domain;
622         grp->unix_name = from->unix_name;
623         grp->type      = from->type;
624 }
625
626 #if 0
627 /***********************************************************
628  Lookup unix name.
629 ************************************************************/
630 static BOOL map_unixname(DOM_MAP_TYPE type,
631                 char *unixname, DOM_NAME_MAP *grp_info)
632 {
633         name_map_entry *gmep;
634         ubi_slList *map_list;
635
636         /*
637          * Initialise and load if not already loaded.
638          */
639         map_list = load_name_map(type);
640
641         for (gmep = (name_map_entry *)ubi_slFirst(map_list);
642              gmep != NULL;
643              gmep = (name_map_entry *)ubi_slNext(gmep ))
644         {
645                 if (strequal(gmep->grp.unix_name, unixname))
646                 {
647                         copy_grp_map_entry(grp_info, &gmep->grp);
648                         DEBUG(7,("map_unixname: Mapping unix name %s to nt group %s.\n",
649                                gmep->grp.unix_name, gmep->grp.nt_name ));
650                         return True;
651                 }
652         }
653
654         return False;
655 }
656
657 #endif
658
659 /***********************************************************
660  Lookup nt name.
661 ************************************************************/
662 static BOOL map_ntname(DOM_MAP_TYPE type, char *ntname, char *ntdomain,
663                                 DOM_NAME_MAP *grp_info)
664 {
665         name_map_entry *gmep;
666         ubi_slList *map_list;
667
668         /*
669          * Initialise and load if not already loaded.
670          */
671         map_list = load_name_map(type);
672
673         for (gmep = (name_map_entry *)ubi_slFirst(map_list);
674              gmep != NULL;
675              gmep = (name_map_entry *)ubi_slNext(gmep ))
676         {
677                 if (strequal(gmep->grp.nt_name  , ntname) &&
678                     strequal(gmep->grp.nt_domain, ntdomain))
679                 {
680                         copy_grp_map_entry(grp_info, &gmep->grp);
681                         DEBUG(7,("map_ntname: Mapping unix name %s to nt name %s.\n",
682                                gmep->grp.unix_name, gmep->grp.nt_name ));
683                         return True;
684                 }
685         }
686
687         return False;
688 }
689
690
691 /***********************************************************
692  Lookup by SID
693 ************************************************************/
694 static BOOL map_sid(DOM_MAP_TYPE type,
695                 DOM_SID *psid, DOM_NAME_MAP *grp_info)
696 {
697         name_map_entry *gmep;
698         ubi_slList *map_list;
699
700         /*
701          * Initialise and load if not already loaded.
702          */
703         map_list = load_name_map(type);
704
705         for (gmep = (name_map_entry *)ubi_slFirst(map_list);
706              gmep != NULL;
707              gmep = (name_map_entry *)ubi_slNext(gmep ))
708         {
709                 if (sid_equal(&gmep->grp.sid, psid))
710                 {
711                         copy_grp_map_entry(grp_info, &gmep->grp);
712                         DEBUG(7,("map_sid: Mapping unix name %s to nt name %s.\n",
713                                gmep->grp.unix_name, gmep->grp.nt_name ));
714                         return True;
715                 }
716         }
717
718         return False;
719 }
720
721 /***********************************************************
722  Lookup by gid_t.
723 ************************************************************/
724 static BOOL map_unixid(DOM_MAP_TYPE type, uint32 unix_id, DOM_NAME_MAP *grp_info)
725 {
726         name_map_entry *gmep;
727         ubi_slList *map_list;
728
729         /*
730          * Initialise and load if not already loaded.
731          */
732         map_list = load_name_map(type);
733
734         for (gmep = (name_map_entry *)ubi_slFirst(map_list);
735              gmep != NULL;
736              gmep = (name_map_entry *)ubi_slNext(gmep ))
737         {
738                 fstring sid_str;
739                 sid_to_string(sid_str, &gmep->grp.sid);
740                 DEBUG(10,("map_unixid: enum entry unix group %s %d nt %s %s\n",
741                                gmep->grp.unix_name, gmep->grp.unix_id, gmep->grp.nt_name, sid_str));
742                 if (gmep->grp.unix_id == unix_id)
743                 {
744                         copy_grp_map_entry(grp_info, &gmep->grp);
745                         DEBUG(7,("map_unixid: Mapping unix name %s to nt name %s type %d\n",
746                                gmep->grp.unix_name, gmep->grp.nt_name, gmep->grp.type));
747                         return True;
748                 }
749         }
750
751         return False;
752 }
753
754 /***********************************************************
755  *
756  * Call four functions to resolve unix group ids and either
757  * local group SIDs or domain group SIDs listed in the local group
758  * or domain group map files.
759  *
760  * Note that it is *NOT* the responsibility of these functions to
761  * resolve entries that are not in the map files.
762  *
763  * Any SID can be in the map files (i.e from any Domain).
764  *
765  ***********************************************************/
766
767 #if 0
768
769 /***********************************************************
770  Lookup a UNIX Group entry by name.
771 ************************************************************/
772 BOOL map_unix_group_name(char *group_name, DOM_NAME_MAP *grp_info)
773 {
774         return map_unixname(DOM_MAP_DOMAIN, group_name, grp_info);
775 }
776
777 /***********************************************************
778  Lookup a UNIX Alias entry by name.
779 ************************************************************/
780 BOOL map_unix_alias_name(char *alias_name, DOM_NAME_MAP *grp_info)
781 {
782         return map_unixname(DOM_MAP_LOCAL, alias_name, grp_info);
783 }
784
785 /***********************************************************
786  Lookup an Alias name entry 
787 ************************************************************/
788 BOOL map_nt_alias_name(char *ntalias_name, char *nt_domain, DOM_NAME_MAP *grp_info)
789 {
790         return map_ntname(DOM_MAP_LOCAL, ntalias_name, nt_domain, grp_info);
791 }
792
793 /***********************************************************
794  Lookup a Group entry
795 ************************************************************/
796 BOOL map_nt_group_name(char *ntgroup_name, char *nt_domain, DOM_NAME_MAP *grp_info)
797 {
798         return map_ntname(DOM_MAP_DOMAIN, ntgroup_name, nt_domain, grp_info);
799 }
800
801 #endif
802
803 /***********************************************************
804  Lookup a Username entry by name.
805 ************************************************************/
806 static BOOL map_nt_username(char *nt_name, char *nt_domain, DOM_NAME_MAP *grp_info)
807 {
808         return map_ntname(DOM_MAP_USER, nt_name, nt_domain, grp_info);
809 }
810
811 /***********************************************************
812  Lookup a Username entry by SID.
813 ************************************************************/
814 static BOOL map_username_sid(DOM_SID *sid, DOM_NAME_MAP *grp_info)
815 {
816         return map_sid(DOM_MAP_USER, sid, grp_info);
817 }
818
819 /***********************************************************
820  Lookup a Username SID entry by uid.
821 ************************************************************/
822 static BOOL map_username_uid(uid_t gid, DOM_NAME_MAP *grp_info)
823 {
824         return map_unixid(DOM_MAP_USER, (uint32)gid, grp_info);
825 }
826
827 /***********************************************************
828  Lookup an Alias SID entry by name.
829 ************************************************************/
830 BOOL map_alias_sid(DOM_SID *psid, DOM_NAME_MAP *grp_info)
831 {
832         return map_sid(DOM_MAP_LOCAL, psid, grp_info);
833 }
834
835 /***********************************************************
836  Lookup a Group entry by sid.
837 ************************************************************/
838 BOOL map_group_sid(DOM_SID *psid, DOM_NAME_MAP *grp_info)
839 {
840         return map_sid(DOM_MAP_DOMAIN, psid, grp_info);
841 }
842
843 /***********************************************************
844  Lookup an Alias SID entry by gid_t.
845 ************************************************************/
846 static BOOL map_alias_gid(gid_t gid, DOM_NAME_MAP *grp_info)
847 {
848         return map_unixid(DOM_MAP_LOCAL, (uint32)gid, grp_info);
849 }
850
851 /***********************************************************
852  Lookup a Group SID entry by gid_t.
853 ************************************************************/
854 static BOOL map_group_gid( gid_t gid, DOM_NAME_MAP *grp_info)
855 {
856         return map_unixid(DOM_MAP_DOMAIN, (uint32)gid, grp_info);
857 }
858
859
860 /************************************************************************
861  Routine to look up User details by UNIX name
862 *************************************************************************/
863 BOOL lookupsmbpwnam(const char *unix_usr_name, DOM_NAME_MAP *grp)
864 {
865         uid_t uid;
866         DEBUG(10,("lookupsmbpwnam: unix user name %s\n", unix_usr_name));
867         if (nametouid(unix_usr_name, &uid))
868         {
869                 return lookupsmbpwuid(uid, grp);
870         }
871         else
872         {
873                 return False;
874         }
875 }
876
877 /************************************************************************
878  Routine to look up a remote nt name
879 *************************************************************************/
880 static BOOL lookup_remote_ntname(const char *ntname, DOM_SID *sid, uint8 *type)
881 {
882         struct cli_state cli;
883         POLICY_HND lsa_pol;
884         fstring srv_name;
885         extern struct ntuser_creds *usr_creds;
886         struct ntuser_creds usr;
887
888         BOOL res3 = True;
889         BOOL res4 = True;
890         uint32 num_sids;
891         DOM_SID *sids;
892         uint8 *types;
893         char *names[1];
894
895         usr_creds = &usr;
896
897         ZERO_STRUCT(usr);
898         pwd_set_nullpwd(&usr.pwd);
899
900         DEBUG(5,("lookup_remote_ntname: %s\n", ntname));
901
902         if (!cli_connect_serverlist(&cli, lp_passwordserver()))
903         {
904                 return False;
905         }
906
907         names[0] = ntname;
908
909         fstrcpy(srv_name, "\\\\");
910         fstrcat(srv_name, cli.desthost);
911         strupper(srv_name);
912
913         /* lookup domain controller; receive a policy handle */
914         res3 = res3 ? lsa_open_policy( srv_name,
915                                 &lsa_pol, True) : False;
916
917         /* send lsa lookup sids call */
918         res4 = res3 ? lsa_lookup_names( &lsa_pol,
919                                        1, names, 
920                                        &sids, &types, &num_sids) : False;
921
922         res3 = res3 ? lsa_close(&lsa_pol) : False;
923
924         if (res4 && res3 && sids != NULL && types != NULL)
925         {
926                 sid_copy(sid, &sids[0]);
927                 *type = types[0];
928         }
929         else
930         {
931                 res3 = False;
932         }
933         if (types != NULL)
934         {
935                 free(types);
936         }
937         
938         if (sids != NULL)
939         {
940                 free(sids);
941         }
942         
943         return res3 && res4;
944 }
945
946 /************************************************************************
947  Routine to look up a remote nt name
948 *************************************************************************/
949 static BOOL get_sid_and_type(const char *fullntname, uint8 expected_type,
950                                 DOM_NAME_MAP *gmep)
951 {
952         /*
953          * check with the PDC to see if it owns the name.  if so,
954          * the SID is resolved with the PDC database.
955          */
956
957         if (lp_server_role() == ROLE_DOMAIN_MEMBER)
958         {
959                 if (lookup_remote_ntname(fullntname, &gmep->sid, &gmep->type))
960                 {
961                         if (sid_front_equal(&gmep->sid, &global_member_sid) &&
962                             strequal(gmep->nt_domain, global_myworkgroup) &&
963                             gmep->type == expected_type)
964                         {
965                                 return True;
966                         }
967                         return False;
968                 }
969         }
970
971         /*
972          * ... otherwise, it's one of ours.  map the sid ourselves,
973          * which can only happen in our own SAM database.
974          */
975
976         if (!strequal(gmep->nt_domain, global_sam_name))
977         {
978                 return False;
979         }
980         if (!pwdb_unixid_to_sam_sid(gmep->unix_id, gmep->type, &gmep->sid))
981         {
982                 return False;
983         }
984
985         return True;
986 }
987
988 /*
989  * used by lookup functions below
990  */
991
992 static fstring nt_name;
993 static fstring unix_name;
994 static fstring nt_domain;
995
996 /*************************************************************************
997  looks up a uid, returns User Information.  
998 *************************************************************************/
999 BOOL lookupsmbpwuid(uid_t uid, DOM_NAME_MAP *gmep)
1000 {
1001         DEBUG(10,("lookupsmbpwuid: unix uid %d\n", uid));
1002         if (map_username_uid(uid, gmep))
1003         {
1004                 return True;
1005         }
1006 #if 0
1007         if (lp_server_role() != ROLE_DOMAIN_NONE)
1008 #endif
1009         {
1010                 gmep->nt_name   = nt_name;
1011                 gmep->unix_name = unix_name;
1012                 gmep->nt_domain = nt_domain;
1013
1014                 gmep->unix_id = (uint32)uid;
1015
1016                 /*
1017                  * ok, assume it's one of ours.  then double-check it
1018                  * if we are a member of a domain
1019                  */
1020
1021                 gmep->type = SID_NAME_USER;
1022                 fstrcpy(gmep->nt_name, uidtoname(uid));
1023                 fstrcpy(gmep->unix_name, gmep->nt_name);
1024
1025                 /*
1026                  * here we should do a LsaLookupNames() call
1027                  * to check the status of the name with the PDC.
1028                  * if the PDC know nothing of the name, it's ours.
1029                  */
1030
1031                 if (lp_server_role() == ROLE_DOMAIN_MEMBER)
1032                 {
1033 #if 0
1034                         lsa_lookup_names(global_myworkgroup, gmep->nt_name, &gmep->sid...);
1035 #endif
1036                 }
1037
1038                 /*
1039                  * ok, it's one of ours.
1040                  */
1041
1042                 gmep->nt_domain = global_sam_name;
1043                 pwdb_unixid_to_sam_sid(gmep->unix_id, gmep->type, &gmep->sid);
1044
1045                 return True;
1046         }
1047
1048         /* oops. */
1049
1050         return False;
1051 }
1052
1053 /*************************************************************************
1054  looks up by NT name, returns User Information.  
1055 *************************************************************************/
1056 BOOL lookupsmbpwntnam(const char *fullntname, DOM_NAME_MAP *gmep)
1057 {
1058         DEBUG(10,("lookupsmbpwntnam: nt user name %s\n", fullntname));
1059
1060         if (!split_domain_name(fullntname, nt_domain, nt_name))
1061         {
1062                 return False;
1063         }
1064
1065         if (map_nt_username(nt_name, nt_domain, gmep))
1066         {
1067                 return True;
1068         }
1069         if (lp_server_role() != ROLE_DOMAIN_NONE)
1070         {
1071                 uid_t uid;
1072                 gmep->nt_name   = nt_name;
1073                 gmep->unix_name = unix_name;
1074                 gmep->nt_domain = nt_domain;
1075
1076                 /*
1077                  * ok, it's one of ours.  we therefore "create" an nt user named
1078                  * after the unix user.  this is the point where "appliance mode"
1079                  * should get its teeth in, as unix users won't really exist,
1080                  * they will only be numbers...
1081                  */
1082
1083                 gmep->type = SID_NAME_USER;
1084                 fstrcpy(gmep->unix_name, gmep->nt_name);
1085                 if (!nametouid(gmep->unix_name, &uid))
1086                 {
1087                         return False;
1088                 }
1089                 gmep->unix_id = (uint32)uid;
1090
1091                 return get_sid_and_type(fullntname, gmep->type, gmep);
1092         }
1093
1094         /* oops. */
1095
1096         return False;
1097 }
1098
1099 /*************************************************************************
1100  looks up by RID, returns User Information.  
1101 *************************************************************************/
1102 BOOL lookupsmbpwsid(DOM_SID *sid, DOM_NAME_MAP *gmep)
1103 {
1104         fstring sid_str;
1105         sid_to_string(sid_str, sid);
1106         DEBUG(10,("lookupsmbpwsid: nt sid %s\n", sid_str));
1107
1108         if (map_username_sid(sid, gmep))
1109         {
1110                 return True;
1111         }
1112         if (lp_server_role() != ROLE_DOMAIN_NONE)
1113         {
1114                 gmep->nt_name   = nt_name;
1115                 gmep->unix_name = unix_name;
1116                 gmep->nt_domain = nt_domain;
1117
1118                 /*
1119                  * here we should do a LsaLookupNames() call
1120                  * to check the status of the name with the PDC.
1121                  * if the PDC know nothing of the name, it's ours.
1122                  */
1123
1124                 if (lp_server_role() == ROLE_DOMAIN_MEMBER)
1125                 {
1126 #if 0
1127                         if (lookup_remote_sid(global_myworkgroup, gmep->sid, gmep->nt_name, gmep->nt_domain...);
1128 #endif
1129                 }
1130
1131                 /*
1132                  * ok, it's one of ours.  we therefore "create" an nt user named
1133                  * after the unix user.  this is the point where "appliance mode"
1134                  * should get its teeth in, as unix users won't really exist,
1135                  * they will only be numbers...
1136                  */
1137
1138                 gmep->type = SID_NAME_USER;
1139                 sid_copy(&gmep->sid, sid);
1140                 if (!pwdb_sam_sid_to_unixid(&gmep->sid, gmep->type, &gmep->unix_id))
1141                 {
1142                         return False;
1143                 }
1144                 fstrcpy(gmep->nt_name, uidtoname((uid_t)gmep->unix_id));
1145                 fstrcpy(gmep->unix_name, gmep->nt_name);
1146                 gmep->nt_domain = global_sam_name;
1147
1148                 return True;
1149         }
1150
1151         /* oops. */
1152
1153         return False;
1154 }
1155
1156 /************************************************************************
1157  Routine to look up group / alias / well-known group RID by UNIX name
1158 *************************************************************************/
1159 BOOL lookupsmbgrpnam(const char *unix_grp_name, DOM_NAME_MAP *grp)
1160 {
1161         gid_t gid;
1162         DEBUG(10,("lookupsmbgrpnam: unix user group %s\n", unix_grp_name));
1163         if (nametogid(unix_grp_name, &gid))
1164         {
1165                 return lookupsmbgrpgid(gid, grp);
1166         }
1167         else
1168         {
1169                 return False;
1170         }
1171 }
1172
1173 /*************************************************************************
1174  looks up a SID, returns name map entry
1175 *************************************************************************/
1176 BOOL lookupsmbgrpsid(DOM_SID *sid, DOM_NAME_MAP *gmep)
1177 {
1178         fstring sid_str;
1179         sid_to_string(sid_str, sid);
1180         DEBUG(10,("lookupsmbgrpsid: nt sid %s\n", sid_str));
1181
1182         if (map_alias_sid(sid, gmep))
1183         {
1184                 return True;
1185         }
1186         if (map_group_sid(sid, gmep))
1187         {
1188                 return True;
1189         }
1190         if (lp_server_role() != ROLE_DOMAIN_NONE)
1191         {
1192                 gmep->nt_name   = nt_name;
1193                 gmep->unix_name = unix_name;
1194                 gmep->nt_domain = nt_domain;
1195
1196                 /*
1197                  * here we should do a LsaLookupNames() call
1198                  * to check the status of the name with the PDC.
1199                  * if the PDC know nothing of the name, it's ours.
1200                  */
1201
1202                 if (lp_server_role() == ROLE_DOMAIN_MEMBER)
1203                 {
1204 #if 0
1205                         lsa_lookup_sids(global_myworkgroup, gmep->sid, gmep->nt_name, gmep->nt_domain...);
1206 #endif
1207                 }
1208
1209                 /*
1210                  * ok, it's one of ours.  we therefore "create" an nt group or
1211                  * alias name named after the unix group.  this is the point
1212                  * where "appliance mode" should get its teeth in, as unix
1213                  * groups won't really exist, they will only be numbers...
1214                  */
1215
1216                 /* name is not explicitly mapped
1217                  * with map files or the PDC
1218                  * so we are responsible for it...
1219                  */
1220
1221                 if (lp_server_role() == ROLE_DOMAIN_MEMBER)
1222                 {
1223                         /* ... as a LOCAL group. */
1224                         gmep->type = SID_NAME_ALIAS;
1225                 }
1226                 else
1227                 {
1228                         /* ... as a DOMAIN group. */
1229                         gmep->type = SID_NAME_DOM_GRP;
1230                 }
1231
1232                 sid_copy(&gmep->sid, sid);
1233                 if (!pwdb_sam_sid_to_unixid(&gmep->sid, gmep->type, &gmep->unix_id))
1234                 {
1235                         return False;
1236                 }
1237                 fstrcpy(gmep->nt_name, gidtoname((gid_t)gmep->unix_id));
1238                 fstrcpy(gmep->unix_name, gmep->nt_name);
1239                 gmep->nt_domain = global_sam_name;
1240
1241                 return True;
1242         }
1243
1244         /* oops */
1245         return False;
1246 }
1247
1248 /*************************************************************************
1249  looks up a gid, returns RID and type local, domain or well-known domain group
1250 *************************************************************************/
1251 BOOL lookupsmbgrpgid(gid_t gid, DOM_NAME_MAP *gmep)
1252 {
1253         DEBUG(10,("lookupsmbgrpgid: unix gid %d\n", (int)gid));
1254         if (map_alias_gid(gid, gmep))
1255         {
1256                 return True;
1257         }
1258         if (map_group_gid(gid, gmep))
1259         {
1260                 return True;
1261         }
1262         if (lp_server_role() != ROLE_DOMAIN_NONE)
1263         {
1264                 gmep->nt_name   = nt_name;
1265                 gmep->unix_name = unix_name;
1266                 gmep->nt_domain = nt_domain;
1267
1268                 gmep->unix_id = (uint32)gid;
1269
1270                 /*
1271                  * here we should do a LsaLookupNames() call
1272                  * to check the status of the name with the PDC.
1273                  * if the PDC know nothing of the name, it's ours.
1274                  */
1275
1276                 if (lp_server_role() == ROLE_DOMAIN_MEMBER)
1277                 {
1278 #if 0
1279                         if (lsa_lookup_names(global_myworkgroup, gmep->nt_name, &gmep->sid...);
1280                         {
1281                                 return True;
1282                         }
1283 #endif
1284                 }
1285
1286                 /*
1287                  * ok, it's one of ours.  we therefore "create" an nt group or
1288                  * alias name named after the unix group.  this is the point
1289                  * where "appliance mode" should get its teeth in, as unix
1290                  * groups won't really exist, they will only be numbers...
1291                  */
1292
1293                 /* name is not explicitly mapped
1294                  * with map files or the PDC
1295                  * so we are responsible for it...
1296                  */
1297
1298                 if (lp_server_role() == ROLE_DOMAIN_MEMBER)
1299                 {
1300                         /* ... as a LOCAL group. */
1301                         gmep->type = SID_NAME_ALIAS;
1302                 }
1303                 else
1304                 {
1305                         /* ... as a DOMAIN group. */
1306                         gmep->type = SID_NAME_DOM_GRP;
1307                 }
1308                 fstrcpy(gmep->nt_name, gidtoname(gid));
1309                 fstrcpy(gmep->unix_name, gmep->nt_name);
1310
1311                 return get_sid_and_type(gmep->nt_name, gmep->type, gmep);
1312         }
1313
1314         /* oops */
1315         return False;
1316 }
1317