diff options
author | Luke Leighton <lkcl@samba.org> | 1998-11-23 21:54:19 +0000 |
---|---|---|
committer | Luke Leighton <lkcl@samba.org> | 1998-11-23 21:54:19 +0000 |
commit | a5cbb4ab27c0167730de45993a77f7fa2727bdb6 (patch) | |
tree | 7fde1c9f75788ec0c1f0b173fa189dd1e2b6388c | |
parent | 4cee58780cb15fe5889b9dd0dc34459512d75062 (diff) | |
download | samba-a5cbb4ab27c0167730de45993a77f7fa2727bdb6.tar.gz samba-a5cbb4ab27c0167730de45993a77f7fa2727bdb6.tar.bz2 samba-a5cbb4ab27c0167730de45993a77f7fa2727bdb6.zip |
remove / add / attempt to stop remove didn't work.
(This used to be commit 82b6292dff38f4e22ee8feab1b54504b95d705fa)
-rw-r--r-- | source3/smbd/groupname.c | 651 |
1 files changed, 651 insertions, 0 deletions
diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c new file mode 100644 index 0000000000..3c09c11830 --- /dev/null +++ b/source3/smbd/groupname.c @@ -0,0 +1,651 @@ +/* + 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. +*/ + +/* + * UNIX gid and Local or Domain SID resolution. This module resolves + * only those entries in the map files, it is *NOT* responsible for + * resolving UNIX groups not listed: that is an entirely different + * matter, altogether... + */ + +/* + * + * + + format of the file is: + + unixname NT Group name + unixname Domain Admins (well-known Domain Group) + unixname DOMAIN_NAME\NT Group name + unixname OTHER_DOMAIN_NAME\NT Group name + unixname DOMAIN_NAME\Domain Admins (well-known Domain Group) + .... + + if the DOMAIN_NAME\ component is left off, then your own domain is assumed. + + * + * + */ + + +#include "includes.h" +extern int DEBUGLEVEL; + +extern fstring global_sam_name; + +/* we can map either local aliases or domain groups */ +typedef enum +{ + GROUP_LOCAL, + GROUP_DOMAIN + +} GROUP_TYPE; + +/************************************************************************** + 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 group_name_info +{ + char *nt_name; + char *nt_domain; + char *unix_name; + + DOM_SID sid; + gid_t unix_gid; + +} GROUP_NAME_INFO; + +typedef struct name_map +{ + ubi_slNode next; + GROUP_NAME_INFO grp; + +} name_map_entry; + +static ubi_slList groupname_map_list; +static ubi_slList aliasname_map_list; + +static void delete_name_entry(name_map_entry *gmep) +{ + if (gmep->grp.nt_name) + { + free(gmep->grp.nt_name); + } + if (gmep->grp.nt_domain) + { + free(gmep->grp.nt_domain); + } + if (gmep->grp.unix_name) + { + free(gmep->grp.unix_name); + } + free((char*)gmep); +} + +/************************************************************************** + Delete all the entries in the name map list. +***************************************************************************/ + +static void delete_map_list(ubi_slList *map_list) +{ + name_map_entry *gmep; + + while ((gmep = (name_map_entry *)ubi_slRemHead(map_list )) != NULL) + { + delete_name_entry(gmep); + } +} + + +/************************************************************************** + makes a group sid out of a domain sid and a _unix_ gid. +***************************************************************************/ +static BOOL make_mydomain_sid(GROUP_NAME_INFO *grp, GROUP_TYPE type) +{ + uint32 tmp_rid; + DOM_SID sid; + uint8 tmp_type; + + DEBUG(10,("make_mydomain_sid\n")); + + if (!map_domain_name_to_sid(&grp->sid, &(grp->nt_domain))) + { + DEBUG(0,("make_mydomain_sid: unknown domain %s\n", + grp->nt_domain)); + return False; + } + + if (strequal(grp->nt_domain, global_sam_name) && + lookup_wk_group_name(grp->nt_name, &sid, &tmp_type)) + { + sid_copy(&grp->sid, &sid); + return True; + } + else + { + if (type == GROUP_DOMAIN) + { + tmp_rid = pwdb_gid_to_group_rid(grp->unix_gid); + } + else + { + tmp_rid = pwdb_gid_to_alias_rid(grp->unix_gid); + } + return sid_append_rid(&(grp->sid), tmp_rid); + } +} + +/************************************************************************** + makes a group sid out of an nt domain, nt group name or a unix group name. +***************************************************************************/ +static BOOL unix_name_to_group_info(GROUP_NAME_INFO *grp, GROUP_TYPE type) +{ + struct group *gptr = NULL; + + /* + * Attempt to get the unix gid_t for this name. + */ + + DEBUG(5,("unix_name_to_group_info: unix_name:%s\n", grp->unix_name)); + + gptr = (struct group *)getgrnam(grp->unix_name); + if (gptr == NULL) + { + DEBUG(0,("unix_name_to_group_info: getgrnam for group %s\ +failed. Error was %s.\n", grp->unix_name, strerror(errno) )); + return False; + } + + grp->unix_gid = (gid_t)gptr->gr_gid; + + DEBUG(5,("unix_name_to_group_info: unix gid:%d\n", grp->unix_gid)); + + /* + * Now map the name to an NT SID+RID. + */ + + if (grp->nt_domain != NULL && !strequal(grp->nt_domain, global_sam_name)) + { + /* Must add client-call lookup code here, to + * resolve remote domain's sid and the group's rid, + * in that domain. + * + * NOTE: it is _incorrect_ to put code here that assumes + * that we can call pwdb_gid_to_group_rid() or _alias_rid(): + * it is a totally different domain for which we are *NOT* + * responsible. + * for foriegn domains for which we are *NOT* the PDC, all + * we can be responsible for is the unix * gid_t to which + * the foriegn SID+rid maps to, on this _local_ machine. + */ + + if (!map_domain_name_to_sid(&grp->sid, &(grp->nt_domain))) + { + DEBUG(0,("unix_name_to_group_info: no known sid for %s\n", + grp->nt_domain)); + return False; + } + + DEBUG(0,("unix_name_to_group_info: cannot resolve domain %s\n", + grp->nt_domain)); + + return False; + } + else + { + return make_mydomain_sid(grp, type); + } +} + +static BOOL make_name_entry(name_map_entry **new_ep, + char *nt_domain, char *nt_group, char *unix_group, + GROUP_TYPE type) +{ + /* + * Create the list entry and add it onto the list. + */ + + DEBUG(5,("make_name_entry:%s,%s,%s\n", nt_domain, nt_group, unix_group)); + + (*new_ep) = (name_map_entry *)malloc(sizeof(name_map_entry)); + if ((*new_ep) == NULL) + { + DEBUG(0,("make_name_entry: malloc fail for name_map_entry.\n")); + return False; + } + + ZERO_STRUCTP(*new_ep); + + (*new_ep)->grp.nt_name = strdup(nt_group ); + (*new_ep)->grp.nt_domain = strdup(nt_domain ); + (*new_ep)->grp.unix_name = strdup(unix_group); + + if ((*new_ep)->grp.nt_name == NULL || + (*new_ep)->grp.unix_name == NULL) + { + DEBUG(0,("make_name_entry: malloc fail for names in name_map_entry.\n")); + delete_name_entry((*new_ep)); + return False; + } + + /* + * look up the group names, make the Group-SID and unix gid + */ + + if (!unix_name_to_group_info(&(*new_ep)->grp, type)) + { + delete_name_entry((*new_ep)); + return False; + } + + return True; +} + +/************************************************************************** + Load a name map file. Sets last accessed timestamp. +***************************************************************************/ +static void load_name_map(GROUP_TYPE type) +{ + static time_t groupmap_file_last_modified = (time_t)0; + static time_t aliasmap_file_last_modified = (time_t)0; + static BOOL initialised_group = False; + static BOOL initialised_alias = False; + char *groupname_map_file = lp_groupname_map(); + char *aliasname_map_file = lp_aliasname_map(); + + SMB_STRUCT_STAT st; + FILE *fp; + char *s; + pstring buf; + name_map_entry *new_ep; + + time_t *file_last_modified; + int *initialised; + char *map_file; + ubi_slList *map_list; + + if (type == GROUP_DOMAIN) + { + file_last_modified = &groupmap_file_last_modified; + initialised = &initialised_group; + map_file = groupname_map_file; + map_list = &groupname_map_list; + } + else + { + file_last_modified = &aliasmap_file_last_modified; + initialised = &initialised_alias; + map_file = aliasname_map_file; + map_list = &aliasname_map_list; + } + + DEBUG(10,("load_name_map : %s\n", map_file)); + + if (!(*initialised)) + { + ubi_slInitList(map_list); + (*initialised) = True; + } + + if (!*map_file) + { + return; + } + + if (sys_stat(map_file, &st) != 0) + { + DEBUG(0, ("load_name_map: Unable to stat file %s. Error was %s\n", + map_file, strerror(errno) )); + return; + } + + /* + * Check if file has changed. + */ + if (st.st_mtime <= (*file_last_modified)) + { + return; + } + + (*file_last_modified) = st.st_mtime; + + /* + * Load the file. + */ + + fp = fopen(map_file,"r"); + if (!fp) + { + DEBUG(0,("load_name_map: can't open name map %s. Error was %s\n", + map_file, strerror(errno))); + return; + } + + /* + * Throw away any previous list. + */ + delete_map_list(map_list); + + DEBUG(4,("load_name_map: Scanning name map %s\n",map_file)); + + while ((s = fgets_slash(buf, sizeof(buf), fp)) != NULL) + { + pstring unixname; + pstring nt_name; + fstring nt_domain; + fstring nt_group; + char *p; + + DEBUG(10,("Read line |%s|\n", s)); + + memset(nt_name, 0, sizeof(nt_name)); + + if (!*s || strchr("#;",*s)) + continue; + + if (!next_token(&s,unixname, "\t\n\r=", sizeof(unixname))) + continue; + + if (!next_token(&s,nt_name, "\t\n\r=", sizeof(nt_name))) + continue; + + trim_string(unixname, " ", " "); + trim_string(nt_name, " ", " "); + + if (!*nt_name) + continue; + + if (!*unixname) + continue; + + DEBUG(5,("unixname = %s, ntname = %s.\n", + unixname, nt_name)); + + p = strchr(nt_name, '\\'); + + if (p == NULL) + { + memset(nt_domain, 0, sizeof(nt_domain)); + fstrcpy(nt_group, nt_name); + } + else + { + *p = 0; + p++; + fstrcpy(nt_domain, nt_name); + fstrcpy(nt_group , p); + } + + if (make_name_entry(&new_ep, nt_domain, nt_name, unixname, type)) + { + ubi_slAddHead(map_list, (ubi_slNode *)new_ep); + } + } + + DEBUG(10,("load_name_map: Added %ld entries to name map.\n", + ubi_slCount(map_list))); + + fclose(fp); +} + +/*********************************************************** + Lookup by SID +************************************************************/ +static BOOL map_sid(GROUP_TYPE type, ubi_slList *map_list, + DOM_SID *psid, gid_t *gid, char *ntname, char *ntdomain) +{ + name_map_entry *gmep; + + /* + * Initialize and load if not already loaded. + */ + load_name_map(type); + + for (gmep = (name_map_entry *)ubi_slFirst(map_list); + gmep != NULL; + gmep = (name_map_entry *)ubi_slNext(gmep )) + { + if (sid_equal(&gmep->grp.sid, psid)) + { + if (gid != NULL) + { + *gid = gmep->grp.unix_gid; + } + if (ntname != NULL) + { + fstrcpy(ntname, gmep->grp.nt_name); + } + if (ntdomain != NULL) + { + fstrcpy(ntdomain, gmep->grp.nt_domain); + } + DEBUG(7,("map_sid: Mapping unix group %s to nt group %s.\n", + gmep->grp.unix_name, gmep->grp.nt_name )); + return True; + } + } + + return False; +} + +/*********************************************************** + Lookup nt name. +************************************************************/ +static BOOL map_ntname(GROUP_TYPE type, ubi_slList *map_list, + char *ntname, char *ntdomain, DOM_SID *psid, + char *unixname, gid_t *gid) +{ + name_map_entry *gmep; + + /* + * Initialize and load if not already loaded. + */ + load_name_map(type); + + for (gmep = (name_map_entry *)ubi_slFirst(&map_list); + gmep != NULL; + gmep = (name_map_entry *)ubi_slNext(gmep )) + { + if (strequal(gmep->grp.nt_name , ntname) && + strequal(gmep->grp.nt_domain, ntdomain)) + { + if (psid != NULL) + { + *psid = gmep->grp.sid; + } + if (gid != NULL) + { + *gid = gmep->grp.unix_gid; + } + if (unixname != NULL) + { + fstrcpy(unixname, gmep->grp.unix_name); + } + DEBUG(7,("map_ntname: Mapping unix group %s to nt group %s.\n", + gmep->grp.unix_name, gmep->grp.nt_name )); + return True; + } + } + + return False; +} + +/*********************************************************** + Lookup unix name. +************************************************************/ +static BOOL map_unixname(GROUP_TYPE type, ubi_slList *map_list, + char *unixname, DOM_SID *psid, char *ntname, char *ntdomain) +{ + name_map_entry *gmep; + + /* + * Initialize and load if not already loaded. + */ + load_name_map(type); + + for (gmep = (name_map_entry *)ubi_slFirst(&map_list); + gmep != NULL; + gmep = (name_map_entry *)ubi_slNext(gmep )) + { + if (strequal(gmep->grp.unix_name, unixname)) + { + if (psid != NULL) + { + *psid = gmep->grp.sid; + } + if (ntname != NULL) + { + fstrcpy(ntname, gmep->grp.nt_name); + } + if (ntdomain != NULL) + { + fstrcpy(ntdomain, gmep->grp.nt_domain); + } + DEBUG(7,("map_unixname: Mapping unix group %s to nt group %s.\n", + gmep->grp.unix_name, gmep->grp.nt_name )); + return True; + } + } + + return False; +} + +/*********************************************************** + Lookup by gid_t. +************************************************************/ +static BOOL map_gid(GROUP_TYPE type, ubi_slList *map_list, + gid_t gid, DOM_SID *psid, char *ntname, char *ntdomain) +{ + name_map_entry *gmep; + + /* + * Initialize and load if not already loaded. + */ + load_name_map(type); + + for (gmep = (name_map_entry *)ubi_slFirst(&map_list); + gmep != NULL; + gmep = (name_map_entry *)ubi_slNext(gmep )) + { + if (gmep->grp.unix_gid == gid) + { + if (psid != NULL) + { + *psid = gmep->grp.sid; + } + if (ntname != NULL) + { + fstrcpy(ntname, gmep->grp.nt_name); + } + if (ntdomain != NULL) + { + fstrcpy(ntdomain, gmep->grp.nt_domain); + } + DEBUG(7,("map_gid: Mapping unix group %s to nt group %s.\n", + gmep->grp.unix_name, gmep->grp.nt_name )); + return True; + } + } + + return False; +} + +/*********************************************************** + * + * Call four functions to resolve unix group ids and either + * local group SIDs or domain group SIDs listed in the local group + * or domain group map files. + * + * Note that it is *NOT* the responsibility of these functions to + * resolve entries that are not in the map files. + * + * Any SID can be in the map files (i.e from any Domain). + * + ***********************************************************/ + +/*********************************************************** + Lookup a Group entry by sid. +************************************************************/ +BOOL map_group_sid(DOM_SID *psid, gid_t *gid, char *group_name, char *nt_domain) +{ + return map_sid(GROUP_DOMAIN, &groupname_map_list, psid, gid, group_name, nt_domain); +} + +/*********************************************************** + Lookup an Alias SID entry by name. +************************************************************/ +BOOL map_alias_sid(DOM_SID *psid, gid_t *gid, char *alias_name, char *nt_domain) +{ + return map_sid(GROUP_LOCAL, &aliasname_map_list, psid, gid, alias_name, nt_domain); +} + +/*********************************************************** + Lookup a UNIX Group entry by name. +************************************************************/ +BOOL map_unix_group_name(char *group_name, DOM_SID *psid, char *ntgroup_name, char *nt_domain) +{ + return map_unixname(GROUP_DOMAIN, &groupname_map_list, group_name, psid, ntgroup_name, nt_domain); +} + +/*********************************************************** + Lookup a UNIX Alias entry by name. +************************************************************/ +BOOL map_unix_alias_name(char *alias_name, DOM_SID *psid, char *ntalias_name, char *nt_domain) +{ + return map_unixname(GROUP_LOCAL, &aliasname_map_list, alias_name, psid, ntalias_name, nt_domain); +} + +/*********************************************************** + Lookup a Group entry +************************************************************/ +BOOL map_nt_group_name(char *ntgroup_name, char *nt_domain, DOM_SID *psid, char *group_name, gid_t *gid) +{ + return map_ntname(GROUP_DOMAIN, &groupname_map_list, ntgroup_name, nt_domain, psid, group_name, gid); +} + +/*********************************************************** + Lookup an Alias name entry +************************************************************/ +BOOL map_nt_alias_name(char *ntalias_name, char *nt_domain, DOM_SID *psid, char *alias_name, gid_t *gid) +{ + return map_ntname(GROUP_LOCAL, &aliasname_map_list, ntalias_name, nt_domain, psid, alias_name, gid); +} + +/*********************************************************** + Lookup an Alias SID entry by gid_t. +************************************************************/ +BOOL map_alias_gid(gid_t gid, DOM_SID *psid, char *nt_als_name, char *nt_domain) +{ + return map_gid(GROUP_LOCAL, &aliasname_map_list, gid, psid, nt_als_name, nt_domain); +} + +/*********************************************************** + Lookup a Group SID entry by gid_t. +************************************************************/ +BOOL map_group_gid( gid_t gid, DOM_SID *psid, char *nt_grp_name, char *nt_domain) +{ + return map_gid(GROUP_DOMAIN, &groupname_map_list, gid, psid, nt_grp_name, nt_domain); +} + |