summaryrefslogtreecommitdiffstats
path: root/source/smbd
diff options
context:
space:
mode:
authorLuke Leighton <lkcl@samba.org>1998-11-23 21:54:19 +0000
committerLuke Leighton <lkcl@samba.org>1998-11-23 21:54:19 +0000
commit82b6292dff38f4e22ee8feab1b54504b95d705fa (patch)
tree4006845fe89df2edd24b430f72e65ecabb9fc3c4 /source/smbd
parente76f593b3572ac881f1aa1fb3326d8b7169b0078 (diff)
downloadsamba-82b6292dff38f4e22ee8feab1b54504b95d705fa.tar.gz
samba-82b6292dff38f4e22ee8feab1b54504b95d705fa.tar.xz
samba-82b6292dff38f4e22ee8feab1b54504b95d705fa.zip
remove / add / attempt to stop remove didn't work.
Diffstat (limited to 'source/smbd')
-rw-r--r--source/smbd/groupname.c651
1 files changed, 651 insertions, 0 deletions
diff --git a/source/smbd/groupname.c b/source/smbd/groupname.c
new file mode 100644
index 00000000000..3c09c118303
--- /dev/null
+++ b/source/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);
+}
+