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_builtin_grp_name(grp->nt_name, &sid, &tmp_type) == 0x0)
143 sid_copy(&grp->sid, &sid);
150 if (type == GROUP_DOMAIN)
152 tmp_rid = pwdb_gid_to_group_rid(grp->unix_gid);
156 tmp_rid = pwdb_gid_to_alias_rid(grp->unix_gid);
158 ret = sid_append_rid(&(grp->sid), tmp_rid);
159 sid_to_string(sid_str, &grp->sid);
160 DEBUG(10,("nt name %s gid %d mapped to %s\n",
161 grp->nt_name, grp->unix_gid, sid_str));
166 /**************************************************************************
167 makes a group sid out of an nt domain, nt group name or a unix group name.
168 ***************************************************************************/
169 static BOOL unix_name_to_group_info(GROUP_NAME_INFO *grp, GROUP_TYPE type)
171 struct group *gptr = NULL;
174 * Attempt to get the unix gid_t for this name.
177 DEBUG(5,("unix_name_to_group_info: unix_name:%s\n", grp->unix_name));
179 gptr = (struct group *)getgrnam(grp->unix_name);
182 DEBUG(0,("unix_name_to_group_info: getgrnam for group %s\
183 failed. Error was %s.\n", grp->unix_name, strerror(errno) ));
187 grp->unix_gid = (gid_t)gptr->gr_gid;
189 DEBUG(5,("unix_name_to_group_info: unix gid:%d\n", grp->unix_gid));
192 * Now map the name to an NT SID+RID.
195 if (grp->nt_domain != NULL && !strequal(grp->nt_domain, global_sam_name))
197 /* Must add client-call lookup code here, to
198 * resolve remote domain's sid and the group's rid,
201 * NOTE: it is _incorrect_ to put code here that assumes
202 * that we can call pwdb_gid_to_group_rid() or _alias_rid():
203 * it is a totally different domain for which we are *NOT*
205 * for foriegn domains for which we are *NOT* the PDC, all
206 * we can be responsible for is the unix * gid_t to which
207 * the foriegn SID+rid maps to, on this _local_ machine.
210 if (!map_domain_name_to_sid(&grp->sid, &(grp->nt_domain)))
212 DEBUG(0,("unix_name_to_group_info: no known sid for %s\n",
218 return make_mydomain_sid(grp, type);
221 static BOOL make_name_entry(name_map_entry **new_ep,
222 char *nt_domain, char *nt_group, char *unix_group,
226 * Create the list entry and add it onto the list.
229 DEBUG(5,("make_name_entry:%s,%s,%s\n", nt_domain, nt_group, unix_group));
231 (*new_ep) = (name_map_entry *)malloc(sizeof(name_map_entry));
232 if ((*new_ep) == NULL)
234 DEBUG(0,("make_name_entry: malloc fail for name_map_entry.\n"));
238 ZERO_STRUCTP(*new_ep);
240 (*new_ep)->grp.nt_name = strdup(nt_group );
241 (*new_ep)->grp.nt_domain = strdup(nt_domain );
242 (*new_ep)->grp.unix_name = strdup(unix_group);
244 if ((*new_ep)->grp.nt_name == NULL ||
245 (*new_ep)->grp.unix_name == NULL)
247 DEBUG(0,("make_name_entry: malloc fail for names in name_map_entry.\n"));
248 delete_name_entry((*new_ep));
253 * look up the group names, make the Group-SID and unix gid
256 if (!unix_name_to_group_info(&(*new_ep)->grp, type))
258 delete_name_entry((*new_ep));
265 /**************************************************************************
266 Load a name map file. Sets last accessed timestamp.
267 ***************************************************************************/
268 static ubi_slList *load_name_map(GROUP_TYPE type)
270 static time_t groupmap_file_last_modified = (time_t)0;
271 static time_t aliasmap_file_last_modified = (time_t)0;
272 static BOOL initialised_group = False;
273 static BOOL initialised_alias = False;
274 char *groupname_map_file = lp_groupname_map();
275 char *aliasname_map_file = lp_aliasname_map();
281 name_map_entry *new_ep;
283 time_t *file_last_modified;
286 ubi_slList *map_list;
288 if (type == GROUP_DOMAIN)
290 file_last_modified = &groupmap_file_last_modified;
291 initialised = &initialised_group;
292 map_file = groupname_map_file;
293 map_list = &groupname_map_list;
297 file_last_modified = &aliasmap_file_last_modified;
298 initialised = &initialised_alias;
299 map_file = aliasname_map_file;
300 map_list = &aliasname_map_list;
305 DEBUG(10,("initialising group map %s\n", map_file));
306 ubi_slInitList(map_list);
307 (*initialised) = True;
315 if (sys_stat(map_file, &st) != 0)
317 DEBUG(0, ("load_name_map: Unable to stat file %s. Error was %s\n",
318 map_file, strerror(errno) ));
323 * Check if file has changed.
325 if (st.st_mtime <= (*file_last_modified))
330 (*file_last_modified) = st.st_mtime;
336 fp = fopen(map_file,"r");
339 DEBUG(0,("load_name_map: can't open name map %s. Error was %s\n",
340 map_file, strerror(errno)));
345 * Throw away any previous list.
347 delete_map_list(map_list);
349 DEBUG(4,("load_name_map: Scanning name map %s\n",map_file));
351 while ((s = fgets_slash(buf, sizeof(buf), fp)) != NULL)
359 DEBUG(10,("Read line |%s|\n", s));
361 memset(nt_name, 0, sizeof(nt_name));
363 if (!*s || strchr("#;",*s))
366 if (!next_token(&s,unixname, "\t\n\r=", sizeof(unixname)))
369 if (!next_token(&s,nt_name, "\t\n\r=", sizeof(nt_name)))
372 trim_string(unixname, " ", " ");
373 trim_string(nt_name, " ", " ");
381 DEBUG(5,("unixname = %s, ntname = %s.\n",
384 p = strchr(nt_name, '\\');
388 memset(nt_domain, 0, sizeof(nt_domain));
389 fstrcpy(nt_group, nt_name);
395 fstrcpy(nt_domain, nt_name);
396 fstrcpy(nt_group , p);
399 if (make_name_entry(&new_ep, nt_domain, nt_name, unixname, type))
401 ubi_slAddTail(map_list, (ubi_slNode *)new_ep);
405 DEBUG(10,("load_name_map: Added %ld entries to name map.\n",
406 ubi_slCount(map_list)));
413 /***********************************************************
415 ************************************************************/
416 static BOOL map_sid(GROUP_TYPE type,
417 DOM_SID *psid, gid_t *gid, char *ntname, char *ntdomain)
419 name_map_entry *gmep;
420 ubi_slList *map_list;
423 * Initialise and load if not already loaded.
425 map_list = load_name_map(type);
427 for (gmep = (name_map_entry *)ubi_slFirst(map_list);
429 gmep = (name_map_entry *)ubi_slNext(gmep ))
431 if (sid_equal(&gmep->grp.sid, psid))
435 *gid = gmep->grp.unix_gid;
439 fstrcpy(ntname, gmep->grp.nt_name);
441 if (ntdomain != NULL)
443 fstrcpy(ntdomain, gmep->grp.nt_domain);
445 DEBUG(7,("map_sid: Mapping unix group %s to nt group %s.\n",
446 gmep->grp.unix_name, gmep->grp.nt_name ));
454 /***********************************************************
456 ************************************************************/
457 static BOOL map_ntname(GROUP_TYPE type,
458 char *ntname, char *ntdomain, DOM_SID *psid,
459 char *unixname, gid_t *gid)
461 name_map_entry *gmep;
462 ubi_slList *map_list;
465 * Initialise and load if not already loaded.
467 map_list = load_name_map(type);
469 for (gmep = (name_map_entry *)ubi_slFirst(map_list);
471 gmep = (name_map_entry *)ubi_slNext(gmep ))
473 if (strequal(gmep->grp.nt_name , ntname) &&
474 strequal(gmep->grp.nt_domain, ntdomain))
478 sid_copy(psid, &gmep->grp.sid);
482 *gid = gmep->grp.unix_gid;
484 if (unixname != NULL)
486 fstrcpy(unixname, gmep->grp.unix_name);
488 DEBUG(7,("map_ntname: Mapping unix group %s to nt group %s.\n",
489 gmep->grp.unix_name, gmep->grp.nt_name ));
497 /***********************************************************
499 ************************************************************/
500 static BOOL map_unixname(GROUP_TYPE type,
501 char *unixname, DOM_SID *psid, char *ntname, char *ntdomain)
503 name_map_entry *gmep;
504 ubi_slList *map_list;
507 * Initialise and load if not already loaded.
509 map_list = load_name_map(type);
511 for (gmep = (name_map_entry *)ubi_slFirst(map_list);
513 gmep = (name_map_entry *)ubi_slNext(gmep ))
515 if (strequal(gmep->grp.unix_name, unixname))
519 sid_copy(psid, &gmep->grp.sid);
523 fstrcpy(ntname, gmep->grp.nt_name);
525 if (ntdomain != NULL)
527 fstrcpy(ntdomain, gmep->grp.nt_domain);
529 DEBUG(7,("map_unixname: Mapping unix group %s to nt group %s.\n",
530 gmep->grp.unix_name, gmep->grp.nt_name ));
538 /***********************************************************
540 ************************************************************/
541 static BOOL map_gid(GROUP_TYPE type,
542 gid_t gid, DOM_SID *psid, char *ntname, char *ntdomain)
544 name_map_entry *gmep;
545 ubi_slList *map_list;
548 * Initialise and load if not already loaded.
550 map_list = load_name_map(type);
552 for (gmep = (name_map_entry *)ubi_slFirst(map_list);
554 gmep = (name_map_entry *)ubi_slNext(gmep ))
557 sid_to_string(sid_str, &gmep->grp.sid);
558 DEBUG(10,("map_gid: enum entry unix group %s %d nt %s %s\n",
559 gmep->grp.unix_name, gmep->grp.unix_gid, gmep->grp.nt_name, sid_str));
560 if (gmep->grp.unix_gid == gid)
564 sid_copy(psid, &gmep->grp.sid);
568 fstrcpy(ntname, gmep->grp.nt_name);
570 if (ntdomain != NULL)
572 fstrcpy(ntdomain, gmep->grp.nt_domain);
574 DEBUG(7,("map_gid: Mapping unix group %s to nt group %s.\n",
575 gmep->grp.unix_name, gmep->grp.nt_name ));
583 /***********************************************************
585 * Call four functions to resolve unix group ids and either
586 * local group SIDs or domain group SIDs listed in the local group
587 * or domain group map files.
589 * Note that it is *NOT* the responsibility of these functions to
590 * resolve entries that are not in the map files.
592 * Any SID can be in the map files (i.e from any Domain).
594 ***********************************************************/
596 /***********************************************************
597 Lookup a Group entry by sid.
598 ************************************************************/
599 BOOL map_group_sid(DOM_SID *psid, gid_t *gid, char *group_name, char *nt_domain)
601 return map_sid(GROUP_DOMAIN, psid, gid, group_name, nt_domain);
604 /***********************************************************
605 Lookup an Alias SID entry by name.
606 ************************************************************/
607 BOOL map_alias_sid(DOM_SID *psid, gid_t *gid, char *alias_name, char *nt_domain)
609 return map_sid(GROUP_LOCAL, psid, gid, alias_name, nt_domain);
612 /***********************************************************
613 Lookup a UNIX Group entry by name.
614 ************************************************************/
615 BOOL map_unix_group_name(char *group_name, DOM_SID *psid, char *ntgroup_name, char *nt_domain)
617 return map_unixname(GROUP_DOMAIN, group_name, psid, ntgroup_name, nt_domain);
620 /***********************************************************
621 Lookup a UNIX Alias entry by name.
622 ************************************************************/
623 BOOL map_unix_alias_name(char *alias_name, DOM_SID *psid, char *ntalias_name, char *nt_domain)
625 return map_unixname(GROUP_LOCAL, alias_name, psid, ntalias_name, nt_domain);
628 /***********************************************************
630 ************************************************************/
631 BOOL map_nt_group_name(char *ntgroup_name, char *nt_domain, DOM_SID *psid, char *group_name, gid_t *gid)
633 return map_ntname(GROUP_DOMAIN, ntgroup_name, nt_domain, psid, group_name, gid);
636 /***********************************************************
637 Lookup an Alias name entry
638 ************************************************************/
639 BOOL map_nt_alias_name(char *ntalias_name, char *nt_domain, DOM_SID *psid, char *alias_name, gid_t *gid)
641 return map_ntname(GROUP_LOCAL, ntalias_name, nt_domain, psid, alias_name, gid);
644 /***********************************************************
645 Lookup an Alias SID entry by gid_t.
646 ************************************************************/
647 BOOL map_alias_gid(gid_t gid, DOM_SID *psid, char *nt_als_name, char *nt_domain)
649 return map_gid(GROUP_LOCAL, gid, psid, nt_als_name, nt_domain);
652 /***********************************************************
653 Lookup a Group SID entry by gid_t.
654 ************************************************************/
655 BOOL map_group_gid( gid_t gid, DOM_SID *psid, char *nt_grp_name, char *nt_domain)
657 return map_gid(GROUP_DOMAIN, gid, psid, nt_grp_name, nt_domain);