/* Unix SMB/Netbios implementation. Version 1.9. Groupname handling Copyright (C) Jeremy Allison 1998. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef USING_GROUPNAME_MAP #include "includes.h" extern DOM_SID global_sam_sid; /************************************************************************** Groupname map functionality. The code loads a groupname map file and (currently) loads it into a linked list. This is slow and memory hungry, but can be changed into a more efficient storage format if the demands on it become excessive. ***************************************************************************/ typedef struct groupname_map { ubi_slNode next; char *windows_name; DOM_SID windows_sid; char *unix_name; gid_t unix_gid; } groupname_map_entry; static ubi_slList groupname_map_list; /************************************************************************** Delete all the entries in the groupname map list. ***************************************************************************/ static void delete_groupname_map_list(void) { groupname_map_entry *gmep; while((gmep = (groupname_map_entry *)ubi_slRemHead( &groupname_map_list )) != NULL) { SAFE_FREE(gmep->windows_name); SAFE_FREE(gmep->unix_name); SAFE_FREE(gmep); } } /************************************************************************** Load a groupname map file. Sets last accessed timestamp. ***************************************************************************/ void load_groupname_map(void) { static time_t groupmap_file_last_modified = (time_t)0; static BOOL initialized = False; char *groupname_map_file = lp_groupname_map(); SMB_STRUCT_STAT st; char **lines; int i; groupname_map_entry *new_ep; if(!initialized) { ubi_slInitList( &groupname_map_list ); initialized = True; } if (!*groupname_map_file) return; if(sys_stat(groupname_map_file, &st) != 0) { DEBUG(0, ("load_groupname_map: Unable to stat file %s. Error was %s\n", groupname_map_file, strerror(errno) )); return; } /* * Check if file has changed. */ if( st.st_mtime <= groupmap_file_last_modified) return; groupmap_file_last_modified = st.st_mtime; /* * Load the file. */ lines = file_lines_load(groupname_map_file,NULL,False); if (!lines) { DEBUG(0,("load_groupname_map: can't open groupname map %s. Error was %s\n", groupname_map_file, strerror(errno))); return; } file_lines_slashcont(lines); /* * Throw away any previous list. */ delete_groupname_map_list(); DEBUG(4,("load_groupname_map: Scanning groupname map %s\n",groupname_map_file)); for (i=0; lines[i]; i++) { pstring unixname; pstring windows_name; gid_t gid; DOM_SID tmp_sid; char *s = lines[i]; DEBUG(10,("load_groupname_map: Read line |%s|\n", s)); if (!*s || strchr_m("#;",*s)) continue; if(!next_token(&s,unixname, "\t\n\r=", sizeof(unixname))) continue; if(!next_token(&s,windows_name, "\t\n\r=", sizeof(windows_name))) continue; trim_string(unixname, " ", " "); trim_string(windows_name, " ", " "); if (!*windows_name) continue; if(!*unixname) continue; DEBUG(5,("load_groupname_map: unixname = %s, windowsname = %s.\n", unixname, windows_name)); /* * Attempt to get the unix gid_t for this name. */ if ((gid = nametogid(unixname)) == (gid_t)-1) DEBUG(0,("load_groupname_map: nametogid for group %s failed.\ Error was %s.\n", unixname, strerror(errno) )); continue; } /* * Now map to an NT SID. */ if(!lookup_wellknown_sid_from_name(windows_name, &tmp_sid)) { /* * It's not a well known name, convert the UNIX gid_t * to a rid within this domain SID. */ tmp_sid = global_sam_sid; tmp_sid.sub_auths[tmp_sid.num_auths++] = pdb_gid_to_group_rid(gid); } /* * Create the list entry and add it onto the list. */ if((new_ep = (groupname_map_entry *)malloc( sizeof(groupname_map_entry) ))== NULL) { DEBUG(0,("load_groupname_map: malloc fail for groupname_map_entry.\n")); fclose(fp); return; } new_ep->unix_gid = gid; new_ep->windows_sid = tmp_sid; new_ep->windows_name = strdup( windows_name ); new_ep->unix_name = strdup( unixname ); if(new_ep->windows_name == NULL || new_ep->unix_name == NULL) { DEBUG(0,("load_groupname_map: malloc fail for names in groupname_map_entry.\n")); fclose(fp); SAFE_FREE(new_ep->windows_name); SAFE_FREE(new_ep->unix_name); SAFE_FREE(new_ep); file_lines_free(lines); return; } memset((char *)&new_ep->next, '\0', sizeof(new_ep->next) ); ubi_slAddHead( &groupname_map_list, (ubi_slNode *)new_ep); } DEBUG(10,("load_groupname_map: Added %ld entries to groupname map.\n", ubi_slCount(&groupname_map_list))); file_lines_free(lines); } /*********************************************************** Lookup a SID entry by gid_t. ************************************************************/ void map_gid_to_sid( gid_t gid, DOM_SID *psid) { groupname_map_entry *gmep; /* * Initialize and load if not already loaded. */ load_groupname_map(); for( gmep = (groupname_map_entry *)ubi_slFirst( &groupname_map_list); gmep; gmep = (groupname_map_entry *)ubi_slNext( gmep )) { if( gmep->unix_gid == gid) { *psid = gmep->windows_sid; DEBUG(7,("map_gid_to_sid: Mapping unix group %s to windows group %s.\n", gmep->unix_name, gmep->windows_name )); return; } } /* * If there's no map, convert the UNIX gid_t * to a rid within this domain SID. */ *psid = global_sam_sid; psid->sub_auths[psid->num_auths++] = pdb_gid_to_group_rid(gid); return; } #else /* USING_GROUPNAME_MAP */ void load_groupname_map(void) {;} #endif /* USING_GROUPNAME_MAP */