[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Wed Jan 7 20:31:04 MST 2015


The branch, master has been updated
       via  b817ce6 Add a script-only idmap module.
      from  a5d383c allow net ads join accept new osServicePack parameter

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit b817ce6d912bd8801aed039c9def1bb042e0d8af
Author: Richard Sharpe <realrichardsharpe at gmail.com>
Date:   Tue Dec 23 17:33:34 2014 -0800

    Add a script-only idmap module.
    
    In this third version I have cleaned up some unused variable warnings that
    only the Samba 3 build found and added a man page based on the idmap_tdb2
    man page. I have also added support for ID_TYPE_BOTH mappings and replaced
    calls to popen with something safer. Also, I removed some non-PC macros.
    
    Signed-off-by: Richard Sharpe <rsharpe at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Thu Jan  8 04:30:32 CET 2015 on sn-devel-104

-----------------------------------------------------------------------

Summary of changes:
 .../{idmap_tdb2.8.xml => idmap_script.8.xml}       |  67 ++--
 source3/winbindd/idmap_script.c                    | 394 +++++++++++++++++++++
 source3/winbindd/wscript_build                     |   8 +
 source3/wscript                                    |   1 +
 4 files changed, 450 insertions(+), 20 deletions(-)
 copy docs-xml/manpages/{idmap_tdb2.8.xml => idmap_script.8.xml} (62%)
 create mode 100644 source3/winbindd/idmap_script.c


Changeset truncated at 500 lines:

diff --git a/docs-xml/manpages/idmap_tdb2.8.xml b/docs-xml/manpages/idmap_script.8.xml
similarity index 62%
copy from docs-xml/manpages/idmap_tdb2.8.xml
copy to docs-xml/manpages/idmap_script.8.xml
index 651a671..e2bf665 100644
--- a/docs-xml/manpages/idmap_tdb2.8.xml
+++ b/docs-xml/manpages/idmap_script.8.xml
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
 <!DOCTYPE refentry PUBLIC "-//Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">
-<refentry id="idmap_tdb2.8">
+<refentry id="idmap_script.8">
 
 <refmeta>
-	<refentrytitle>idmap_tdb2</refentrytitle>
+	<refentrytitle>idmap_script</refentrytitle>
 	<manvolnum>8</manvolnum>
 	<refmiscinfo class="source">Samba</refmiscinfo>
 	<refmiscinfo class="manual">System Administration tools</refmiscinfo>
@@ -13,22 +13,23 @@
 
 <refnamediv>
 	<refname>idmap_tdb2</refname>
-	<refpurpose>Samba's idmap_tdb2 Backend for Winbind</refpurpose>
+	<refpurpose>Samba's idmap_script Backend for Winbind</refpurpose>
 </refnamediv>
 
 <refsynopsisdiv>
 	<title>DESCRIPTION</title>
 
 	<para>
-	The idmap_tdb2 plugin is a substitute for the default idmap_tdb
+	The idmap_script plugin is a substitute for the idmap_tdb2
 	backend used by winbindd for storing SID/uid/gid mapping tables
-	in clustered environments with Samba and CTDB.
+	in clustered environments with Samba and CTDB. It is a read only
+	backend that uses a script to perform mapping.
 	</para>
 
 	<para>
-	In contrast to read only backends like idmap_rid, it is an allocating
-	backend: This means that it needs to allocate new user and group IDs in
-	order to create new mappings.
+	It was developed out of the idmap_tdb2 back end and does not store
+	SID/uid/gid mappings in a TDB, since the winbind_cache tdb will
+	store the mappings once they are provided.
 	</para>
 </refsynopsisdiv>
 
@@ -48,9 +49,7 @@
 		<term>script</term>
 		<listitem><para>
 			This option can be used to configure an external program
-			for performing id mappings instead of using the tdb
-			counter. The mappings are then stored int tdb2 idmap
-			database. For details see the section on IDMAP SCRIPT below.
+			for performing id mappings.
 		</para></listitem>
 		</varlistentry>
 	</variablelist>
@@ -82,6 +81,7 @@
 	SIDTOID S-1-xxxx
 	IDTOSID UID xxxx
 	IDTOSID GID xxxx
+	IDTOSID XID xxxx
 	</programlisting>
 
 	<para>
@@ -92,35 +92,62 @@
 	<programlisting>
 	UID:yyyy
 	GID:yyyy
-	SID:yyyy
+	XID:yyyy
+	SID:ssss
 	ERR:yyyy
 	</programlisting>
+
+	<para>
+	XID indicates that the ID returned should be both a UID and a GID.
+	That is, it requests an ID_TYPE_BOTH, but it is ultimately up to
+	the script whether or not it can honor that request. It can choose
+	to return a UID or a GID mapping only.
+	</para>
 </refsect1>
 
 <refsect1>
 	<title>EXAMPLES</title>
 
 	<para>
-	This example shows how tdb2 is used as a the default idmap backend.
+	This example shows how script is used as a the default idmap backend
+	using an external program via the script parameter:
 	</para>
 
 	<programlisting>
 	[global]
-	idmap config * : backend = tdb2
+	idmap config * : backend = script
 	idmap config * : range = 1000000-2000000
+	idmap config * : script = /usr/local/samba/bin/idmap_script.sh
 	</programlisting>
 
 	<para>
-	This example shows how tdb2 is used as a the default idmap backend
-	using an external program via the script parameter:
+	This shows a simple script to partially perform the task:
 	</para>
 
 	<programlisting>
-	[global]
-	idmap config * : backend = tdb2
-	idmap config * : range = 1000000-2000000
-	idmap config * : script = /usr/local/samba/bin/idmap_script.sh
+	#!/bin/sh
+	#
+	# Uncomment this if you want some logging
+	#echo $@ >> /tmp/idmap.sh.log
+	if [ "$1" == "SIDTOID" ]
+	then
+		# Note. The number returned has to be within the range defined
+		#echo "Sending UID:1000005" >> /tmp/idmap.sh.log
+		echo "UID:1000005"
+		exit 0
+	else
+		#echo "Sending ERR: No idea what to do" >> /tmp/idmap.sh.log
+		echo "ERR: No idea what to do"
+		exit 1
+	fi
 	</programlisting>
+
+	<para>
+	Clearly, this script is not enough, as it should probably use wbinfo
+	to determine if an incoming SID is a user or group SID and then
+	look up the mapping in a table or use some other mechanism for
+	mapping SIDs to UIDs and etc.
+	</para>
 </refsect1>
 
 <refsect1>
diff --git a/source3/winbindd/idmap_script.c b/source3/winbindd/idmap_script.c
new file mode 100644
index 0000000..3a0d685
--- /dev/null
+++ b/source3/winbindd/idmap_script.c
@@ -0,0 +1,394 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   idmap script backend, used for Samba setups where you need to map SIDs to
+   specific UIDs/GIDs.
+
+   Copyright (C) Richard Sharpe 2014.
+
+   This is heavily based upon idmap_tdb2.c, which is:
+
+   Copyright (C) Tim Potter 2000
+   Copyright (C) Jim McDonough <jmcd at us.ibm.com> 2003
+   Copyright (C) Jeremy Allison 2006
+   Copyright (C) Simo Sorce 2003-2006
+   Copyright (C) Michael Adam 2009-2010
+
+   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.
+*/
+
+#include "includes.h"
+#include "system/filesys.h"
+#include "winbindd.h"
+#include "idmap.h"
+#include "idmap_rw.h"
+#include "../libcli/security/dom_sid.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_IDMAP
+
+struct idmap_script_context {
+	const char *script; /* script to provide idmaps */
+};
+
+/*
+  run a script to perform a mapping
+
+  The script should accept the following command lines:
+
+      SIDTOID S-1-xxxx -> XID:<id> | ERR:<str>
+      SIDTOID S-1-xxxx -> UID:<id> | ERR:<str>
+      SIDTOID S-1-xxxx -> GID:<id> | ERR:<str>
+      IDTOSID XID xxxx -> SID:<sid> | ERR:<str>
+      IDTOSID UID xxxx -> SID:<sid> | ERR:<str>
+      IDTOSID GID xxxx -> SID:<sid> | ERR:<str>
+
+  where XID means both a UID and a GID. This is the case for ID_TYPE_BOTH.
+
+  TODO: Needs more validation ... like that we got a UID when we asked for one.
+ */
+static NTSTATUS idmap_script_script(struct idmap_script_context *ctx,
+				    struct id_map *map, const char *fmt, ...)
+{
+	va_list ap;
+	char *cmd, **lines;
+	int numlines = 0;
+	unsigned long v;
+
+	cmd = talloc_asprintf(ctx, "%s ", ctx->script);
+	if (!cmd) {
+		DEBUG(10, ("Unable to allocate memory for the script command!\n"));
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	va_start(ap, fmt);
+	cmd = talloc_vasprintf_append(cmd, fmt, ap);
+	va_end(ap);
+	if (!cmd) {
+		DEBUG(10, ("Unable to allocate memory for the script command!\n"));
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	lines = file_lines_pload(cmd, &numlines);
+	talloc_free(cmd);
+	if (!lines) {
+		return NT_STATUS_NONE_MAPPED;
+	}
+
+	DEBUG(10,("idmap script gave %d lines, first: %s\n", numlines,
+		lines[0]));
+
+	if (sscanf(lines[0], "XID:%lu", &v) == 1) {
+		map->xid.id   = v;
+		map->xid.type = ID_TYPE_BOTH;
+	} else if (sscanf(lines[0], "UID:%lu", &v) == 1) {
+		map->xid.id   = v;
+		map->xid.type = ID_TYPE_UID;
+	} else if (sscanf(lines[0], "GID:%lu", &v) == 1) {
+		map->xid.id   = v;
+		map->xid.type = ID_TYPE_GID;
+	} else if (strncmp(lines[0], "SID:S-", 6) == 0) {
+		if (!string_to_sid(map->sid, &lines[0][4])) {
+			DEBUG(0,("Bad SID in '%s' from idmap script %s\n",
+				 lines[0], ctx->script));
+			talloc_free(lines);
+			return NT_STATUS_NONE_MAPPED;
+		}
+	} else {
+		DEBUG(0,("Bad reply '%s' from idmap script %s\n",
+			 lines[0], ctx->script));
+		talloc_free(lines);
+		return NT_STATUS_NONE_MAPPED;
+	}
+
+	talloc_free(lines);
+	return NT_STATUS_OK;
+}
+
+/*
+  Single id to sid lookup function.
+*/
+static NTSTATUS idmap_script_id_to_sid(struct idmap_domain *dom,
+				       struct id_map *map)
+{
+	NTSTATUS ret;
+	char *keystr;
+	char *sidstr;
+	struct idmap_script_context *ctx = dom->private_data;
+
+	if (!dom || !map) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	/* apply filters before checking */
+	if (!idmap_unix_id_is_in_range(map->xid.id, dom)) {
+		DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
+				map->xid.id, dom->low_id, dom->high_id));
+		return NT_STATUS_NONE_MAPPED;
+	}
+
+	switch (map->xid.type) {
+
+	case ID_TYPE_UID:
+		keystr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id);
+		break;
+
+	case ID_TYPE_GID:
+		keystr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id);
+		break;
+
+	case ID_TYPE_BOTH:
+		keystr = talloc_asprintf(ctx, "XID %lu", (unsigned long)map->xid.id);
+		break;
+
+	default:
+		DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type));
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	if (keystr == NULL) {
+		DEBUG(0, ("Out of memory!\n"));
+		ret = NT_STATUS_NO_MEMORY;
+		goto done;
+	}
+
+	DEBUG(10,("Running script to fetch mapping %s\n", keystr));
+
+	ret = idmap_script_script(ctx, map, "IDTOSID %s", keystr);
+	if (!NT_STATUS_IS_OK(ret)) {
+		goto done;
+	}
+
+	sidstr = sid_string_talloc(keystr, map->sid);
+	if (!sidstr) {
+		ret = NT_STATUS_NO_MEMORY;
+		goto done;
+	}
+
+	DEBUG(10,("Found id %s:%d -> %s\n", keystr, map->xid.id,
+		  (const char *)sidstr));
+	ret = NT_STATUS_OK;
+
+done:
+	talloc_free(keystr);
+	return ret;
+}
+
+/*
+ Single sid to id lookup function.
+*/
+static NTSTATUS idmap_script_sid_to_id(struct idmap_domain *dom,
+				       struct id_map *map)
+{
+	NTSTATUS ret;
+	char *keystr;
+	struct idmap_script_context *ctx = dom->private_data;
+	TALLOC_CTX *tmp_ctx = talloc_stackframe();
+
+	keystr = sid_string_talloc(tmp_ctx, map->sid);
+	if (keystr == NULL) {
+		DEBUG(0, ("Out of memory!\n"));
+		ret = NT_STATUS_NO_MEMORY;
+		goto done;
+	}
+
+	DEBUG(10,("Fetching record %s\n", keystr));
+
+	if (ctx->script == NULL) {
+		ret = NT_STATUS_NONE_MAPPED;
+		goto done;
+	}
+
+	ret = idmap_script_script(ctx, map, "SIDTOID %s", keystr);
+	if (!NT_STATUS_IS_OK(ret)) {
+		goto done;
+	}
+
+	/* apply filters before returning result */
+	if (!idmap_unix_id_is_in_range(map->xid.id, dom)) {
+		DEBUG(5, ("Script returned id (%u) out of range (%u - %u)."
+			  " Filtered!\n",
+			  map->xid.id, dom->low_id, dom->high_id));
+		ret = NT_STATUS_NONE_MAPPED;
+		goto done;
+	}
+
+done:
+	talloc_free(tmp_ctx);
+	return ret;
+}
+
+static NTSTATUS idmap_script_unixids_to_sids(struct idmap_domain *dom,
+				      struct id_map **ids)
+{
+	NTSTATUS ret;
+	int i, num_mapped = 0;
+
+	DEBUG(10, ("%s called ...\n", __func__));
+	/* Init status to avoid surprise ... */
+	for (i = 0; ids[i]; i++) {
+		ids[i]->status = ID_UNKNOWN;
+	}
+
+	for (i = 0; ids[i]; i++) {
+		ret = idmap_script_id_to_sid(dom, ids[i]);
+		if (!NT_STATUS_IS_OK(ret)) {
+			if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
+				ids[i]->status = ID_UNMAPPED;
+				continue;
+			}
+
+			/*
+			 * We cannot keep going if it is other than mapping
+			 * failed.
+			 */
+			goto done;
+		}
+
+		ids[i]->status = ID_MAPPED;
+		num_mapped++;
+	}
+
+	ret = NT_STATUS_OK;
+
+done:
+	if (NT_STATUS_IS_OK(ret)) {
+		if (i == 0 || num_mapped == 0) {
+			ret = NT_STATUS_NONE_MAPPED;
+		}
+		else if (num_mapped < i) {
+			ret = STATUS_SOME_UNMAPPED;
+		} else {
+			DEBUG(10, ("Returning NT_STATUS_OK\n"));
+			ret = NT_STATUS_OK;
+		}
+	}
+
+	return ret;
+}
+
+static NTSTATUS idmap_script_sids_to_unixids(struct idmap_domain *dom,
+				      struct id_map **ids)
+{
+	NTSTATUS ret;
+	int i, num_mapped = 0;
+
+	DEBUG(10, ("%s called ...\n", __func__));
+	/* Init status to avoid surprise ... */
+	for (i = 0; ids[i]; i++) {
+		ids[i]->status = ID_UNKNOWN;
+	}
+
+	for (i = 0; ids[i]; i++) {
+		ret = idmap_script_sid_to_id(dom, ids[i]);
+		if (!NT_STATUS_IS_OK(ret)) {
+			if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
+				ids[i]->status = ID_UNMAPPED;
+				continue;
+			}
+
+			/*
+			 * We cannot keep going if it is other than mapping
+			 * failed.
+			 */
+			goto done;
+		}
+
+		ids[i]->status = ID_MAPPED;
+		num_mapped++;
+	}
+
+	ret = NT_STATUS_OK;
+
+done:
+	if (NT_STATUS_IS_OK(ret)) {
+		if (i == 0 || num_mapped == 0) {
+			ret = NT_STATUS_NONE_MAPPED;
+		}
+		else if (num_mapped < i) {
+			ret = STATUS_SOME_UNMAPPED;
+		} else {
+			DEBUG(10, ("Returning NT_STATUS_OK\n"));
+			ret = NT_STATUS_OK;
+		}
+	}
+
+	return ret;
+}
+
+/*
+ *   Initialise idmap_script database.
+ */
+static NTSTATUS idmap_script_db_init(struct idmap_domain *dom)
+{
+	NTSTATUS ret;
+	struct idmap_script_context *ctx;
+	char *config_option = NULL;
+	const char * idmap_script = NULL;
+
+	DEBUG(10, ("%s called ...\n", __func__));
+
+	ctx = talloc_zero(dom, struct idmap_script_context);
+	if (!ctx) {
+		DEBUG(0, ("Out of memory!\n"));
+		ret = NT_STATUS_NO_MEMORY;
+		goto failed;
+	}
+
+	config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
+	if (config_option == NULL) {
+		DEBUG(0, ("Out of memory!\n"));
+		ret = NT_STATUS_NO_MEMORY;
+		goto failed;


-- 
Samba Shared Repository


More information about the samba-cvs mailing list