fixed an uninitialized variable in lookupsmbgrpgid() and
[samba.git] / source / 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                 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         SMB_STRUCT_STAT st;
483         FILE *fp;
484         char *s;
485         pstring buf;
486         name_map_entry *new_ep;
487
488         time_t *file_last_modified = NULL;
489         int    *initialised = NULL;
490         char   *map_file = NULL;
491         ubi_slList *map_list = NULL;
492
493         switch (type)
494         {
495                 case DOM_MAP_DOMAIN:
496                 {
497                         file_last_modified = &groupmap_file_last_modified;
498                         initialised        = &initialised_group;
499                         map_file           = groupname_map_file;
500                         map_list           = &groupname_map_list;
501
502                         break;
503                 }
504                 case DOM_MAP_LOCAL:
505                 {
506                         file_last_modified = &aliasmap_file_last_modified;
507                         initialised        = &initialised_alias;
508                         map_file           = aliasname_map_file;
509                         map_list           = &aliasname_map_list;
510
511                         break;
512                 }
513                 case DOM_MAP_USER:
514                 {
515                         file_last_modified = &ntusrmap_file_last_modified;
516                         initialised        = &initialised_ntusr;
517                         map_file           = ntusrname_map_file;
518                         map_list           = &ntusrname_map_list;
519
520                         break;
521                 }
522         }
523
524         if (!(*initialised))
525         {
526                 DEBUG(10,("initialising map %s\n", map_file));
527                 ubi_slInitList(map_list);
528                 (*initialised) = True;
529         }
530
531         if (!*map_file)
532         {
533                 return map_list;
534         }
535
536         if (sys_stat(map_file, &st) != 0)
537         {
538                 DEBUG(0, ("load_name_map: Unable to stat file %s. Error was %s\n",
539                            map_file, strerror(errno) ));
540                 return map_list;
541         }
542
543         /*
544          * Check if file has changed.
545          */
546         if (st.st_mtime <= (*file_last_modified))
547         {
548                 return map_list;
549         }
550
551         (*file_last_modified) = st.st_mtime;
552
553         /*
554          * Load the file.
555          */
556
557         fp = fopen(map_file,"r");
558         if (!fp)
559         {
560                 DEBUG(0,("load_name_map: can't open name map %s. Error was %s\n",
561                           map_file, strerror(errno)));
562                 return map_list;
563         }
564
565         /*
566          * Throw away any previous list.
567          */
568         delete_map_list(map_list);
569
570         DEBUG(4,("load_name_map: Scanning name map %s\n",map_file));
571
572         while ((s = fgets_slash(buf, sizeof(buf), fp)) != NULL)
573         {
574                 pstring unixname;
575                 pstring nt_name;
576                 fstring nt_domain;
577                 fstring ntname;
578                 char *p;
579
580                 DEBUG(10,("Read line |%s|\n", s));
581
582                 memset(nt_name, 0, sizeof(nt_name));
583
584                 if (!*s || strchr("#;",*s))
585                         continue;
586
587                 if (!next_token(&s,unixname, "\t\n\r=", sizeof(unixname)))
588                         continue;
589
590                 if (!next_token(&s,nt_name, "\t\n\r=", sizeof(nt_name)))
591                         continue;
592
593                 trim_string(unixname, " ", " ");
594                 trim_string(nt_name, " ", " ");
595
596                 if (!*nt_name)
597                         continue;
598
599                 if (!*unixname)
600                         continue;
601
602                 p = strchr(nt_name, '\\');
603
604                 if (p == NULL)
605                 {
606                         memset(nt_domain, 0, sizeof(nt_domain));
607                         fstrcpy(ntname, nt_name);
608                 }
609                 else
610                 {
611                         *p = 0;
612                         p++;
613                         fstrcpy(nt_domain, nt_name);
614                         fstrcpy(ntname , p);
615                 }
616
617                 if (make_name_entry(&new_ep, nt_domain, ntname, unixname, type))
618                 {
619                         ubi_slAddTail(map_list, (ubi_slNode *)new_ep);
620                         DEBUG(5,("unixname = %s, ntname = %s\\%s type = %d\n",
621                                   new_ep->grp.unix_name,
622                                   new_ep->grp.nt_domain,
623                                   new_ep->grp.nt_name,
624                                   new_ep->grp.type));
625                 }
626         }
627
628         DEBUG(10,("load_name_map: Added %ld entries to name map.\n",
629                    ubi_slCount(map_list)));
630
631         fclose(fp);
632
633         return map_list;
634 }
635
636 static void copy_grp_map_entry(DOM_NAME_MAP *grp, const DOM_NAME_MAP *from)
637 {
638         sid_copy(&grp->sid, &from->sid);
639         grp->unix_id   = from->unix_id;
640         grp->nt_name   = from->nt_name;
641         grp->nt_domain = from->nt_domain;
642         grp->unix_name = from->unix_name;
643         grp->type      = from->type;
644 }
645
646 #if 0
647 /***********************************************************
648  Lookup unix name.
649 ************************************************************/
650 static BOOL map_unixname(DOM_MAP_TYPE type,
651                 char *unixname, DOM_NAME_MAP *grp_info)
652 {
653         name_map_entry *gmep;
654         ubi_slList *map_list;
655
656         /*
657          * Initialise and load if not already loaded.
658          */
659         map_list = load_name_map(type);
660
661         for (gmep = (name_map_entry *)ubi_slFirst(map_list);
662              gmep != NULL;
663              gmep = (name_map_entry *)ubi_slNext(gmep ))
664         {
665                 if (strequal(gmep->grp.unix_name, unixname))
666                 {
667                         copy_grp_map_entry(grp_info, &gmep->grp);
668                         DEBUG(7,("map_unixname: Mapping unix name %s to nt group %s.\n",
669                                gmep->grp.unix_name, gmep->grp.nt_name ));
670                         return True;
671                 }
672         }
673
674         return False;
675 }
676
677 #endif
678
679 /***********************************************************
680  Lookup nt name.
681 ************************************************************/
682 static BOOL map_ntname(DOM_MAP_TYPE type, char *ntname, char *ntdomain,
683                                 DOM_NAME_MAP *grp_info)
684 {
685         name_map_entry *gmep;
686         ubi_slList *map_list;
687
688         /*
689          * Initialise and load if not already loaded.
690          */
691         map_list = load_name_map(type);
692
693         for (gmep = (name_map_entry *)ubi_slFirst(map_list);
694              gmep != NULL;
695              gmep = (name_map_entry *)ubi_slNext(gmep ))
696         {
697                 if (strequal(gmep->grp.nt_name  , ntname) &&
698                     strequal(gmep->grp.nt_domain, ntdomain))
699                 {
700                         copy_grp_map_entry(grp_info, &gmep->grp);
701                         DEBUG(7,("map_ntname: Mapping unix name %s to nt name %s.\n",
702                                gmep->grp.unix_name, gmep->grp.nt_name ));
703                         return True;
704                 }
705         }
706
707         return False;
708 }
709
710
711 /***********************************************************
712  Lookup by SID
713 ************************************************************/
714 static BOOL map_sid(DOM_MAP_TYPE type,
715                 DOM_SID *psid, DOM_NAME_MAP *grp_info)
716 {
717         name_map_entry *gmep;
718         ubi_slList *map_list;
719
720         /*
721          * Initialise and load if not already loaded.
722          */
723         map_list = load_name_map(type);
724
725         for (gmep = (name_map_entry *)ubi_slFirst(map_list);
726              gmep != NULL;
727              gmep = (name_map_entry *)ubi_slNext(gmep ))
728         {
729                 if (sid_equal(&gmep->grp.sid, psid))
730                 {
731                         copy_grp_map_entry(grp_info, &gmep->grp);
732                         DEBUG(7,("map_sid: Mapping unix name %s to nt name %s.\n",
733                                gmep->grp.unix_name, gmep->grp.nt_name ));
734                         return True;
735                 }
736         }
737
738         return False;
739 }
740
741 /***********************************************************
742  Lookup by gid_t.
743 ************************************************************/
744 static BOOL map_unixid(DOM_MAP_TYPE type, uint32 unix_id, DOM_NAME_MAP *grp_info)
745 {
746         name_map_entry *gmep;
747         ubi_slList *map_list;
748
749         /*
750          * Initialise and load if not already loaded.
751          */
752         map_list = load_name_map(type);
753
754         for (gmep = (name_map_entry *)ubi_slFirst(map_list);
755              gmep != NULL;
756              gmep = (name_map_entry *)ubi_slNext(gmep ))
757         {
758                 fstring sid_str;
759                 sid_to_string(sid_str, &gmep->grp.sid);
760                 DEBUG(10,("map_unixid: enum entry unix group %s %d nt %s %s\n",
761                                gmep->grp.unix_name, gmep->grp.unix_id, gmep->grp.nt_name, sid_str));
762                 if (gmep->grp.unix_id == unix_id)
763                 {
764                         copy_grp_map_entry(grp_info, &gmep->grp);
765                         DEBUG(7,("map_unixid: Mapping unix name %s to nt name %s type %d\n",
766                                gmep->grp.unix_name, gmep->grp.nt_name, gmep->grp.type));
767                         return True;
768                 }
769         }
770
771         return False;
772 }
773
774 /***********************************************************
775  *
776  * Call four functions to resolve unix group ids and either
777  * local group SIDs or domain group SIDs listed in the local group
778  * or domain group map files.
779  *
780  * Note that it is *NOT* the responsibility of these functions to
781  * resolve entries that are not in the map files.
782  *
783  * Any SID can be in the map files (i.e from any Domain).
784  *
785  ***********************************************************/
786
787 #if 0
788
789 /***********************************************************
790  Lookup a UNIX Group entry by name.
791 ************************************************************/
792 BOOL map_unix_group_name(char *group_name, DOM_NAME_MAP *grp_info)
793 {
794         return map_unixname(DOM_MAP_DOMAIN, group_name, grp_info);
795 }
796
797 /***********************************************************
798  Lookup a UNIX Alias entry by name.
799 ************************************************************/
800 BOOL map_unix_alias_name(char *alias_name, DOM_NAME_MAP *grp_info)
801 {
802         return map_unixname(DOM_MAP_LOCAL, alias_name, grp_info);
803 }
804
805 /***********************************************************
806  Lookup an Alias name entry 
807 ************************************************************/
808 BOOL map_nt_alias_name(char *ntalias_name, char *nt_domain, DOM_NAME_MAP *grp_info)
809 {
810         return map_ntname(DOM_MAP_LOCAL, ntalias_name, nt_domain, grp_info);
811 }
812
813 /***********************************************************
814  Lookup a Group entry
815 ************************************************************/
816 BOOL map_nt_group_name(char *ntgroup_name, char *nt_domain, DOM_NAME_MAP *grp_info)
817 {
818         return map_ntname(DOM_MAP_DOMAIN, ntgroup_name, nt_domain, grp_info);
819 }
820
821 #endif
822
823 /***********************************************************
824  Lookup a Username entry by name.
825 ************************************************************/
826 static BOOL map_nt_username(char *nt_name, char *nt_domain, DOM_NAME_MAP *grp_info)
827 {
828         return map_ntname(DOM_MAP_USER, nt_name, nt_domain, grp_info);
829 }
830
831 /***********************************************************
832  Lookup a Username entry by SID.
833 ************************************************************/
834 static BOOL map_username_sid(DOM_SID *sid, DOM_NAME_MAP *grp_info)
835 {
836         return map_sid(DOM_MAP_USER, sid, grp_info);
837 }
838
839 /***********************************************************
840  Lookup a Username SID entry by uid.
841 ************************************************************/
842 static BOOL map_username_uid(uid_t gid, DOM_NAME_MAP *grp_info)
843 {
844         return map_unixid(DOM_MAP_USER, (uint32)gid, grp_info);
845 }
846
847 /***********************************************************
848  Lookup an Alias SID entry by name.
849 ************************************************************/
850 BOOL map_alias_sid(DOM_SID *psid, DOM_NAME_MAP *grp_info)
851 {
852         return map_sid(DOM_MAP_LOCAL, psid, grp_info);
853 }
854
855 /***********************************************************
856  Lookup a Group entry by sid.
857 ************************************************************/
858 BOOL map_group_sid(DOM_SID *psid, DOM_NAME_MAP *grp_info)
859 {
860         return map_sid(DOM_MAP_DOMAIN, psid, grp_info);
861 }
862
863 /***********************************************************
864  Lookup an Alias SID entry by gid_t.
865 ************************************************************/
866 static BOOL map_alias_gid(gid_t gid, DOM_NAME_MAP *grp_info)
867 {
868         return map_unixid(DOM_MAP_LOCAL, (uint32)gid, grp_info);
869 }
870
871 /***********************************************************
872  Lookup a Group SID entry by gid_t.
873 ************************************************************/
874 static BOOL map_group_gid( gid_t gid, DOM_NAME_MAP *grp_info)
875 {
876         return map_unixid(DOM_MAP_DOMAIN, (uint32)gid, grp_info);
877 }
878
879
880 /************************************************************************
881  Routine to look up User details by UNIX name
882 *************************************************************************/
883 BOOL lookupsmbpwnam(const char *unix_usr_name, DOM_NAME_MAP *grp)
884 {
885         uid_t uid;
886         DEBUG(10,("lookupsmbpwnam: unix user name %s\n", unix_usr_name));
887         if (nametouid(unix_usr_name, &uid))
888         {
889                 return lookupsmbpwuid(uid, grp);
890         }
891         else
892         {
893                 return False;
894         }
895 }
896
897 /************************************************************************
898  Routine to look up a remote nt name
899 *************************************************************************/
900 static BOOL lookup_remote_ntname(const char *ntname, DOM_SID *sid, uint8 *type)
901 {
902         struct cli_state cli;
903         POLICY_HND lsa_pol;
904         uint16 fnum_lsa;
905         fstring srv_name;
906
907         BOOL res3 = True;
908         BOOL res4 = True;
909         uint32 num_sids;
910         DOM_SID *sids;
911         uint8 *types;
912         const char *names[1];
913
914         if (!cli_connect_serverlist(&cli, lp_passwordserver()))
915         {
916                 return False;
917         }
918
919         names[0] = ntname;
920
921         fstrcpy(srv_name, "\\\\");
922         fstrcat(srv_name, cli.desthost);
923         strupper(srv_name);
924
925         /* open LSARPC session. */
926         res3 = res3 ? cli_nt_session_open(&cli, PIPE_LSARPC, &fnum_lsa) : False;
927
928         /* lookup domain controller; receive a policy handle */
929         res3 = res3 ? lsa_open_policy(&cli, fnum_lsa,
930                                 srv_name,
931                                 &lsa_pol, True) : False;
932
933         /* send lsa lookup sids call */
934         res4 = res3 ? lsa_lookup_names(&cli, fnum_lsa, 
935                                        &lsa_pol,
936                                        1, names, 
937                                        &sids, &types, &num_sids) : False;
938
939         res3 = res3 ? lsa_close(&cli, fnum_lsa, &lsa_pol) : False;
940
941         cli_nt_session_close(&cli, fnum_lsa);
942
943         if (res4 && res3 && sids != NULL && types != NULL)
944         {
945                 sid_copy(sid, &sids[0]);
946                 *type = types[0];
947         }
948         else
949         {
950                 res3 = False;
951         }
952         if (types != NULL)
953         {
954                 free(types);
955         }
956         
957         if (sids != NULL)
958         {
959                 free(sids);
960         }
961         
962         return res3 && res4;
963 }
964
965 /************************************************************************
966  Routine to look up a remote nt name
967 *************************************************************************/
968 static BOOL get_sid_and_type(const char *fullntname, uint8 expected_type,
969                                 DOM_NAME_MAP *gmep)
970 {
971         /*
972          * check with the PDC to see if it owns the name.  if so,
973          * the SID is resolved with the PDC database.
974          */
975
976         if (lp_server_role() == ROLE_DOMAIN_MEMBER)
977         {
978                 if (lookup_remote_ntname(fullntname, &gmep->sid, &gmep->type))
979                 {
980                         if (sid_front_equal(&gmep->sid, &global_member_sid) &&
981                             strequal(gmep->nt_domain, global_myworkgroup) &&
982                             gmep->type == expected_type)
983                         {
984                                 return True;
985                         }
986                         return False;
987                 }
988         }
989
990         /*
991          * ... otherwise, it's one of ours.  map the sid ourselves,
992          * which can only happen in our own SAM database.
993          */
994
995         if (!strequal(gmep->nt_domain, global_sam_name))
996         {
997                 return False;
998         }
999         if (!pwdb_unixid_to_sam_sid(gmep->unix_id, gmep->type, &gmep->sid))
1000         {
1001                 return False;
1002         }
1003
1004         return True;
1005 }
1006
1007 /*
1008  * used by lookup functions below
1009  */
1010
1011 static fstring nt_name;
1012 static fstring unix_name;
1013 static fstring nt_domain;
1014
1015 /*************************************************************************
1016  looks up a uid, returns User Information.  
1017 *************************************************************************/
1018 BOOL lookupsmbpwuid(uid_t uid, DOM_NAME_MAP *gmep)
1019 {
1020         DEBUG(10,("lookupsmbpwuid: unix uid %d\n", uid));
1021         if (map_username_uid(uid, gmep))
1022         {
1023                 return True;
1024         }
1025         if (lp_server_role() != ROLE_DOMAIN_NONE)
1026         {
1027                 gmep->nt_name   = nt_name;
1028                 gmep->unix_name = unix_name;
1029                 gmep->nt_domain = nt_domain;
1030
1031                 gmep->unix_id = (uint32)uid;
1032
1033                 /*
1034                  * ok, assume it's one of ours.  then double-check it
1035                  * if we are a member of a domain
1036                  */
1037
1038                 gmep->type = SID_NAME_USER;
1039                 fstrcpy(gmep->nt_name, uidtoname(uid));
1040                 fstrcpy(gmep->unix_name, gmep->nt_name);
1041
1042                 /*
1043                  * here we should do a LsaLookupNames() call
1044                  * to check the status of the name with the PDC.
1045                  * if the PDC know nothing of the name, it's ours.
1046                  */
1047
1048                 if (lp_server_role() == ROLE_DOMAIN_MEMBER)
1049                 {
1050 #if 0
1051                         lsa_lookup_names(global_myworkgroup, gmep->nt_name, &gmep->sid...);
1052 #endif
1053                 }
1054
1055                 /*
1056                  * ok, it's one of ours.
1057                  */
1058
1059                 gmep->nt_domain = global_sam_name;
1060                 pwdb_unixid_to_sam_sid(gmep->unix_id, gmep->type, &gmep->sid);
1061
1062                 return True;
1063         }
1064
1065         /* oops. */
1066
1067         return False;
1068 }
1069
1070 /*************************************************************************
1071  looks up by NT name, returns User Information.  
1072 *************************************************************************/
1073 BOOL lookupsmbpwntnam(char *fullntname, DOM_NAME_MAP *gmep)
1074 {
1075         DEBUG(10,("lookupsmbpwntnam: nt user name %s\n", fullntname));
1076
1077         if (!split_domain_name(fullntname, nt_domain, nt_name))
1078         {
1079                 return False;
1080         }
1081
1082         if (map_nt_username(nt_name, nt_domain, gmep))
1083         {
1084                 return True;
1085         }
1086         if (lp_server_role() != ROLE_DOMAIN_NONE)
1087         {
1088                 uid_t uid;
1089                 gmep->nt_name   = nt_name;
1090                 gmep->unix_name = unix_name;
1091                 gmep->nt_domain = nt_domain;
1092
1093                 /*
1094                  * ok, it's one of ours.  we therefore "create" an nt user named
1095                  * after the unix user.  this is the point where "appliance mode"
1096                  * should get its teeth in, as unix users won't really exist,
1097                  * they will only be numbers...
1098                  */
1099
1100                 gmep->type = SID_NAME_USER;
1101                 fstrcpy(gmep->unix_name, gmep->nt_name);
1102                 if (!nametouid(gmep->unix_name, &uid))
1103                 {
1104                         return False;
1105                 }
1106                 gmep->unix_id = (uint32)uid;
1107
1108                 return get_sid_and_type(fullntname, gmep->type, gmep);
1109         }
1110
1111         /* oops. */
1112
1113         return False;
1114 }
1115
1116 /*************************************************************************
1117  looks up by RID, returns User Information.  
1118 *************************************************************************/
1119 BOOL lookupsmbpwsid(DOM_SID *sid, DOM_NAME_MAP *gmep)
1120 {
1121         fstring sid_str;
1122         sid_to_string(sid_str, sid);
1123         DEBUG(10,("lookupsmbpwsid: nt sid %s\n", sid_str));
1124
1125         if (map_username_sid(sid, gmep))
1126         {
1127                 return True;
1128         }
1129         if (lp_server_role() != ROLE_DOMAIN_NONE)
1130         {
1131                 gmep->nt_name   = nt_name;
1132                 gmep->unix_name = unix_name;
1133                 gmep->nt_domain = nt_domain;
1134
1135                 /*
1136                  * here we should do a LsaLookupNames() call
1137                  * to check the status of the name with the PDC.
1138                  * if the PDC know nothing of the name, it's ours.
1139                  */
1140
1141                 if (lp_server_role() == ROLE_DOMAIN_MEMBER)
1142                 {
1143 #if 0
1144                         if (lookup_remote_sid(global_myworkgroup, gmep->sid, gmep->nt_name, gmep->nt_domain...);
1145 #endif
1146                 }
1147
1148                 /*
1149                  * ok, it's one of ours.  we therefore "create" an nt user named
1150                  * after the unix user.  this is the point where "appliance mode"
1151                  * should get its teeth in, as unix users won't really exist,
1152                  * they will only be numbers...
1153                  */
1154
1155                 gmep->type = SID_NAME_USER;
1156                 sid_copy(&gmep->sid, sid);
1157                 if (!pwdb_sam_sid_to_unixid(&gmep->sid, gmep->type, &gmep->unix_id))
1158                 {
1159                         return False;
1160                 }
1161                 fstrcpy(gmep->nt_name, uidtoname((uid_t)gmep->unix_id));
1162                 fstrcpy(gmep->unix_name, gmep->nt_name);
1163                 gmep->nt_domain = global_sam_name;
1164
1165                 return True;
1166         }
1167
1168         /* oops. */
1169
1170         return False;
1171 }
1172
1173 /************************************************************************
1174  Routine to look up group / alias / well-known group RID by UNIX name
1175 *************************************************************************/
1176 BOOL lookupsmbgrpnam(const char *unix_grp_name, DOM_NAME_MAP *grp)
1177 {
1178         gid_t gid;
1179         DEBUG(10,("lookupsmbgrpnam: unix user group %s\n", unix_grp_name));
1180         if (nametogid(unix_grp_name, &gid))
1181         {
1182                 return lookupsmbgrpgid(gid, grp);
1183         }
1184         else
1185         {
1186                 return False;
1187         }
1188 }
1189
1190 /*************************************************************************
1191  looks up a SID, returns name map entry
1192 *************************************************************************/
1193 BOOL lookupsmbgrpsid(DOM_SID *sid, DOM_NAME_MAP *gmep)
1194 {
1195         fstring sid_str;
1196         sid_to_string(sid_str, sid);
1197         DEBUG(10,("lookupsmbgrpsid: nt sid %s\n", sid_str));
1198
1199         if (map_alias_sid(sid, gmep))
1200         {
1201                 return True;
1202         }
1203         if (map_group_sid(sid, gmep))
1204         {
1205                 return True;
1206         }
1207         if (lp_server_role() != ROLE_DOMAIN_NONE)
1208         {
1209                 gmep->nt_name   = nt_name;
1210                 gmep->unix_name = unix_name;
1211                 gmep->nt_domain = nt_domain;
1212
1213                 /*
1214                  * here we should do a LsaLookupNames() call
1215                  * to check the status of the name with the PDC.
1216                  * if the PDC know nothing of the name, it's ours.
1217                  */
1218
1219                 if (lp_server_role() == ROLE_DOMAIN_MEMBER)
1220                 {
1221 #if 0
1222                         lsa_lookup_sids(global_myworkgroup, gmep->sid, gmep->nt_name, gmep->nt_domain...);
1223 #endif
1224                 }
1225
1226                 /*
1227                  * ok, it's one of ours.  we therefore "create" an nt group or
1228                  * alias name named after the unix group.  this is the point
1229                  * where "appliance mode" should get its teeth in, as unix
1230                  * groups won't really exist, they will only be numbers...
1231                  */
1232
1233                 /* name is not explicitly mapped
1234                  * with map files or the PDC
1235                  * so we are responsible for it...
1236                  */
1237
1238                 if (lp_server_role() == ROLE_DOMAIN_MEMBER)
1239                 {
1240                         /* ... as a LOCAL group. */
1241                         gmep->type = SID_NAME_ALIAS;
1242                 }
1243                 else
1244                 {
1245                         /* ... as a DOMAIN group. */
1246                         gmep->type = SID_NAME_DOM_GRP;
1247                 }
1248
1249                 sid_copy(&gmep->sid, sid);
1250                 if (!pwdb_sam_sid_to_unixid(&gmep->sid, gmep->type, &gmep->unix_id))
1251                 {
1252                         return False;
1253                 }
1254                 fstrcpy(gmep->nt_name, gidtoname((gid_t)gmep->unix_id));
1255                 fstrcpy(gmep->unix_name, gmep->nt_name);
1256                 gmep->nt_domain = global_sam_name;
1257
1258                 return True;
1259         }
1260
1261         /* oops */
1262         return False;
1263 }
1264
1265 /*************************************************************************
1266  looks up a gid, returns RID and type local, domain or well-known domain group
1267 *************************************************************************/
1268 BOOL lookupsmbgrpgid(gid_t gid, DOM_NAME_MAP *gmep)
1269 {
1270         DEBUG(10,("lookupsmbgrpgid: unix gid %d\n", (int)gid));
1271         if (map_alias_gid(gid, gmep))
1272         {
1273                 return True;
1274         }
1275         if (map_group_gid(gid, gmep))
1276         {
1277                 return True;
1278         }
1279         if (lp_server_role() != ROLE_DOMAIN_NONE)
1280         {
1281                 gmep->nt_name   = nt_name;
1282                 gmep->unix_name = unix_name;
1283                 gmep->nt_domain = nt_domain;
1284
1285                 gmep->unix_id = (uint32)gid;
1286
1287                 /*
1288                  * here we should do a LsaLookupNames() call
1289                  * to check the status of the name with the PDC.
1290                  * if the PDC know nothing of the name, it's ours.
1291                  */
1292
1293                 if (lp_server_role() == ROLE_DOMAIN_MEMBER)
1294                 {
1295 #if 0
1296                         if (lsa_lookup_names(global_myworkgroup, gmep->nt_name, &gmep->sid...);
1297                         {
1298                                 return True;
1299                         }
1300 #endif
1301                 }
1302
1303                 /*
1304                  * ok, it's one of ours.  we therefore "create" an nt group or
1305                  * alias name named after the unix group.  this is the point
1306                  * where "appliance mode" should get its teeth in, as unix
1307                  * groups won't really exist, they will only be numbers...
1308                  */
1309
1310                 /* name is not explicitly mapped
1311                  * with map files or the PDC
1312                  * so we are responsible for it...
1313                  */
1314
1315                 if (lp_server_role() == ROLE_DOMAIN_MEMBER)
1316                 {
1317                         /* ... as a LOCAL group. */
1318                         gmep->type = SID_NAME_ALIAS;
1319                 }
1320                 else
1321                 {
1322                         /* ... as a DOMAIN group. */
1323                         gmep->type = SID_NAME_DOM_GRP;
1324                 }
1325                 fstrcpy(gmep->nt_name, gidtoname(gid));
1326                 fstrcpy(gmep->unix_name, gmep->nt_name);
1327
1328                 return get_sid_and_type(gmep->nt_name, gmep->type, gmep);
1329         }
1330
1331         /* oops */
1332         return False;
1333 }
1334