2 Unix SMB/Netbios implementation.
5 Copyright (C) Jeremy Allison 1998.
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.
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.
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.
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...
33 format of the file is:
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)
42 if the DOMAIN_NAME\ component is left off, then your own domain is assumed.
50 extern int DEBUGLEVEL;
52 extern fstring global_sam_name;
54 /* we can map either local aliases or domain groups */
62 /**************************************************************************
63 Groupname map functionality. The code loads a groupname map file and
64 (currently) loads it into a linked list. This is slow and memory
65 hungry, but can be changed into a more efficient storage format
66 if the demands on it become excessive.
67 ***************************************************************************/
69 typedef struct group_name_info
80 typedef struct name_map
87 static ubi_slList groupname_map_list;
88 static ubi_slList aliasname_map_list;
90 static void delete_name_entry(name_map_entry *gmep)
92 if (gmep->grp.nt_name)
94 free(gmep->grp.nt_name);
96 if (gmep->grp.nt_domain)
98 free(gmep->grp.nt_domain);
100 if (gmep->grp.unix_name)
102 free(gmep->grp.unix_name);
107 /**************************************************************************
108 Delete all the entries in the name map list.
109 ***************************************************************************/
111 static void delete_map_list(ubi_slList *map_list)
113 name_map_entry *gmep;
115 while ((gmep = (name_map_entry *)ubi_slRemHead(map_list )) != NULL)
117 delete_name_entry(gmep);
122 /**************************************************************************
123 makes a group sid out of a domain sid and a _unix_ gid.
124 ***************************************************************************/
125 static BOOL make_mydomain_sid(GROUP_NAME_INFO *grp, GROUP_TYPE type)
131 DEBUG(10,("make_mydomain_sid\n"));
133 if (!map_domain_name_to_sid(&grp->sid, &(grp->nt_domain)))
135 DEBUG(0,("make_mydomain_sid: unknown domain %s\n",
140 if (strequal(grp->nt_domain, global_sam_name) &&
141 lookup_wk_group_name(grp->nt_name, &sid, &tmp_type))
143 sid_copy(&grp->sid, &sid);
148 if (type == GROUP_DOMAIN)
150 tmp_rid = pwdb_gid_to_group_rid(grp->unix_gid);
154 tmp_rid = pwdb_gid_to_alias_rid(grp->unix_gid);
156 return sid_append_rid(&(grp->sid), tmp_rid);
160 /**************************************************************************
161 makes a group sid out of an nt domain, nt group name or a unix group name.
162 ***************************************************************************/
163 static BOOL unix_name_to_group_info(GROUP_NAME_INFO *grp, GROUP_TYPE type)
165 struct group *gptr = NULL;
168 * Attempt to get the unix gid_t for this name.
171 DEBUG(5,("unix_name_to_group_info: unix_name:%s\n", grp->unix_name));
173 gptr = (struct group *)getgrnam(grp->unix_name);
176 DEBUG(0,("unix_name_to_group_info: getgrnam for group %s\
177 failed. Error was %s.\n", grp->unix_name, strerror(errno) ));
181 grp->unix_gid = (gid_t)gptr->gr_gid;
183 DEBUG(5,("unix_name_to_group_info: unix gid:%d\n", grp->unix_gid));
186 * Now map the name to an NT SID+RID.
189 if (grp->nt_domain != NULL && !strequal(grp->nt_domain, global_sam_name))
191 /* Must add client-call lookup code here, to
192 * resolve remote domain's sid and the group's rid,
195 * NOTE: it is _incorrect_ to put code here that assumes
196 * that we can call pwdb_gid_to_group_rid() or _alias_rid():
197 * it is a totally different domain for which we are *NOT*
199 * for foriegn domains for which we are *NOT* the PDC, all
200 * we can be responsible for is the unix * gid_t to which
201 * the foriegn SID+rid maps to, on this _local_ machine.
204 if (!map_domain_name_to_sid(&grp->sid, &(grp->nt_domain)))
206 DEBUG(0,("unix_name_to_group_info: no known sid for %s\n",
211 DEBUG(0,("unix_name_to_group_info: cannot resolve domain %s\n",
218 return make_mydomain_sid(grp, type);
222 static BOOL make_name_entry(name_map_entry **new_ep,
223 char *nt_domain, char *nt_group, char *unix_group,
227 * Create the list entry and add it onto the list.
230 DEBUG(5,("make_name_entry:%s,%s,%s\n", nt_domain, nt_group, unix_group));
232 (*new_ep) = (name_map_entry *)malloc(sizeof(name_map_entry));
233 if ((*new_ep) == NULL)
235 DEBUG(0,("make_name_entry: malloc fail for name_map_entry.\n"));
239 ZERO_STRUCTP(*new_ep);
241 (*new_ep)->grp.nt_name = strdup(nt_group );
242 (*new_ep)->grp.nt_domain = strdup(nt_domain );
243 (*new_ep)->grp.unix_name = strdup(unix_group);
245 if ((*new_ep)->grp.nt_name == NULL ||
246 (*new_ep)->grp.unix_name == NULL)
248 DEBUG(0,("make_name_entry: malloc fail for names in name_map_entry.\n"));
249 delete_name_entry((*new_ep));
254 * look up the group names, make the Group-SID and unix gid
257 if (!unix_name_to_group_info(&(*new_ep)->grp, type))
259 delete_name_entry((*new_ep));
266 /**************************************************************************
267 Load a name map file. Sets last accessed timestamp.
268 ***************************************************************************/
269 static void load_name_map(GROUP_TYPE type)
271 static time_t groupmap_file_last_modified = (time_t)0;
272 static time_t aliasmap_file_last_modified = (time_t)0;
273 static BOOL initialised_group = False;
274 static BOOL initialised_alias = False;
275 char *groupname_map_file = lp_groupname_map();
276 char *aliasname_map_file = lp_aliasname_map();
282 name_map_entry *new_ep;
284 time_t *file_last_modified;
287 ubi_slList *map_list;
289 if (type == GROUP_DOMAIN)
291 file_last_modified = &groupmap_file_last_modified;
292 initialised = &initialised_group;
293 map_file = groupname_map_file;
294 map_list = &groupname_map_list;
298 file_last_modified = &aliasmap_file_last_modified;
299 initialised = &initialised_alias;
300 map_file = aliasname_map_file;
301 map_list = &aliasname_map_list;
304 DEBUG(10,("load_name_map : %s\n", map_file));
308 ubi_slInitList(map_list);
309 (*initialised) = True;
317 if (sys_stat(map_file, &st) != 0)
319 DEBUG(0, ("load_name_map: Unable to stat file %s. Error was %s\n",
320 map_file, strerror(errno) ));
325 * Check if file has changed.
327 if (st.st_mtime <= (*file_last_modified))
332 (*file_last_modified) = st.st_mtime;
338 fp = fopen(map_file,"r");
341 DEBUG(0,("load_name_map: can't open name map %s. Error was %s\n",
342 map_file, strerror(errno)));
347 * Throw away any previous list.
349 delete_map_list(map_list);
351 DEBUG(4,("load_name_map: Scanning name map %s\n",map_file));
353 while ((s = fgets_slash(buf, sizeof(buf), fp)) != NULL)
361 DEBUG(10,("Read line |%s|\n", s));
363 memset(nt_name, 0, sizeof(nt_name));
365 if (!*s || strchr("#;",*s))
368 if (!next_token(&s,unixname, "\t\n\r=", sizeof(unixname)))
371 if (!next_token(&s,nt_name, "\t\n\r=", sizeof(nt_name)))
374 trim_string(unixname, " ", " ");
375 trim_string(nt_name, " ", " ");
383 DEBUG(5,("unixname = %s, ntname = %s.\n",
386 p = strchr(nt_name, '\\');
390 memset(nt_domain, 0, sizeof(nt_domain));
391 fstrcpy(nt_group, nt_name);
397 fstrcpy(nt_domain, nt_name);
398 fstrcpy(nt_group , p);
401 if (make_name_entry(&new_ep, nt_domain, nt_name, unixname, type))
403 ubi_slAddHead(map_list, (ubi_slNode *)new_ep);
407 DEBUG(10,("load_name_map: Added %ld entries to name map.\n",
408 ubi_slCount(map_list)));
413 /***********************************************************
415 ************************************************************/
416 static BOOL map_sid(GROUP_TYPE type, ubi_slList *map_list,
417 DOM_SID *psid, gid_t *gid, char *ntname, char *ntdomain)
419 name_map_entry *gmep;
422 * Initialize and load if not already loaded.
426 for (gmep = (name_map_entry *)ubi_slFirst(map_list);
428 gmep = (name_map_entry *)ubi_slNext(gmep ))
430 if (sid_equal(&gmep->grp.sid, psid))
434 *gid = gmep->grp.unix_gid;
438 fstrcpy(ntname, gmep->grp.nt_name);
440 if (ntdomain != NULL)
442 fstrcpy(ntdomain, gmep->grp.nt_domain);
444 DEBUG(7,("map_sid: Mapping unix group %s to nt group %s.\n",
445 gmep->grp.unix_name, gmep->grp.nt_name ));
453 /***********************************************************
455 ************************************************************/
456 static BOOL map_ntname(GROUP_TYPE type, ubi_slList *map_list,
457 char *ntname, char *ntdomain, DOM_SID *psid,
458 char *unixname, gid_t *gid)
460 name_map_entry *gmep;
463 * Initialize and load if not already loaded.
467 for (gmep = (name_map_entry *)ubi_slFirst(&map_list);
469 gmep = (name_map_entry *)ubi_slNext(gmep ))
471 if (strequal(gmep->grp.nt_name , ntname) &&
472 strequal(gmep->grp.nt_domain, ntdomain))
476 *psid = gmep->grp.sid;
480 *gid = gmep->grp.unix_gid;
482 if (unixname != NULL)
484 fstrcpy(unixname, gmep->grp.unix_name);
486 DEBUG(7,("map_ntname: Mapping unix group %s to nt group %s.\n",
487 gmep->grp.unix_name, gmep->grp.nt_name ));
495 /***********************************************************
497 ************************************************************/
498 static BOOL map_unixname(GROUP_TYPE type, ubi_slList *map_list,
499 char *unixname, DOM_SID *psid, char *ntname, char *ntdomain)
501 name_map_entry *gmep;
504 * Initialize and load if not already loaded.
508 for (gmep = (name_map_entry *)ubi_slFirst(&map_list);
510 gmep = (name_map_entry *)ubi_slNext(gmep ))
512 if (strequal(gmep->grp.unix_name, unixname))
516 *psid = gmep->grp.sid;
520 fstrcpy(ntname, gmep->grp.nt_name);
522 if (ntdomain != NULL)
524 fstrcpy(ntdomain, gmep->grp.nt_domain);
526 DEBUG(7,("map_unixname: Mapping unix group %s to nt group %s.\n",
527 gmep->grp.unix_name, gmep->grp.nt_name ));
535 /***********************************************************
537 ************************************************************/
538 static BOOL map_gid(GROUP_TYPE type, ubi_slList *map_list,
539 gid_t gid, DOM_SID *psid, char *ntname, char *ntdomain)
541 name_map_entry *gmep;
544 * Initialize and load if not already loaded.
548 for (gmep = (name_map_entry *)ubi_slFirst(&map_list);
550 gmep = (name_map_entry *)ubi_slNext(gmep ))
552 if (gmep->grp.unix_gid == gid)
556 *psid = gmep->grp.sid;
560 fstrcpy(ntname, gmep->grp.nt_name);
562 if (ntdomain != NULL)
564 fstrcpy(ntdomain, gmep->grp.nt_domain);
566 DEBUG(7,("map_gid: Mapping unix group %s to nt group %s.\n",
567 gmep->grp.unix_name, gmep->grp.nt_name ));
575 /***********************************************************
577 * Call four functions to resolve unix group ids and either
578 * local group SIDs or domain group SIDs listed in the local group
579 * or domain group map files.
581 * Note that it is *NOT* the responsibility of these functions to
582 * resolve entries that are not in the map files.
584 * Any SID can be in the map files (i.e from any Domain).
586 ***********************************************************/
588 /***********************************************************
589 Lookup a Group entry by sid.
590 ************************************************************/
591 BOOL map_group_sid(DOM_SID *psid, gid_t *gid, char *group_name, char *nt_domain)
593 return map_sid(GROUP_DOMAIN, &groupname_map_list, psid, gid, group_name, nt_domain);
596 /***********************************************************
597 Lookup an Alias SID entry by name.
598 ************************************************************/
599 BOOL map_alias_sid(DOM_SID *psid, gid_t *gid, char *alias_name, char *nt_domain)
601 return map_sid(GROUP_LOCAL, &aliasname_map_list, psid, gid, alias_name, nt_domain);
604 /***********************************************************
605 Lookup a UNIX Group entry by name.
606 ************************************************************/
607 BOOL map_unix_group_name(char *group_name, DOM_SID *psid, char *ntgroup_name, char *nt_domain)
609 return map_unixname(GROUP_DOMAIN, &groupname_map_list, group_name, psid, ntgroup_name, nt_domain);
612 /***********************************************************
613 Lookup a UNIX Alias entry by name.
614 ************************************************************/
615 BOOL map_unix_alias_name(char *alias_name, DOM_SID *psid, char *ntalias_name, char *nt_domain)
617 return map_unixname(GROUP_LOCAL, &aliasname_map_list, alias_name, psid, ntalias_name, nt_domain);
620 /***********************************************************
622 ************************************************************/
623 BOOL map_nt_group_name(char *ntgroup_name, char *nt_domain, DOM_SID *psid, char *group_name, gid_t *gid)
625 return map_ntname(GROUP_DOMAIN, &groupname_map_list, ntgroup_name, nt_domain, psid, group_name, gid);
628 /***********************************************************
629 Lookup an Alias name entry
630 ************************************************************/
631 BOOL map_nt_alias_name(char *ntalias_name, char *nt_domain, DOM_SID *psid, char *alias_name, gid_t *gid)
633 return map_ntname(GROUP_LOCAL, &aliasname_map_list, ntalias_name, nt_domain, psid, alias_name, gid);
636 /***********************************************************
637 Lookup an Alias SID entry by gid_t.
638 ************************************************************/
639 BOOL map_alias_gid(gid_t gid, DOM_SID *psid, char *nt_als_name, char *nt_domain)
641 return map_gid(GROUP_LOCAL, &aliasname_map_list, gid, psid, nt_als_name, nt_domain);
644 /***********************************************************
645 Lookup a Group SID entry by gid_t.
646 ************************************************************/
647 BOOL map_group_gid( gid_t gid, DOM_SID *psid, char *nt_grp_name, char *nt_domain)
649 return map_gid(GROUP_DOMAIN, &groupname_map_list, gid, psid, nt_grp_name, nt_domain);