[patch] idmap backend = external

Matthew Mastracci matt at aclaro.com
Sat Apr 8 22:08:08 GMT 2006


I've updated the patch slightly to address some feedback from the IRC 
channel and some things I've noticed:

  - Pass the IDMAP interface version to the script's init method now 
(scripts should probably check this to avoid surprises on interface 
version changes)
  - Debug messages are at higher levels to avoid spamming the logs
  - Fixed some spaces that should have been tabs

Here's a quick overview of the parameters/return responses expected. 
For all invocations, a zero return code translates to "NT_STATUS_OK" 
while a non-zero return code translates to "NT_STATUS_UNSUCCESSFUL":

Command          Parameter(s)              Return Values (1 per line)
init             interface_version      -> no return values
set_mapping	 sid uid/gid id_type    -> no return values
allocate_rid     rid_type               -> rid
allocate_id	 id_type                -> id
get_sid_from_id	 id id_type             -> sid
get_id_from_sid  sid                    -> id id_type

For all script calls, id_type is 1 for user and 2 for group (matching 
the internal Samba definitions)

Matthew Mastracci wrote:

> I've been working on implementing a new idmap backend that would 
> delegate all id-mapping work to an external script invoked for the 
> various get_id_from_sid/allocate_XXX methods.
-------------- next part --------------
--- samba-orig/source/configure	2006-03-29 21:53:13.000000000 -0700
+++ samba-3.0.22/source/configure	2006-04-08 08:17:35.019836640 -0600
@@ -32033,7 +32033,7 @@
 _ACEOF
 
     CPPFLAGS="$CPPFLAGS -DLDAP_DEPRECATED"
-    default_static_modules="$default_static_modules pdb_ldap idmap_ldap";
+    default_static_modules="$default_static_modules pdb_ldap idmap_ldap idmap_external";
     default_shared_modules="$default_shared_modules";
     SMBLDAP="lib/smbldap.o"
     SMBLDAPUTIL="lib/smbldap_util.o"
@@ -45538,6 +45538,7 @@
 MODULE_rpc_spoolss=STATIC
 MODULE_rpc_srv=STATIC
 MODULE_idmap_tdb=STATIC
+MODULE_idmap_external=STATIC
 
 
 # Check whether --with-static-modules or --without-static-modules was given.
@@ -46314,6 +46315,42 @@
 
 
 
+	echo "$as_me:$LINENO: checking how to build idmap_external" >&5
+echo $ECHO_N "checking how to build idmap_external... $ECHO_C" >&6
+	if test "$MODULE_idmap_external"; then
+		DEST=$MODULE_idmap_external
+	elif test "$MODULE_idmap" -a "$MODULE_DEFAULT_idmap_external"; then
+		DEST=$MODULE_idmap
+	else
+		DEST=$MODULE_DEFAULT_idmap_external
+	fi
+
+	if test x"$DEST" = xSHARED; then
+
+cat >>confdefs.h <<\_ACEOF
+#define idmap_external_init init_module
+_ACEOF
+
+		IDMAP_MODULES="$IDMAP_MODULES "bin/external.$SHLIBEXT""
+		echo "$as_me:$LINENO: result: shared" >&5
+echo "${ECHO_T}shared" >&6
+
+		string_shared_modules="$string_shared_modules idmap_external"
+	elif test x"$DEST" = xSTATIC; then
+		init_static_modules_idmap="$init_static_modules_idmap idmap_external_init();"
+		string_static_modules="$string_static_modules idmap_external"
+		IDMAP_STATIC="$IDMAP_STATIC sam/idmap_external.o"
+
+
+		echo "$as_me:$LINENO: result: static" >&5
+echo "${ECHO_T}static" >&6
+	else
+	    string_ignored_modules="$string_ignored_modules idmap_external"
+		echo "$as_me:$LINENO: result: not" >&5
+echo "${ECHO_T}not" >&6
+	fi
+
+
 	echo "$as_me:$LINENO: checking how to build idmap_ldap" >&5
 echo $ECHO_N "checking how to build idmap_ldap... $ECHO_C" >&6
 	if test "$MODULE_idmap_ldap"; then
diff -ur samba-orig/source/configure.in samba-3.0.22/source/configure.in
--- samba-orig/source/configure.in	2006-02-20 13:33:23.000000000 -0700
+++ samba-3.0.22/source/configure.in	2006-04-08 08:16:29.006872136 -0600
@@ -2852,7 +2852,7 @@
   if test x"$ac_cv_lib_ext_ldap_ldap_init" = x"yes"; then
     AC_DEFINE(HAVE_LDAP,1,[Whether ldap is available])
     CPPFLAGS="$CPPFLAGS -DLDAP_DEPRECATED"
-    default_static_modules="$default_static_modules pdb_ldap idmap_ldap";
+    default_static_modules="$default_static_modules pdb_ldap idmap_ldap idmap_smbldap idmap_external";
     default_shared_modules="$default_shared_modules";
     SMBLDAP="lib/smbldap.o"
     SMBLDAPUTIL="lib/smbldap_util.o"
@@ -5108,6 +5108,7 @@
 MODULE_rpc_spoolss=STATIC
 MODULE_rpc_srv=STATIC
 MODULE_idmap_tdb=STATIC
+MODULE_idmap_external=STATIC
 
 AC_ARG_WITH(static-modules,
 [  --with-static-modules=MODULES  Comma-seperated list of names of modules to statically link in],
@@ -5163,6 +5164,7 @@
 SMB_MODULE(rpc_echo, \$(RPC_ECHO_OBJ), "bin/librpc_echo.$SHLIBEXT", RPC)
 SMB_SUBSYSTEM(RPC,smbd/server.o)
 
+SMB_MODULE(idmap_external, sam/idmap_external.o, "bin/external.$SHLIBEXT", IDMAP)
 SMB_MODULE(idmap_ldap, sam/idmap_ldap.o, "bin/ldap.$SHLIBEXT", IDMAP)
 SMB_MODULE(idmap_tdb, sam/idmap_tdb.o, "bin/tdb.$SHLIBEXT", IDMAP)
 SMB_MODULE(idmap_rid, sam/idmap_rid.o, "bin/rid.$SHLIBEXT", IDMAP)
diff -ur samba-orig/source/include/config.h.in samba-3.0.22/source/include/config.h.in
--- samba-orig/source/include/config.h.in	2006-03-29 21:53:11.000000000 -0700
+++ samba-3.0.22/source/include/config.h.in	2006-04-08 08:17:31.134427312 -0600
@@ -2157,6 +2157,9 @@
 /* Whether to build idmap_ad as shared module */
 #undef idmap_ad_init
 
+/* Whether to build idmap_external as shared module */
+#undef idmap_external_init
+
 /* Whether to build idmap_ldap as shared module */
 #undef idmap_ldap_init
 
--- /dev/null	2005-04-07 12:00:38.604651250 -0400
+++ samba-3.0.22/source/sam/idmap_external.c	2006-04-09 15:03:59.000000000 -0400
@@ -0,0 +1,259 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   idmap external backend
+
+   Copyright (C) Matthew Mastracci 		2006
+
+   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"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_IDMAP
+
+
+struct external_idmap_state {
+	pstring script;
+};
+
+static struct external_idmap_state external_state;
+
+/***********************************************************************
+ This function cannot be called to modify a mapping, only set a new one
+***********************************************************************/
+
+static NTSTATUS external_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
+{
+	pstring commandline;
+	int ret;
+
+	pstr_sprintf(commandline, "%s %s %ld %ld", 
+		external_state.script, "set_mapping", 
+		((id_type & ID_USERID) ? (unsigned long)id.uid : (unsigned long)id.gid),
+		id_type);
+	ret = smbrun(commandline, NULL);
+	if (ret != 0)
+		return NT_STATUS_UNSUCCESSFUL;
+
+	DEBUG((ret) ? 1 : 5, ("external_set_mapping: script returned %d\n", ret));
+
+	return NT_STATUS_OK;
+}
+
+/*****************************************************************************
+ Allocate a new RID
+*****************************************************************************/
+
+static NTSTATUS external_allocate_rid(uint32 *rid, int rid_type)
+{
+	pstring commandline;
+	int ret;
+	int numlines;
+	char **qlines;
+	int fd;
+
+	pstr_sprintf(commandline, "%s %s %ld", external_state.script, 
+		"allocate_rid", rid_type);
+
+	ret = smbrun(commandline, &fd);
+	DEBUG((ret) ? 1 : 5, ("external_allocate_rid: script returned %d\n", ret));
+	if (fd != -1) {
+		qlines = fd_lines_load(fd, &numlines);
+		DEBUG(5, ("external_allocate_rid: script output %d line(s)\n", numlines));
+		if (numlines == 1) {
+			*rid = atol(qlines[0]);
+		} 
+		else {
+			ret = -1;
+		}	
+
+		file_lines_free(qlines);
+		close(fd);
+	}
+
+	return (ret) ? NT_STATUS_UNSUCCESSFUL : NT_STATUS_OK;
+}
+
+/*****************************************************************************
+ Allocate a new uid or gid
+*****************************************************************************/
+
+static NTSTATUS external_allocate_id(unid_t *id, int id_type)
+{
+	pstring commandline;
+	int ret;
+	int numlines;
+	char **qlines;
+	int fd;
+
+	pstr_sprintf(commandline, "%s %s %ld %ld", 
+		external_state.script, "allocate_id", 
+		id_type);
+
+	ret = smbrun(commandline, &fd);
+	DEBUG((ret) ? 1 : 5, ("external_allocate_id: script returned %d\n", ret));
+	if (fd != -1) {
+		qlines = fd_lines_load(fd, &numlines);
+		DEBUG(5, ("external_allocate_id: script output %d line(s)\n", numlines));
+		if (numlines == 1) {
+			if (id_type & ID_USERID)
+				id->uid = atol(qlines[0]);
+			else
+				id->gid = atol(qlines[0]);
+		} 
+		else {
+			ret = -1;
+		}	
+
+		file_lines_free(qlines);
+		close(fd);
+	}
+
+	return (ret) ? NT_STATUS_UNSUCCESSFUL : NT_STATUS_OK;
+}
+
+/*****************************************************************************
+ get a sid from an id
+*****************************************************************************/
+
+static NTSTATUS external_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
+{
+	pstring commandline;
+	int ret;
+	int numlines;
+	char **qlines;
+	int fd;
+
+	pstr_sprintf(commandline, "%s %s %ld %ld", 
+		external_state.script, "get_sid_from_id",
+		((id_type & ID_USERID) ? (unsigned long)id.uid : (unsigned long)id.gid),
+		id_type);
+
+	ret = smbrun(commandline, &fd);
+	DEBUG((ret) ? 1 : 5, ("external_get_sid_from_id: script returned %d\n", ret));
+	if (fd != -1) {
+		qlines = fd_lines_load(fd, &numlines);
+		DEBUG(5, ("external_get_sid_from_id: script output %d line(s)\n", numlines));
+		if (numlines == 1) {
+			if (!string_to_sid(sid, qlines[0])) {
+				DEBUG(0, ("external_get_sid_from_id: script returned invalid SID: %s\n", qlines[0]));
+				ret = -1;
+			}
+		} 
+		else {
+			ret = -1;
+		}	
+
+		file_lines_free(qlines);
+		close(fd);
+	}
+
+	return (ret) ? NT_STATUS_UNSUCCESSFUL : NT_STATUS_OK;
+}
+
+/***********************************************************************
+ Get an id from a sid 
+***********************************************************************/
+
+static NTSTATUS external_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid)
+{
+	pstring commandline;
+	int ret;
+	int numlines;
+	char **qlines;
+	int fd;
+	pstring sid_str;
+
+	sid_to_string(sid_str, sid);
+	pstr_sprintf(commandline, "%s %s %s", external_state.script, 
+		"get_id_from_sid", sid_str);
+
+	ret = smbrun(commandline, &fd);
+	DEBUG((ret) ? 1 : 5, ("external_get_id_from_sid: script returned %d\n", ret));
+	if (fd != -1) {
+		qlines = fd_lines_load(fd, &numlines);
+		DEBUG(5, ("external_get_id_from_sid: script output %d line(s)\n", numlines));
+		if (numlines == 2) {
+			*id_type = atoi(qlines[1]);
+			if (*id_type & ID_USERID)
+				id->uid = atol(qlines[0]);
+			else
+				id->gid = atol(qlines[0]);
+		} 
+		else {
+			ret = -1;
+		}	
+
+		file_lines_free(qlines);
+		close(fd);
+	}
+
+	return (ret) ? NT_STATUS_UNSUCCESSFUL : NT_STATUS_OK;
+}
+
+/*****************************************************************************
+ Initialise idmap database. 
+*****************************************************************************/
+
+static NTSTATUS external_idmap_init( char *params )
+{
+	pstring commandline;
+	int ret;
+
+	/* assume script is the only parameter */
+	pstr_sprintf(external_state.script, "%s", params);
+	
+	pstr_sprintf(commandline, "%s %s %d", external_state.script, "init", SMB_IDMAP_INTERFACE_VERSION);
+	ret = smbrun(commandline, NULL);
+	if (ret != 0)
+		return NT_STATUS_UNSUCCESSFUL;
+
+	DEBUG((ret) ? 1 : 5, ("external_idmap_init: script returned %d\n", ret));
+
+	return NT_STATUS_OK;
+}
+
+/*****************************************************************************
+ End the session
+*****************************************************************************/
+
+static NTSTATUS external_idmap_close(void)
+{
+	return NT_STATUS_OK;
+}
+
+
+static void external_idmap_status(void)
+{
+	DEBUG(0, ("External IDMAP Status not available\n"));
+}
+
+static struct idmap_methods external_methods = {
+	external_idmap_init,
+	external_allocate_rid,
+	external_allocate_id,
+	external_get_sid_from_id,
+	external_get_id_from_sid,
+	external_set_mapping,
+	external_idmap_close,
+	external_idmap_status
+};
+
+NTSTATUS idmap_external_init(void)
+{
+	return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "external", &external_methods);
+}




More information about the samba-technical mailing list