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