summaryrefslogtreecommitdiff
path: root/source4/scripting/python
diff options
context:
space:
mode:
Diffstat (limited to 'source4/scripting/python')
-rw-r--r--source4/scripting/python/STATUS14
-rw-r--r--source4/scripting/python/ac_pkg_swig.m4125
-rw-r--r--source4/scripting/python/config.m483
-rw-r--r--source4/scripting/python/config.mk37
-rw-r--r--source4/scripting/python/examples/netbios.py28
-rwxr-xr-xsource4/scripting/python/examples/samr.py114
-rwxr-xr-xsource4/scripting/python/examples/winreg.py87
-rw-r--r--source4/scripting/python/misc.i121
-rw-r--r--source4/scripting/python/misc.py123
-rw-r--r--source4/scripting/python/misc_wrap.c3976
-rw-r--r--source4/scripting/python/modules.c69
-rw-r--r--source4/scripting/python/modules.h26
-rw-r--r--source4/scripting/python/pytalloc.c52
-rw-r--r--source4/scripting/python/pytalloc.h51
-rw-r--r--source4/scripting/python/samba/__init__.py238
-rw-r--r--source4/scripting/python/samba/getopt.py116
-rw-r--r--source4/scripting/python/samba/hostconfig.py33
-rw-r--r--source4/scripting/python/samba/idmap.py82
-rw-r--r--source4/scripting/python/samba/ndr.py28
-rw-r--r--source4/scripting/python/samba/provision.py1531
-rw-r--r--source4/scripting/python/samba/samba3.py711
-rw-r--r--source4/scripting/python/samba/samdb.py227
-rw-r--r--source4/scripting/python/samba/samr.py759
-rw-r--r--source4/scripting/python/samba/tests/__init__.py98
-rw-r--r--source4/scripting/python/samba/tests/dcerpc/__init__.py0
-rw-r--r--source4/scripting/python/samba/tests/dcerpc/bare.py48
-rw-r--r--source4/scripting/python/samba/tests/dcerpc/registry.py50
-rw-r--r--source4/scripting/python/samba/tests/dcerpc/rpcecho.py69
-rw-r--r--source4/scripting/python/samba/tests/dcerpc/sam.py46
-rw-r--r--source4/scripting/python/samba/tests/dcerpc/unix.py37
-rw-r--r--source4/scripting/python/samba/tests/provision.py124
-rw-r--r--source4/scripting/python/samba/tests/samba3.py210
-rw-r--r--source4/scripting/python/samba/tests/samdb.py84
-rw-r--r--source4/scripting/python/samba/tests/upgrade.py37
-rwxr-xr-xsource4/scripting/python/samba/torture/pytorture51
-rw-r--r--source4/scripting/python/samba/torture/spoolss.py437
-rwxr-xr-xsource4/scripting/python/samba/torture/torture_samr.py221
-rwxr-xr-xsource4/scripting/python/samba/torture/torture_tdb.py90
-rwxr-xr-xsource4/scripting/python/samba/torture/winreg.py165
-rw-r--r--source4/scripting/python/samba/upgrade.py437
-rw-r--r--source4/scripting/python/subunit/__init__.py388
-rw-r--r--source4/scripting/python/uuidmodule.c58
42 files changed, 11281 insertions, 0 deletions
diff --git a/source4/scripting/python/STATUS b/source4/scripting/python/STATUS
new file mode 100644
index 0000000000..ee67b8bc7a
--- /dev/null
+++ b/source4/scripting/python/STATUS
@@ -0,0 +1,14 @@
+dsdb/samdb/ldb_modules/tests/samba3sam.py: Fix remaining failing tests
+lib/ldb/tests/python/ldap.py: Fix remaining 3 FIXME's
+command-line vampire
+provisioning: combine some of the python dictionaries
+finish scripting/bin/smbstatus.py
+
+not important before making Python the default:
+- hierarchy (rename samr -> dcerpc.samr, misc -> samba.misc, etc)
+- scripting/python/samba/upgrade.py
+- install python modules into system
+- SWAT
+- __ndr_pack__/__ndr_unpack__ members for the NDR struct bindings
+- generate docstrings in DCE/RPC bindings
+- eliminate some variables from the python interface because they can be induced
diff --git a/source4/scripting/python/ac_pkg_swig.m4 b/source4/scripting/python/ac_pkg_swig.m4
new file mode 100644
index 0000000000..8d3561a0a7
--- /dev/null
+++ b/source4/scripting/python/ac_pkg_swig.m4
@@ -0,0 +1,125 @@
+##### http://autoconf-archive.cryp.to/ac_pkg_swig.html
+#
+# SYNOPSIS
+#
+# AC_PROG_SWIG([major.minor.micro])
+#
+# DESCRIPTION
+#
+# This macro searches for a SWIG installation on your system. If
+# found you should call SWIG via $(SWIG). You can use the optional
+# first argument to check if the version of the available SWIG is
+# greater than or equal to the value of the argument. It should have
+# the format: N[.N[.N]] (N is a number between 0 and 999. Only the
+# first N is mandatory.)
+#
+# If the version argument is given (e.g. 1.3.17), AC_PROG_SWIG checks
+# that the swig package is this version number or higher.
+#
+# In configure.in, use as:
+#
+# AC_PROG_SWIG(1.3.17)
+# SWIG_ENABLE_CXX
+# SWIG_MULTI_MODULE_SUPPORT
+# SWIG_PYTHON
+#
+# LAST MODIFICATION
+#
+# 2006-10-22
+#
+# COPYLEFT
+#
+# Copyright (c) 2006 Sebastian Huber <sebastian-huber@web.de>
+# Copyright (c) 2006 Alan W. Irwin <irwin@beluga.phys.uvic.ca>
+# Copyright (c) 2006 Rafael Laboissiere <rafael@laboissiere.net>
+# Copyright (c) 2006 Andrew Collier <colliera@ukzn.ac.za>
+#
+# 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., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+#
+# As a special exception, the respective Autoconf Macro's copyright
+# owner gives unlimited permission to copy, distribute and modify the
+# configure scripts that are the output of Autoconf when processing
+# the Macro. You need not follow the terms of the GNU General Public
+# License when using or distributing such scripts, even though
+# portions of the text of the Macro appear in them. The GNU General
+# Public License (GPL) does govern all other use of the material that
+# constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the
+# Autoconf Macro released by the Autoconf Macro Archive. When you
+# make and distribute a modified version of the Autoconf Macro, you
+# may extend this special exception to the GPL to apply to your
+# modified version as well.
+
+AC_DEFUN([AC_PROG_SWIG],[
+ AC_PATH_PROG([SWIG],[swig])
+ if test -z "$SWIG" ; then
+ AC_MSG_WARN([cannot find 'swig' program. You should look at http://www.swig.org])
+ SWIG='no'
+ elif test -n "$1" ; then
+ AC_MSG_CHECKING([for SWIG version])
+ [swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`]
+ AC_MSG_RESULT([$swig_version])
+ if test -n "$swig_version" ; then
+ # Calculate the required version number components
+ [required=$1]
+ [required_major=`echo $required | sed 's/[^0-9].*//'`]
+ if test -z "$required_major" ; then
+ [required_major=0]
+ fi
+ [required=`echo $required | sed 's/[0-9]*[^0-9]//'`]
+ [required_minor=`echo $required | sed 's/[^0-9].*//'`]
+ if test -z "$required_minor" ; then
+ [required_minor=0]
+ fi
+ [required=`echo $required | sed 's/[0-9]*[^0-9]//'`]
+ [required_patch=`echo $required | sed 's/[^0-9].*//'`]
+ if test -z "$required_patch" ; then
+ [required_patch=0]
+ fi
+ # Calculate the available version number components
+ [available=$swig_version]
+ [available_major=`echo $available | sed 's/[^0-9].*//'`]
+ if test -z "$available_major" ; then
+ [available_major=0]
+ fi
+ [available=`echo $available | sed 's/[0-9]*[^0-9]//'`]
+ [available_minor=`echo $available | sed 's/[^0-9].*//'`]
+ if test -z "$available_minor" ; then
+ [available_minor=0]
+ fi
+ [available=`echo $available | sed 's/[0-9]*[^0-9]//'`]
+ [available_patch=`echo $available | sed 's/[^0-9].*//'`]
+ if test -z "$available_patch" ; then
+ [available_patch=0]
+ fi
+ if test $available_major -ne $required_major \
+ -o $available_minor -ne $required_minor \
+ -o $available_patch -lt $required_patch ; then
+ AC_MSG_WARN([SWIG version >= $1 is required if you would like to work on the SWIG bindings. You have $swig_version. ])
+ SWIG='no'
+ else
+ AC_MSG_NOTICE([SWIG executable is '$SWIG'])
+ SWIG_LIB=`$SWIG -swiglib`
+ AC_MSG_NOTICE([SWIG library directory is '$SWIG_LIB'])
+ fi
+ else
+ AC_MSG_WARN([cannot determine SWIG version])
+ SWIG='no'
+ fi
+ fi
+ AC_SUBST([SWIG_LIB])
+])
diff --git a/source4/scripting/python/config.m4 b/source4/scripting/python/config.m4
new file mode 100644
index 0000000000..af13b6ae69
--- /dev/null
+++ b/source4/scripting/python/config.m4
@@ -0,0 +1,83 @@
+m4_include(scripting/python/ac_pkg_swig.m4)
+
+AC_ARG_VAR([PYTHON_VERSION],[The installed Python
+ version to use, for example '2.3'. This string
+ will be appended to the Python interpreter
+ canonical name.])
+
+AC_PROG_SWIG(1.3.35)
+
+AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]])
+if test -z "$PYTHON"; then
+ working_python=no
+ AC_MSG_WARN([No python found])
+fi
+
+AC_DEFUN([TRY_LINK_PYTHON],
+[
+ if test $working_python = no; then
+ ac_save_LIBS="$LIBS"
+ ac_save_CFLAGS="$CFLAGS"
+ LIBS="$LIBS $1"
+ CFLAGS="$CFLAGS $2"
+
+ AC_TRY_LINK([
+ /* we have our own configure tests */
+ #include <Python.h>
+ ],[
+ Py_InitModule(NULL, NULL);
+ ],[
+ PYTHON_LDFLAGS="$1"
+ PYTHON_CFLAGS="$2"
+ working_python=yes
+ ])
+ LIBS="$ac_save_LIBS"
+ CFLAGS="$ac_save_CFLAGS"
+ fi
+])
+
+dnl assume no working python
+working_python=no
+
+if test -z "$PYTHON_VERSION"; then
+ AC_PATH_PROGS([PYTHON_CONFIG], [python2.6-config python2.5-config python2.4-config python-config])
+else
+ AC_PATH_PROG([PYTHON_CONFIG], [python[$PYTHON_VERSION]-config])
+fi
+
+if test -z "$PYTHON_CONFIG"; then
+ AC_MSG_WARN([No python-config found])
+else
+ TRY_LINK_PYTHON([`$PYTHON_CONFIG --ldflags`], [`$PYTHON_CONFIG --includes`])
+ TRY_LINK_PYTHON([`$PYTHON_CONFIG --ldflags`], [`$PYTHON_CONFIG --cflags`])
+ if x$working_python = xno; then
+ # It seems the library path isn't included on some systems
+ base=`$PYTHON_CONFIG --prefix`
+ TRY_LINK_PYTHON([`echo -n -L${base}/lib " "; $PYTHON_CONFIG --ldflags`], [`$PYTHON_CONFIG --includes`])
+ TRY_LINK_PYTHON([`echo -n -L${base}/lib " "; $PYTHON_CONFIG --ldflags`], [`$PYTHON_CONFIG --cflags`])
+ fi
+fi
+
+if test x$PYTHON != x
+then
+ DISTUTILS_CFLAGS=`$PYTHON -c "from distutils import sysconfig; print '-I%s -I%s %s' % (sysconfig.get_python_inc(), sysconfig.get_python_inc(plat_specific=1), sysconfig.get_config_var('CFLAGS'))"`
+ DISTUTILS_LDFLAGS=`$PYTHON -c "from distutils import sysconfig; print '%s %s -lpython%s -L%s' % (sysconfig.get_config_var('LIBS'), sysconfig.get_config_var('SYSLIBS'), sysconfig.get_config_var('VERSION'), sysconfig.get_config_var('LIBPL'))"`
+ TRY_LINK_PYTHON($DISTUTILS_LDFLAGS, $DISTUTILS_CFLAGS)
+fi
+
+SMB_EXT_LIB(EXT_LIB_PYTHON, [$PYTHON_LDFLAGS], [$PYTHON_CFLAGS])
+
+AC_MSG_CHECKING(working python module support)
+if test $working_python = yes; then
+ SMB_ENABLE(EXT_LIB_PYTHON,YES)
+ SMB_ENABLE(LIBPYTHON,YES)
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_ERROR([Python not found. Please install Python 2.x and its development headers/libraries.])
+fi
+
+AC_MSG_CHECKING(python library directory)
+pythondir=`$PYTHON -c "from distutils import sysconfig; print sysconfig.get_python_lib(1, 0, '\\${prefix}')"`
+AC_MSG_RESULT($pythondir)
+
+AC_SUBST(pythondir)
diff --git a/source4/scripting/python/config.mk b/source4/scripting/python/config.mk
new file mode 100644
index 0000000000..b494ee6e8d
--- /dev/null
+++ b/source4/scripting/python/config.mk
@@ -0,0 +1,37 @@
+[SUBSYSTEM::LIBPYTHON]
+PUBLIC_DEPENDENCIES = EXT_LIB_PYTHON
+PRIVATE_DEPENDENCIES = PYTALLOC
+INIT_FUNCTION_SENTINEL = { NULL, NULL }
+
+LIBPYTHON_OBJ_FILES = $(addprefix $(pyscriptsrcdir)/, modules.o)
+
+[SUBSYSTEM::PYTALLOC]
+PUBLIC_DEPENDENCIES = EXT_LIB_PYTHON LIBTALLOC
+
+PYTALLOC_OBJ_FILES = $(addprefix $(pyscriptsrcdir)/, pytalloc.o)
+
+[PYTHON::python_uuid]
+PRIVATE_DEPENDENCIES = LIBNDR
+
+python_uuid_OBJ_FILES = $(pyscriptsrcdir)/uuidmodule.o
+
+[PYTHON::python_misc]
+LIBRARY_REALNAME = samba/_misc.$(SHLIBEXT)
+PRIVATE_DEPENDENCIES = LIBNDR LIBLDB SAMDB CREDENTIALS
+
+python_misc_OBJ_FILES = $(pyscriptsrcdir)/misc_wrap.o
+
+$(python_misc_OBJ_FILES): CFLAGS+=$(CFLAG_NO_UNUSED_MACROS) $(CFLAG_NO_CAST_QUAL)
+
+_PY_FILES = $(shell find $(pyscriptsrcdir)/samba $(pyscriptsrcdir)/subunit -name "*.py")
+
+$(foreach pyfile, $(_PY_FILES),$(eval $(call python_py_module_template,$(patsubst $(pyscriptsrcdir)/%,%,$(pyfile)),$(pyfile))))
+
+$(eval $(call python_py_module_template,samba/misc.py,$(pyscriptsrcdir)/misc.py))
+
+EPYDOC_OPTIONS = --no-private --url http://www.samba.org/ --no-sourcecode
+
+epydoc:: pythonmods
+ PYTHONPATH=$(pythonbuilddir) epydoc $(EPYDOC_OPTIONS) samba tdb ldb subunit
+
+install:: installpython
diff --git a/source4/scripting/python/examples/netbios.py b/source4/scripting/python/examples/netbios.py
new file mode 100644
index 0000000000..3671076a59
--- /dev/null
+++ b/source4/scripting/python/examples/netbios.py
@@ -0,0 +1,28 @@
+#!/usr/bin/python
+
+# Unix SMB/CIFS implementation.
+# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+from samba.netbios import Node
+
+n = Node()
+(reply_from, names, addresses) = n.query_name("GANIEDA", "192.168.4.0",
+ timeout=4)
+
+print "Received reply from %s:" % (reply_from, )
+print "Names: %r" % (names, )
+print "Addresses: %r" % (addresses, )
diff --git a/source4/scripting/python/examples/samr.py b/source4/scripting/python/examples/samr.py
new file mode 100755
index 0000000000..1f2afbe688
--- /dev/null
+++ b/source4/scripting/python/examples/samr.py
@@ -0,0 +1,114 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Unix SMB/CIFS implementation.
+# Copyright © Jelmer Vernooij <jelmer@samba.org> 2008
+#
+# Based on samr.js © Andrew Tridgell <tridge@samba.org>
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+import sys
+
+sys.path.insert(0, "bin/python")
+
+from samba.dcerpc import samr, security, lsa
+
+def FillUserInfo(samr, dom_handle, users, level):
+ """fill a user array with user information from samrQueryUserInfo"""
+ for i in range(len(users)):
+ user_handle = samr.OpenUser(handle, security.SEC_FLAG_MAXIMUM_ALLOWED, users[i].idx)
+ info = samr.QueryUserInfo(user_handle, level)
+ info.name = users[i].name
+ info.idx = users[i].idx
+ users[i] = info
+ samr.Close(user_handle)
+
+def toArray((handle, array, num_entries)):
+ ret = []
+ for x in range(num_entries):
+ ret.append((array.entries[x].idx, array.entries[x].name))
+ return ret
+
+
+def test_Connect(samr):
+ """test the samr_Connect interface"""
+ print "Testing samr_Connect"
+ return samr.Connect2(None, security.SEC_FLAG_MAXIMUM_ALLOWED)
+
+def test_LookupDomain(samr, handle, domain):
+ """test the samr_LookupDomain interface"""
+ print "Testing samr_LookupDomain"
+ return samr.LookupDomain(handle, domain)
+
+def test_OpenDomain(samr, handle, sid):
+ """test the samr_OpenDomain interface"""
+ print "Testing samr_OpenDomain"
+ return samr.OpenDomain(handle, security.SEC_FLAG_MAXIMUM_ALLOWED, sid)
+
+def test_EnumDomainUsers(samr, dom_handle):
+ """test the samr_EnumDomainUsers interface"""
+ print "Testing samr_EnumDomainUsers"
+ users = toArray(samr.EnumDomainUsers(dom_handle, 0, 0, -1))
+ print "Found %d users" % len(users)
+ for idx, user in users:
+ print "\t%s\t(%d)" % (user, idx)
+
+def test_EnumDomainGroups(samr, dom_handle):
+ """test the samr_EnumDomainGroups interface"""
+ print "Testing samr_EnumDomainGroups"
+ groups = toArray(samr.EnumDomainGroups(dom_handle, 0, 0))
+ print "Found %d groups" % len(groups)
+ for idx, group in groups:
+ print "\t%s\t(%d)" % (group, idx)
+
+def test_domain_ops(samr, dom_handle):
+ """test domain specific ops"""
+ test_EnumDomainUsers(samr, dom_handle)
+ test_EnumDomainGroups(samr, dom_handle)
+
+def test_EnumDomains(samr, handle):
+ """test the samr_EnumDomains interface"""
+ print "Testing samr_EnumDomains"
+
+ domains = toArray(samr.EnumDomains(handle, 0, -1))
+ print "Found %d domains" % len(domains)
+ for idx, domain in domains:
+ print "\t%s (%d)" % (domain, idx)
+ for idx, domain in domains:
+ print "Testing domain %s" % domain
+ sid = samr.LookupDomain(handle, domain)
+ dom_handle = test_OpenDomain(samr, handle, sid)
+ test_domain_ops(samr, dom_handle)
+ samr.Close(dom_handle)
+
+if len(sys.argv) != 2:
+ print "Usage: samr.js <BINDING>"
+ sys.exit(1)
+
+binding = sys.argv[1]
+
+print "Connecting to %s" % binding
+try:
+ samr = samr.samr(binding)
+except Exception, e:
+ print "Failed to connect to %s: %s" % (binding, e.message)
+ sys.exit(1)
+
+handle = test_Connect(samr)
+test_EnumDomains(samr, handle)
+samr.Close(handle)
+
+print "All OK"
diff --git a/source4/scripting/python/examples/winreg.py b/source4/scripting/python/examples/winreg.py
new file mode 100755
index 0000000000..80b48ecfd7
--- /dev/null
+++ b/source4/scripting/python/examples/winreg.py
@@ -0,0 +1,87 @@
+#!/usr/bin/python
+#
+# tool to manipulate a remote registry
+# Copyright Andrew Tridgell 2005
+# Copyright Jelmer Vernooij 2007
+# Released under the GNU GPL v3 or later
+#
+
+import sys
+
+# Find right directory when running from source tree
+sys.path.insert(0, "bin/python")
+
+from samba.dcerpc import winreg
+import optparse
+import samba.getopt as options
+
+parser = optparse.OptionParser("%s <BINDING> [path]" % sys.argv[0])
+sambaopts = options.SambaOptions(parser)
+parser.add_option_group(sambaopts)
+parser.add_option("--createkey", type="string", metavar="KEYNAME",
+ help="create a key")
+
+opts, args = parser.parse_args()
+
+if len(args) < 1:
+ parser.print_usage()
+ sys.exit(-1)
+
+binding = args[0]
+
+print "Connecting to " + binding
+conn = winreg.winreg(binding, sambaopts.get_loadparm())
+
+def list_values(key):
+ (num_values, max_valnamelen, max_valbufsize) = conn.QueryInfoKey(key, winreg.String())[4:8]
+ for i in range(num_values):
+ name = winreg.StringBuf()
+ name.size = max_valnamelen
+ (name, type, data, _, data_len) = conn.EnumValue(key, i, name, 0, "", max_valbufsize, 0)
+ print "\ttype=%-30s size=%4d '%s'" % type, len, name
+ if type in (winreg.REG_SZ, winreg.REG_EXPAND_SZ):
+ print "\t\t'%s'" % data
+# if (v.type == reg.REG_MULTI_SZ) {
+# for (j in v.value) {
+# printf("\t\t'%s'\n", v.value[j])
+# }
+# }
+# if (v.type == reg.REG_DWORD || v.type == reg.REG_DWORD_BIG_ENDIAN) {
+# printf("\t\t0x%08x (%d)\n", v.value, v.value)
+# }
+# if (v.type == reg.REG_QWORD) {
+# printf("\t\t0x%llx (%lld)\n", v.value, v.value)
+# }
+
+def list_path(key, path):
+ count = 0
+ (num_subkeys, max_subkeylen, max_subkeysize) = conn.QueryInfoKey(key, winreg.String())[1:4]
+ for i in range(num_subkeys):
+ name = winreg.StringBuf()
+ name.size = max_subkeysize
+ keyclass = winreg.StringBuf()
+ keyclass.size = max_subkeysize
+ (name, _, _) = conn.EnumKey(key, i, name, keyclass=keyclass, last_changed_time=None)[0]
+ subkey = conn.OpenKey(key, name, 0, winreg.KEY_QUERY_VALUE | winreg.KEY_ENUMERATE_SUB_KEYS)
+ count += list_path(subkey, "%s\\%s" % (path, name))
+ list_values(subkey)
+ return count
+
+if len(args) > 1:
+ root = args[1]
+else:
+ root = "HKLM"
+
+if opts.createkey:
+ reg.create_key("HKLM\\SOFTWARE", opt.createkey)
+else:
+ print "Listing registry tree '%s'" % root
+ try:
+ root_key = getattr(conn, "Open%s" % root)(None, winreg.KEY_QUERY_VALUE | winreg.KEY_ENUMERATE_SUB_KEYS)
+ except AttributeError:
+ print "Unknown root key name %s" % root
+ sys.exit(1)
+ count = list_path(root_key, root)
+ if count == 0:
+ print "No entries found"
+ sys.exit(1)
diff --git a/source4/scripting/python/misc.i b/source4/scripting/python/misc.i
new file mode 100644
index 0000000000..81be7d5c16
--- /dev/null
+++ b/source4/scripting/python/misc.i
@@ -0,0 +1,121 @@
+/*
+ Unix SMB/CIFS implementation.
+ Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+%module(docstring="Python bindings for miscellaneous Samba functions.",package="samba.misc") misc
+
+%{
+#include "includes.h"
+#include "ldb.h"
+#include "param/param.h"
+#include "auth/credentials/credentials.h"
+#include "dsdb/samdb/samdb.h"
+#include "lib/ldb-samba/ldif_handlers.h"
+#include "librpc/ndr/libndr.h"
+#include "version.h"
+%}
+
+%import "stdint.i"
+%include "exception.i"
+%import "../../lib/talloc/talloc.i"
+%import "../../lib/ldb/ldb.i"
+%import "../../auth/credentials/credentials.i"
+%import "../../param/param.i"
+%import "../../libcli/security/security.i"
+%include "../../libcli/util/errors.i"
+
+%feature("docstring") generate_random_str "S.random_password(len) -> string\n" \
+ "Generate random password with specified length.";
+
+%rename(random_password) generate_random_str;
+char *generate_random_str(TALLOC_CTX *mem_ctx, size_t len);
+
+%feature("docstring") ldb_set_credentials "S.set_credentials(credentials)\n"
+ "Set credentials to use when connecting.";
+
+%feature("docstring") ldb_set_session_info "S.set_session_info(session_info)\n"
+ "Set session info to use when connecting.";
+
+%feature("docstring") ldb_set_loadparm "S.set_loadparm(session_info)\n"
+ "Set loadparm context to use when connecting.";
+
+%inline %{
+void ldb_set_credentials(struct ldb_context *ldb, struct cli_credentials *creds)
+{
+ ldb_set_opaque(ldb, "credentials", creds);
+}
+
+void ldb_set_session_info(struct ldb_context *ldb, struct auth_session_info *session_info)
+{
+ ldb_set_opaque(ldb, "sessionInfo", session_info);
+}
+
+void ldb_set_loadparm(struct ldb_context *ldb, struct loadparm_context *lp_ctx)
+{
+ ldb_set_opaque(ldb, "loadparm", lp_ctx);
+}
+
+%}
+
+%feature("docstring") samdb_set_domain_sid "S.set_domain_sid(sid)\n"
+ "Set SID of domain to use.";
+bool samdb_set_domain_sid(struct ldb_context *ldb,
+ const struct dom_sid *dom_sid_in);
+
+WERROR dsdb_attach_schema_from_ldif_file(struct ldb_context *ldb, const char *pf, const char *df);
+
+%feature("docstring") version "version()\n"
+ "Obtain the Samba version.";
+
+%inline {
+const char *version(void)
+{
+ return SAMBA_VERSION_STRING;
+}
+}
+int dsdb_set_global_schema(struct ldb_context *ldb);
+%feature("docstring") ldb_register_samba_handlers "register_samba_handlers()\n"
+ "Register Samba-specific LDB modules and schemas.";
+int ldb_register_samba_handlers(struct ldb_context *ldb);
+
+%inline %{
+bool dsdb_set_ntds_invocation_id(struct ldb_context *ldb, const char *guid)
+{
+ struct GUID invocation_id_in;
+ if (NT_STATUS_IS_ERR(GUID_from_string(guid, &invocation_id_in))) {
+ return false;
+ }
+ return samdb_set_ntds_invocation_id(ldb, &invocation_id_in);
+}
+%}
+
+char *private_path(TALLOC_CTX* mem_ctx, struct loadparm_context *lp_ctx,
+ const char *name);
+
+typedef unsigned long time_t;
+
+/*
+ convert from unix time to NT time
+*/
+%inline %{
+uint64_t unix2nttime(time_t t)
+{
+ NTTIME nt;
+ unix_to_nt_time(&nt, t);
+ return (uint64_t)nt;
+}
+%}
diff --git a/source4/scripting/python/misc.py b/source4/scripting/python/misc.py
new file mode 100644
index 0000000000..e52d7df11d
--- /dev/null
+++ b/source4/scripting/python/misc.py
@@ -0,0 +1,123 @@
+# This file was automatically generated by SWIG (http://www.swig.org).
+# Version 1.3.36
+#
+# Don't modify this file, modify the SWIG interface instead.
+
+"""
+Python bindings for miscellaneous Samba functions.
+"""
+
+import _misc
+import new
+new_instancemethod = new.instancemethod
+try:
+ _swig_property = property
+except NameError:
+ pass # Python < 2.2 doesn't have 'property'.
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+ if (name == "thisown"): return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'PySwigObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name,None)
+ if method: return method(self,value)
+ if (not static) or hasattr(self,name):
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+ return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+ if (name == "thisown"): return self.this.own()
+ method = class_type.__swig_getmethods__.get(name,None)
+ if method: return method(self)
+ raise AttributeError,name
+
+def _swig_repr(self):
+ try: strthis = "proxy of " + self.this.__repr__()
+ except: strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+import types
+try:
+ _object = types.ObjectType
+ _newclass = 1
+except AttributeError:
+ class _object : pass
+ _newclass = 0
+del types
+
+
+def _swig_setattr_nondynamic_method(set):
+ def set_attr(self,name,value):
+ if (name == "thisown"): return self.this.own(value)
+ if hasattr(self,name) or (name == "this"):
+ set(self,name,value)
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+ return set_attr
+
+
+import ldb
+import credentials
+import param
+import security
+
+def random_password(*args, **kwargs):
+ """
+ S.random_password(len) -> string
+ Generate random password with specified length.
+ """
+ return _misc.random_password(*args, **kwargs)
+
+def ldb_set_credentials(*args, **kwargs):
+ """
+ S.set_credentials(credentials)
+ Set credentials to use when connecting.
+ """
+ return _misc.ldb_set_credentials(*args, **kwargs)
+
+def ldb_set_session_info(*args, **kwargs):
+ """
+ S.set_session_info(session_info)
+ Set session info to use when connecting.
+ """
+ return _misc.ldb_set_session_info(*args, **kwargs)
+
+def ldb_set_loadparm(*args, **kwargs):
+ """
+ S.set_loadparm(session_info)
+ Set loadparm context to use when connecting.
+ """
+ return _misc.ldb_set_loadparm(*args, **kwargs)
+
+def samdb_set_domain_sid(*args, **kwargs):
+ """
+ S.set_domain_sid(sid)
+ Set SID of domain to use.
+ """
+ return _misc.samdb_set_domain_sid(*args, **kwargs)
+dsdb_attach_schema_from_ldif_file = _misc.dsdb_attach_schema_from_ldif_file
+
+def version(*args):
+ """
+ version()
+ Obtain the Samba version.
+ """
+ return _misc.version(*args)
+dsdb_set_global_schema = _misc.dsdb_set_global_schema
+
+def ldb_register_samba_handlers(*args, **kwargs):
+ """
+ register_samba_handlers()
+ Register Samba-specific LDB modules and schemas.
+ """
+ return _misc.ldb_register_samba_handlers(*args, **kwargs)
+dsdb_set_ntds_invocation_id = _misc.dsdb_set_ntds_invocation_id
+private_path = _misc.private_path
+unix2nttime = _misc.unix2nttime
+
+
diff --git a/source4/scripting/python/misc_wrap.c b/source4/scripting/python/misc_wrap.c
new file mode 100644
index 0000000000..3aee83f72c
--- /dev/null
+++ b/source4/scripting/python/misc_wrap.c
@@ -0,0 +1,3976 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 1.3.36
+ *
+ * This file is not intended to be easily readable and contains a number of
+ * coding conventions designed to improve portability and efficiency. Do not make
+ * changes to this file unless you know what you are doing--modify the SWIG
+ * interface file instead.
+ * ----------------------------------------------------------------------------- */
+
+#define SWIGPYTHON
+#define SWIG_PYTHON_NO_BUILD_NONE
+/* -----------------------------------------------------------------------------
+ * This section contains generic SWIG labels for method/variable
+ * declarations/attributes, and other compiler dependent labels.
+ * ----------------------------------------------------------------------------- */
+
+/* template workaround for compilers that cannot correctly implement the C++ standard */
+#ifndef SWIGTEMPLATEDISAMBIGUATOR
+# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560)
+# define SWIGTEMPLATEDISAMBIGUATOR template
+# elif defined(__HP_aCC)
+/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */
+/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */
+# define SWIGTEMPLATEDISAMBIGUATOR template
+# else
+# define SWIGTEMPLATEDISAMBIGUATOR
+# endif
+#endif
+
+/* inline attribute */
+#ifndef SWIGINLINE
+# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__))
+# define SWIGINLINE inline
+# else
+# define SWIGINLINE
+# endif
+#endif
+
+/* attribute recognised by some compilers to avoid 'unused' warnings */
+#ifndef SWIGUNUSED
+# if defined(__GNUC__)
+# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
+# define SWIGUNUSED __attribute__ ((__unused__))
+# else
+# define SWIGUNUSED
+# endif
+# elif defined(__ICC)
+# define SWIGUNUSED __attribute__ ((__unused__))
+# else
+# define SWIGUNUSED
+# endif
+#endif
+
+#ifndef SWIG_MSC_UNSUPPRESS_4505
+# if defined(_MSC_VER)
+# pragma warning(disable : 4505) /* unreferenced local function has been removed */
+# endif
+#endif
+
+#ifndef SWIGUNUSEDPARM
+# ifdef __cplusplus
+# define SWIGUNUSEDPARM(p)
+# else
+# define SWIGUNUSEDPARM(p) p SWIGUNUSED
+# endif
+#endif
+
+/* internal SWIG method */
+#ifndef SWIGINTERN
+# define SWIGINTERN static SWIGUNUSED
+#endif
+
+/* internal inline SWIG method */
+#ifndef SWIGINTERNINLINE
+# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE
+#endif
+
+/* exporting methods */
+#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+# ifndef GCC_HASCLASSVISIBILITY
+# define GCC_HASCLASSVISIBILITY
+# endif
+#endif
+
+#ifndef SWIGEXPORT
+# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+# if defined(STATIC_LINKED)
+# define SWIGEXPORT
+# else
+# define SWIGEXPORT __declspec(dllexport)
+# endif
+# else
+# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY)
+# define SWIGEXPORT __attribute__ ((visibility("default")))
+# else
+# define SWIGEXPORT
+# endif
+# endif
+#endif
+
+/* calling conventions for Windows */
+#ifndef SWIGSTDCALL
+# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+# define SWIGSTDCALL __stdcall
+# else
+# define SWIGSTDCALL
+# endif
+#endif
+
+/* Deal with Microsoft's attempt at deprecating C standard runtime functions */
+#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
+# define _CRT_SECURE_NO_DEPRECATE
+#endif
+
+/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */
+#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE)
+# define _SCL_SECURE_NO_DEPRECATE
+#endif
+
+
+
+/* Python.h has to appear first */
+#include <Python.h>
+
+/* -----------------------------------------------------------------------------
+ * swigrun.swg
+ *
+ * This file contains generic CAPI SWIG runtime support for pointer
+ * type checking.
+ * ----------------------------------------------------------------------------- */
+
+/* This should only be incremented when either the layout of swig_type_info changes,
+ or for whatever reason, the runtime changes incompatibly */
+#define SWIG_RUNTIME_VERSION "4"
+
+/* define SWIG_TYPE_TABLE_NAME as "SWIG_TYPE_TABLE" */
+#ifdef SWIG_TYPE_TABLE
+# define SWIG_QUOTE_STRING(x) #x
+# define SWIG_EXPAND_AND_QUOTE_STRING(x) SWIG_QUOTE_STRING(x)
+# define SWIG_TYPE_TABLE_NAME SWIG_EXPAND_AND_QUOTE_STRING(SWIG_TYPE_TABLE)
+#else
+# define SWIG_TYPE_TABLE_NAME
+#endif
+
+/*
+ You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for
+ creating a static or dynamic library from the swig runtime code.
+ In 99.9% of the cases, swig just needs to declare them as 'static'.
+
+ But only do this if is strictly necessary, ie, if you have problems
+ with your compiler or so.
+*/
+
+#ifndef SWIGRUNTIME
+# define SWIGRUNTIME SWIGINTERN
+#endif
+
+#ifndef SWIGRUNTIMEINLINE
+# define SWIGRUNTIMEINLINE SWIGRUNTIME SWIGINLINE
+#endif
+
+/* Generic buffer size */
+#ifndef SWIG_BUFFER_SIZE
+# define SWIG_BUFFER_SIZE 1024
+#endif
+
+/* Flags for pointer conversions */
+#define SWIG_POINTER_DISOWN 0x1
+#define SWIG_CAST_NEW_MEMORY 0x2
+
+/* Flags for new pointer objects */
+#define SWIG_POINTER_OWN 0x1
+
+
+/*
+ Flags/methods for returning states.
+
+ The swig conversion methods, as ConvertPtr, return and integer
+ that tells if the conversion was successful or not. And if not,
+ an error code can be returned (see swigerrors.swg for the codes).
+
+ Use the following macros/flags to set or process the returning
+ states.
+
+ In old swig versions, you usually write code as:
+
+ if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) {
+ // success code
+ } else {
+ //fail code
+ }
+
+ Now you can be more explicit as:
+
+ int res = SWIG_ConvertPtr(obj,vptr,ty.flags);
+ if (SWIG_IsOK(res)) {
+ // success code
+ } else {
+ // fail code
+ }
+
+ that seems to be the same, but now you can also do
+
+ Type *ptr;
+ int res = SWIG_ConvertPtr(obj,(void **)(&ptr),ty.flags);
+ if (SWIG_IsOK(res)) {
+ // success code
+ if (SWIG_IsNewObj(res) {
+ ...
+ delete *ptr;
+ } else {
+ ...
+ }
+ } else {
+ // fail code
+ }
+
+ I.e., now SWIG_ConvertPtr can return new objects and you can
+ identify the case and take care of the deallocation. Of course that
+ requires also to SWIG_ConvertPtr to return new result values, as
+
+ int SWIG_ConvertPtr(obj, ptr,...) {
+ if (<obj is ok>) {
+ if (<need new object>) {
+ *ptr = <ptr to new allocated object>;
+ return SWIG_NEWOBJ;
+ } else {
+ *ptr = <ptr to old object>;
+ return SWIG_OLDOBJ;
+ }
+ } else {
+ return SWIG_BADOBJ;
+ }
+ }
+
+ Of course, returning the plain '0(success)/-1(fail)' still works, but you can be
+ more explicit by returning SWIG_BADOBJ, SWIG_ERROR or any of the
+ swig errors code.
+
+ Finally, if the SWIG_CASTRANK_MODE is enabled, the result code
+ allows to return the 'cast rank', for example, if you have this
+
+ int food(double)
+ int fooi(int);
+
+ and you call
+
+ food(1) // cast rank '1' (1 -> 1.0)
+ fooi(1) // cast rank '0'
+
+ just use the SWIG_AddCast()/SWIG_CheckState()
+
+
+ */
+#define SWIG_OK (0)
+#define SWIG_ERROR (-1)
+#define SWIG_IsOK(r) (r >= 0)
+#define SWIG_ArgError(r) ((r != SWIG_ERROR) ? r : SWIG_TypeError)
+
+/* The CastRankLimit says how many bits are used for the cast rank */
+#define SWIG_CASTRANKLIMIT (1 << 8)
+/* The NewMask denotes the object was created (using new/malloc) */
+#define SWIG_NEWOBJMASK (SWIG_CASTRANKLIMIT << 1)
+/* The TmpMask is for in/out typemaps that use temporal objects */
+#define SWIG_TMPOBJMASK (SWIG_NEWOBJMASK << 1)
+/* Simple returning values */
+#define SWIG_BADOBJ (SWIG_ERROR)
+#define SWIG_OLDOBJ (SWIG_OK)
+#define SWIG_NEWOBJ (SWIG_OK | SWIG_NEWOBJMASK)
+#define SWIG_TMPOBJ (SWIG_OK | SWIG_TMPOBJMASK)
+/* Check, add and del mask methods */
+#define SWIG_AddNewMask(r) (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r)
+#define SWIG_DelNewMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r)
+#define SWIG_IsNewObj(r) (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK))
+#define SWIG_AddTmpMask(r) (SWIG_IsOK(r) ? (r | SWIG_TMPOBJMASK) : r)
+#define SWIG_DelTmpMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_TMPOBJMASK) : r)
+#define SWIG_IsTmpObj(r) (SWIG_IsOK(r) && (r & SWIG_TMPOBJMASK))
+
+
+/* Cast-Rank Mode */
+#if defined(SWIG_CASTRANK_MODE)
+# ifndef SWIG_TypeRank
+# define SWIG_TypeRank unsigned long
+# endif
+# ifndef SWIG_MAXCASTRANK /* Default cast allowed */
+# define SWIG_MAXCASTRANK (2)
+# endif
+# define SWIG_CASTRANKMASK ((SWIG_CASTRANKLIMIT) -1)
+# define SWIG_CastRank(r) (r & SWIG_CASTRANKMASK)
+SWIGINTERNINLINE int SWIG_AddCast(int r) {
+ return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r;
+}
+SWIGINTERNINLINE int SWIG_CheckState(int r) {
+ return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0;
+}
+#else /* no cast-rank mode */
+# define SWIG_AddCast
+# define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0)
+#endif
+
+
+
+
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void *(*swig_converter_func)(void *, int *);
+typedef struct swig_type_info *(*swig_dycast_func)(void **);
+
+/* Structure to store information on one type */
+typedef struct swig_type_info {
+ const char *name; /* mangled name of this type */
+ const char *str; /* human readable name of this type */
+ swig_dycast_func dcast; /* dynamic cast function down a hierarchy */
+ struct swig_cast_info *cast; /* linked list of types that can cast into this type */
+ void *clientdata; /* language specific type data */
+ int owndata; /* flag if the structure owns the clientdata */
+} swig_type_info;
+
+/* Structure to store a type and conversion function used for casting */
+typedef struct swig_cast_info {
+ swig_type_info *type; /* pointer to type that is equivalent to this type */
+ swig_converter_func converter; /* function to cast the void pointers */
+ struct swig_cast_info *next; /* pointer to next cast in linked list */
+ struct swig_cast_info *prev; /* pointer to the previous cast */
+} swig_cast_info;
+
+/* Structure used to store module information
+ * Each module generates one structure like this, and the runtime collects
+ * all of these structures and stores them in a circularly linked list.*/
+typedef struct swig_module_info {
+ swig_type_info **types; /* Array of pointers to swig_type_info structures that are in this module */
+ size_t size; /* Number of types in this module */
+ struct swig_module_info *next; /* Pointer to next element in circularly linked list */
+ swig_type_info **type_initial; /* Array of initially generated type structures */
+ swig_cast_info **cast_initial; /* Array of initially generated casting structures */
+ void *clientdata; /* Language specific module data */
+} swig_module_info;
+
+/*
+ Compare two type names skipping the space characters, therefore
+ "char*" == "char *" and "Class<int>" == "Class<int >", etc.
+
+ Return 0 when the two name types are equivalent, as in
+ strncmp, but skipping ' '.
+*/
+SWIGRUNTIME int
+SWIG_TypeNameComp(const char *f1, const char *l1,
+ const char *f2, const char *l2) {
+ for (;(f1 != l1) && (f2 != l2); ++f1, ++f2) {
+ while ((*f1 == ' ') && (f1 != l1)) ++f1;
+ while ((*f2 == ' ') && (f2 != l2)) ++f2;
+ if (*f1 != *f2) return (*f1 > *f2) ? 1 : -1;
+ }
+ return (int)((l1 - f1) - (l2 - f2));
+}
+
+/*
+ Check type equivalence in a name list like <name1>|<name2>|...
+ Return 0 if not equal, 1 if equal
+*/
+SWIGRUNTIME int
+SWIG_TypeEquiv(const char *nb, const char *tb) {
+ int equiv = 0;
+ const char* te = tb + strlen(tb);
+ const char* ne = nb;
+ while (!equiv && *ne) {
+ for (nb = ne; *ne; ++ne) {
+ if (*ne == '|') break;
+ }
+ equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0;
+ if (*ne) ++ne;
+ }
+ return equiv;
+}
+
+/*
+ Check type equivalence in a name list like <name1>|<name2>|...
+ Return 0 if equal, -1 if nb < tb, 1 if nb > tb
+*/
+SWIGRUNTIME int
+SWIG_TypeCompare(const char *nb, const char *tb) {
+ int equiv = 0;
+ const char* te = tb + strlen(tb);
+ const char* ne = nb;
+ while (!equiv && *ne) {
+ for (nb = ne; *ne; ++ne) {
+ if (*ne == '|') break;
+ }
+ equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0;
+ if (*ne) ++ne;
+ }
+ return equiv;
+}
+
+
+/* think of this as a c++ template<> or a scheme macro */
+#define SWIG_TypeCheck_Template(comparison, ty) \
+ if (ty) { \
+ swig_cast_info *iter = ty->cast; \
+ while (iter) { \
+ if (comparison) { \
+ if (iter == ty->cast) return iter; \
+ /* Move iter to the top of the linked list */ \
+ iter->prev->next = iter->next; \
+ if (iter->next) \
+ iter->next->prev = iter->prev; \
+ iter->next = ty->cast; \
+ iter->prev = 0; \
+ if (ty->cast) ty->cast->prev = iter; \
+ ty->cast = iter; \
+ return iter; \
+ } \
+ iter = iter->next; \
+ } \
+ } \
+ return 0
+
+/*
+ Check the typename
+*/
+SWIGRUNTIME swig_cast_info *
+SWIG_TypeCheck(const char *c, swig_type_info *ty) {
+ SWIG_TypeCheck_Template(strcmp(iter->type->name, c) == 0, ty);
+}
+
+/* Same as previous function, except strcmp is replaced with a pointer comparison */
+SWIGRUNTIME swig_cast_info *
+SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *into) {
+ SWIG_TypeCheck_Template(iter->type == from, into);
+}
+
+/*
+ Cast a pointer up an inheritance hierarchy
+*/
+SWIGRUNTIMEINLINE void *
+SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) {
+ return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory);
+}
+
+/*
+ Dynamic pointer casting. Down an inheritance hierarchy
+*/
+SWIGRUNTIME swig_type_info *
+SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) {
+ swig_type_info *lastty = ty;
+ if (!ty || !ty->dcast) return ty;
+ while (ty && (ty->dcast)) {
+ ty = (*ty->dcast)(ptr);
+ if (ty) lastty = ty;
+ }
+ return lastty;
+}
+
+/*
+ Return the name associated with this type
+*/
+SWIGRUNTIMEINLINE const char *
+SWIG_TypeName(const swig_type_info *ty) {
+ return ty->name;
+}
+
+/*
+ Return the pretty name associated with this type,
+ that is an unmangled type name in a form presentable to the user.
+*/
+SWIGRUNTIME const char *
+SWIG_TypePrettyName(const swig_type_info *type) {
+ /* The "str" field contains the equivalent pretty names of the
+ type, separated by vertical-bar characters. We choose
+ to print the last name, as it is often (?) the most
+ specific. */
+ if (!type) return NULL;
+ if (type->str != NULL) {
+ const char *last_name = type->str;
+ const char *s;
+ for (s = type->str; *s; s++)
+ if (*s == '|') last_name = s+1;
+ return last_name;
+ }
+ else
+ return type->name;
+}
+
+/*
+ Set the clientdata field for a type
+*/
+SWIGRUNTIME void
+SWIG_TypeClientData(swig_type_info *ti, void *clientdata) {
+ swig_cast_info *cast = ti->cast;
+ /* if (ti->clientdata == clientdata) return; */
+ ti->clientdata = clientdata;
+
+ while (cast) {
+ if (!cast->converter) {
+ swig_type_info *tc = cast->type;
+ if (!tc->clientdata) {
+ SWIG_TypeClientData(tc, clientdata);
+ }
+ }
+ cast = cast->next;
+ }
+}
+SWIGRUNTIME void
+SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) {
+ SWIG_TypeClientData(ti, clientdata);
+ ti->owndata = 1;
+}
+
+/*
+ Search for a swig_type_info structure only by mangled name
+ Search is a O(log #types)
+
+ We start searching at module start, and finish searching when start == end.
+ Note: if start == end at the beginning of the function, we go all the way around
+ the circular list.
+*/
+SWIGRUNTIME swig_type_info *
+SWIG_MangledTypeQueryModule(swig_module_info *start,
+ swig_module_info *end,
+ const char *name) {
+ swig_module_info *iter = start;
+ do {
+ if (iter->size) {
+ register size_t l = 0;
+ register size_t r = iter->size - 1;
+ do {
+ /* since l+r >= 0, we can (>> 1) instead (/ 2) */
+ register size_t i = (l + r) >> 1;
+ const char *iname = iter->types[i]->name;
+ if (iname) {
+ register int compare = strcmp(name, iname);
+ if (compare == 0) {
+ return iter->types[i];
+ } else if (compare < 0) {
+ if (i) {
+ r = i - 1;
+ } else {
+ break;
+ }
+ } else if (compare > 0) {
+ l = i + 1;
+ }
+ } else {
+ break; /* should never happen */
+ }
+ } while (l <= r);
+ }
+ iter = iter->next;
+ } while (iter != end);
+ return 0;
+}
+
+/*
+ Search for a swig_type_info structure for either a mangled name or a human readable name.
+ It first searches the mangled names of the types, which is a O(log #types)
+ If a type is not found it then searches the human readable names, which is O(#types).
+
+ We start searching at module start, and finish searching when start == end.
+ Note: if start == end at the beginning of the function, we go all the way around
+ the circular list.
+*/
+SWIGRUNTIME swig_type_info *
+SWIG_TypeQueryModule(swig_module_info *start,
+ swig_module_info *end,
+ const char *name) {
+ /* STEP 1: Search the name field using binary search */
+ swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name);
+ if (ret) {
+ return ret;
+ } else {
+ /* STEP 2: If the type hasn't been found, do a complete search
+ of the str field (the human readable name) */
+ swig_module_info *iter = start;
+ do {
+ register size_t i = 0;
+ for (; i < iter->size; ++i) {
+ if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name)))
+ return iter->types[i];
+ }
+ iter = iter->next;
+ } while (iter != end);
+ }
+
+ /* neither found a match */
+ return 0;
+}
+
+/*
+ Pack binary data into a string
+*/
+SWIGRUNTIME char *
+SWIG_PackData(char *c, void *ptr, size_t sz) {
+ static const char hex[17] = "0123456789abcdef";
+ register const unsigned char *u = (unsigned char *) ptr;
+ register const unsigned char *eu = u + sz;
+ for (; u != eu; ++u) {
+ register unsigned char uu = *u;
+ *(c++) = hex[(uu & 0xf0) >> 4];
+ *(c++) = hex[uu & 0xf];
+ }
+ return c;
+}
+
+/*
+ Unpack binary data from a string
+*/
+SWIGRUNTIME const char *
+SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
+ register unsigned char *u = (unsigned char *) ptr;
+ register const unsigned char *eu = u + sz;
+ for (; u != eu; ++u) {
+ register char d = *(c++);
+ register unsigned char uu;
+ if ((d >= '0') && (d <= '9'))
+ uu = ((d - '0') << 4);
+ else if ((d >= 'a') && (d <= 'f'))
+ uu = ((d - ('a'-10)) << 4);
+ else
+ return (char *) 0;
+ d = *(c++);
+ if ((d >= '0') && (d <= '9'))
+ uu |= (d - '0');
+ else if ((d >= 'a') && (d <= 'f'))
+ uu |= (d - ('a'-10));
+ else
+ return (char *) 0;
+ *u = uu;
+ }
+ return c;
+}
+
+/*
+ Pack 'void *' into a string buffer.
+*/
+SWIGRUNTIME char *
+SWIG_PackVoidPtr(char *buff, void *ptr, const char *name, size_t bsz) {
+ char *r = buff;
+ if ((2*sizeof(void *) + 2) > bsz) return 0;
+ *(r++) = '_';
+ r = SWIG_PackData(r,&ptr,sizeof(void *));
+ if (strlen(name) + 1 > (bsz - (r - buff))) return 0;
+ strcpy(r,name);
+ return buff;
+}
+
+SWIGRUNTIME const char *
+SWIG_UnpackVoidPtr(const char *c, void **ptr, const char *name) {
+ if (*c != '_') {
+ if (strcmp(c,"NULL") == 0) {
+ *ptr = (void *) 0;
+ return name;
+ } else {
+ return 0;
+ }
+ }
+ return SWIG_UnpackData(++c,ptr,sizeof(void *));
+}
+
+SWIGRUNTIME char *
+SWIG_PackDataName(char *buff, void *ptr, size_t sz, const char *name, size_t bsz) {
+ char *r = buff;
+ size_t lname = (name ? strlen(name) : 0);
+ if ((2*sz + 2 + lname) > bsz) return 0;
+ *(r++) = '_';
+ r = SWIG_PackData(r,ptr,sz);
+ if (lname) {
+ strncpy(r,name,lname+1);
+ } else {
+ *r = 0;
+ }
+ return buff;
+}
+
+SWIGRUNTIME const char *
+SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) {
+ if (*c != '_') {
+ if (strcmp(c,"NULL") == 0) {
+ memset(ptr,0,sz);
+ return name;
+ } else {
+ return 0;
+ }
+ }
+ return SWIG_UnpackData(++c,ptr,sz);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Errors in SWIG */
+#define SWIG_UnknownError -1
+#define SWIG_IOError -2
+#define SWIG_RuntimeError -3
+#define SWIG_IndexError -4
+#define SWIG_TypeError -5
+#define SWIG_DivisionByZero -6
+#define SWIG_OverflowError -7
+#define SWIG_SyntaxError -8
+#define SWIG_ValueError -9
+#define SWIG_SystemError -10
+#define SWIG_AttributeError -11
+#define SWIG_MemoryError -12
+#define SWIG_NullReferenceError -13
+
+
+
+
+/* Add PyOS_snprintf for old Pythons */
+#if PY_VERSION_HEX < 0x02020000
+# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WATCOM)
+# define PyOS_snprintf _snprintf
+# else
+# define PyOS_snprintf snprintf
+# endif
+#endif
+
+/* A crude PyString_FromFormat implementation for old Pythons */
+#if PY_VERSION_HEX < 0x02020000
+
+#ifndef SWIG_PYBUFFER_SIZE
+# define SWIG_PYBUFFER_SIZE 1024
+#endif
+
+static PyObject *
+PyString_FromFormat(const char *fmt, ...) {
+ va_list ap;
+ char buf[SWIG_PYBUFFER_SIZE * 2];
+ int res;
+ va_start(ap, fmt);
+ res = vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ return (res < 0 || res >= (int)sizeof(buf)) ? 0 : PyString_FromString(buf);
+}
+#endif
+
+/* Add PyObject_Del for old Pythons */
+#if PY_VERSION_HEX < 0x01060000
+# define PyObject_Del(op) PyMem_DEL((op))
+#endif
+#ifndef PyObject_DEL
+# define PyObject_DEL PyObject_Del
+#endif
+
+/* A crude PyExc_StopIteration exception for old Pythons */
+#if PY_VERSION_HEX < 0x02020000
+# ifndef PyExc_StopIteration
+# define PyExc_StopIteration PyExc_RuntimeError
+# endif
+# ifndef PyObject_GenericGetAttr
+# define PyObject_GenericGetAttr 0
+# endif
+#endif
+/* Py_NotImplemented is defined in 2.1 and up. */
+#if PY_VERSION_HEX < 0x02010000
+# ifndef Py_NotImplemented
+# define Py_NotImplemented PyExc_RuntimeError
+# endif
+#endif
+
+
+/* A crude PyString_AsStringAndSize implementation for old Pythons */
+#if PY_VERSION_HEX < 0x02010000
+# ifndef PyString_AsStringAndSize
+# define PyString_AsStringAndSize(obj, s, len) {*s = PyString_AsString(obj); *len = *s ? strlen(*s) : 0;}
+# endif
+#endif
+
+/* PySequence_Size for old Pythons */
+#if PY_VERSION_HEX < 0x02000000
+# ifndef PySequence_Size
+# define PySequence_Size PySequence_Length
+# endif
+#endif
+
+
+/* PyBool_FromLong for old Pythons */
+#if PY_VERSION_HEX < 0x02030000
+static
+PyObject *PyBool_FromLong(long ok)
+{
+ PyObject *result = ok ? Py_True : Py_False;
+ Py_INCREF(result);
+ return result;
+}
+#endif
+
+/* Py_ssize_t for old Pythons */
+/* This code is as recommended by: */
+/* http://www.python.org/dev/peps/pep-0353/#conversion-guidelines */
+#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
+typedef int Py_ssize_t;
+# define PY_SSIZE_T_MAX INT_MAX
+# define PY_SSIZE_T_MIN INT_MIN
+#endif
+
+/* -----------------------------------------------------------------------------
+ * error manipulation
+ * ----------------------------------------------------------------------------- */
+
+SWIGRUNTIME PyObject*
+SWIG_Python_ErrorType(int code) {
+ PyObject* type = 0;
+ switch(code) {
+ case SWIG_MemoryError:
+ type = PyExc_MemoryError;
+ break;
+ case SWIG_IOError:
+ type = PyExc_IOError;
+ break;
+ case SWIG_RuntimeError:
+ type = PyExc_RuntimeError;
+ break;
+ case SWIG_IndexError:
+ type = PyExc_IndexError;
+ break;
+ case SWIG_TypeError:
+ type = PyExc_TypeError;
+ break;
+ case SWIG_DivisionByZero:
+ type = PyExc_ZeroDivisionError;
+ break;
+ case SWIG_OverflowError:
+ type = PyExc_OverflowError;
+ break;
+ case SWIG_SyntaxError:
+ type = PyExc_SyntaxError;
+ break;
+ case SWIG_ValueError:
+ type = PyExc_ValueError;
+ break;
+ case SWIG_SystemError:
+ type = PyExc_SystemError;
+ break;
+ case SWIG_AttributeError:
+ type = PyExc_AttributeError;
+ break;
+ default:
+ type = PyExc_RuntimeError;
+ }
+ return type;
+}
+
+
+SWIGRUNTIME void
+SWIG_Python_AddErrorMsg(const char* mesg)
+{
+ PyObject *type = 0;
+ PyObject *value = 0;
+ PyObject *traceback = 0;
+
+ if (PyErr_Occurred()) PyErr_Fetch(&type, &value, &traceback);
+ if (value) {
+ PyObject *old_str = PyObject_Str(value);
+ PyErr_Clear();
+ Py_XINCREF(type);
+ PyErr_Format(type, "%s %s", PyString_AsString(old_str), mesg);
+ Py_DECREF(old_str);
+ Py_DECREF(value);
+ } else {
+ PyErr_SetString(PyExc_RuntimeError, mesg);
+ }
+}
+
+
+
+#if defined(SWIG_PYTHON_NO_THREADS)
+# if defined(SWIG_PYTHON_THREADS)
+# undef SWIG_PYTHON_THREADS
+# endif
+#endif
+#if defined(SWIG_PYTHON_THREADS) /* Threading support is enabled */
+# if !defined(SWIG_PYTHON_USE_GIL) && !defined(SWIG_PYTHON_NO_USE_GIL)
+# if (PY_VERSION_HEX >= 0x02030000) /* For 2.3 or later, use the PyGILState calls */
+# define SWIG_PYTHON_USE_GIL
+# endif
+# endif
+# if defined(SWIG_PYTHON_USE_GIL) /* Use PyGILState threads calls */
+# ifndef SWIG_PYTHON_INITIALIZE_THREADS
+# define SWIG_PYTHON_INITIALIZE_THREADS PyEval_InitThreads()
+# endif
+# ifdef __cplusplus /* C++ code */
+ class SWIG_Python_Thread_Block {
+ bool status;
+ PyGILState_STATE state;
+ public:
+ void end() { if (status) { PyGILState_Release(state); status = false;} }
+ SWIG_Python_Thread_Block() : status(true), state(PyGILState_Ensure()) {}
+ ~SWIG_Python_Thread_Block() { end(); }
+ };
+ class SWIG_Python_Thread_Allow {
+ bool status;
+ PyThreadState *save;
+ public:
+ void end() { if (status) { PyEval_RestoreThread(save); status = false; }}
+ SWIG_Python_Thread_Allow() : status(true), save(PyEval_SaveThread()) {}
+ ~SWIG_Python_Thread_Allow() { end(); }
+ };
+# define SWIG_PYTHON_THREAD_BEGIN_BLOCK SWIG_Python_Thread_Block _swig_thread_block
+# define SWIG_PYTHON_THREAD_END_BLOCK _swig_thread_block.end()
+# define SWIG_PYTHON_THREAD_BEGIN_ALLOW SWIG_Python_Thread_Allow _swig_thread_allow
+# define SWIG_PYTHON_THREAD_END_ALLOW _swig_thread_allow.end()
+# else /* C code */
+# define SWIG_PYTHON_THREAD_BEGIN_BLOCK PyGILState_STATE _swig_thread_block = PyGILState_Ensure()
+# define SWIG_PYTHON_THREAD_END_BLOCK PyGILState_Release(_swig_thread_block)
+# define SWIG_PYTHON_THREAD_BEGIN_ALLOW PyThreadState *_swig_thread_allow = PyEval_SaveThread()
+# define SWIG_PYTHON_THREAD_END_ALLOW PyEval_RestoreThread(_swig_thread_allow)
+# endif
+# else /* Old thread way, not implemented, user must provide it */
+# if !defined(SWIG_PYTHON_INITIALIZE_THREADS)
+# define SWIG_PYTHON_INITIALIZE_THREADS
+# endif
+# if !defined(SWIG_PYTHON_THREAD_BEGIN_BLOCK)
+# define SWIG_PYTHON_THREAD_BEGIN_BLOCK
+# endif
+# if !defined(SWIG_PYTHON_THREAD_END_BLOCK)
+# define SWIG_PYTHON_THREAD_END_BLOCK
+# endif
+# if !defined(SWIG_PYTHON_THREAD_BEGIN_ALLOW)
+# define SWIG_PYTHON_THREAD_BEGIN_ALLOW
+# endif
+# if !defined(SWIG_PYTHON_THREAD_END_ALLOW)
+# define SWIG_PYTHON_THREAD_END_ALLOW
+# endif
+# endif
+#else /* No thread support */
+# define SWIG_PYTHON_INITIALIZE_THREADS
+# define SWIG_PYTHON_THREAD_BEGIN_BLOCK
+# define SWIG_PYTHON_THREAD_END_BLOCK
+# define SWIG_PYTHON_THREAD_BEGIN_ALLOW
+# define SWIG_PYTHON_THREAD_END_ALLOW
+#endif
+
+/* -----------------------------------------------------------------------------
+ * Python API portion that goes into the runtime
+ * ----------------------------------------------------------------------------- */
+
+#ifdef __cplusplus
+extern "C" {
+#if 0
+} /* cc-mode */
+#endif
+#endif
+
+/* -----------------------------------------------------------------------------
+ * Constant declarations
+ * ----------------------------------------------------------------------------- */
+
+/* Constant Types */
+#define SWIG_PY_POINTER 4
+#define SWIG_PY_BINARY 5
+
+/* Constant information structure */
+typedef struct swig_const_info {
+ int type;
+ char *name;
+ long lvalue;
+ double dvalue;
+ void *pvalue;
+ swig_type_info **ptype;
+} swig_const_info;
+
+#ifdef __cplusplus
+#if 0
+{ /* cc-mode */
+#endif
+}
+#endif
+
+
+/* -----------------------------------------------------------------------------
+ * See the LICENSE file for information on copyright, usage and redistribution
+ * of SWIG, and the README file for authors - http://www.swig.org/release.html.
+ *
+ * pyrun.swg
+ *
+ * This file contains the runtime support for Python modules
+ * and includes code for managing global variables and pointer
+ * type checking.
+ *
+ * ----------------------------------------------------------------------------- */
+
+/* Common SWIG API */
+
+/* for raw pointers */
+#define SWIG_Python_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, 0)
+#define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtr(obj, pptr, type, flags)
+#define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, own)
+#define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(ptr, type, flags)
+#define SWIG_CheckImplicit(ty) SWIG_Python_CheckImplicit(ty)
+#define SWIG_AcquirePtr(ptr, src) SWIG_Python_AcquirePtr(ptr, src)
+#define swig_owntype int
+
+/* for raw packed data */
+#define SWIG_ConvertPacked(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty)
+#define SWIG_NewPackedObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type)
+
+/* for class or struct pointers */
+#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_ConvertPtr(obj, pptr, type, flags)
+#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_NewPointerObj(ptr, type, flags)
+
+/* for C or C++ function pointers */
+#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_Python_ConvertFunctionPtr(obj, pptr, type)
+#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_Python_NewPointerObj(ptr, type, 0)
+
+/* for C++ member pointers, ie, member methods */
+#define SWIG_ConvertMember(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty)
+#define SWIG_NewMemberObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type)
+
+
+/* Runtime API */
+
+#define SWIG_GetModule(clientdata) SWIG_Python_GetModule()
+#define SWIG_SetModule(clientdata, pointer) SWIG_Python_SetModule(pointer)
+#define SWIG_NewClientData(obj) PySwigClientData_New(obj)
+
+#define SWIG_SetErrorObj SWIG_Python_SetErrorObj
+#define SWIG_SetErrorMsg SWIG_Python_SetErrorMsg
+#define SWIG_ErrorType(code) SWIG_Python_ErrorType(code)
+#define SWIG_Error(code, msg) SWIG_Python_SetErrorMsg(SWIG_ErrorType(code), msg)
+#define SWIG_fail goto fail
+
+
+/* Runtime API implementation */
+
+/* Error manipulation */
+
+SWIGINTERN void
+SWIG_Python_SetErrorObj(PyObject *errtype, PyObject *obj) {
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ PyErr_SetObject(errtype, obj);
+ Py_DECREF(obj);
+ SWIG_PYTHON_THREAD_END_BLOCK;
+}
+
+SWIGINTERN void
+SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) {
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ PyErr_SetString(errtype, (char *) msg);
+ SWIG_PYTHON_THREAD_END_BLOCK;
+}
+
+#define SWIG_Python_Raise(obj, type, desc) SWIG_Python_SetErrorObj(SWIG_Python_ExceptionType(desc), obj)
+
+/* Set a constant value */
+
+SWIGINTERN void
+SWIG_Python_SetConstant(PyObject *d, const char *name, PyObject *obj) {
+ PyDict_SetItemString(d, (char*) name, obj);
+ Py_DECREF(obj);
+}
+
+/* Append a value to the result obj */
+
+SWIGINTERN PyObject*
+SWIG_Python_AppendOutput(PyObject* result, PyObject* obj) {
+#if !defined(SWIG_PYTHON_OUTPUT_TUPLE)
+ if (!result) {
+ result = obj;
+ } else if (result == Py_None) {
+ Py_DECREF(result);
+ result = obj;
+ } else {
+ if (!PyList_Check(result)) {
+ PyObject *o2 = result;
+ result = PyList_New(1);
+ PyList_SetItem(result, 0, o2);
+ }
+ PyList_Append(result,obj);
+ Py_DECREF(obj);
+ }
+ return result;
+#else
+ PyObject* o2;
+ PyObject* o3;
+ if (!result) {
+ result = obj;
+ } else if (result == Py_None) {
+ Py_DECREF(result);
+ result = obj;
+ } else {
+ if (!PyTuple_Check(result)) {
+ o2 = result;
+ result = PyTuple_New(1);
+ PyTuple_SET_ITEM(result, 0, o2);
+ }
+ o3 = PyTuple_New(1);
+ PyTuple_SET_ITEM(o3, 0, obj);
+ o2 = result;
+ result = PySequence_Concat(o2, o3);
+ Py_DECREF(o2);
+ Py_DECREF(o3);
+ }
+ return result;
+#endif
+}
+
+/* Unpack the argument tuple */
+
+SWIGINTERN int
+SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, PyObject **objs)
+{
+ if (!args) {
+ if (!min && !max) {
+ return 1;
+ } else {
+ PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got none",
+ name, (min == max ? "" : "at least "), (int)min);
+ return 0;
+ }
+ }
+ if (!PyTuple_Check(args)) {
+ PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple");
+ return 0;
+ } else {
+ register Py_ssize_t l = PyTuple_GET_SIZE(args);
+ if (l < min) {
+ PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d",
+ name, (min == max ? "" : "at least "), (int)min, (int)l);
+ return 0;
+ } else if (l > max) {
+ PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d",
+ name, (min == max ? "" : "at most "), (int)max, (int)l);
+ return 0;
+ } else {
+ register int i;
+ for (i = 0; i < l; ++i) {
+ objs[i] = PyTuple_GET_ITEM(args, i);
+ }
+ for (; l < max; ++l) {
+ objs[l] = 0;
+ }
+ return i + 1;
+ }
+ }
+}
+
+/* A functor is a function object with one single object argument */
+#if PY_VERSION_HEX >= 0x02020000
+#define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunctionObjArgs(functor, obj, NULL);
+#else
+#define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunction(functor, "O", obj);
+#endif
+
+/*
+ Helper for static pointer initialization for both C and C++ code, for example
+ static PyObject *SWIG_STATIC_POINTER(MyVar) = NewSomething(...);
+*/
+#ifdef __cplusplus
+#define SWIG_STATIC_POINTER(var) var
+#else
+#define SWIG_STATIC_POINTER(var) var = 0; if (!var) var
+#endif
+
+/* -----------------------------------------------------------------------------
+ * Pointer declarations
+ * ----------------------------------------------------------------------------- */
+
+/* Flags for new pointer objects */
+#define SWIG_POINTER_NOSHADOW (SWIG_POINTER_OWN << 1)
+#define SWIG_POINTER_NEW (SWIG_POINTER_NOSHADOW | SWIG_POINTER_OWN)
+
+#define SWIG_POINTER_IMPLICIT_CONV (SWIG_POINTER_DISOWN << 1)
+
+#ifdef __cplusplus
+extern "C" {
+#if 0
+} /* cc-mode */
+#endif
+#endif
+
+/* How to access Py_None */
+#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+# ifndef SWIG_PYTHON_NO_BUILD_NONE
+# ifndef SWIG_PYTHON_BUILD_NONE
+# define SWIG_PYTHON_BUILD_NONE
+# endif
+# endif
+#endif
+
+#ifdef SWIG_PYTHON_BUILD_NONE
+# ifdef Py_None
+# undef Py_None
+# define Py_None SWIG_Py_None()
+# endif
+SWIGRUNTIMEINLINE PyObject *
+_SWIG_Py_None(void)
+{
+ PyObject *none = Py_BuildValue((char*)"");
+ Py_DECREF(none);
+ return none;
+}
+SWIGRUNTIME PyObject *
+SWIG_Py_None(void)
+{
+ static PyObject *SWIG_STATIC_POINTER(none) = _SWIG_Py_None();
+ return none;
+}
+#endif
+
+/* The python void return value */
+
+SWIGRUNTIMEINLINE PyObject *
+SWIG_Py_Void(void)
+{
+ PyObject *none = Py_None;
+ Py_INCREF(none);
+ return none;
+}
+
+/* PySwigClientData */
+
+typedef struct {
+ PyObject *klass;
+ PyObject *newraw;
+ PyObject *newargs;
+ PyObject *destroy;
+ int delargs;
+ int implicitconv;
+} PySwigClientData;
+
+SWIGRUNTIMEINLINE int
+SWIG_Python_CheckImplicit(swig_type_info *ty)
+{
+ PySwigClientData *data = (PySwigClientData *)ty->clientdata;
+ return data ? data->implicitconv : 0;
+}
+
+SWIGRUNTIMEINLINE PyObject *
+SWIG_Python_ExceptionType(swig_type_info *desc) {
+ PySwigClientData *data = desc ? (PySwigClientData *) desc->clientdata : 0;
+ PyObject *klass = data ? data->klass : 0;
+ return (klass ? klass : PyExc_RuntimeError);
+}
+
+
+SWIGRUNTIME PySwigClientData *
+PySwigClientData_New(PyObject* obj)
+{
+ if (!obj) {
+ return 0;
+ } else {
+ PySwigClientData *data = (PySwigClientData *)malloc(sizeof(PySwigClientData));
+ /* the klass element */
+ data->klass = obj;
+ Py_INCREF(data->klass);
+ /* the newraw method and newargs arguments used to create a new raw instance */
+ if (PyClass_Check(obj)) {
+ data->newraw = 0;
+ data->newargs = obj;
+ Py_INCREF(obj);
+ } else {
+#if (PY_VERSION_HEX < 0x02020000)
+ data->newraw = 0;
+#else
+ data->newraw = PyObject_GetAttrString(data->klass, (char *)"__new__");
+#endif
+ if (data->newraw) {
+ Py_INCREF(data->newraw);
+ data->newargs = PyTuple_New(1);
+ PyTuple_SetItem(data->newargs, 0, obj);
+ } else {
+ data->newargs = obj;
+ }
+ Py_INCREF(data->newargs);
+ }
+ /* the destroy method, aka as the C++ delete method */
+ data->destroy = PyObject_GetAttrString(data->klass, (char *)"__swig_destroy__");
+ if (PyErr_Occurred()) {
+ PyErr_Clear();
+ data->destroy = 0;
+ }
+ if (data->destroy) {
+ int flags;
+ Py_INCREF(data->destroy);
+ flags = PyCFunction_GET_FLAGS(data->destroy);
+#ifdef METH_O
+ data->delargs = !(flags & (METH_O));
+#else
+ data->delargs = 0;
+#endif
+ } else {
+ data->delargs = 0;
+ }
+ data->implicitconv = 0;
+ return data;
+ }
+}
+
+SWIGRUNTIME void
+PySwigClientData_Del(PySwigClientData* data)
+{
+ Py_XDECREF(data->newraw);
+ Py_XDECREF(data->newargs);
+ Py_XDECREF(data->destroy);
+}
+
+/* =============== PySwigObject =====================*/
+
+typedef struct {
+ PyObject_HEAD
+ void *ptr;
+ swig_type_info *ty;
+ int own;
+ PyObject *next;
+} PySwigObject;
+
+SWIGRUNTIME PyObject *
+PySwigObject_long(PySwigObject *v)
+{
+ return PyLong_FromVoidPtr(v->ptr);
+}
+
+SWIGRUNTIME PyObject *
+PySwigObject_format(const char* fmt, PySwigObject *v)
+{
+ PyObject *res = NULL;
+ PyObject *args = PyTuple_New(1);
+ if (args) {
+ if (PyTuple_SetItem(args, 0, PySwigObject_long(v)) == 0) {
+ PyObject *ofmt = PyString_FromString(fmt);
+ if (ofmt) {
+ res = PyString_Format(ofmt,args);
+ Py_DECREF(ofmt);
+ }
+ Py_DECREF(args);
+ }
+ }
+ return res;
+}
+
+SWIGRUNTIME PyObject *
+PySwigObject_oct(PySwigObject *v)
+{
+ return PySwigObject_format("%o",v);
+}
+
+SWIGRUNTIME PyObject *
+PySwigObject_hex(PySwigObject *v)
+{
+ return PySwigObject_format("%x",v);
+}
+
+SWIGRUNTIME PyObject *
+#ifdef METH_NOARGS
+PySwigObject_repr(PySwigObject *v)
+#else
+PySwigObject_repr(PySwigObject *v, PyObject *args)
+#endif
+{
+ const char *name = SWIG_TypePrettyName(v->ty);
+ PyObject *hex = PySwigObject_hex(v);
+ PyObject *repr = PyString_FromFormat("<Swig Object of type '%s' at 0x%s>", name, PyString_AsString(hex));
+ Py_DECREF(hex);
+ if (v->next) {
+#ifdef METH_NOARGS
+ PyObject *nrep = PySwigObject_repr((PySwigObject *)v->next);
+#else
+ PyObject *nrep = PySwigObject_repr((PySwigObject *)v->next, args);
+#endif
+ PyString_ConcatAndDel(&repr,nrep);
+ }
+ return repr;
+}
+
+SWIGRUNTIME int
+PySwigObject_print(PySwigObject *v, FILE *fp, int SWIGUNUSEDPARM(flags))
+{
+#ifdef METH_NOARGS
+ PyObject *repr = PySwigObject_repr(v);
+#else
+ PyObject *repr = PySwigObject_repr(v, NULL);
+#endif
+ if (repr) {
+ fputs(PyString_AsString(repr), fp);
+ Py_DECREF(repr);
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+SWIGRUNTIME PyObject *
+PySwigObject_str(PySwigObject *v)
+{
+ char result[SWIG_BUFFER_SIZE];
+ return SWIG_PackVoidPtr(result, v->ptr, v->ty->name, sizeof(result)) ?
+ PyString_FromString(result) : 0;
+}
+
+SWIGRUNTIME int
+PySwigObject_compare(PySwigObject *v, PySwigObject *w)
+{
+ void *i = v->ptr;
+ void *j = w->ptr;
+ return (i < j) ? -1 : ((i > j) ? 1 : 0);
+}
+
+SWIGRUNTIME PyTypeObject* _PySwigObject_type(void);
+
+SWIGRUNTIME PyTypeObject*
+PySwigObject_type(void) {
+ static PyTypeObject *SWIG_STATIC_POINTER(type) = _PySwigObject_type();
+ return type;
+}
+
+SWIGRUNTIMEINLINE int
+PySwigObject_Check(PyObject *op) {
+ return ((op)->ob_type == PySwigObject_type())
+ || (strcmp((op)->ob_type->tp_name,"PySwigObject") == 0);
+}
+
+SWIGRUNTIME PyObject *
+PySwigObject_New(void *ptr, swig_type_info *ty, int own);
+
+SWIGRUNTIME void
+PySwigObject_dealloc(PyObject *v)
+{
+ PySwigObject *sobj = (PySwigObject *) v;
+ PyObject *next = sobj->next;
+ if (sobj->own == SWIG_POINTER_OWN) {
+ swig_type_info *ty = sobj->ty;
+ PySwigClientData *data = ty ? (PySwigClientData *) ty->clientdata : 0;
+ PyObject *destroy = data ? data->destroy : 0;
+ if (destroy) {
+ /* destroy is always a VARARGS method */
+ PyObject *res;
+ if (data->delargs) {
+ /* we need to create a temporal object to carry the destroy operation */
+ PyObject *tmp = PySwigObject_New(sobj->ptr, ty, 0);
+ res = SWIG_Python_CallFunctor(destroy, tmp);
+ Py_DECREF(tmp);
+ } else {
+ PyCFunction meth = PyCFunction_GET_FUNCTION(destroy);
+ PyObject *mself = PyCFunction_GET_SELF(destroy);
+ res = ((*meth)(mself, v));
+ }
+ Py_XDECREF(res);
+ }
+#if !defined(SWIG_PYTHON_SILENT_MEMLEAK)
+ else {
+ const char *name = SWIG_TypePrettyName(ty);
+ printf("swig/python detected a memory leak of type '%s', no destructor found.\n", (name ? name : "unknown"));
+ }
+#endif
+ }
+ Py_XDECREF(next);
+ PyObject_DEL(v);
+}
+
+SWIGRUNTIME PyObject*
+PySwigObject_append(PyObject* v, PyObject* next)
+{
+ PySwigObject *sobj = (PySwigObject *) v;
+#ifndef METH_O
+ PyObject *tmp = 0;
+ if (!PyArg_ParseTuple(next,(char *)"O:append", &tmp)) return NULL;
+ next = tmp;
+#endif
+ if (!PySwigObject_Check(next)) {
+ return NULL;
+ }
+ sobj->next = next;
+ Py_INCREF(next);
+ return SWIG_Py_Void();
+}
+
+SWIGRUNTIME PyObject*
+#ifdef METH_NOARGS
+PySwigObject_next(PyObject* v)
+#else
+PySwigObject_next(PyObject* v, PyObject *SWIGUNUSEDPARM(args))
+#endif
+{
+ PySwigObject *sobj = (PySwigObject *) v;
+ if (sobj->next) {
+ Py_INCREF(sobj->next);
+ return sobj->next;
+ } else {
+ return SWIG_Py_Void();
+ }
+}
+
+SWIGINTERN PyObject*
+#ifdef METH_NOARGS
+PySwigObject_disown(PyObject *v)
+#else
+PySwigObject_disown(PyObject* v, PyObject *SWIGUNUSEDPARM(args))
+#endif
+{
+ PySwigObject *sobj = (PySwigObject *)v;
+ sobj->own = 0;
+ return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject*
+#ifdef METH_NOARGS
+PySwigObject_acquire(PyObject *v)
+#else
+PySwigObject_acquire(PyObject* v, PyObject *SWIGUNUSEDPARM(args))
+#endif
+{
+ PySwigObject *sobj = (PySwigObject *)v;
+ sobj->own = SWIG_POINTER_OWN;
+ return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject*
+PySwigObject_own(PyObject *v, PyObject *args)
+{
+ PyObject *val = 0;
+#if (PY_VERSION_HEX < 0x02020000)
+ if (!PyArg_ParseTuple(args,(char *)"|O:own",&val))
+#else
+ if (!PyArg_UnpackTuple(args, (char *)"own", 0, 1, &val))
+#endif
+ {
+ return NULL;
+ }
+ else
+ {
+ PySwigObject *sobj = (PySwigObject *)v;
+ PyObject *obj = PyBool_FromLong(sobj->own);
+ if (val) {
+#ifdef METH_NOARGS
+ if (PyObject_IsTrue(val)) {
+ PySwigObject_acquire(v);
+ } else {
+ PySwigObject_disown(v);
+ }
+#else
+ if (PyObject_IsTrue(val)) {
+ PySwigObject_acquire(v,args);
+ } else {
+ PySwigObject_disown(v,args);
+ }
+#endif
+ }
+ return obj;
+ }
+}
+
+#ifdef METH_O
+static PyMethodDef
+swigobject_methods[] = {
+ {(char *)"disown", (PyCFunction)PySwigObject_disown, METH_NOARGS, (char *)"releases ownership of the pointer"},
+ {(char *)"acquire", (PyCFunction)PySwigObject_acquire, METH_NOARGS, (char *)"aquires ownership of the pointer"},
+ {(char *)"own", (PyCFunction)PySwigObject_own, METH_VARARGS, (char *)"returns/sets ownership of the pointer"},
+ {(char *)"append", (PyCFunction)PySwigObject_append, METH_O, (char *)"appends another 'this' object"},
+ {(char *)"next", (PyCFunction)PySwigObject_next, METH_NOARGS, (char *)"returns the next 'this' object"},
+ {(char *)"__repr__",(PyCFunction)PySwigObject_repr, METH_NOARGS, (char *)"returns object representation"},
+ {0, 0, 0, 0}
+};
+#else
+static PyMethodDef
+swigobject_methods[] = {
+ {(char *)"disown", (PyCFunction)PySwigObject_disown, METH_VARARGS, (char *)"releases ownership of the pointer"},
+ {(char *)"acquire", (PyCFunction)PySwigObject_acquire, METH_VARARGS, (char *)"aquires ownership of the pointer"},
+ {(char *)"own", (PyCFunction)PySwigObject_own, METH_VARARGS, (char *)"returns/sets ownership of the pointer"},
+ {(char *)"append", (PyCFunction)PySwigObject_append, METH_VARARGS, (char *)"appends another 'this' object"},
+ {(char *)"next", (PyCFunction)PySwigObject_next, METH_VARARGS, (char *)"returns the next 'this' object"},
+ {(char *)"__repr__",(PyCFunction)PySwigObject_repr, METH_VARARGS, (char *)"returns object representation"},
+ {0, 0, 0, 0}
+};
+#endif
+
+#if PY_VERSION_HEX < 0x02020000
+SWIGINTERN PyObject *
+PySwigObject_getattr(PySwigObject *sobj,char *name)
+{
+ return Py_FindMethod(swigobject_methods, (PyObject *)sobj, name);
+}
+#endif
+
+SWIGRUNTIME PyTypeObject*
+_PySwigObject_type(void) {
+ static char swigobject_doc[] = "Swig object carries a C/C++ instance pointer";
+
+ static PyNumberMethods PySwigObject_as_number = {
+ (binaryfunc)0, /*nb_add*/
+ (binaryfunc)0, /*nb_subtract*/
+ (binaryfunc)0, /*nb_multiply*/
+ (binaryfunc)0, /*nb_divide*/
+ (binaryfunc)0, /*nb_remainder*/
+ (binaryfunc)0, /*nb_divmod*/
+ (ternaryfunc)0,/*nb_power*/
+ (unaryfunc)0, /*nb_negative*/
+ (unaryfunc)0, /*nb_positive*/
+ (unaryfunc)0, /*nb_absolute*/
+ (inquiry)0, /*nb_nonzero*/
+ 0, /*nb_invert*/
+ 0, /*nb_lshift*/
+ 0, /*nb_rshift*/
+ 0, /*nb_and*/
+ 0, /*nb_xor*/
+ 0, /*nb_or*/
+ (coercion)0, /*nb_coerce*/
+ (unaryfunc)PySwigObject_long, /*nb_int*/
+ (unaryfunc)PySwigObject_long, /*nb_long*/
+ (unaryfunc)0, /*nb_float*/
+ (unaryfunc)PySwigObject_oct, /*nb_oct*/
+ (unaryfunc)PySwigObject_hex, /*nb_hex*/
+#if PY_VERSION_HEX >= 0x02050000 /* 2.5.0 */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index */
+#elif PY_VERSION_HEX >= 0x02020000 /* 2.2.0 */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_true_divide */
+#elif PY_VERSION_HEX >= 0x02000000 /* 2.0.0 */
+ 0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_or */
+#endif
+ };
+
+ static PyTypeObject pyswigobject_type;
+ static int type_init = 0;
+ if (!type_init) {
+ const PyTypeObject tmp
+ = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+ (char *)"PySwigObject", /* tp_name */
+ sizeof(PySwigObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)PySwigObject_dealloc, /* tp_dealloc */
+ (printfunc)PySwigObject_print, /* tp_print */
+#if PY_VERSION_HEX < 0x02020000
+ (getattrfunc)PySwigObject_getattr, /* tp_getattr */
+#else
+ (getattrfunc)0, /* tp_getattr */
+#endif
+ (setattrfunc)0, /* tp_setattr */
+ (cmpfunc)PySwigObject_compare, /* tp_compare */
+ (reprfunc)PySwigObject_repr, /* tp_repr */
+ &PySwigObject_as_number, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ (hashfunc)0, /* tp_hash */
+ (ternaryfunc)0, /* tp_call */
+ (reprfunc)PySwigObject_str, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ swigobject_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+#if PY_VERSION_HEX >= 0x02020000
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ swigobject_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+ 0, /* tp_bases */
+ 0, /* tp_mro */
+ 0, /* tp_cache */
+ 0, /* tp_subclasses */
+ 0, /* tp_weaklist */
+#endif
+#if PY_VERSION_HEX >= 0x02030000
+ 0, /* tp_del */
+#endif
+#ifdef COUNT_ALLOCS
+ 0,0,0,0 /* tp_alloc -> tp_next */
+#endif
+ };
+ pyswigobject_type = tmp;
+ pyswigobject_type.ob_type = &PyType_Type;
+ type_init = 1;
+ }
+ return &pyswigobject_type;
+}
+
+SWIGRUNTIME PyObject *
+PySwigObject_New(void *ptr, swig_type_info *ty, int own)
+{
+ PySwigObject *sobj = PyObject_NEW(PySwigObject, PySwigObject_type());
+ if (sobj) {
+ sobj->ptr = ptr;
+ sobj->ty = ty;
+ sobj->own = own;
+ sobj->next = 0;
+ }
+ return (PyObject *)sobj;
+}
+
+/* -----------------------------------------------------------------------------
+ * Implements a simple Swig Packed type, and use it instead of string
+ * ----------------------------------------------------------------------------- */
+
+typedef struct {
+ PyObject_HEAD
+ void *pack;
+ swig_type_info *ty;
+ size_t size;
+} PySwigPacked;
+
+SWIGRUNTIME int
+PySwigPacked_print(PySwigPacked *v, FILE *fp, int SWIGUNUSEDPARM(flags))
+{
+ char result[SWIG_BUFFER_SIZE];
+ fputs("<Swig Packed ", fp);
+ if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))) {
+ fputs("at ", fp);
+ fputs(result, fp);
+ }
+ fputs(v->ty->name,fp);
+ fputs(">", fp);
+ return 0;
+}
+
+SWIGRUNTIME PyObject *
+PySwigPacked_repr(PySwigPacked *v)
+{
+ char result[SWIG_BUFFER_SIZE];
+ if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))) {
+ return PyString_FromFormat("<Swig Packed at %s%s>", result, v->ty->name);
+ } else {
+ return PyString_FromFormat("<Swig Packed %s>", v->ty->name);
+ }
+}
+
+SWIGRUNTIME PyObject *
+PySwigPacked_str(PySwigPacked *v)
+{
+ char result[SWIG_BUFFER_SIZE];
+ if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))){
+ return PyString_FromFormat("%s%s", result, v->ty->name);
+ } else {
+ return PyString_FromString(v->ty->name);
+ }
+}
+
+SWIGRUNTIME int
+PySwigPacked_compare(PySwigPacked *v, PySwigPacked *w)
+{
+ size_t i = v->size;
+ size_t j = w->size;
+ int s = (i < j) ? -1 : ((i > j) ? 1 : 0);
+ return s ? s : strncmp((char *)v->pack, (char *)w->pack, 2*v->size);
+}
+
+SWIGRUNTIME PyTypeObject* _PySwigPacked_type(void);
+
+SWIGRUNTIME PyTypeObject*
+PySwigPacked_type(void) {
+ static PyTypeObject *SWIG_STATIC_POINTER(type) = _PySwigPacked_type();
+ return type;
+}
+
+SWIGRUNTIMEINLINE int
+PySwigPacked_Check(PyObject *op) {
+ return ((op)->ob_type == _PySwigPacked_type())
+ || (strcmp((op)->ob_type->tp_name,"PySwigPacked") == 0);
+}
+
+SWIGRUNTIME void
+PySwigPacked_dealloc(PyObject *v)
+{
+ if (PySwigPacked_Check(v)) {
+ PySwigPacked *sobj = (PySwigPacked *) v;
+ free(sobj->pack);
+ }
+ PyObject_DEL(v);
+}
+
+SWIGRUNTIME PyTypeObject*
+_PySwigPacked_type(void) {
+ static char swigpacked_doc[] = "Swig object carries a C/C++ instance pointer";
+ static PyTypeObject pyswigpacked_type;
+ static int type_init = 0;
+ if (!type_init) {
+ const PyTypeObject tmp
+ = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+ (char *)"PySwigPacked", /* tp_name */
+ sizeof(PySwigPacked), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)PySwigPacked_dealloc, /* tp_dealloc */
+ (printfunc)PySwigPacked_print, /* tp_print */
+ (getattrfunc)0, /* tp_getattr */
+ (setattrfunc)0, /* tp_setattr */
+ (cmpfunc)PySwigPacked_compare, /* tp_compare */
+ (reprfunc)PySwigPacked_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ (hashfunc)0, /* tp_hash */
+ (ternaryfunc)0, /* tp_call */
+ (reprfunc)PySwigPacked_str, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ swigpacked_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+#if PY_VERSION_HEX >= 0x02020000
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+ 0, /* tp_bases */
+ 0, /* tp_mro */
+ 0, /* tp_cache */
+ 0, /* tp_subclasses */
+ 0, /* tp_weaklist */
+#endif
+#if PY_VERSION_HEX >= 0x02030000
+ 0, /* tp_del */
+#endif
+#ifdef COUNT_ALLOCS
+ 0,0,0,0 /* tp_alloc -> tp_next */
+#endif
+ };
+ pyswigpacked_type = tmp;
+ pyswigpacked_type.ob_type = &PyType_Type;
+ type_init = 1;
+ }
+ return &pyswigpacked_type;
+}
+
+SWIGRUNTIME PyObject *
+PySwigPacked_New(void *ptr, size_t size, swig_type_info *ty)
+{
+ PySwigPacked *sobj = PyObject_NEW(PySwigPacked, PySwigPacked_type());
+ if (sobj) {
+ void *pack = malloc(size);
+ if (pack) {
+ memcpy(pack, ptr, size);
+ sobj->pack = pack;
+ sobj->ty = ty;
+ sobj->size = size;
+ } else {
+ PyObject_DEL((PyObject *) sobj);
+ sobj = 0;
+ }
+ }
+ return (PyObject *) sobj;
+}
+
+SWIGRUNTIME swig_type_info *
+PySwigPacked_UnpackData(PyObject *obj, void *ptr, size_t size)
+{
+ if (PySwigPacked_Check(obj)) {
+ PySwigPacked *sobj = (PySwigPacked *)obj;
+ if (sobj->size != size) return 0;
+ memcpy(ptr, sobj->pack, size);
+ return sobj->ty;
+ } else {
+ return 0;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * pointers/data manipulation
+ * ----------------------------------------------------------------------------- */
+
+SWIGRUNTIMEINLINE PyObject *
+_SWIG_This(void)
+{
+ return PyString_FromString("this");
+}
+
+SWIGRUNTIME PyObject *
+SWIG_This(void)
+{
+ static PyObject *SWIG_STATIC_POINTER(swig_this) = _SWIG_This();
+ return swig_this;
+}
+
+/* #define SWIG_PYTHON_SLOW_GETSET_THIS */
+
+SWIGRUNTIME PySwigObject *
+SWIG_Python_GetSwigThis(PyObject *pyobj)
+{
+ if (PySwigObject_Check(pyobj)) {
+ return (PySwigObject *) pyobj;
+ } else {
+ PyObject *obj = 0;
+#if (!defined(SWIG_PYTHON_SLOW_GETSET_THIS) && (PY_VERSION_HEX >= 0x02030000))
+ if (PyInstance_Check(pyobj)) {
+ obj = _PyInstance_Lookup(pyobj, SWIG_This());
+ } else {
+ PyObject **dictptr = _PyObject_GetDictPtr(pyobj);
+ if (dictptr != NULL) {
+ PyObject *dict = *dictptr;
+ obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0;
+ } else {
+#ifdef PyWeakref_CheckProxy
+ if (PyWeakref_CheckProxy(pyobj)) {
+ PyObject *wobj = PyWeakref_GET_OBJECT(pyobj);
+ return wobj ? SWIG_Python_GetSwigThis(wobj) : 0;
+ }
+#endif
+ obj = PyObject_GetAttr(pyobj,SWIG_This());
+ if (obj) {
+ Py_DECREF(obj);
+ } else {
+ if (PyErr_Occurred()) PyErr_Clear();
+ return 0;
+ }
+ }
+ }
+#else
+ obj = PyObject_GetAttr(pyobj,SWIG_This());
+ if (obj) {
+ Py_DECREF(obj);
+ } else {
+ if (PyErr_Occurred()) PyErr_Clear();
+ return 0;
+ }
+#endif
+ if (obj && !PySwigObject_Check(obj)) {
+ /* a PyObject is called 'this', try to get the 'real this'
+ PySwigObject from it */
+ return SWIG_Python_GetSwigThis(obj);
+ }
+ return (PySwigObject *)obj;
+ }
+}
+
+/* Acquire a pointer value */
+
+SWIGRUNTIME int
+SWIG_Python_AcquirePtr(PyObject *obj, int own) {
+ if (own == SWIG_POINTER_OWN) {
+ PySwigObject *sobj = SWIG_Python_GetSwigThis(obj);
+ if (sobj) {
+ int oldown = sobj->own;
+ sobj->own = own;
+ return oldown;
+ }
+ }
+ return 0;
+}
+
+/* Convert a pointer value */
+
+SWIGRUNTIME int
+SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) {
+ if (!obj) return SWIG_ERROR;
+ if (obj == Py_None) {
+ if (ptr) *ptr = 0;
+ return SWIG_OK;
+ } else {
+ PySwigObject *sobj = SWIG_Python_GetSwigThis(obj);
+ if (own)
+ *own = 0;
+ while (sobj) {
+ void *vptr = sobj->ptr;
+ if (ty) {
+ swig_type_info *to = sobj->ty;
+ if (to == ty) {
+ /* no type cast needed */
+ if (ptr) *ptr = vptr;
+ break;
+ } else {
+ swig_cast_info *tc = SWIG_TypeCheck(to->name,ty);
+ if (!tc) {
+ sobj = (PySwigObject *)sobj->next;
+ } else {
+ if (ptr) {
+ int newmemory = 0;
+ *ptr = SWIG_TypeCast(tc,vptr,&newmemory);
+ if (newmemory == SWIG_CAST_NEW_MEMORY) {
+ assert(own);
+ if (own)
+ *own = *own | SWIG_CAST_NEW_MEMORY;
+ }
+ }
+ break;
+ }
+ }
+ } else {
+ if (ptr) *ptr = vptr;
+ break;
+ }
+ }
+ if (sobj) {
+ if (own)
+ *own = *own | sobj->own;
+ if (flags & SWIG_POINTER_DISOWN) {
+ sobj->own = 0;
+ }
+ return SWIG_OK;
+ } else {
+ int res = SWIG_ERROR;
+ if (flags & SWIG_POINTER_IMPLICIT_CONV) {
+ PySwigClientData *data = ty ? (PySwigClientData *) ty->clientdata : 0;
+ if (data && !data->implicitconv) {
+ PyObject *klass = data->klass;
+ if (klass) {
+ PyObject *impconv;
+ data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/
+ impconv = SWIG_Python_CallFunctor(klass, obj);
+ data->implicitconv = 0;
+ if (PyErr_Occurred()) {
+ PyErr_Clear();
+ impconv = 0;
+ }
+ if (impconv) {
+ PySwigObject *iobj = SWIG_Python_GetSwigThis(impconv);
+ if (iobj) {
+ void *vptr;
+ res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0);
+ if (SWIG_IsOK(res)) {
+ if (ptr) {
+ *ptr = vptr;
+ /* transfer the ownership to 'ptr' */
+ iobj->own = 0;
+ res = SWIG_AddCast(res);
+ res = SWIG_AddNewMask(res);
+ } else {
+ res = SWIG_AddCast(res);
+ }
+ }
+ }
+ Py_DECREF(impconv);
+ }
+ }
+ }
+ }
+ return res;
+ }
+ }
+}
+
+/* Convert a function ptr value */
+
+SWIGRUNTIME int
+SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) {
+ if (!PyCFunction_Check(obj)) {
+ return SWIG_ConvertPtr(obj, ptr, ty, 0);
+ } else {
+ void *vptr = 0;
+
+ /* here we get the method pointer for callbacks */
+ const char *doc = (((PyCFunctionObject *)obj) -> m_ml -> ml_doc);
+ const char *desc = doc ? strstr(doc, "swig_ptr: ") : 0;
+ if (desc) {
+ desc = ty ? SWIG_UnpackVoidPtr(desc + 10, &vptr, ty->name) : 0;
+ if (!desc) return SWIG_ERROR;
+ }
+ if (ty) {
+ swig_cast_info *tc = SWIG_TypeCheck(desc,ty);
+ if (tc) {
+ int newmemory = 0;
+ *ptr = SWIG_TypeCast(tc,vptr,&newmemory);
+ assert(!newmemory); /* newmemory handling not yet implemented */
+ } else {
+ return SWIG_ERROR;
+ }
+ } else {
+ *ptr = vptr;
+ }
+ return SWIG_OK;
+ }
+}
+
+/* Convert a packed value value */
+
+SWIGRUNTIME int
+SWIG_Python_ConvertPacked(PyObject *obj, void *ptr, size_t sz, swig_type_info *ty) {
+ swig_type_info *to = PySwigPacked_UnpackData(obj, ptr, sz);
+ if (!to) return SWIG_ERROR;
+ if (ty) {
+ if (to != ty) {
+ /* check type cast? */
+ swig_cast_info *tc = SWIG_TypeCheck(to->name,ty);
+ if (!tc) return SWIG_ERROR;
+ }
+ }
+ return SWIG_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * Create a new pointer object
+ * ----------------------------------------------------------------------------- */
+
+/*
+ Create a new instance object, whitout calling __init__, and set the
+ 'this' attribute.
+*/
+
+SWIGRUNTIME PyObject*
+SWIG_Python_NewShadowInstance(PySwigClientData *data, PyObject *swig_this)
+{
+#if (PY_VERSION_HEX >= 0x02020000)
+ PyObject *inst = 0;
+ PyObject *newraw = data->newraw;
+ if (newraw) {
+ inst = PyObject_Call(newraw, data->newargs, NULL);
+ if (inst) {
+#if !defined(SWIG_PYTHON_SLOW_GETSET_THIS)
+ PyObject **dictptr = _PyObject_GetDictPtr(inst);
+ if (dictptr != NULL) {
+ PyObject *dict = *dictptr;
+ if (dict == NULL) {
+ dict = PyDict_New();
+ *dictptr = dict;
+ PyDict_SetItem(dict, SWIG_This(), swig_this);
+ }
+ }
+#else
+ PyObject *key = SWIG_This();
+ PyObject_SetAttr(inst, key, swig_this);
+#endif
+ }
+ } else {
+ PyObject *dict = PyDict_New();
+ PyDict_SetItem(dict, SWIG_This(), swig_this);
+ inst = PyInstance_NewRaw(data->newargs, dict);
+ Py_DECREF(dict);
+ }
+ return inst;
+#else
+#if (PY_VERSION_HEX >= 0x02010000)
+ PyObject *inst;
+ PyObject *dict = PyDict_New();
+ PyDict_SetItem(dict, SWIG_This(), swig_this);
+ inst = PyInstance_NewRaw(data->newargs, dict);
+ Py_DECREF(dict);
+ return (PyObject *) inst;
+#else
+ PyInstanceObject *inst = PyObject_NEW(PyInstanceObject, &PyInstance_Type);
+ if (inst == NULL) {
+ return NULL;
+ }
+ inst->in_class = (PyClassObject *)data->newargs;
+ Py_INCREF(inst->in_class);
+ inst->in_dict = PyDict_New();
+ if (inst->in_dict == NULL) {
+ Py_DECREF(inst);
+ return NULL;
+ }
+#ifdef Py_TPFLAGS_HAVE_WEAKREFS
+ inst->in_weakreflist = NULL;
+#endif
+#ifdef Py_TPFLAGS_GC
+ PyObject_GC_Init(inst);
+#endif
+ PyDict_SetItem(inst->in_dict, SWIG_This(), swig_this);
+ return (PyObject *) inst;
+#endif
+#endif
+}
+
+SWIGRUNTIME void
+SWIG_Python_SetSwigThis(PyObject *inst, PyObject *swig_this)
+{
+ PyObject *dict;
+#if (PY_VERSION_HEX >= 0x02020000) && !defined(SWIG_PYTHON_SLOW_GETSET_THIS)
+ PyObject **dictptr = _PyObject_GetDictPtr(inst);
+ if (dictptr != NULL) {
+ dict = *dictptr;
+ if (dict == NULL) {
+ dict = PyDict_New();
+ *dictptr = dict;
+ }
+ PyDict_SetItem(dict, SWIG_This(), swig_this);
+ return;
+ }
+#endif
+ dict = PyObject_GetAttrString(inst, (char*)"__dict__");
+ PyDict_SetItem(dict, SWIG_This(), swig_this);
+ Py_DECREF(dict);
+}
+
+
+SWIGINTERN PyObject *
+SWIG_Python_InitShadowInstance(PyObject *args) {
+ PyObject *obj[2];
+ if (!SWIG_Python_UnpackTuple(args,(char*)"swiginit", 2, 2, obj)) {
+ return NULL;
+ } else {
+ PySwigObject *sthis = SWIG_Python_GetSwigThis(obj[0]);
+ if (sthis) {
+ PySwigObject_append((PyObject*) sthis, obj[1]);
+ } else {
+ SWIG_Python_SetSwigThis(obj[0], obj[1]);
+ }
+ return SWIG_Py_Void();
+ }
+}
+
+/* Create a new pointer object */
+
+SWIGRUNTIME PyObject *
+SWIG_Python_NewPointerObj(void *ptr, swig_type_info *type, int flags) {
+ if (!ptr) {
+ return SWIG_Py_Void();
+ } else {
+ int own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0;
+ PyObject *robj = PySwigObject_New(ptr, type, own);
+ PySwigClientData *clientdata = type ? (PySwigClientData *)(type->clientdata) : 0;
+ if (clientdata && !(flags & SWIG_POINTER_NOSHADOW)) {
+ PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj);
+ if (inst) {
+ Py_DECREF(robj);
+ robj = inst;
+ }
+ }
+ return robj;
+ }
+}
+
+/* Create a new packed object */
+
+SWIGRUNTIMEINLINE PyObject *
+SWIG_Python_NewPackedObj(void *ptr, size_t sz, swig_type_info *type) {
+ return ptr ? PySwigPacked_New((void *) ptr, sz, type) : SWIG_Py_Void();
+}
+
+/* -----------------------------------------------------------------------------*
+ * Get type list
+ * -----------------------------------------------------------------------------*/
+
+#ifdef SWIG_LINK_RUNTIME
+void *SWIG_ReturnGlobalTypeList(void *);
+#endif
+
+SWIGRUNTIME swig_module_info *
+SWIG_Python_GetModule(void) {
+ static void *type_pointer = (void *)0;
+ /* first check if module already created */
+ if (!type_pointer) {
+#ifdef SWIG_LINK_RUNTIME
+ type_pointer = SWIG_ReturnGlobalTypeList((void *)0);
+#else
+ type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
+ (char*)"type_pointer" SWIG_TYPE_TABLE_NAME);
+ if (PyErr_Occurred()) {
+ PyErr_Clear();
+ type_pointer = (void *)0;
+ }
+#endif
+ }
+ return (swig_module_info *) type_pointer;
+}
+
+#if PY_MAJOR_VERSION < 2
+/* PyModule_AddObject function was introduced in Python 2.0. The following function
+ is copied out of Python/modsupport.c in python version 2.3.4 */
+SWIGINTERN int
+PyModule_AddObject(PyObject *m, char *name, PyObject *o)
+{
+ PyObject *dict;
+ if (!PyModule_Check(m)) {
+ PyErr_SetString(PyExc_TypeError,
+ "PyModule_AddObject() needs module as first arg");
+ return SWIG_ERROR;
+ }
+ if (!o) {
+ PyErr_SetString(PyExc_TypeError,
+ "PyModule_AddObject() needs non-NULL value");
+ return SWIG_ERROR;
+ }
+
+ dict = PyModule_GetDict(m);
+ if (dict == NULL) {
+ /* Internal error -- modules must have a dict! */
+ PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__",
+ PyModule_GetName(m));
+ return SWIG_ERROR;
+ }
+ if (PyDict_SetItemString(dict, name, o))
+ return SWIG_ERROR;
+ Py_DECREF(o);
+ return SWIG_OK;
+}
+#endif
+
+SWIGRUNTIME void
+SWIG_Python_DestroyModule(void *vptr)
+{
+ swig_module_info *swig_module = (swig_module_info *) vptr;
+ swig_type_info **types = swig_module->types;
+ size_t i;
+ for (i =0; i < swig_module->size; ++i) {
+ swig_type_info *ty = types[i];
+ if (ty->owndata) {
+ PySwigClientData *data = (PySwigClientData *) ty->clientdata;
+ if (data) PySwigClientData_Del(data);
+ }
+ }
+ Py_DECREF(SWIG_This());
+}
+
+SWIGRUNTIME void
+SWIG_Python_SetModule(swig_module_info *swig_module) {
+ static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} };/* Sentinel */
+
+ PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
+ swig_empty_runtime_method_table);
+ PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule);
+ if (pointer && module) {
+ PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer);
+ } else {
+ Py_XDECREF(pointer);
+ }
+}
+
+/* The python cached type query */
+SWIGRUNTIME PyObject *
+SWIG_Python_TypeCache(void) {
+ static PyObject *SWIG_STATIC_POINTER(cache) = PyDict_New();
+ return cache;
+}
+
+SWIGRUNTIME swig_type_info *
+SWIG_Python_TypeQuery(const char *type)
+{
+ PyObject *cache = SWIG_Python_TypeCache();
+ PyObject *key = PyString_FromString(type);
+ PyObject *obj = PyDict_GetItem(cache, key);
+ swig_type_info *descriptor;
+ if (obj) {
+ descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj);
+ } else {
+ swig_module_info *swig_module = SWIG_Python_GetModule();
+ descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type);
+ if (descriptor) {
+ obj = PyCObject_FromVoidPtr(descriptor, NULL);
+ PyDict_SetItem(cache, key, obj);
+ Py_DECREF(obj);
+ }
+ }
+ Py_DECREF(key);
+ return descriptor;
+}
+
+/*
+ For backward compatibility only
+*/
+#define SWIG_POINTER_EXCEPTION 0
+#define SWIG_arg_fail(arg) SWIG_Python_ArgFail(arg)
+#define SWIG_MustGetPtr(p, type, argnum, flags) SWIG_Python_MustGetPtr(p, type, argnum, flags)
+
+SWIGRUNTIME int
+SWIG_Python_AddErrMesg(const char* mesg, int infront)
+{
+ if (PyErr_Occurred()) {
+ PyObject *type = 0;
+ PyObject *value = 0;
+ PyObject *traceback = 0;
+ PyErr_Fetch(&type, &value, &traceback);
+ if (value) {
+ PyObject *old_str = PyObject_Str(value);
+ Py_XINCREF(type);
+ PyErr_Clear();
+ if (infront) {
+ PyErr_Format(type, "%s %s", mesg, PyString_AsString(old_str));
+ } else {
+ PyErr_Format(type, "%s %s", PyString_AsString(old_str), mesg);
+ }
+ Py_DECREF(old_str);
+ }
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+SWIGRUNTIME int
+SWIG_Python_ArgFail(int argnum)
+{
+ if (PyErr_Occurred()) {
+ /* add information about failing argument */
+ char mesg[256];
+ PyOS_snprintf(mesg, sizeof(mesg), "argument number %d:", argnum);
+ return SWIG_Python_AddErrMesg(mesg, 1);
+ } else {
+ return 0;
+ }
+}
+
+SWIGRUNTIMEINLINE const char *
+PySwigObject_GetDesc(PyObject *self)
+{
+ PySwigObject *v = (PySwigObject *)self;
+ swig_type_info *ty = v ? v->ty : 0;
+ return ty ? ty->str : (char*)"";
+}
+
+SWIGRUNTIME void
+SWIG_Python_TypeError(const char *type, PyObject *obj)
+{
+ if (type) {
+#if defined(SWIG_COBJECT_TYPES)
+ if (obj && PySwigObject_Check(obj)) {
+ const char *otype = (const char *) PySwigObject_GetDesc(obj);
+ if (otype) {
+ PyErr_Format(PyExc_TypeError, "a '%s' is expected, 'PySwigObject(%s)' is received",
+ type, otype);
+ return;
+ }
+ } else
+#endif
+ {
+ const char *otype = (obj ? obj->ob_type->tp_name : 0);
+ if (otype) {
+ PyObject *str = PyObject_Str(obj);
+ const char *cstr = str ? PyString_AsString(str) : 0;
+ if (cstr) {
+ PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s(%s)' is received",
+ type, otype, cstr);
+ } else {
+ PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s' is received",
+ type, otype);
+ }
+ Py_XDECREF(str);
+ return;
+ }
+ }
+ PyErr_Format(PyExc_TypeError, "a '%s' is expected", type);
+ } else {
+ PyErr_Format(PyExc_TypeError, "unexpected type is received");
+ }
+}
+
+
+/* Convert a pointer value, signal an exception on a type mismatch */
+SWIGRUNTIME void *
+SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags) {
+ void *result;
+ if (SWIG_Python_ConvertPtr(obj, &result, ty, flags) == -1) {
+ PyErr_Clear();
+ if (flags & SWIG_POINTER_EXCEPTION) {
+ SWIG_Python_TypeError(SWIG_TypePrettyName(ty), obj);
+ SWIG_Python_ArgFail(argnum);
+ }
+ }
+ return result;
+}
+
+
+#ifdef __cplusplus
+#if 0
+{ /* cc-mode */
+#endif
+}
+#endif
+
+
+
+#define SWIG_exception_fail(code, msg) do { SWIG_Error(code, msg); SWIG_fail; } while(0)
+
+#define SWIG_contract_assert(expr, msg) if (!(expr)) { SWIG_Error(SWIG_RuntimeError, msg); SWIG_fail; } else
+
+
+
+ #define SWIG_exception(code, msg) do { SWIG_Error(code, msg); SWIG_fail;; } while(0)
+
+
+/* -------- TYPES TABLE (BEGIN) -------- */
+
+#define SWIGTYPE_p_TALLOC_CTX swig_types[0]
+#define SWIGTYPE_p_auth_session_info swig_types[1]
+#define SWIGTYPE_p_char swig_types[2]
+#define SWIGTYPE_p_cli_credentials swig_types[3]
+#define SWIGTYPE_p_dom_sid swig_types[4]
+#define SWIGTYPE_p_int swig_types[5]
+#define SWIGTYPE_p_ldb_context swig_types[6]
+#define SWIGTYPE_p_ldb_dn swig_types[7]
+#define SWIGTYPE_p_ldb_ldif swig_types[8]
+#define SWIGTYPE_p_ldb_message swig_types[9]
+#define SWIGTYPE_p_ldb_message_element swig_types[10]
+#define SWIGTYPE_p_ldb_result swig_types[11]
+#define SWIGTYPE_p_loadparm_context swig_types[12]
+#define SWIGTYPE_p_loadparm_service swig_types[13]
+#define SWIGTYPE_p_long_long swig_types[14]
+#define SWIGTYPE_p_param_context swig_types[15]
+#define SWIGTYPE_p_param_opt swig_types[16]
+#define SWIGTYPE_p_param_section swig_types[17]
+#define SWIGTYPE_p_security_descriptor swig_types[18]
+#define SWIGTYPE_p_security_token swig_types[19]
+#define SWIGTYPE_p_short swig_types[20]
+#define SWIGTYPE_p_signed_char swig_types[21]
+#define SWIGTYPE_p_unsigned_char swig_types[22]
+#define SWIGTYPE_p_unsigned_int swig_types[23]
+#define SWIGTYPE_p_unsigned_long swig_types[24]
+#define SWIGTYPE_p_unsigned_long_long swig_types[25]
+#define SWIGTYPE_p_unsigned_short swig_types[26]
+static swig_type_info *swig_types[28];
+static swig_module_info swig_module = {swig_types, 27, 0, 0, 0, 0};
+#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
+#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
+
+/* -------- TYPES TABLE (END) -------- */
+
+#if (PY_VERSION_HEX <= 0x02000000)
+# if !defined(SWIG_PYTHON_CLASSIC)
+# error "This python version requires swig to be run with the '-classic' option"
+# endif
+#endif
+#if (PY_VERSION_HEX <= 0x02020000)
+# error "This python version requires swig to be run with the '-nomodern' option"
+#endif
+#if (PY_VERSION_HEX <= 0x02020000)
+# error "This python version requires swig to be run with the '-nomodernargs' option"
+#endif
+#ifndef METH_O
+# error "This python version requires swig to be run with the '-nofastunpack' option"
+#endif
+#ifdef SWIG_TypeQuery
+# undef SWIG_TypeQuery
+#endif
+#define SWIG_TypeQuery SWIG_Python_TypeQuery
+
+/*-----------------------------------------------
+ @(target):= _misc.so
+ ------------------------------------------------*/
+#define SWIG_init init_misc
+
+#define SWIG_name "_misc"
+
+#define SWIGVERSION 0x010336
+#define SWIG_VERSION SWIGVERSION
+
+
+#define SWIG_as_voidptr(a) (void *)((const void *)(a))
+#define SWIG_as_voidptrptr(a) ((void)SWIG_as_voidptr(*a),(void**)(a))
+
+
+#include "includes.h"
+#include "ldb.h"
+#include "param/param.h"
+#include "auth/credentials/credentials.h"
+#include "dsdb/samdb/samdb.h"
+#include "lib/ldb-samba/ldif_handlers.h"
+#include "librpc/ndr/libndr.h"
+#include "version.h"
+
+
+#include "libcli/util/pyerrors.h"
+
+
+SWIGINTERN int
+SWIG_AsVal_double (PyObject *obj, double *val)
+{
+ int res = SWIG_TypeError;
+ if (PyFloat_Check(obj)) {
+ if (val) *val = PyFloat_AsDouble(obj);
+ return SWIG_OK;
+ } else if (PyInt_Check(obj)) {
+ if (val) *val = PyInt_AsLong(obj);
+ return SWIG_OK;
+ } else if (PyLong_Check(obj)) {
+ double v = PyLong_AsDouble(obj);
+ if (!PyErr_Occurred()) {
+ if (val) *val = v;
+ return SWIG_OK;
+ } else {
+ PyErr_Clear();
+ }
+ }
+#ifdef SWIG_PYTHON_CAST_MODE
+ {
+ int dispatch = 0;
+ double d = PyFloat_AsDouble(obj);
+ if (!PyErr_Occurred()) {
+ if (val) *val = d;
+ return SWIG_AddCast(SWIG_OK);
+ } else {
+ PyErr_Clear();
+ }
+ if (!dispatch) {
+ long v = PyLong_AsLong(obj);
+ if (!PyErr_Occurred()) {
+ if (val) *val = v;
+ return SWIG_AddCast(SWIG_AddCast(SWIG_OK));
+ } else {
+ PyErr_Clear();
+ }
+ }
+ }
+#endif
+ return res;
+}
+
+
+#include <float.h>
+
+
+#include <math.h>
+
+
+SWIGINTERNINLINE int
+SWIG_CanCastAsInteger(double *d, double min, double max) {
+ double x = *d;
+ if ((min <= x && x <= max)) {
+ double fx = floor(x);
+ double cx = ceil(x);
+ double rd = ((x - fx) < 0.5) ? fx : cx; /* simple rint */
+ if ((errno == EDOM) || (errno == ERANGE)) {
+ errno = 0;
+ } else {
+ double summ, reps, diff;
+ if (rd < x) {
+ diff = x - rd;
+ } else if (rd > x) {
+ diff = rd - x;
+ } else {
+ return 1;
+ }
+ summ = rd + x;
+ reps = diff/summ;
+ if (reps < 8*DBL_EPSILON) {
+ *d = rd;
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+
+SWIGINTERN int
+SWIG_AsVal_unsigned_SS_long (PyObject *obj, unsigned long *val)
+{
+ if (PyInt_Check(obj)) {
+ long v = PyInt_AsLong(obj);
+ if (v >= 0) {
+ if (val) *val = v;
+ return SWIG_OK;
+ } else {
+ return SWIG_OverflowError;
+ }
+ } else if (PyLong_Check(obj)) {
+ unsigned long v = PyLong_AsUnsignedLong(obj);
+ if (!PyErr_Occurred()) {
+ if (val) *val = v;
+ return SWIG_OK;
+ } else {
+ PyErr_Clear();
+ }
+ }
+#ifdef SWIG_PYTHON_CAST_MODE
+ {
+ int dispatch = 0;
+ unsigned long v = PyLong_AsUnsignedLong(obj);
+ if (!PyErr_Occurred()) {
+ if (val) *val = v;
+ return SWIG_AddCast(SWIG_OK);
+ } else {
+ PyErr_Clear();
+ }
+ if (!dispatch) {
+ double d;
+ int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d));
+ if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULONG_MAX)) {
+ if (val) *val = (unsigned long)(d);
+ return res;
+ }
+ }
+ }
+#endif
+ return SWIG_TypeError;
+}
+
+
+SWIGINTERNINLINE int
+SWIG_AsVal_size_t (PyObject * obj, size_t *val)
+{
+ unsigned long v;
+ int res = SWIG_AsVal_unsigned_SS_long (obj, val ? &v : 0);
+ if (SWIG_IsOK(res) && val) *val = (size_t)(v);
+ return res;
+}
+
+
+SWIGINTERN swig_type_info*
+SWIG_pchar_descriptor(void)
+{
+ static int init = 0;
+ static swig_type_info* info = 0;
+ if (!init) {
+ info = SWIG_TypeQuery("_p_char");
+ init = 1;
+ }
+ return info;
+}
+
+
+SWIGINTERNINLINE PyObject *
+SWIG_FromCharPtrAndSize(const char* carray, size_t size)
+{
+ if (carray) {
+ if (size > INT_MAX) {
+ swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
+ return pchar_descriptor ?
+ SWIG_NewPointerObj((char *)(carray), pchar_descriptor, 0) : SWIG_Py_Void();
+ } else {
+ return PyString_FromStringAndSize(carray, (int)(size));
+ }
+ } else {
+ return SWIG_Py_Void();
+ }
+}
+
+
+SWIGINTERNINLINE PyObject *
+SWIG_FromCharPtr(const char *cptr)
+{
+ return SWIG_FromCharPtrAndSize(cptr, (cptr ? strlen(cptr) : 0));
+}
+
+
+void ldb_set_credentials(struct ldb_context *ldb, struct cli_credentials *creds)
+{
+ ldb_set_opaque(ldb, "credentials", creds);
+}
+
+void ldb_set_session_info(struct ldb_context *ldb, struct auth_session_info *session_info)
+{
+ ldb_set_opaque(ldb, "sessionInfo", session_info);
+}
+
+void ldb_set_loadparm(struct ldb_context *ldb, struct loadparm_context *lp_ctx)
+{
+ ldb_set_opaque(ldb, "loadparm", lp_ctx);
+}
+
+
+
+SWIGINTERNINLINE PyObject*
+ SWIG_From_bool (bool value)
+{
+ return PyBool_FromLong(value ? 1 : 0);
+}
+
+
+SWIGINTERN int
+SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
+{
+ if (PyString_Check(obj)) {
+ char *cstr; Py_ssize_t len;
+ PyString_AsStringAndSize(obj, &cstr, &len);
+ if (cptr) {
+ if (alloc) {
+ /*
+ In python the user should not be able to modify the inner
+ string representation. To warranty that, if you define
+ SWIG_PYTHON_SAFE_CSTRINGS, a new/copy of the python string
+ buffer is always returned.
+
+ The default behavior is just to return the pointer value,
+ so, be careful.
+ */
+#if defined(SWIG_PYTHON_SAFE_CSTRINGS)
+ if (*alloc != SWIG_OLDOBJ)
+#else
+ if (*alloc == SWIG_NEWOBJ)
+#endif
+ {
+ *cptr = (char *)memcpy((char *)malloc((len + 1)*sizeof(char)), cstr, sizeof(char)*(len + 1));
+ *alloc = SWIG_NEWOBJ;
+ }
+ else {
+ *cptr = cstr;
+ *alloc = SWIG_OLDOBJ;
+ }
+ } else {
+ *cptr = PyString_AsString(obj);
+ }
+ }
+ if (psize) *psize = len + 1;
+ return SWIG_OK;
+ } else {
+ swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
+ if (pchar_descriptor) {
+ void* vptr = 0;
+ if (SWIG_ConvertPtr(obj, &vptr, pchar_descriptor, 0) == SWIG_OK) {
+ if (cptr) *cptr = (char *) vptr;
+ if (psize) *psize = vptr ? (strlen((char *)vptr) + 1) : 0;
+ if (alloc) *alloc = SWIG_OLDOBJ;
+ return SWIG_OK;
+ }
+ }
+ }
+ return SWIG_TypeError;
+}
+
+
+
+
+
+const char *version(void)
+{
+ return SAMBA_VERSION_STRING;
+}
+
+
+ #define SWIG_From_long PyInt_FromLong
+
+
+SWIGINTERNINLINE PyObject *
+SWIG_From_int (int value)
+{
+ return SWIG_From_long (value);
+}
+
+
+bool dsdb_set_ntds_invocation_id(struct ldb_context *ldb, const char *guid)
+{
+ struct GUID invocation_id_in;
+ if (NT_STATUS_IS_ERR(GUID_from_string(guid, &invocation_id_in))) {
+ return false;
+ }
+ return samdb_set_ntds_invocation_id(ldb, &invocation_id_in);
+}
+
+
+uint64_t unix2nttime(time_t t)
+{
+ NTTIME nt;
+ unix_to_nt_time(&nt, t);
+ return (uint64_t)nt;
+}
+
+
+#include <limits.h>
+#if !defined(SWIG_NO_LLONG_MAX)
+# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__)
+# define LLONG_MAX __LONG_LONG_MAX__
+# define LLONG_MIN (-LLONG_MAX - 1LL)
+# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL)
+# endif
+#endif
+
+
+SWIGINTERNINLINE PyObject*
+SWIG_From_long_SS_long (long long value)
+{
+ return ((value < LONG_MIN) || (value > LONG_MAX)) ?
+ PyLong_FromLongLong(value) : PyInt_FromLong((long)(value));
+}
+
+
+SWIGINTERNINLINE PyObject*
+SWIG_From_unsigned_SS_long_SS_long (unsigned long long value)
+{
+ return (value > LONG_MAX) ?
+ PyLong_FromUnsignedLongLong(value) : PyInt_FromLong((long)(value));
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+SWIGINTERN PyObject *_wrap_random_password(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+ PyObject *resultobj = 0;
+ TALLOC_CTX *arg1 = (TALLOC_CTX *) 0 ;
+ size_t arg2 ;
+ size_t val2 ;
+ int ecode2 = 0 ;
+ PyObject * obj0 = 0 ;
+ char * kwnames[] = {
+ (char *) "len", NULL
+ };
+ char *result = 0 ;
+
+ arg1 = NULL;
+ if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O:random_password",kwnames,&obj0)) SWIG_fail;
+ ecode2 = SWIG_AsVal_size_t(obj0, &val2);
+ if (!SWIG_IsOK(ecode2)) {
+ SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "random_password" "', argument " "2"" of type '" "size_t""'");
+ }
+ arg2 = (size_t)(val2);
+ result = (char *)generate_random_str(arg1,arg2);
+ resultobj = SWIG_FromCharPtr((const char *)result);
+ return resultobj;
+fail:
+ return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ldb_set_credentials(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+ PyObject *resultobj = 0;
+ struct ldb_context *arg1 = (struct ldb_context *) 0 ;
+ struct cli_credentials *arg2 = (struct cli_credentials *) 0 ;
+ void *argp1 = 0 ;
+ int res1 = 0 ;
+ void *argp2 = 0 ;
+ int res2 = 0 ;
+ PyObject * obj0 = 0 ;
+ PyObject * obj1 = 0 ;
+ char * kwnames[] = {
+ (char *) "ldb",(char *) "creds", NULL
+ };
+
+ arg2 = NULL;
+ if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O|O:ldb_set_credentials",kwnames,&obj0,&obj1)) SWIG_fail;
+ res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ldb_context, 0 | 0 );
+ if (!SWIG_IsOK(res1)) {
+ SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ldb_set_credentials" "', argument " "1"" of type '" "struct ldb_context *""'");
+ }
+ arg1 = (struct ldb_context *)(argp1);
+ if (obj1) {
+ res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_cli_credentials, 0 | 0 );
+ if (!SWIG_IsOK(res2)) {
+ SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ldb_set_credentials" "', argument " "2"" of type '" "struct cli_credentials *""'");
+ }
+ arg2 = (struct cli_credentials *)(argp2);
+ }
+ if (arg1 == NULL)
+ SWIG_exception(SWIG_ValueError,
+ "ldb context must be non-NULL");
+ ldb_set_credentials(arg1,arg2);
+ resultobj = SWIG_Py_Void();
+ return resultobj;
+fail:
+ return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ldb_set_session_info(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+ PyObject *resultobj = 0;
+ struct ldb_context *arg1 = (struct ldb_context *) 0 ;
+ struct auth_session_info *arg2 = (struct auth_session_info *) 0 ;
+ void *argp1 = 0 ;
+ int res1 = 0 ;
+ void *argp2 = 0 ;
+ int res2 = 0 ;
+ PyObject * obj0 = 0 ;
+ PyObject * obj1 = 0 ;
+ char * kwnames[] = {
+ (char *) "ldb",(char *) "session_info", NULL
+ };
+
+ if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO:ldb_set_session_info",kwnames,&obj0,&obj1)) SWIG_fail;
+ res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ldb_context, 0 | 0 );
+ if (!SWIG_IsOK(res1)) {
+ SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ldb_set_session_info" "', argument " "1"" of type '" "struct ldb_context *""'");
+ }
+ arg1 = (struct ldb_context *)(argp1);
+ res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_auth_session_info, 0 | 0 );
+ if (!SWIG_IsOK(res2)) {
+ SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ldb_set_session_info" "', argument " "2"" of type '" "struct auth_session_info *""'");
+ }
+ arg2 = (struct auth_session_info *)(argp2);
+ if (arg1 == NULL)
+ SWIG_exception(SWIG_ValueError,
+ "ldb context must be non-NULL");
+ ldb_set_session_info(arg1,arg2);
+ resultobj = SWIG_Py_Void();
+ return resultobj;
+fail:
+ return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ldb_set_loadparm(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+ PyObject *resultobj = 0;
+ struct ldb_context *arg1 = (struct ldb_context *) 0 ;
+ struct loadparm_context *arg2 = (struct loadparm_context *) 0 ;
+ void *argp1 = 0 ;
+ int res1 = 0 ;
+ void *argp2 = 0 ;
+ int res2 = 0 ;
+ PyObject * obj0 = 0 ;
+ PyObject * obj1 = 0 ;
+ char * kwnames[] = {
+ (char *) "ldb",(char *) "lp_ctx", NULL
+ };
+
+ arg2 = loadparm_init(NULL);
+ if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O|O:ldb_set_loadparm",kwnames,&obj0,&obj1)) SWIG_fail;
+ res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ldb_context, 0 | 0 );
+ if (!SWIG_IsOK(res1)) {
+ SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ldb_set_loadparm" "', argument " "1"" of type '" "struct ldb_context *""'");
+ }
+ arg1 = (struct ldb_context *)(argp1);
+ if (obj1) {
+ res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_loadparm_context, 0 | 0 );
+ if (!SWIG_IsOK(res2)) {
+ SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ldb_set_loadparm" "', argument " "2"" of type '" "struct loadparm_context *""'");
+ }
+ arg2 = (struct loadparm_context *)(argp2);
+ }
+ if (arg1 == NULL)
+ SWIG_exception(SWIG_ValueError,
+ "ldb context must be non-NULL");
+ ldb_set_loadparm(arg1,arg2);
+ resultobj = SWIG_Py_Void();
+ return resultobj;
+fail:
+ return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_samdb_set_domain_sid(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+ PyObject *resultobj = 0;
+ struct ldb_context *arg1 = (struct ldb_context *) 0 ;
+ struct dom_sid *arg2 = (struct dom_sid *) 0 ;
+ void *argp1 = 0 ;
+ int res1 = 0 ;
+ void *argp2 = 0 ;
+ int res2 = 0 ;
+ PyObject * obj0 = 0 ;
+ PyObject * obj1 = 0 ;
+ char * kwnames[] = {
+ (char *) "ldb",(char *) "dom_sid_in", NULL
+ };
+ bool result;
+
+ if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO:samdb_set_domain_sid",kwnames,&obj0,&obj1)) SWIG_fail;
+ res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ldb_context, 0 | 0 );
+ if (!SWIG_IsOK(res1)) {
+ SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "samdb_set_domain_sid" "', argument " "1"" of type '" "struct ldb_context *""'");
+ }
+ arg1 = (struct ldb_context *)(argp1);
+ res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_dom_sid, 0 | 0 );
+ if (!SWIG_IsOK(res2)) {
+ SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "samdb_set_domain_sid" "', argument " "2"" of type '" "struct dom_sid const *""'");
+ }
+ arg2 = (struct dom_sid *)(argp2);
+ if (arg1 == NULL)
+ SWIG_exception(SWIG_ValueError,
+ "ldb context must be non-NULL");
+ result = (bool)samdb_set_domain_sid(arg1,(struct dom_sid const *)arg2);
+ resultobj = SWIG_From_bool((bool)(result));
+ return resultobj;
+fail:
+ return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_dsdb_attach_schema_from_ldif_file(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+ PyObject *resultobj = 0;
+ struct ldb_context *arg1 = (struct ldb_context *) 0 ;
+ char *arg2 = (char *) 0 ;
+ char *arg3 = (char *) 0 ;
+ void *argp1 = 0 ;
+ int res1 = 0 ;
+ int res2 ;
+ char *buf2 = 0 ;
+ int alloc2 = 0 ;
+ int res3 ;
+ char *buf3 = 0 ;
+ int alloc3 = 0 ;
+ PyObject * obj0 = 0 ;
+ PyObject * obj1 = 0 ;
+ PyObject * obj2 = 0 ;
+ char * kwnames[] = {
+ (char *) "ldb",(char *) "pf",(char *) "df", NULL
+ };
+ WERROR result;
+
+ if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO:dsdb_attach_schema_from_ldif_file",kwnames,&obj0,&obj1,&obj2)) SWIG_fail;
+ res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ldb_context, 0 | 0 );
+ if (!SWIG_IsOK(res1)) {
+ SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "dsdb_attach_schema_from_ldif_file" "', argument " "1"" of type '" "struct ldb_context *""'");
+ }
+ arg1 = (struct ldb_context *)(argp1);
+ res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+ if (!SWIG_IsOK(res2)) {
+ SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "dsdb_attach_schema_from_ldif_file" "', argument " "2"" of type '" "char const *""'");
+ }
+ arg2 = (char *)(buf2);
+ res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
+ if (!SWIG_IsOK(res3)) {
+ SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "dsdb_attach_schema_from_ldif_file" "', argument " "3"" of type '" "char const *""'");
+ }
+ arg3 = (char *)(buf3);
+ if (arg1 == NULL)
+ SWIG_exception(SWIG_ValueError,
+ "ldb context must be non-NULL");
+ result = dsdb_attach_schema_from_ldif_file(arg1,(char const *)arg2,(char const *)arg3);
+ if (!W_ERROR_IS_OK(result)) {
+ PyErr_SetWERROR(result);
+ SWIG_fail;
+ } else if (resultobj == NULL) {
+ resultobj = Py_None;
+ }
+ if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+ if (alloc3 == SWIG_NEWOBJ) free((char*)buf3);
+ return resultobj;
+fail:
+ if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+ if (alloc3 == SWIG_NEWOBJ) free((char*)buf3);
+ return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_version(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+ PyObject *resultobj = 0;
+ char *result = 0 ;
+
+ if (!SWIG_Python_UnpackTuple(args,"version",0,0,0)) SWIG_fail;
+ result = (char *)version();
+ resultobj = SWIG_FromCharPtr((const char *)result);
+ return resultobj;
+fail:
+ return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_dsdb_set_global_schema(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+ PyObject *resultobj = 0;
+ struct ldb_context *arg1 = (struct ldb_context *) 0 ;
+ void *argp1 = 0 ;
+ int res1 = 0 ;
+ PyObject * obj0 = 0 ;
+ char * kwnames[] = {
+ (char *) "ldb", NULL
+ };
+ int result;
+
+ if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O:dsdb_set_global_schema",kwnames,&obj0)) SWIG_fail;
+ res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ldb_context, 0 | 0 );
+ if (!SWIG_IsOK(res1)) {
+ SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "dsdb_set_global_schema" "', argument " "1"" of type '" "struct ldb_context *""'");
+ }
+ arg1 = (struct ldb_context *)(argp1);
+ if (arg1 == NULL)
+ SWIG_exception(SWIG_ValueError,
+ "ldb context must be non-NULL");
+ result = (int)dsdb_set_global_schema(arg1);
+ resultobj = SWIG_From_int((int)(result));
+ return resultobj;
+fail:
+ return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ldb_register_samba_handlers(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+ PyObject *resultobj = 0;
+ struct ldb_context *arg1 = (struct ldb_context *) 0 ;
+ void *argp1 = 0 ;
+ int res1 = 0 ;
+ PyObject * obj0 = 0 ;
+ char * kwnames[] = {
+ (char *) "ldb", NULL
+ };
+ int result;
+
+ if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O:ldb_register_samba_handlers",kwnames,&obj0)) SWIG_fail;
+ res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ldb_context, 0 | 0 );
+ if (!SWIG_IsOK(res1)) {
+ SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ldb_register_samba_handlers" "', argument " "1"" of type '" "struct ldb_context *""'");
+ }
+ arg1 = (struct ldb_context *)(argp1);
+ if (arg1 == NULL)
+ SWIG_exception(SWIG_ValueError,
+ "ldb context must be non-NULL");
+ result = (int)ldb_register_samba_handlers(arg1);
+ resultobj = SWIG_From_int((int)(result));
+ return resultobj;
+fail:
+ return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_dsdb_set_ntds_invocation_id(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+ PyObject *resultobj = 0;
+ struct ldb_context *arg1 = (struct ldb_context *) 0 ;
+ char *arg2 = (char *) 0 ;
+ void *argp1 = 0 ;
+ int res1 = 0 ;
+ int res2 ;
+ char *buf2 = 0 ;
+ int alloc2 = 0 ;
+ PyObject * obj0 = 0 ;
+ PyObject * obj1 = 0 ;
+ char * kwnames[] = {
+ (char *) "ldb",(char *) "guid", NULL
+ };
+ bool result;
+
+ if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO:dsdb_set_ntds_invocation_id",kwnames,&obj0,&obj1)) SWIG_fail;
+ res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ldb_context, 0 | 0 );
+ if (!SWIG_IsOK(res1)) {
+ SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "dsdb_set_ntds_invocation_id" "', argument " "1"" of type '" "struct ldb_context *""'");
+ }
+ arg1 = (struct ldb_context *)(argp1);
+ res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+ if (!SWIG_IsOK(res2)) {
+ SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "dsdb_set_ntds_invocation_id" "', argument " "2"" of type '" "char const *""'");
+ }
+ arg2 = (char *)(buf2);
+ if (arg1 == NULL)
+ SWIG_exception(SWIG_ValueError,
+ "ldb context must be non-NULL");
+ result = (bool)dsdb_set_ntds_invocation_id(arg1,(char const *)arg2);
+ resultobj = SWIG_From_bool((bool)(result));
+ if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+ return resultobj;
+fail:
+ if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+ return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_private_path(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+ PyObject *resultobj = 0;
+ TALLOC_CTX *arg1 = (TALLOC_CTX *) 0 ;
+ struct loadparm_context *arg2 = (struct loadparm_context *) 0 ;
+ char *arg3 = (char *) 0 ;
+ void *argp2 = 0 ;
+ int res2 = 0 ;
+ int res3 ;
+ char *buf3 = 0 ;
+ int alloc3 = 0 ;
+ PyObject * obj0 = 0 ;
+ PyObject * obj1 = 0 ;
+ char * kwnames[] = {
+ (char *) "lp_ctx",(char *) "name", NULL
+ };
+ char *result = 0 ;
+
+ arg2 = loadparm_init(NULL);
+ arg1 = NULL;
+ if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"|OO:private_path",kwnames,&obj0,&obj1)) SWIG_fail;
+ if (obj0) {
+ res2 = SWIG_ConvertPtr(obj0, &argp2,SWIGTYPE_p_loadparm_context, 0 | 0 );
+ if (!SWIG_IsOK(res2)) {
+ SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "private_path" "', argument " "2"" of type '" "struct loadparm_context *""'");
+ }
+ arg2 = (struct loadparm_context *)(argp2);
+ }
+ if (obj1) {
+ res3 = SWIG_AsCharPtrAndSize(obj1, &buf3, NULL, &alloc3);
+ if (!SWIG_IsOK(res3)) {
+ SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "private_path" "', argument " "3"" of type '" "char const *""'");
+ }
+ arg3 = (char *)(buf3);
+ }
+ result = (char *)private_path(arg1,arg2,(char const *)arg3);
+ resultobj = SWIG_FromCharPtr((const char *)result);
+ if (alloc3 == SWIG_NEWOBJ) free((char*)buf3);
+ return resultobj;
+fail:
+ if (alloc3 == SWIG_NEWOBJ) free((char*)buf3);
+ return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_unix2nttime(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+ PyObject *resultobj = 0;
+ time_t arg1 ;
+ unsigned long val1 ;
+ int ecode1 = 0 ;
+ PyObject * obj0 = 0 ;
+ char * kwnames[] = {
+ (char *) "t", NULL
+ };
+ uint64_t result;
+
+ if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O:unix2nttime",kwnames,&obj0)) SWIG_fail;
+ ecode1 = SWIG_AsVal_unsigned_SS_long(obj0, &val1);
+ if (!SWIG_IsOK(ecode1)) {
+ SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "unix2nttime" "', argument " "1"" of type '" "time_t""'");
+ }
+ arg1 = (time_t)(val1);
+ result = (uint64_t)unix2nttime(arg1);
+ resultobj = SWIG_From_unsigned_SS_long_SS_long((unsigned long long)(result));
+ return resultobj;
+fail:
+ return NULL;
+}
+
+
+static PyMethodDef SwigMethods[] = {
+ { (char *)"random_password", (PyCFunction) _wrap_random_password, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+ "S.random_password(len) -> string\n"
+ "Generate random password with specified length.\n"
+ ""},
+ { (char *)"ldb_set_credentials", (PyCFunction) _wrap_ldb_set_credentials, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+ "S.set_credentials(credentials)\n"
+ "Set credentials to use when connecting.\n"
+ ""},
+ { (char *)"ldb_set_session_info", (PyCFunction) _wrap_ldb_set_session_info, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+ "S.set_session_info(session_info)\n"
+ "Set session info to use when connecting.\n"
+ ""},
+ { (char *)"ldb_set_loadparm", (PyCFunction) _wrap_ldb_set_loadparm, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+ "S.set_loadparm(session_info)\n"
+ "Set loadparm context to use when connecting.\n"
+ ""},
+ { (char *)"samdb_set_domain_sid", (PyCFunction) _wrap_samdb_set_domain_sid, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+ "S.set_domain_sid(sid)\n"
+ "Set SID of domain to use.\n"
+ ""},
+ { (char *)"dsdb_attach_schema_from_ldif_file", (PyCFunction) _wrap_dsdb_attach_schema_from_ldif_file, METH_VARARGS | METH_KEYWORDS, NULL},
+ { (char *)"version", (PyCFunction)_wrap_version, METH_NOARGS, (char *)"\n"
+ "version()\n"
+ "Obtain the Samba version.\n"
+ ""},
+ { (char *)"dsdb_set_global_schema", (PyCFunction) _wrap_dsdb_set_global_schema, METH_VARARGS | METH_KEYWORDS, NULL},
+ { (char *)"ldb_register_samba_handlers", (PyCFunction) _wrap_ldb_register_samba_handlers, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+ "register_samba_handlers()\n"
+ "Register Samba-specific LDB modules and schemas.\n"
+ ""},
+ { (char *)"dsdb_set_ntds_invocation_id", (PyCFunction) _wrap_dsdb_set_ntds_invocation_id, METH_VARARGS | METH_KEYWORDS, NULL},
+ { (char *)"private_path", (PyCFunction) _wrap_private_path, METH_VARARGS | METH_KEYWORDS, NULL},
+ { (char *)"unix2nttime", (PyCFunction) _wrap_unix2nttime, METH_VARARGS | METH_KEYWORDS, NULL},
+ { NULL, NULL, 0, NULL }
+};
+
+
+/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */
+
+static swig_type_info _swigt__p_TALLOC_CTX = {"_p_TALLOC_CTX", "TALLOC_CTX *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_auth_session_info = {"_p_auth_session_info", "struct auth_session_info *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_char = {"_p_char", "char *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_cli_credentials = {"_p_cli_credentials", "struct cli_credentials *|cli_credentials *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_dom_sid = {"_p_dom_sid", "struct dom_sid *|dom_sid *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_int = {"_p_int", "intptr_t *|int *|int_least32_t *|int_fast32_t *|int32_t *|int_fast16_t *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_ldb_context = {"_p_ldb_context", "struct ldb_context *|ldb *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_ldb_dn = {"_p_ldb_dn", "struct ldb_dn *|ldb_dn *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_ldb_ldif = {"_p_ldb_ldif", "struct ldb_ldif *|ldb_ldif *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_ldb_message = {"_p_ldb_message", "ldb_msg *|struct ldb_message *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_ldb_message_element = {"_p_ldb_message_element", "struct ldb_message_element *|ldb_message_element *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_ldb_result = {"_p_ldb_result", "struct ldb_result *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_loadparm_context = {"_p_loadparm_context", "struct loadparm_context *|loadparm_context *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_loadparm_service = {"_p_loadparm_service", "struct loadparm_service *|loadparm_service *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_long_long = {"_p_long_long", "int_least64_t *|int_fast64_t *|int64_t *|long long *|intmax_t *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_param_context = {"_p_param_context", "struct param_context *|param *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_param_opt = {"_p_param_opt", "struct param_opt *|param_opt *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_param_section = {"_p_param_section", "struct param_section *|param_section *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_security_descriptor = {"_p_security_descriptor", "struct security_descriptor *|security_descriptor *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_security_token = {"_p_security_token", "struct security_token *|security_token *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_short = {"_p_short", "short *|int_least16_t *|int16_t *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_signed_char = {"_p_signed_char", "signed char *|int_least8_t *|int_fast8_t *|int8_t *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_unsigned_char = {"_p_unsigned_char", "unsigned char *|uint_least8_t *|uint_fast8_t *|uint8_t *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_unsigned_int = {"_p_unsigned_int", "uintptr_t *|uint_least32_t *|uint_fast32_t *|uint32_t *|unsigned int *|uint_fast16_t *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_unsigned_long = {"_p_unsigned_long", "unsigned long *|time_t *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_unsigned_long_long = {"_p_unsigned_long_long", "uint_least64_t *|uint_fast64_t *|uint64_t *|unsigned long long *|uintmax_t *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_unsigned_short = {"_p_unsigned_short", "unsigned short *|uint_least16_t *|uint16_t *", 0, 0, (void*)0, 0};
+
+static swig_type_info *swig_type_initial[] = {
+ &_swigt__p_TALLOC_CTX,
+ &_swigt__p_auth_session_info,
+ &_swigt__p_char,
+ &_swigt__p_cli_credentials,
+ &_swigt__p_dom_sid,
+ &_swigt__p_int,
+ &_swigt__p_ldb_context,
+ &_swigt__p_ldb_dn,
+ &_swigt__p_ldb_ldif,
+ &_swigt__p_ldb_message,
+ &_swigt__p_ldb_message_element,
+ &_swigt__p_ldb_result,
+ &_swigt__p_loadparm_context,
+ &_swigt__p_loadparm_service,
+ &_swigt__p_long_long,
+ &_swigt__p_param_context,
+ &_swigt__p_param_opt,
+ &_swigt__p_param_section,
+ &_swigt__p_security_descriptor,
+ &_swigt__p_security_token,
+ &_swigt__p_short,
+ &_swigt__p_signed_char,
+ &_swigt__p_unsigned_char,
+ &_swigt__p_unsigned_int,
+ &_swigt__p_unsigned_long,
+ &_swigt__p_unsigned_long_long,
+ &_swigt__p_unsigned_short,
+};
+
+static swig_cast_info _swigc__p_TALLOC_CTX[] = { {&_swigt__p_TALLOC_CTX, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_auth_session_info[] = { {&_swigt__p_auth_session_info, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_char[] = { {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_cli_credentials[] = { {&_swigt__p_cli_credentials, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_dom_sid[] = { {&_swigt__p_dom_sid, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_int[] = { {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_ldb_context[] = { {&_swigt__p_ldb_context, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_ldb_dn[] = { {&_swigt__p_ldb_dn, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_ldb_ldif[] = { {&_swigt__p_ldb_ldif, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_ldb_message[] = { {&_swigt__p_ldb_message, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_ldb_message_element[] = { {&_swigt__p_ldb_message_element, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_ldb_result[] = { {&_swigt__p_ldb_result, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_loadparm_context[] = { {&_swigt__p_loadparm_context, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_loadparm_service[] = { {&_swigt__p_loadparm_service, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_long_long[] = { {&_swigt__p_long_long, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_param_context[] = { {&_swigt__p_param_context, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_param_opt[] = { {&_swigt__p_param_opt, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_param_section[] = { {&_swigt__p_param_section, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_security_descriptor[] = { {&_swigt__p_security_descriptor, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_security_token[] = { {&_swigt__p_security_token, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_short[] = { {&_swigt__p_short, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_signed_char[] = { {&_swigt__p_signed_char, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_unsigned_char[] = { {&_swigt__p_unsigned_char, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_unsigned_int[] = { {&_swigt__p_unsigned_int, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_unsigned_long[] = { {&_swigt__p_unsigned_long, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_unsigned_long_long[] = { {&_swigt__p_unsigned_long_long, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_unsigned_short[] = { {&_swigt__p_unsigned_short, 0, 0, 0},{0, 0, 0, 0}};
+
+static swig_cast_info *swig_cast_initial[] = {
+ _swigc__p_TALLOC_CTX,
+ _swigc__p_auth_session_info,
+ _swigc__p_char,
+ _swigc__p_cli_credentials,
+ _swigc__p_dom_sid,
+ _swigc__p_int,
+ _swigc__p_ldb_context,
+ _swigc__p_ldb_dn,
+ _swigc__p_ldb_ldif,
+ _swigc__p_ldb_message,
+ _swigc__p_ldb_message_element,
+ _swigc__p_ldb_result,
+ _swigc__p_loadparm_context,
+ _swigc__p_loadparm_service,
+ _swigc__p_long_long,
+ _swigc__p_param_context,
+ _swigc__p_param_opt,
+ _swigc__p_param_section,
+ _swigc__p_security_descriptor,
+ _swigc__p_security_token,
+ _swigc__p_short,
+ _swigc__p_signed_char,
+ _swigc__p_unsigned_char,
+ _swigc__p_unsigned_int,
+ _swigc__p_unsigned_long,
+ _swigc__p_unsigned_long_long,
+ _swigc__p_unsigned_short,
+};
+
+
+/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */
+
+static swig_const_info swig_const_table[] = {
+{0, 0, 0, 0.0, 0, 0}};
+
+#ifdef __cplusplus
+}
+#endif
+/* -----------------------------------------------------------------------------
+ * Type initialization:
+ * This problem is tough by the requirement that no dynamic
+ * memory is used. Also, since swig_type_info structures store pointers to
+ * swig_cast_info structures and swig_cast_info structures store pointers back
+ * to swig_type_info structures, we need some lookup code at initialization.
+ * The idea is that swig generates all the structures that are needed.
+ * The runtime then collects these partially filled structures.
+ * The SWIG_InitializeModule function takes these initial arrays out of
+ * swig_module, and does all the lookup, filling in the swig_module.types
+ * array with the correct data and linking the correct swig_cast_info
+ * structures together.
+ *
+ * The generated swig_type_info structures are assigned staticly to an initial
+ * array. We just loop through that array, and handle each type individually.
+ * First we lookup if this type has been already loaded, and if so, use the
+ * loaded structure instead of the generated one. Then we have to fill in the
+ * cast linked list. The cast data is initially stored in something like a
+ * two-dimensional array. Each row corresponds to a type (there are the same
+ * number of rows as there are in the swig_type_initial array). Each entry in
+ * a column is one of the swig_cast_info structures for that type.
+ * The cast_initial array is actually an array of arrays, because each row has
+ * a variable number of columns. So to actually build the cast linked list,
+ * we find the array of casts associated with the type, and loop through it
+ * adding the casts to the list. The one last trick we need to do is making
+ * sure the type pointer in the swig_cast_info struct is correct.
+ *
+ * First off, we lookup the cast->type name to see if it is already loaded.
+ * There are three cases to handle:
+ * 1) If the cast->type has already been loaded AND the type we are adding
+ * casting info to has not been loaded (it is in this module), THEN we
+ * replace the cast->type pointer with the type pointer that has already
+ * been loaded.
+ * 2) If BOTH types (the one we are adding casting info to, and the
+ * cast->type) are loaded, THEN the cast info has already been loaded by
+ * the previous module so we just ignore it.
+ * 3) Finally, if cast->type has not already been loaded, then we add that
+ * swig_cast_info to the linked list (because the cast->type) pointer will
+ * be correct.
+ * ----------------------------------------------------------------------------- */
+
+#ifdef __cplusplus
+extern "C" {
+#if 0
+} /* c-mode */
+#endif
+#endif
+
+#if 0
+#define SWIGRUNTIME_DEBUG
+#endif
+
+
+SWIGRUNTIME void
+SWIG_InitializeModule(void *clientdata) {
+ size_t i;
+ swig_module_info *module_head, *iter;
+ int found, init;
+
+ clientdata = clientdata;
+
+ /* check to see if the circular list has been setup, if not, set it up */
+ if (swig_module.next==0) {
+ /* Initialize the swig_module */
+ swig_module.type_initial = swig_type_initial;
+ swig_module.cast_initial = swig_cast_initial;
+ swig_module.next = &swig_module;
+ init = 1;
+ } else {
+ init = 0;
+ }
+
+ /* Try and load any already created modules */
+ module_head = SWIG_GetModule(clientdata);
+ if (!module_head) {
+ /* This is the first module loaded for this interpreter */
+ /* so set the swig module into the interpreter */
+ SWIG_SetModule(clientdata, &swig_module);
+ module_head = &swig_module;
+ } else {
+ /* the interpreter has loaded a SWIG module, but has it loaded this one? */
+ found=0;
+ iter=module_head;
+ do {
+ if (iter==&swig_module) {
+ found=1;
+ break;
+ }
+ iter=iter->next;
+ } while (iter!= module_head);
+
+ /* if the is found in the list, then all is done and we may leave */
+ if (found) return;
+ /* otherwise we must add out module into the list */
+ swig_module.next = module_head->next;
+ module_head->next = &swig_module;
+ }
+
+ /* When multiple interpeters are used, a module could have already been initialized in
+ a different interpreter, but not yet have a pointer in this interpreter.
+ In this case, we do not want to continue adding types... everything should be
+ set up already */
+ if (init == 0) return;
+
+ /* Now work on filling in swig_module.types */
+#ifdef SWIGRUNTIME_DEBUG
+ printf("SWIG_InitializeModule: size %d\n", swig_module.size);
+#endif
+ for (i = 0; i < swig_module.size; ++i) {
+ swig_type_info *type = 0;
+ swig_type_info *ret;
+ swig_cast_info *cast;
+
+#ifdef SWIGRUNTIME_DEBUG
+ printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name);
+#endif
+
+ /* if there is another module already loaded */
+ if (swig_module.next != &swig_module) {
+ type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name);
+ }
+ if (type) {
+ /* Overwrite clientdata field */
+#ifdef SWIGRUNTIME_DEBUG
+ printf("SWIG_InitializeModule: found type %s\n", type->name);
+#endif
+ if (swig_module.type_initial[i]->clientdata) {
+ type->clientdata = swig_module.type_initial[i]->clientdata;
+#ifdef SWIGRUNTIME_DEBUG
+ printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name);
+#endif
+ }
+ } else {
+ type = swig_module.type_initial[i];
+ }
+
+ /* Insert casting types */
+ cast = swig_module.cast_initial[i];
+ while (cast->type) {
+ /* Don't need to add information already in the list */
+ ret = 0;
+#ifdef SWIGRUNTIME_DEBUG
+ printf("SWIG_InitializeModule: look cast %s\n", cast->type->name);
+#endif
+ if (swig_module.next != &swig_module) {
+ ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name);
+#ifdef SWIGRUNTIME_DEBUG
+ if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name);
+#endif
+ }
+ if (ret) {
+ if (type == swig_module.type_initial[i]) {
+#ifdef SWIGRUNTIME_DEBUG
+ printf("SWIG_InitializeModule: skip old type %s\n", ret->name);
+#endif
+ cast->type = ret;
+ ret = 0;
+ } else {
+ /* Check for casting already in the list */
+ swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type);
+#ifdef SWIGRUNTIME_DEBUG
+ if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name);
+#endif
+ if (!ocast) ret = 0;
+ }
+ }
+
+ if (!ret) {
+#ifdef SWIGRUNTIME_DEBUG
+ printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name);
+#endif
+ if (type->cast) {
+ type->cast->prev = cast;
+ cast->next = type->cast;
+ }
+ type->cast = cast;
+ }
+ cast++;
+ }
+ /* Set entry in modules->types array equal to the type */
+ swig_module.types[i] = type;
+ }
+ swig_module.types[i] = 0;
+
+#ifdef SWIGRUNTIME_DEBUG
+ printf("**** SWIG_InitializeModule: Cast List ******\n");
+ for (i = 0; i < swig_module.size; ++i) {
+ int j = 0;
+ swig_cast_info *cast = swig_module.cast_initial[i];
+ printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name);
+ while (cast->type) {
+ printf("SWIG_InitializeModule: cast type %s\n", cast->type->name);
+ cast++;
+ ++j;
+ }
+ printf("---- Total casts: %d\n",j);
+ }
+ printf("**** SWIG_InitializeModule: Cast List ******\n");
+#endif
+}
+
+/* This function will propagate the clientdata field of type to
+* any new swig_type_info structures that have been added into the list
+* of equivalent types. It is like calling
+* SWIG_TypeClientData(type, clientdata) a second time.
+*/
+SWIGRUNTIME void
+SWIG_PropagateClientData(void) {
+ size_t i;
+ swig_cast_info *equiv;
+ static int init_run = 0;
+
+ if (init_run) return;
+ init_run = 1;
+
+ for (i = 0; i < swig_module.size; i++) {
+ if (swig_module.types[i]->clientdata) {
+ equiv = swig_module.types[i]->cast;
+ while (equiv) {
+ if (!equiv->converter) {
+ if (equiv->type && !equiv->type->clientdata)
+ SWIG_TypeClientData(equiv->type, swig_module.types[i]->clientdata);
+ }
+ equiv = equiv->next;
+ }
+ }
+ }
+}
+
+#ifdef __cplusplus
+#if 0
+{
+ /* c-mode */
+#endif
+}
+#endif
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /* Python-specific SWIG API */
+#define SWIG_newvarlink() SWIG_Python_newvarlink()
+#define SWIG_addvarlink(p, name, get_attr, set_attr) SWIG_Python_addvarlink(p, name, get_attr, set_attr)
+#define SWIG_InstallConstants(d, constants) SWIG_Python_InstallConstants(d, constants)
+
+ /* -----------------------------------------------------------------------------
+ * global variable support code.
+ * ----------------------------------------------------------------------------- */
+
+ typedef struct swig_globalvar {
+ char *name; /* Name of global variable */
+ PyObject *(*get_attr)(void); /* Return the current value */
+ int (*set_attr)(PyObject *); /* Set the value */
+ struct swig_globalvar *next;
+ } swig_globalvar;
+
+ typedef struct swig_varlinkobject {
+ PyObject_HEAD
+ swig_globalvar *vars;
+ } swig_varlinkobject;
+
+ SWIGINTERN PyObject *
+ swig_varlink_repr(swig_varlinkobject *SWIGUNUSEDPARM(v)) {
+ return PyString_FromString("<Swig global variables>");
+ }
+
+ SWIGINTERN PyObject *
+ swig_varlink_str(swig_varlinkobject *v) {
+ PyObject *str = PyString_FromString("(");
+ swig_globalvar *var;
+ for (var = v->vars; var; var=var->next) {
+ PyString_ConcatAndDel(&str,PyString_FromString(var->name));
+ if (var->next) PyString_ConcatAndDel(&str,PyString_FromString(", "));
+ }
+ PyString_ConcatAndDel(&str,PyString_FromString(")"));
+ return str;
+ }
+
+ SWIGINTERN int
+ swig_varlink_print(swig_varlinkobject *v, FILE *fp, int SWIGUNUSEDPARM(flags)) {
+ PyObject *str = swig_varlink_str(v);
+ fprintf(fp,"Swig global variables ");
+ fprintf(fp,"%s\n", PyString_AsString(str));
+ Py_DECREF(str);
+ return 0;
+ }
+
+ SWIGINTERN void
+ swig_varlink_dealloc(swig_varlinkobject *v) {
+ swig_globalvar *var = v->vars;
+ while (var) {
+ swig_globalvar *n = var->next;
+ free(var->name);
+ free(var);
+ var = n;
+ }
+ }
+
+ SWIGINTERN PyObject *
+ swig_varlink_getattr(swig_varlinkobject *v, char *n) {
+ PyObject *res = NULL;
+ swig_globalvar *var = v->vars;
+ while (var) {
+ if (strcmp(var->name,n) == 0) {
+ res = (*var->get_attr)();
+ break;
+ }
+ var = var->next;
+ }
+ if (res == NULL && !PyErr_Occurred()) {
+ PyErr_SetString(PyExc_NameError,"Unknown C global variable");
+ }
+ return res;
+ }
+
+ SWIGINTERN int
+ swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) {
+ int res = 1;
+ swig_globalvar *var = v->vars;
+ while (var) {
+ if (strcmp(var->name,n) == 0) {
+ res = (*var->set_attr)(p);
+ break;
+ }
+ var = var->next;
+ }
+ if (res == 1 && !PyErr_Occurred()) {
+ PyErr_SetString(PyExc_NameError,"Unknown C global variable");
+ }
+ return res;
+ }
+
+ SWIGINTERN PyTypeObject*
+ swig_varlink_type(void) {
+ static char varlink__doc__[] = "Swig var link object";
+ static PyTypeObject varlink_type;
+ static int type_init = 0;
+ if (!type_init) {
+ const PyTypeObject tmp
+ = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /* Number of items in variable part (ob_size) */
+ (char *)"swigvarlink", /* Type name (tp_name) */
+ sizeof(swig_varlinkobject), /* Basic size (tp_basicsize) */
+ 0, /* Itemsize (tp_itemsize) */
+ (destructor) swig_varlink_dealloc, /* Deallocator (tp_dealloc) */
+ (printfunc) swig_varlink_print, /* Print (tp_print) */
+ (getattrfunc) swig_varlink_getattr, /* get attr (tp_getattr) */
+ (setattrfunc) swig_varlink_setattr, /* Set attr (tp_setattr) */
+ 0, /* tp_compare */
+ (reprfunc) swig_varlink_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ (reprfunc)swig_varlink_str, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ 0, /* tp_flags */
+ varlink__doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+#if PY_VERSION_HEX >= 0x02020000
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* tp_iter -> tp_weaklist */
+#endif
+#if PY_VERSION_HEX >= 0x02030000
+ 0, /* tp_del */
+#endif
+#ifdef COUNT_ALLOCS
+ 0,0,0,0 /* tp_alloc -> tp_next */
+#endif
+ };
+ varlink_type = tmp;
+ varlink_type.ob_type = &PyType_Type;
+ type_init = 1;
+ }
+ return &varlink_type;
+ }
+
+ /* Create a variable linking object for use later */
+ SWIGINTERN PyObject *
+ SWIG_Python_newvarlink(void) {
+ swig_varlinkobject *result = PyObject_NEW(swig_varlinkobject, swig_varlink_type());
+ if (result) {
+ result->vars = 0;
+ }
+ return ((PyObject*) result);
+ }
+
+ SWIGINTERN void
+ SWIG_Python_addvarlink(PyObject *p, char *name, PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) {
+ swig_varlinkobject *v = (swig_varlinkobject *) p;
+ swig_globalvar *gv = (swig_globalvar *) malloc(sizeof(swig_globalvar));
+ if (gv) {
+ size_t size = strlen(name)+1;
+ gv->name = (char *)malloc(size);
+ if (gv->name) {
+ strncpy(gv->name,name,size);
+ gv->get_attr = get_attr;
+ gv->set_attr = set_attr;
+ gv->next = v->vars;
+ }
+ }
+ v->vars = gv;
+ }
+
+ SWIGINTERN PyObject *
+ SWIG_globals(void) {
+ static PyObject *_SWIG_globals = 0;
+ if (!_SWIG_globals) _SWIG_globals = SWIG_newvarlink();
+ return _SWIG_globals;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * constants/methods manipulation
+ * ----------------------------------------------------------------------------- */
+
+ /* Install Constants */
+ SWIGINTERN void
+ SWIG_Python_InstallConstants(PyObject *d, swig_const_info constants[]) {
+ PyObject *obj = 0;
+ size_t i;
+ for (i = 0; constants[i].type; ++i) {
+ switch(constants[i].type) {
+ case SWIG_PY_POINTER:
+ obj = SWIG_NewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0);
+ break;
+ case SWIG_PY_BINARY:
+ obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype));
+ break;
+ default:
+ obj = 0;
+ break;
+ }
+ if (obj) {
+ PyDict_SetItemString(d, constants[i].name, obj);
+ Py_DECREF(obj);
+ }
+ }
+ }
+
+ /* -----------------------------------------------------------------------------*/
+ /* Fix SwigMethods to carry the callback ptrs when needed */
+ /* -----------------------------------------------------------------------------*/
+
+ SWIGINTERN void
+ SWIG_Python_FixMethods(PyMethodDef *methods,
+ swig_const_info *const_table,
+ swig_type_info **types,
+ swig_type_info **types_initial) {
+ size_t i;
+ for (i = 0; methods[i].ml_name; ++i) {
+ const char *c = methods[i].ml_doc;
+ if (c && (c = strstr(c, "swig_ptr: "))) {
+ int j;
+ swig_const_info *ci = 0;
+ const char *name = c + 10;
+ for (j = 0; const_table[j].type; ++j) {
+ if (strncmp(const_table[j].name, name,
+ strlen(const_table[j].name)) == 0) {
+ ci = &(const_table[j]);
+ break;
+ }
+ }
+ if (ci) {
+ size_t shift = (ci->ptype) - types;
+ swig_type_info *ty = types_initial[shift];
+ size_t ldoc = (c - methods[i].ml_doc);
+ size_t lptr = strlen(ty->name)+2*sizeof(void*)+2;
+ char *ndoc = (char*)malloc(ldoc + lptr + 10);
+ if (ndoc) {
+ char *buff = ndoc;
+ void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0;
+ if (ptr) {
+ strncpy(buff, methods[i].ml_doc, ldoc);
+ buff += ldoc;
+ strncpy(buff, "swig_ptr: ", 10);
+ buff += 10;
+ SWIG_PackVoidPtr(buff, ptr, ty->name, lptr);
+ methods[i].ml_doc = ndoc;
+ }
+ }
+ }
+ }
+ }
+ }
+
+#ifdef __cplusplus
+}
+#endif
+
+/* -----------------------------------------------------------------------------*
+ * Partial Init method
+ * -----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+#endif
+SWIGEXPORT void SWIG_init(void) {
+ PyObject *m, *d;
+
+ /* Fix SwigMethods to carry the callback ptrs when needed */
+ SWIG_Python_FixMethods(SwigMethods, swig_const_table, swig_types, swig_type_initial);
+
+ m = Py_InitModule((char *) SWIG_name, SwigMethods);
+ d = PyModule_GetDict(m);
+
+ SWIG_InitializeModule(0);
+ SWIG_InstallConstants(d,swig_const_table);
+
+
+}
+
diff --git a/source4/scripting/python/modules.c b/source4/scripting/python/modules.c
new file mode 100644
index 0000000000..0fe15b2fda
--- /dev/null
+++ b/source4/scripting/python/modules.c
@@ -0,0 +1,69 @@
+/*
+ Unix SMB/CIFS implementation.
+ Samba utility functions
+ Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include <Python.h>
+
+extern void init_ldb(void);
+extern void init_security(void);
+extern void init_registry(void);
+extern void init_param(void);
+extern void init_misc(void);
+extern void init_ldb(void);
+extern void init_auth(void);
+extern void init_credentials(void);
+extern void init_tdb(void);
+extern void init_dcerpc(void);
+extern void init_events(void);
+extern void inituuid(void);
+extern void init_net(void);
+extern void initecho(void);
+extern void initdfs(void);
+extern void initdrsuapi(void);
+extern void initwinreg(void);
+extern void initepmapper(void);
+extern void initinitshutdown(void);
+extern void initmgmt(void);
+extern void initnet(void);
+extern void initatsvc(void);
+extern void initsamr(void);
+extern void initlsa(void);
+extern void initsvcctl(void);
+extern void initwkssvc(void);
+extern void initunixinfo(void);
+extern void init_libcli_nbt(void);
+extern void init_libcli_smb(void);
+
+static struct _inittab py_modules[] = { STATIC_LIBPYTHON_MODULES };
+
+void py_load_samba_modules(void)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(py_modules); i++) {
+ PyImport_ExtendInittab(&py_modules[i]);
+ }
+}
+
+void py_update_path(const char *bindir)
+{
+ char *newpath;
+ asprintf(&newpath, "%s/python:%s/../scripting/python:%s", bindir, bindir, Py_GetPath());
+ PySys_SetPath(newpath);
+ free(newpath);
+}
diff --git a/source4/scripting/python/modules.h b/source4/scripting/python/modules.h
new file mode 100644
index 0000000000..238c73455f
--- /dev/null
+++ b/source4/scripting/python/modules.h
@@ -0,0 +1,26 @@
+/*
+ Unix SMB/CIFS implementation.
+ Samba utility functions
+ Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __SAMBA_PYTHON_MODULES_H__
+#define __SAMBA_PYTHON_MODULES_H__
+
+void py_load_samba_modules(void);
+void py_update_path(const char *bindir);
+
+#endif /* __SAMBA_PYTHON_MODULES_H__ */
diff --git a/source4/scripting/python/pytalloc.c b/source4/scripting/python/pytalloc.c
new file mode 100644
index 0000000000..ca476e9604
--- /dev/null
+++ b/source4/scripting/python/pytalloc.c
@@ -0,0 +1,52 @@
+/*
+ Unix SMB/CIFS implementation.
+ Python/Talloc glue
+ Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "scripting/python/pytalloc.h"
+
+void py_talloc_dealloc(PyObject* self)
+{
+ py_talloc_Object *obj = (py_talloc_Object *)self;
+ talloc_free(obj->talloc_ctx);
+ obj->talloc_ctx = NULL;
+ PyObject_Del(self);
+}
+
+PyObject *py_talloc_import_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx,
+ void *ptr)
+{
+ py_talloc_Object *ret = PyObject_New(py_talloc_Object, py_type);
+ ret->talloc_ctx = talloc_new(NULL);
+ if (ret->talloc_ctx == NULL) {
+ return NULL;
+ }
+ if (talloc_reference(ret->talloc_ctx, mem_ctx) == NULL) {
+ return NULL;
+ }
+ ret->ptr = ptr;
+ return (PyObject *)ret;
+}
+
+PyObject *py_talloc_default_repr(PyObject *py_obj)
+{
+ py_talloc_Object *obj = (py_talloc_Object *)py_obj;
+ PyTypeObject *type = (PyTypeObject*)PyObject_Type((PyObject *)obj);
+
+ return PyString_FromFormat("<%s talloc object at 0x%x>", type->tp_name, (intptr_t)py_obj);
+}
diff --git a/source4/scripting/python/pytalloc.h b/source4/scripting/python/pytalloc.h
new file mode 100644
index 0000000000..aad5840a67
--- /dev/null
+++ b/source4/scripting/python/pytalloc.h
@@ -0,0 +1,51 @@
+/*
+ Unix SMB/CIFS implementation.
+ Samba utility functions
+ Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _PY_TALLOC_H_
+#define _PY_TALLOC_H_
+
+#include <Python.h>
+
+typedef struct {
+ PyObject_HEAD
+ TALLOC_CTX *talloc_ctx;
+ void *ptr;
+} py_talloc_Object;
+
+/* Deallocate a py_talloc_Object */
+void py_talloc_dealloc(PyObject* self);
+
+/* Retrieve the pointer for a py_talloc_object. Like talloc_get_type()
+ * but for py_talloc_Objects. */
+
+/* FIXME: Call PyErr_SetString(PyExc_TypeError, "expected " __STR(type) ")
+ * when talloc_get_type() returns NULL. */
+#define py_talloc_get_type(py_obj, type) \
+ talloc_get_type(py_talloc_get_ptr(py_obj), type)
+
+#define py_talloc_get_ptr(py_obj) ((py_talloc_Object *)py_obj)->ptr
+#define py_talloc_get_mem_ctx(py_obj) ((py_talloc_Object *)py_obj)->talloc_ctx
+
+PyObject *py_talloc_import_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx, void *ptr);
+#define py_talloc_import(py_type, talloc_ptr) py_talloc_import_ex(py_type, talloc_ptr, talloc_ptr)
+
+/* Sane default implementation of reprfunc. */
+PyObject *py_talloc_default_repr(PyObject *py_obj);
+
+#endif /* _PY_TALLOC_H_ */
diff --git a/source4/scripting/python/samba/__init__.py b/source4/scripting/python/samba/__init__.py
new file mode 100644
index 0000000000..e191227108
--- /dev/null
+++ b/source4/scripting/python/samba/__init__.py
@@ -0,0 +1,238 @@
+#!/usr/bin/python
+
+# Unix SMB/CIFS implementation.
+# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008
+#
+# Based on the original in EJS:
+# Copyright (C) Andrew Tridgell <tridge@samba.org> 2005
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+"""Samba 4."""
+
+__docformat__ = "restructuredText"
+
+import os
+
+def _in_source_tree():
+ """Check whether the script is being run from the source dir. """
+ return os.path.exists("%s/../../../samba4-skip" % os.path.dirname(__file__))
+
+
+# When running, in-tree, make sure bin/python is in the PYTHONPATH
+if _in_source_tree():
+ import sys
+ srcdir = "%s/../../.." % os.path.dirname(__file__)
+ sys.path.append("%s/bin/python" % srcdir)
+ default_ldb_modules_dir = "%s/bin/modules/ldb" % srcdir
+else:
+ default_ldb_modules_dir = None
+
+
+import ldb
+import credentials
+import misc
+
+class Ldb(ldb.Ldb):
+ """Simple Samba-specific LDB subclass that takes care
+ of setting up the modules dir, credentials pointers, etc.
+
+ Please note that this is intended to be for all Samba LDB files,
+ not necessarily the Sam database. For Sam-specific helper
+ functions see samdb.py.
+ """
+ def __init__(self, url=None, session_info=None, credentials=None,
+ modules_dir=None, lp=None):
+ """Open a Samba Ldb file.
+
+ :param url: Optional LDB URL to open
+ :param session_info: Optional session information
+ :param credentials: Optional credentials, defaults to anonymous.
+ :param modules_dir: Modules directory, if not the default.
+ :param lp: Loadparm object, optional.
+
+ This is different from a regular Ldb file in that the Samba-specific
+ modules-dir is used by default and that credentials and session_info
+ can be passed through (required by some modules).
+ """
+ super(Ldb, self).__init__()
+
+ if modules_dir is not None:
+ self.set_modules_dir(modules_dir)
+ elif default_ldb_modules_dir is not None:
+ self.set_modules_dir(default_ldb_modules_dir)
+
+ if credentials is not None:
+ self.set_credentials(credentials)
+
+ if session_info is not None:
+ self.set_session_info(session_info)
+
+ assert misc.ldb_register_samba_handlers(self) == 0
+
+ if lp is not None:
+ self.set_loadparm(lp)
+
+ def msg(l,text):
+ print text
+ #self.set_debug(msg)
+
+ if url is not None:
+ self.connect(url)
+
+
+ set_credentials = misc.ldb_set_credentials
+ set_session_info = misc.ldb_set_session_info
+ set_loadparm = misc.ldb_set_loadparm
+
+ def searchone(self, attribute, basedn=None, expression=None,
+ scope=ldb.SCOPE_BASE):
+ """Search for one attribute as a string.
+
+ :param basedn: BaseDN for the search.
+ :param attribute: Name of the attribute
+ :param expression: Optional search expression.
+ :param scope: Search scope (defaults to base).
+ :return: Value of attribute as a string or None if it wasn't found.
+ """
+ res = self.search(basedn, scope, expression, [attribute])
+ if len(res) != 1 or res[0][attribute] is None:
+ return None
+ values = set(res[0][attribute])
+ assert len(values) == 1
+ return self.schema_format_value(attribute, values.pop())
+
+ def erase(self):
+ """Erase this ldb, removing all records."""
+ # delete the specials
+ for attr in ["@INDEXLIST", "@ATTRIBUTES", "@SUBCLASSES", "@MODULES",
+ "@OPTIONS", "@PARTITION", "@KLUDGEACL"]:
+ try:
+ self.delete(attr)
+ except ldb.LdbError, (LDB_ERR_NO_SUCH_OBJECT, _):
+ # Ignore missing dn errors
+ pass
+
+ basedn = ""
+ # and the rest
+ for msg in self.search(basedn, ldb.SCOPE_SUBTREE,
+ "(&(|(objectclass=*)(distinguishedName=*))(!(distinguishedName=@BASEINFO)))",
+ ["distinguishedName"]):
+ try:
+ self.delete(msg.dn)
+ except ldb.LdbError, (LDB_ERR_NO_SUCH_OBJECT, _):
+ # Ignore no such object errors
+ pass
+
+ res = self.search(basedn, ldb.SCOPE_SUBTREE, "(&(|(objectclass=*)(distinguishedName=*))(!(distinguishedName=@BASEINFO)))", ["distinguishedName"])
+ assert len(res) == 0
+
+ def erase_partitions(self):
+ """Erase an ldb, removing all records."""
+ res = self.search("", ldb.SCOPE_BASE, "(objectClass=*)",
+ ["namingContexts"])
+ assert len(res) == 1
+ if not "namingContexts" in res[0]:
+ return
+ for basedn in res[0]["namingContexts"]:
+ previous_remaining = 1
+ current_remaining = 0
+
+ k = 0
+ while ++k < 10 and (previous_remaining != current_remaining):
+ # and the rest
+ try:
+ res2 = self.search(basedn, ldb.SCOPE_SUBTREE, "(|(objectclass=*)(distinguishedName=*))", ["distinguishedName"])
+ except ldb.LdbError, (LDB_ERR_NO_SUCH_OBJECT, _):
+ # Ignore missing dn errors
+ return
+
+ previous_remaining = current_remaining
+ current_remaining = len(res2)
+ for msg in res2:
+ try:
+ self.delete(msg.dn)
+ # Ignore no such object errors
+ except ldb.LdbError, (LDB_ERR_NO_SUCH_OBJECT, _):
+ pass
+ # Ignore not allowed on non leaf errors
+ except ldb.LdbError, (LDB_ERR_NOT_ALLOWED_ON_NON_LEAF, _):
+ pass
+
+ def load_ldif_file_add(self, ldif_path):
+ """Load a LDIF file.
+
+ :param ldif_path: Path to LDIF file.
+ """
+ self.add_ldif(open(ldif_path, 'r').read())
+
+ def add_ldif(self, ldif):
+ """Add data based on a LDIF string.
+
+ :param ldif: LDIF text.
+ """
+ for changetype, msg in self.parse_ldif(ldif):
+ assert changetype == ldb.CHANGETYPE_NONE
+ self.add(msg)
+
+ def modify_ldif(self, ldif):
+ """Modify database based on a LDIF string.
+
+ :param ldif: LDIF text.
+ """
+ for changetype, msg in self.parse_ldif(ldif):
+ self.modify(msg)
+
+
+def substitute_var(text, values):
+ """substitute strings of the form ${NAME} in str, replacing
+ with substitutions from subobj.
+
+ :param text: Text in which to subsitute.
+ :param values: Dictionary with keys and values.
+ """
+
+ for (name, value) in values.items():
+ assert isinstance(name, str), "%r is not a string" % name
+ assert isinstance(value, str), "Value %r for %s is not a string" % (value, name)
+ text = text.replace("${%s}" % name, value)
+
+ return text
+
+
+def check_all_substituted(text):
+ """Make sure that all substitution variables in a string have been replaced.
+ If not, raise an exception.
+
+ :param text: The text to search for substitution variables
+ """
+ if not "${" in text:
+ return
+
+ var_start = text.find("${")
+ var_end = text.find("}", var_start)
+
+ raise Exception("Not all variables substituted: %s" % text[var_start:var_end+1])
+
+
+def valid_netbios_name(name):
+ """Check whether a name is valid as a NetBIOS name. """
+ # FIXME: There are probably more constraints here.
+ # crh has a paragraph on this in his book (1.4.1.1)
+ if len(name) > 15:
+ return False
+ return True
+
+version = misc.version
diff --git a/source4/scripting/python/samba/getopt.py b/source4/scripting/python/samba/getopt.py
new file mode 100644
index 0000000000..c12245f6c5
--- /dev/null
+++ b/source4/scripting/python/samba/getopt.py
@@ -0,0 +1,116 @@
+#!/usr/bin/python
+
+# Samba-specific bits for optparse
+# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+"""Support for parsing Samba-related command-line options."""
+
+import optparse
+from credentials import Credentials, AUTO_USE_KERBEROS, DONT_USE_KERBEROS, MUST_USE_KERBEROS
+from hostconfig import Hostconfig
+
+__docformat__ = "restructuredText"
+
+class SambaOptions(optparse.OptionGroup):
+ """General Samba-related command line options."""
+ def __init__(self, parser):
+ optparse.OptionGroup.__init__(self, parser, "Samba Common Options")
+ self.add_option("-s", "--configfile", action="callback",
+ type=str, metavar="FILE", help="Configuration file",
+ callback=self._load_configfile)
+ self._configfile = None
+
+ def get_loadparm_path(self):
+ """Return the path to the smb.conf file specified on the command line. """
+ return self._configfile
+
+ def _load_configfile(self, option, opt_str, arg, parser):
+ self._configfile = arg
+
+ def get_loadparm(self):
+ """Return a loadparm object with data specified on the command line. """
+ import os, param
+ lp = param.LoadParm()
+ if self._configfile is not None:
+ lp.load(self._configfile)
+ elif os.getenv("SMB_CONF_PATH") is not None:
+ lp.load(os.getenv("SMB_CONF_PATH"))
+ else:
+ lp.load_default()
+ return lp
+
+ def get_hostconfig(self):
+ return Hostconfig(self.get_loadparm())
+
+
+class VersionOptions(optparse.OptionGroup):
+ """Command line option for printing Samba version."""
+ def __init__(self, parser):
+ optparse.OptionGroup.__init__(self, parser, "Version Options")
+
+
+class CredentialsOptions(optparse.OptionGroup):
+ """Command line options for specifying credentials."""
+ def __init__(self, parser):
+ self.no_pass = False
+ optparse.OptionGroup.__init__(self, parser, "Credentials Options")
+ self.add_option("--simple-bind-dn", metavar="DN", action="callback",
+ callback=self._set_simple_bind_dn, type=str,
+ help="DN to use for a simple bind")
+ self.add_option("--password", metavar="PASSWORD", action="callback",
+ help="Password", type=str, callback=self._set_password)
+ self.add_option("-U", "--username", metavar="USERNAME",
+ action="callback", type=str,
+ help="Username", callback=self._parse_username)
+ self.add_option("-W", "--workgroup", metavar="WORKGROUP",
+ action="callback", type=str,
+ help="Workgroup", callback=self._parse_workgroup)
+ self.add_option("-N", "--no-pass", action="store_true",
+ help="Don't ask for a password")
+ self.add_option("-k", "--kerberos", metavar="KERBEROS",
+ action="callback", type=str,
+ help="Use Kerberos", callback=self._set_kerberos)
+ self.creds = Credentials()
+
+ def _parse_username(self, option, opt_str, arg, parser):
+ self.creds.parse_string(arg)
+
+ def _parse_workgroup(self, option, opt_str, arg, parser):
+ self.creds.set_domain(arg)
+
+ def _set_password(self, option, opt_str, arg, parser):
+ self.creds.set_password(arg)
+
+ def _set_kerberos(self, option, opt_str, arg, parser):
+ if bool(arg) or arg.lower() == "yes":
+ self.creds.set_kerberos_state(MUST_USE_KERBEROS)
+ else:
+ self.creds.set_kerberos_state(DONT_USE_KERBEROS)
+
+ def _set_simple_bind_dn(self, option, opt_str, arg, parser):
+ self.creds.set_bind_dn(arg)
+
+ def get_credentials(self, lp):
+ """Obtain the credentials set on the command-line.
+
+ :param lp: Loadparm object to use.
+ :return: Credentials object
+ """
+ self.creds.guess(lp)
+ if not self.no_pass:
+ self.creds.set_cmdline_callbacks()
+ return self.creds
diff --git a/source4/scripting/python/samba/hostconfig.py b/source4/scripting/python/samba/hostconfig.py
new file mode 100644
index 0000000000..313e3420b0
--- /dev/null
+++ b/source4/scripting/python/samba/hostconfig.py
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+
+# Unix SMB/CIFS implementation.
+# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+from samdb import SamDB
+
+class Hostconfig(object):
+ """Aggregate object that contains all information about the configuration
+ of a Samba host."""
+
+ def __init__(self, lp):
+ self.lp = lp
+
+ def get_samdb(self, session_info, credentials):
+ return SamDB(url=self.lp.get("sam database"),
+ session_info=session_info, credentials=credentials,
+ lp=self.lp)
+
diff --git a/source4/scripting/python/samba/idmap.py b/source4/scripting/python/samba/idmap.py
new file mode 100644
index 0000000000..755ec52c7b
--- /dev/null
+++ b/source4/scripting/python/samba/idmap.py
@@ -0,0 +1,82 @@
+#!/usr/bin/python
+
+# Unix SMB/CIFS implementation.
+# Copyright (C) 2008 Kai Blin <kai@samba.org>
+#
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+"""Convenience functions for using the idmap database."""
+
+__docformat__ = "restructuredText"
+
+import samba
+import misc
+import ldb
+
+class IDmapDB(samba.Ldb):
+ """The IDmap database."""
+
+ # Mappings for ID_TYPE_UID, ID_TYPE_GID and ID_TYPE_BOTH
+ TYPE_UID = 1
+ TYPE_GID = 2
+ TYPE_BOTH = 3
+
+ def __init__(self, url=None, session_info=None, credentials=None,
+ modules_dir=None, lp=None):
+ """Open the IDmap Database.
+
+ :param url: URL of the database.
+ """
+ self.lp = lp
+
+ super(IDmapDB, self).__init__(session_info=session_info, credentials=credentials,
+ modules_dir=modules_dir, lp=lp)
+ if url:
+ self.connect(url)
+ else:
+ self.connect(lp.get("idmap database"))
+
+ def connect(self, url):
+ super(IDmapDB, self).connect(misc.private_path(self.lp, url))
+
+ def setup_name_mapping(self, sid, type, unixid):
+ """Setup a mapping between a sam name and a unix name.
+
+ :param sid: SID of the NT-side of the mapping.
+ :param unixname: Unix name to map to.
+ """
+ type_string = ""
+ if type == self.TYPE_UID:
+ type_string = "ID_TYPE_UID"
+ elif type == self.TYPE_GID:
+ type_string = "ID_TYPE_GID"
+ elif type == self.TYPE_BOTH:
+ type_string = "ID_TYPE_BOTH"
+ else:
+ return
+
+ mod = """
+dn: CN=%s
+xidNumber: %s
+objectSid: %s
+objectClass: sidMap
+type: %s
+cn: %s
+
+""" % (sid, unixid, sid, type_string, sid)
+ self.add(self.parse_ldif(mod).next()[1])
+
+
diff --git a/source4/scripting/python/samba/ndr.py b/source4/scripting/python/samba/ndr.py
new file mode 100644
index 0000000000..e718ff3422
--- /dev/null
+++ b/source4/scripting/python/samba/ndr.py
@@ -0,0 +1,28 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Unix SMB/CIFS implementation.
+# Copyright © Jelmer Vernooij <jelmer@samba.org> 2008
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+def ndr_pack(object):
+ return object.__ndr_pack__()
+
+
+def ndr_unpack(cls, data):
+ object = cls()
+ object.__ndr_unpack__(data)
+ return object
diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py
new file mode 100644
index 0000000000..68f61532ad
--- /dev/null
+++ b/source4/scripting/python/samba/provision.py
@@ -0,0 +1,1531 @@
+#
+# Unix SMB/CIFS implementation.
+# backend code for provisioning a Samba4 server
+
+# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008
+# Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
+#
+# Based on the original in EJS:
+# Copyright (C) Andrew Tridgell <tridge@samba.org> 2005
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+"""Functions for setting up a Samba configuration."""
+
+from base64 import b64encode
+import os
+import pwd
+import grp
+import time
+import uuid, misc
+import socket
+import param
+import registry
+import samba
+from auth import system_session
+from samba import Ldb, substitute_var, valid_netbios_name, check_all_substituted
+from samba.samdb import SamDB
+from samba.idmap import IDmapDB
+import security
+import urllib
+from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError, \
+ LDB_ERR_NO_SUCH_OBJECT, timestring, CHANGETYPE_MODIFY, CHANGETYPE_NONE
+
+__docformat__ = "restructuredText"
+
+DEFAULTSITE = "Default-First-Site-Name"
+
+class InvalidNetbiosName(Exception):
+ """A specified name was not a valid NetBIOS name."""
+ def __init__(self, name):
+ super(InvalidNetbiosName, self).__init__("The name '%r' is not a valid NetBIOS name" % name)
+
+
+class ProvisionPaths(object):
+ def __init__(self):
+ self.shareconf = None
+ self.hklm = None
+ self.hkcu = None
+ self.hkcr = None
+ self.hku = None
+ self.hkpd = None
+ self.hkpt = None
+ self.samdb = None
+ self.idmapdb = None
+ self.secrets = None
+ self.keytab = None
+ self.dns_keytab = None
+ self.dns = None
+ self.winsdb = None
+ self.private_dir = None
+ self.ldapdir = None
+ self.slapdconf = None
+ self.modulesconf = None
+ self.memberofconf = None
+ self.fedoradsinf = None
+ self.fedoradspartitions = None
+ self.olmmron = None
+ self.olmmrserveridsconf = None
+ self.olmmrsyncreplconf = None
+
+class ProvisionNames(object):
+ def __init__(self):
+ self.rootdn = None
+ self.domaindn = None
+ self.configdn = None
+ self.schemadn = None
+ self.ldapmanagerdn = None
+ self.dnsdomain = None
+ self.realm = None
+ self.netbiosname = None
+ self.domain = None
+ self.hostname = None
+ self.sitename = None
+ self.smbconf = None
+
+
+class ProvisionResult(object):
+ def __init__(self):
+ self.paths = None
+ self.domaindn = None
+ self.lp = None
+ self.samdb = None
+
+def check_install(lp, session_info, credentials):
+ """Check whether the current install seems ok.
+
+ :param lp: Loadparm context
+ :param session_info: Session information
+ :param credentials: Credentials
+ """
+ if lp.get("realm") == "":
+ raise Exception("Realm empty")
+ ldb = Ldb(lp.get("sam database"), session_info=session_info,
+ credentials=credentials, lp=lp)
+ if len(ldb.search("(cn=Administrator)")) != 1:
+ raise "No administrator account found"
+
+
+def findnss(nssfn, names):
+ """Find a user or group from a list of possibilities.
+
+ :param nssfn: NSS Function to try (should raise KeyError if not found)
+ :param names: Names to check.
+ :return: Value return by first names list.
+ """
+ for name in names:
+ try:
+ return nssfn(name)
+ except KeyError:
+ pass
+ raise KeyError("Unable to find user/group %r" % names)
+
+
+findnss_uid = lambda names: findnss(pwd.getpwnam, names)[2]
+findnss_gid = lambda names: findnss(grp.getgrnam, names)[2]
+
+
+def read_and_sub_file(file, subst_vars):
+ """Read a file and sub in variables found in it
+
+ :param file: File to be read (typically from setup directory)
+ param subst_vars: Optional variables to subsitute in the file.
+ """
+ data = open(file, 'r').read()
+ if subst_vars is not None:
+ data = substitute_var(data, subst_vars)
+ check_all_substituted(data)
+ return data
+
+
+def setup_add_ldif(ldb, ldif_path, subst_vars=None):
+ """Setup a ldb in the private dir.
+
+ :param ldb: LDB file to import data into
+ :param ldif_path: Path of the LDIF file to load
+ :param subst_vars: Optional variables to subsitute in LDIF.
+ """
+ assert isinstance(ldif_path, str)
+
+ data = read_and_sub_file(ldif_path, subst_vars)
+ ldb.add_ldif(data)
+
+
+def setup_modify_ldif(ldb, ldif_path, subst_vars=None):
+ """Modify a ldb in the private dir.
+
+ :param ldb: LDB object.
+ :param ldif_path: LDIF file path.
+ :param subst_vars: Optional dictionary with substitution variables.
+ """
+ data = read_and_sub_file(ldif_path, subst_vars)
+
+ ldb.modify_ldif(data)
+
+
+def setup_ldb(ldb, ldif_path, subst_vars):
+ """Import a LDIF a file into a LDB handle, optionally substituting variables.
+
+ :note: Either all LDIF data will be added or none (using transactions).
+
+ :param ldb: LDB file to import into.
+ :param ldif_path: Path to the LDIF file.
+ :param subst_vars: Dictionary with substitution variables.
+ """
+ assert ldb is not None
+ ldb.transaction_start()
+ try:
+ setup_add_ldif(ldb, ldif_path, subst_vars)
+ except:
+ ldb.transaction_cancel()
+ raise
+ ldb.transaction_commit()
+
+
+def setup_file(template, fname, subst_vars):
+ """Setup a file in the private dir.
+
+ :param template: Path of the template file.
+ :param fname: Path of the file to create.
+ :param subst_vars: Substitution variables.
+ """
+ f = fname
+
+ if os.path.exists(f):
+ os.unlink(f)
+
+ data = read_and_sub_file(template, subst_vars)
+ open(f, 'w').write(data)
+
+
+def provision_paths_from_lp(lp, dnsdomain):
+ """Set the default paths for provisioning.
+
+ :param lp: Loadparm context.
+ :param dnsdomain: DNS Domain name
+ """
+ paths = ProvisionPaths()
+ paths.private_dir = lp.get("private dir")
+ paths.keytab = "secrets.keytab"
+ paths.dns_keytab = "dns.keytab"
+
+ paths.shareconf = os.path.join(paths.private_dir, "share.ldb")
+ paths.samdb = os.path.join(paths.private_dir, lp.get("sam database") or "samdb.ldb")
+ paths.idmapdb = os.path.join(paths.private_dir, lp.get("idmap database") or "idmap.ldb")
+ paths.secrets = os.path.join(paths.private_dir, lp.get("secrets database") or "secrets.ldb")
+ paths.templates = os.path.join(paths.private_dir, "templates.ldb")
+ paths.dns = os.path.join(paths.private_dir, dnsdomain + ".zone")
+ paths.namedconf = os.path.join(paths.private_dir, "named.conf")
+ paths.namedtxt = os.path.join(paths.private_dir, "named.txt")
+ paths.krb5conf = os.path.join(paths.private_dir, "krb5.conf")
+ paths.winsdb = os.path.join(paths.private_dir, "wins.ldb")
+ paths.s4_ldapi_path = os.path.join(paths.private_dir, "ldapi")
+ paths.phpldapadminconfig = os.path.join(paths.private_dir,
+ "phpldapadmin-config.php")
+ paths.ldapdir = os.path.join(paths.private_dir,
+ "ldap")
+ paths.slapdconf = os.path.join(paths.ldapdir,
+ "slapd.conf")
+ paths.modulesconf = os.path.join(paths.ldapdir,
+ "modules.conf")
+ paths.memberofconf = os.path.join(paths.ldapdir,
+ "memberof.conf")
+ paths.fedoradsinf = os.path.join(paths.ldapdir,
+ "fedorads.inf")
+ paths.fedoradspartitions = os.path.join(paths.ldapdir,
+ "fedorads-partitions.ldif")
+ paths.olmmrserveridsconf = os.path.join(paths.ldapdir,
+ "mmr_serverids.conf")
+ paths.olmmrsyncreplconf = os.path.join(paths.ldapdir,
+ "mmr_syncrepl.conf")
+ paths.hklm = "hklm.ldb"
+ paths.hkcr = "hkcr.ldb"
+ paths.hkcu = "hkcu.ldb"
+ paths.hku = "hku.ldb"
+ paths.hkpd = "hkpd.ldb"
+ paths.hkpt = "hkpt.ldb"
+
+ paths.sysvol = lp.get("path", "sysvol")
+
+ paths.netlogon = lp.get("path", "netlogon")
+
+ paths.smbconf = lp.configfile()
+
+ return paths
+
+
+def guess_names(lp=None, hostname=None, domain=None, dnsdomain=None, serverrole=None,
+ rootdn=None, domaindn=None, configdn=None, schemadn=None, serverdn=None,
+ sitename=None):
+ """Guess configuration settings to use."""
+
+ if hostname is None:
+ hostname = socket.gethostname().split(".")[0].lower()
+
+ netbiosname = hostname.upper()
+ if not valid_netbios_name(netbiosname):
+ raise InvalidNetbiosName(netbiosname)
+
+ hostname = hostname.lower()
+
+ if dnsdomain is None:
+ dnsdomain = lp.get("realm")
+
+ if serverrole is None:
+ serverrole = lp.get("server role")
+
+ assert dnsdomain is not None
+ realm = dnsdomain.upper()
+
+ if lp.get("realm").upper() != realm:
+ raise Exception("realm '%s' in %s must match chosen realm '%s'" %
+ (lp.get("realm"), lp.configfile(), realm))
+
+ dnsdomain = dnsdomain.lower()
+
+ if serverrole == "domain controller":
+ if domain is None:
+ domain = lp.get("workgroup")
+ if domaindn is None:
+ domaindn = "DC=" + dnsdomain.replace(".", ",DC=")
+ if lp.get("workgroup").upper() != domain.upper():
+ raise Exception("workgroup '%s' in smb.conf must match chosen domain '%s'",
+ lp.get("workgroup"), domain)
+ else:
+ domain = netbiosname
+ if domaindn is None:
+ domaindn = "CN=" + netbiosname
+
+ assert domain is not None
+ domain = domain.upper()
+ if not valid_netbios_name(domain):
+ raise InvalidNetbiosName(domain)
+
+ if rootdn is None:
+ rootdn = domaindn
+
+ if configdn is None:
+ configdn = "CN=Configuration," + rootdn
+ if schemadn is None:
+ schemadn = "CN=Schema," + configdn
+
+ if sitename is None:
+ sitename=DEFAULTSITE
+
+ names = ProvisionNames()
+ names.rootdn = rootdn
+ names.domaindn = domaindn
+ names.configdn = configdn
+ names.schemadn = schemadn
+ names.ldapmanagerdn = "CN=Manager," + rootdn
+ names.dnsdomain = dnsdomain
+ names.domain = domain
+ names.realm = realm
+ names.netbiosname = netbiosname
+ names.hostname = hostname
+ names.sitename = sitename
+ names.serverdn = "CN=%s,CN=Servers,CN=%s,CN=Sites,%s" % (netbiosname, sitename, configdn)
+
+ return names
+
+
+def make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole,
+ targetdir):
+ if hostname is None:
+ hostname = socket.gethostname().split(".")[0].lower()
+
+ if serverrole is None:
+ serverrole = "standalone"
+
+ assert serverrole in ("domain controller", "member server", "standalone")
+ if serverrole == "domain controller":
+ smbconfsuffix = "dc"
+ elif serverrole == "member server":
+ smbconfsuffix = "member"
+ elif serverrole == "standalone":
+ smbconfsuffix = "standalone"
+
+ assert domain is not None
+ assert realm is not None
+
+ default_lp = param.LoadParm()
+ #Load non-existant file
+ default_lp.load(smbconf)
+
+ if targetdir is not None:
+ privatedir_line = "private dir = " + os.path.abspath(os.path.join(targetdir, "private"))
+ lockdir_line = "lock dir = " + os.path.abspath(targetdir)
+
+ default_lp.set("lock dir", os.path.abspath(targetdir))
+ else:
+ privatedir_line = ""
+ lockdir_line = ""
+
+ sysvol = os.path.join(default_lp.get("lock dir"), "sysvol")
+ netlogon = os.path.join(sysvol, realm.lower(), "scripts")
+
+ setup_file(setup_path("provision.smb.conf.%s" % smbconfsuffix),
+ smbconf, {
+ "HOSTNAME": hostname,
+ "DOMAIN": domain,
+ "REALM": realm,
+ "SERVERROLE": serverrole,
+ "NETLOGONPATH": netlogon,
+ "SYSVOLPATH": sysvol,
+ "PRIVATEDIR_LINE": privatedir_line,
+ "LOCKDIR_LINE": lockdir_line
+ })
+
+
+
+def setup_name_mappings(samdb, idmap, sid, domaindn, root_uid, nobody_uid,
+ users_gid, wheel_gid):
+ """setup reasonable name mappings for sam names to unix names.
+
+ :param samdb: SamDB object.
+ :param idmap: IDmap db object.
+ :param sid: The domain sid.
+ :param domaindn: The domain DN.
+ :param root_uid: uid of the UNIX root user.
+ :param nobody_uid: uid of the UNIX nobody user.
+ :param users_gid: gid of the UNIX users group.
+ :param wheel_gid: gid of the UNIX wheel group."""
+ # add some foreign sids if they are not present already
+ samdb.add_foreign(domaindn, "S-1-5-7", "Anonymous")
+ samdb.add_foreign(domaindn, "S-1-1-0", "World")
+ samdb.add_foreign(domaindn, "S-1-5-2", "Network")
+ samdb.add_foreign(domaindn, "S-1-5-18", "System")
+ samdb.add_foreign(domaindn, "S-1-5-11", "Authenticated Users")
+
+ idmap.setup_name_mapping("S-1-5-7", idmap.TYPE_UID, nobody_uid)
+ idmap.setup_name_mapping("S-1-5-32-544", idmap.TYPE_GID, wheel_gid)
+
+ idmap.setup_name_mapping(sid + "-500", idmap.TYPE_UID, root_uid)
+ idmap.setup_name_mapping(sid + "-513", idmap.TYPE_GID, users_gid)
+
+
+def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
+ credentials, names,
+ serverrole, ldap_backend=None,
+ ldap_backend_type=None, erase=False):
+ """Setup the partitions for the SAM database.
+
+ Alternatively, provision() may call this, and then populate the database.
+
+ :note: This will wipe the Sam Database!
+
+ :note: This function always removes the local SAM LDB file. The erase
+ parameter controls whether to erase the existing data, which
+ may not be stored locally but in LDAP.
+ """
+ assert session_info is not None
+
+ samdb = SamDB(samdb_path, session_info=session_info,
+ credentials=credentials, lp=lp)
+
+ # Wipes the database
+ try:
+ samdb.erase()
+ except:
+ os.unlink(samdb_path)
+
+ samdb = SamDB(samdb_path, session_info=session_info,
+ credentials=credentials, lp=lp)
+
+ #Add modules to the list to activate them by default
+ #beware often order is important
+ #
+ # Some Known ordering constraints:
+ # - rootdse must be first, as it makes redirects from "" -> cn=rootdse
+ # - objectclass must be before password_hash, because password_hash checks
+ # that the objectclass is of type person (filled in by objectclass
+ # module when expanding the objectclass list)
+ # - partition must be last
+ # - each partition has its own module list then
+ modules_list = ["rootdse",
+ "paged_results",
+ "ranged_results",
+ "anr",
+ "server_sort",
+ "extended_dn",
+ "asq",
+ "rdn_name",
+ "objectclass",
+ "samldb",
+ "kludge_acl",
+ "operational"]
+ tdb_modules_list = [
+ "subtree_rename",
+ "subtree_delete",
+ "linked_attributes"]
+ modules_list2 = ["show_deleted",
+ "partition"]
+
+ domaindn_ldb = "users.ldb"
+ if ldap_backend is not None:
+ domaindn_ldb = ldap_backend
+ configdn_ldb = "configuration.ldb"
+ if ldap_backend is not None:
+ configdn_ldb = ldap_backend
+ schemadn_ldb = "schema.ldb"
+ if ldap_backend is not None:
+ schema_ldb = ldap_backend
+ schemadn_ldb = ldap_backend
+
+ if ldap_backend_type == "fedora-ds":
+ backend_modules = ["nsuniqueid", "paged_searches"]
+ # We can handle linked attributes here, as we don't have directory-side subtree operations
+ tdb_modules_list = ["linked_attributes"]
+ elif ldap_backend_type == "openldap":
+ backend_modules = ["normalise", "entryuuid", "paged_searches"]
+ # OpenLDAP handles subtree renames, so we don't want to do any of these things
+ tdb_modules_list = None
+ elif ldap_backend is not None:
+ raise "LDAP Backend specified, but LDAP Backend Type not specified"
+ elif serverrole == "domain controller":
+ backend_modules = ["repl_meta_data"]
+ else:
+ backend_modules = ["objectguid"]
+
+ if tdb_modules_list is None:
+ tdb_modules_list_as_string = ""
+ else:
+ tdb_modules_list_as_string = ","+",".join(tdb_modules_list)
+
+ samdb.transaction_start()
+ try:
+ setup_add_ldif(samdb, setup_path("provision_partitions.ldif"), {
+ "SCHEMADN": names.schemadn,
+ "SCHEMADN_LDB": schemadn_ldb,
+ "SCHEMADN_MOD2": ",objectguid",
+ "CONFIGDN": names.configdn,
+ "CONFIGDN_LDB": configdn_ldb,
+ "DOMAINDN": names.domaindn,
+ "DOMAINDN_LDB": domaindn_ldb,
+ "SCHEMADN_MOD": "schema_fsmo,instancetype",
+ "CONFIGDN_MOD": "naming_fsmo,instancetype",
+ "DOMAINDN_MOD": "pdc_fsmo,password_hash,instancetype",
+ "MODULES_LIST": ",".join(modules_list),
+ "TDB_MODULES_LIST": tdb_modules_list_as_string,
+ "MODULES_LIST2": ",".join(modules_list2),
+ "BACKEND_MOD": ",".join(backend_modules),
+ })
+
+ except:
+ samdb.transaction_cancel()
+ raise
+
+ samdb.transaction_commit()
+
+ samdb = SamDB(samdb_path, session_info=session_info,
+ credentials=credentials, lp=lp)
+
+ samdb.transaction_start()
+ try:
+ message("Setting up sam.ldb attributes")
+ samdb.load_ldif_file_add(setup_path("provision_init.ldif"))
+
+ message("Setting up sam.ldb rootDSE")
+ setup_samdb_rootdse(samdb, setup_path, names)
+
+ if erase:
+ message("Erasing data from partitions")
+ samdb.erase_partitions()
+
+ except:
+ samdb.transaction_cancel()
+ raise
+
+ samdb.transaction_commit()
+
+ return samdb
+
+
+def secretsdb_become_dc(secretsdb, setup_path, domain, realm, dnsdomain,
+ netbiosname, domainsid, keytab_path, samdb_url,
+ dns_keytab_path, dnspass, machinepass):
+ """Add DC-specific bits to a secrets database.
+
+ :param secretsdb: Ldb Handle to the secrets database
+ :param setup_path: Setup path function
+ :param machinepass: Machine password
+ """
+ setup_ldb(secretsdb, setup_path("secrets_dc.ldif"), {
+ "MACHINEPASS_B64": b64encode(machinepass),
+ "DOMAIN": domain,
+ "REALM": realm,
+ "DNSDOMAIN": dnsdomain,
+ "DOMAINSID": str(domainsid),
+ "SECRETS_KEYTAB": keytab_path,
+ "NETBIOSNAME": netbiosname,
+ "SAM_LDB": samdb_url,
+ "DNS_KEYTAB": dns_keytab_path,
+ "DNSPASS_B64": b64encode(dnspass),
+ })
+
+
+def setup_secretsdb(path, setup_path, session_info, credentials, lp):
+ """Setup the secrets database.
+
+ :param path: Path to the secrets database.
+ :param setup_path: Get the path to a setup file.
+ :param session_info: Session info.
+ :param credentials: Credentials
+ :param lp: Loadparm context
+ :return: LDB handle for the created secrets database
+ """
+ if os.path.exists(path):
+ os.unlink(path)
+ secrets_ldb = Ldb(path, session_info=session_info, credentials=credentials,
+ lp=lp)
+ secrets_ldb.erase()
+ secrets_ldb.load_ldif_file_add(setup_path("secrets_init.ldif"))
+ secrets_ldb = Ldb(path, session_info=session_info, credentials=credentials,
+ lp=lp)
+ secrets_ldb.load_ldif_file_add(setup_path("secrets.ldif"))
+
+ if credentials is not None and credentials.authentication_requested():
+ if credentials.get_bind_dn() is not None:
+ setup_add_ldif(secrets_ldb, setup_path("secrets_simple_ldap.ldif"), {
+ "LDAPMANAGERDN": credentials.get_bind_dn(),
+ "LDAPMANAGERPASS_B64": b64encode(credentials.get_password())
+ })
+ else:
+ setup_add_ldif(secrets_ldb, setup_path("secrets_sasl_ldap.ldif"), {
+ "LDAPADMINUSER": credentials.get_username(),
+ "LDAPADMINREALM": credentials.get_realm(),
+ "LDAPADMINPASS_B64": b64encode(credentials.get_password())
+ })
+
+ return secrets_ldb
+
+
+def setup_templatesdb(path, setup_path, session_info, credentials, lp):
+ """Setup the templates database.
+
+ :param path: Path to the database.
+ :param setup_path: Function for obtaining the path to setup files.
+ :param session_info: Session info
+ :param credentials: Credentials
+ :param lp: Loadparm context
+ """
+ templates_ldb = SamDB(path, session_info=session_info,
+ credentials=credentials, lp=lp)
+ # Wipes the database
+ try:
+ templates_ldb.erase()
+ except:
+ os.unlink(path)
+
+ templates_ldb.load_ldif_file_add(setup_path("provision_templates_init.ldif"))
+
+ templates_ldb = SamDB(path, session_info=session_info,
+ credentials=credentials, lp=lp)
+
+ templates_ldb.load_ldif_file_add(setup_path("provision_templates.ldif"))
+
+
+def setup_registry(path, setup_path, session_info, credentials, lp):
+ """Setup the registry.
+
+ :param path: Path to the registry database
+ :param setup_path: Function that returns the path to a setup.
+ :param session_info: Session information
+ :param credentials: Credentials
+ :param lp: Loadparm context
+ """
+ reg = registry.Registry()
+ hive = registry.open_ldb(path, session_info=session_info,
+ credentials=credentials, lp_ctx=lp)
+ reg.mount_hive(hive, "HKEY_LOCAL_MACHINE")
+ provision_reg = setup_path("provision.reg")
+ assert os.path.exists(provision_reg)
+ reg.diff_apply(provision_reg)
+
+
+def setup_idmapdb(path, setup_path, session_info, credentials, lp):
+ """Setup the idmap database.
+
+ :param path: path to the idmap database
+ :param setup_path: Function that returns a path to a setup file
+ :param session_info: Session information
+ :param credentials: Credentials
+ :param lp: Loadparm context
+ """
+ if os.path.exists(path):
+ os.unlink(path)
+
+ idmap_ldb = IDmapDB(path, session_info=session_info,
+ credentials=credentials, lp=lp)
+
+ idmap_ldb.erase()
+ idmap_ldb.load_ldif_file_add(setup_path("idmap_init.ldif"))
+ return idmap_ldb
+
+
+def setup_samdb_rootdse(samdb, setup_path, names):
+ """Setup the SamDB rootdse.
+
+ :param samdb: Sam Database handle
+ :param setup_path: Obtain setup path
+ """
+ setup_add_ldif(samdb, setup_path("provision_rootdse_add.ldif"), {
+ "SCHEMADN": names.schemadn,
+ "NETBIOSNAME": names.netbiosname,
+ "DNSDOMAIN": names.dnsdomain,
+ "REALM": names.realm,
+ "DNSNAME": "%s.%s" % (names.hostname, names.dnsdomain),
+ "DOMAINDN": names.domaindn,
+ "ROOTDN": names.rootdn,
+ "CONFIGDN": names.configdn,
+ "SERVERDN": names.serverdn,
+ })
+
+
+def setup_self_join(samdb, names,
+ machinepass, dnspass,
+ domainsid, invocationid, setup_path,
+ policyguid):
+ """Join a host to its own domain."""
+ assert isinstance(invocationid, str)
+ setup_add_ldif(samdb, setup_path("provision_self_join.ldif"), {
+ "CONFIGDN": names.configdn,
+ "SCHEMADN": names.schemadn,
+ "DOMAINDN": names.domaindn,
+ "SERVERDN": names.serverdn,
+ "INVOCATIONID": invocationid,
+ "NETBIOSNAME": names.netbiosname,
+ "DEFAULTSITE": names.sitename,
+ "DNSNAME": "%s.%s" % (names.hostname, names.dnsdomain),
+ "MACHINEPASS_B64": b64encode(machinepass),
+ "DNSPASS_B64": b64encode(dnspass),
+ "REALM": names.realm,
+ "DOMAIN": names.domain,
+ "DNSDOMAIN": names.dnsdomain})
+ setup_add_ldif(samdb, setup_path("provision_group_policy.ldif"), {
+ "POLICYGUID": policyguid,
+ "DNSDOMAIN": names.dnsdomain,
+ "DOMAINSID": str(domainsid),
+ "DOMAINDN": names.domaindn})
+
+
+def setup_samdb(path, setup_path, session_info, credentials, lp,
+ names, message,
+ domainsid, aci, domainguid, policyguid,
+ fill, adminpass, krbtgtpass,
+ machinepass, invocationid, dnspass,
+ serverrole, ldap_backend=None,
+ ldap_backend_type=None):
+ """Setup a complete SAM Database.
+
+ :note: This will wipe the main SAM database file!
+ """
+
+ erase = (fill != FILL_DRS)
+
+ # Also wipes the database
+ setup_samdb_partitions(path, setup_path, message=message, lp=lp,
+ credentials=credentials, session_info=session_info,
+ names=names,
+ ldap_backend=ldap_backend, serverrole=serverrole,
+ ldap_backend_type=ldap_backend_type, erase=erase)
+
+ samdb = SamDB(path, session_info=session_info,
+ credentials=credentials, lp=lp)
+
+ message("Pre-loading the Samba 4 and AD schema")
+ samdb.set_domain_sid(domainsid)
+ if serverrole == "domain controller":
+ samdb.set_invocation_id(invocationid)
+
+ load_schema(setup_path, samdb, names.schemadn, names.netbiosname,
+ names.configdn, names.sitename, names.serverdn,
+ names.hostname)
+
+ samdb.transaction_start()
+
+ try:
+ message("Adding DomainDN: %s (permitted to fail)" % names.domaindn)
+ if serverrole == "domain controller":
+ domain_oc = "domainDNS"
+ else:
+ domain_oc = "samba4LocalDomain"
+
+ setup_add_ldif(samdb, setup_path("provision_basedn.ldif"), {
+ "DOMAINDN": names.domaindn,
+ "ACI": aci,
+ "DOMAIN_OC": domain_oc
+ })
+
+ message("Modifying DomainDN: " + names.domaindn + "")
+ if domainguid is not None:
+ domainguid_mod = "replace: objectGUID\nobjectGUID: %s\n-" % domainguid
+ else:
+ domainguid_mod = ""
+
+ setup_modify_ldif(samdb, setup_path("provision_basedn_modify.ldif"), {
+ "LDAPTIME": timestring(int(time.time())),
+ "DOMAINSID": str(domainsid),
+ "SCHEMADN": names.schemadn,
+ "NETBIOSNAME": names.netbiosname,
+ "DEFAULTSITE": names.sitename,
+ "CONFIGDN": names.configdn,
+ "SERVERDN": names.serverdn,
+ "POLICYGUID": policyguid,
+ "DOMAINDN": names.domaindn,
+ "DOMAINGUID_MOD": domainguid_mod,
+ })
+
+ message("Adding configuration container (permitted to fail)")
+ setup_add_ldif(samdb, setup_path("provision_configuration_basedn.ldif"), {
+ "CONFIGDN": names.configdn,
+ "ACI": aci,
+ })
+ message("Modifying configuration container")
+ setup_modify_ldif(samdb, setup_path("provision_configuration_basedn_modify.ldif"), {
+ "CONFIGDN": names.configdn,
+ "SCHEMADN": names.schemadn,
+ })
+
+ message("Adding schema container (permitted to fail)")
+ setup_add_ldif(samdb, setup_path("provision_schema_basedn.ldif"), {
+ "SCHEMADN": names.schemadn,
+ "ACI": aci,
+ })
+ message("Modifying schema container")
+
+ prefixmap = open(setup_path("prefixMap.txt"), 'r').read()
+
+ setup_modify_ldif(samdb,
+ setup_path("provision_schema_basedn_modify.ldif"), {
+ "SCHEMADN": names.schemadn,
+ "NETBIOSNAME": names.netbiosname,
+ "DEFAULTSITE": names.sitename,
+ "CONFIGDN": names.configdn,
+ "SERVERDN": names.serverdn,
+ "PREFIXMAP_B64": b64encode(prefixmap)
+ })
+
+ message("Setting up sam.ldb Samba4 schema")
+ setup_add_ldif(samdb, setup_path("schema_samba4.ldif"),
+ {"SCHEMADN": names.schemadn })
+ message("Setting up sam.ldb AD schema")
+ setup_add_ldif(samdb, setup_path("schema.ldif"),
+ {"SCHEMADN": names.schemadn})
+
+ message("Setting up sam.ldb configuration data")
+ setup_add_ldif(samdb, setup_path("provision_configuration.ldif"), {
+ "CONFIGDN": names.configdn,
+ "NETBIOSNAME": names.netbiosname,
+ "DEFAULTSITE": names.sitename,
+ "DNSDOMAIN": names.dnsdomain,
+ "DOMAIN": names.domain,
+ "SCHEMADN": names.schemadn,
+ "DOMAINDN": names.domaindn,
+ "SERVERDN": names.serverdn
+ })
+
+ message("Setting up display specifiers")
+ setup_add_ldif(samdb, setup_path("display_specifiers.ldif"),
+ {"CONFIGDN": names.configdn})
+
+ message("Adding users container (permitted to fail)")
+ setup_add_ldif(samdb, setup_path("provision_users_add.ldif"), {
+ "DOMAINDN": names.domaindn})
+ message("Modifying users container")
+ setup_modify_ldif(samdb, setup_path("provision_users_modify.ldif"), {
+ "DOMAINDN": names.domaindn})
+ message("Adding computers container (permitted to fail)")
+ setup_add_ldif(samdb, setup_path("provision_computers_add.ldif"), {
+ "DOMAINDN": names.domaindn})
+ message("Modifying computers container")
+ setup_modify_ldif(samdb, setup_path("provision_computers_modify.ldif"), {
+ "DOMAINDN": names.domaindn})
+ message("Setting up sam.ldb data")
+ setup_add_ldif(samdb, setup_path("provision.ldif"), {
+ "DOMAINDN": names.domaindn,
+ "NETBIOSNAME": names.netbiosname,
+ "DEFAULTSITE": names.sitename,
+ "CONFIGDN": names.configdn,
+ "SERVERDN": names.serverdn
+ })
+
+ if fill == FILL_FULL:
+ message("Setting up sam.ldb users and groups")
+ setup_add_ldif(samdb, setup_path("provision_users.ldif"), {
+ "DOMAINDN": names.domaindn,
+ "DOMAINSID": str(domainsid),
+ "CONFIGDN": names.configdn,
+ "ADMINPASS_B64": b64encode(adminpass),
+ "KRBTGTPASS_B64": b64encode(krbtgtpass),
+ })
+
+ if serverrole == "domain controller":
+ message("Setting up self join")
+ setup_self_join(samdb, names=names, invocationid=invocationid,
+ dnspass=dnspass,
+ machinepass=machinepass,
+ domainsid=domainsid, policyguid=policyguid,
+ setup_path=setup_path)
+
+ except:
+ samdb.transaction_cancel()
+ raise
+
+ samdb.transaction_commit()
+ return samdb
+
+
+FILL_FULL = "FULL"
+FILL_NT4SYNC = "NT4SYNC"
+FILL_DRS = "DRS"
+
+def provision(setup_dir, message, session_info,
+ credentials, smbconf=None, targetdir=None, samdb_fill=FILL_FULL, realm=None,
+ rootdn=None, domaindn=None, schemadn=None, configdn=None,
+ serverdn=None,
+ domain=None, hostname=None, hostip=None, hostip6=None,
+ domainsid=None, adminpass=None, krbtgtpass=None, domainguid=None,
+ policyguid=None, invocationid=None, machinepass=None,
+ dnspass=None, root=None, nobody=None, nogroup=None, users=None,
+ wheel=None, backup=None, aci=None, serverrole=None,
+ ldap_backend=None, ldap_backend_type=None, sitename=None):
+ """Provision samba4
+
+ :note: caution, this wipes all existing data!
+ """
+
+ def setup_path(file):
+ return os.path.join(setup_dir, file)
+
+ if domainsid is None:
+ domainsid = security.random_sid()
+ else:
+ domainsid = security.Sid(domainsid)
+
+ if policyguid is None:
+ policyguid = str(uuid.uuid4())
+ if adminpass is None:
+ adminpass = misc.random_password(12)
+ if krbtgtpass is None:
+ krbtgtpass = misc.random_password(12)
+ if machinepass is None:
+ machinepass = misc.random_password(12)
+ if dnspass is None:
+ dnspass = misc.random_password(12)
+ root_uid = findnss_uid([root or "root"])
+ nobody_uid = findnss_uid([nobody or "nobody"])
+ users_gid = findnss_gid([users or "users"])
+ if wheel is None:
+ wheel_gid = findnss_gid(["wheel", "adm"])
+ else:
+ wheel_gid = findnss_gid([wheel])
+ if aci is None:
+ aci = "# no aci for local ldb"
+
+ if targetdir is not None:
+ if (not os.path.exists(os.path.join(targetdir, "etc"))):
+ os.makedirs(os.path.join(targetdir, "etc"))
+ smbconf = os.path.join(targetdir, "etc", "smb.conf")
+
+ # only install a new smb.conf if there isn't one there already
+ if not os.path.exists(smbconf):
+ make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole,
+ targetdir)
+
+ lp = param.LoadParm()
+ lp.load(smbconf)
+
+ names = guess_names(lp=lp, hostname=hostname, domain=domain,
+ dnsdomain=realm, serverrole=serverrole, sitename=sitename,
+ rootdn=rootdn, domaindn=domaindn, configdn=configdn, schemadn=schemadn,
+ serverdn=serverdn)
+
+ paths = provision_paths_from_lp(lp, names.dnsdomain)
+
+ if hostip is None:
+ hostip = socket.getaddrinfo(names.hostname, None, socket.AF_INET, socket.AI_CANONNAME, socket.IPPROTO_IP)[0][-1][0]
+
+ if hostip6 is None:
+ try:
+ hostip6 = socket.getaddrinfo(names.hostname, None, socket.AF_INET6, socket.AI_CANONNAME, socket.IPPROTO_IP)[0][-1][0]
+ except socket.gaierror:
+ pass
+
+ if serverrole is None:
+ serverrole = lp.get("server role")
+
+ assert serverrole in ("domain controller", "member server", "standalone")
+ if invocationid is None and serverrole == "domain controller":
+ invocationid = str(uuid.uuid4())
+
+ if not os.path.exists(paths.private_dir):
+ os.mkdir(paths.private_dir)
+
+ ldapi_url = "ldapi://%s" % urllib.quote(paths.s4_ldapi_path, safe="")
+
+ if ldap_backend is not None:
+ if ldap_backend == "ldapi":
+ # provision-backend will set this path suggested slapd command line / fedorads.inf
+ ldap_backend = "ldapi://%s" % urllib.quote(os.path.join(paths.private_dir, "ldap", "ldapi"), safe="")
+
+ # only install a new shares config db if there is none
+ if not os.path.exists(paths.shareconf):
+ message("Setting up share.ldb")
+ share_ldb = Ldb(paths.shareconf, session_info=session_info,
+ credentials=credentials, lp=lp)
+ share_ldb.load_ldif_file_add(setup_path("share.ldif"))
+
+
+ message("Setting up secrets.ldb")
+ secrets_ldb = setup_secretsdb(paths.secrets, setup_path,
+ session_info=session_info,
+ credentials=credentials, lp=lp)
+
+ message("Setting up the registry")
+ setup_registry(paths.hklm, setup_path, session_info,
+ credentials=credentials, lp=lp)
+
+ message("Setting up templates db")
+ setup_templatesdb(paths.templates, setup_path, session_info=session_info,
+ credentials=credentials, lp=lp)
+
+ message("Setting up idmap db")
+ idmap = setup_idmapdb(paths.idmapdb, setup_path, session_info=session_info,
+ credentials=credentials, lp=lp)
+
+ samdb = setup_samdb(paths.samdb, setup_path, session_info=session_info,
+ credentials=credentials, lp=lp, names=names,
+ message=message,
+ domainsid=domainsid,
+ aci=aci, domainguid=domainguid, policyguid=policyguid,
+ fill=samdb_fill,
+ adminpass=adminpass, krbtgtpass=krbtgtpass,
+ invocationid=invocationid,
+ machinepass=machinepass, dnspass=dnspass,
+ serverrole=serverrole, ldap_backend=ldap_backend,
+ ldap_backend_type=ldap_backend_type)
+
+ if lp.get("server role") == "domain controller":
+ if paths.netlogon is None:
+ message("Existing smb.conf does not have a [netlogon] share, but you are configuring a DC.")
+ message("Please either remove %s or see the template at %s" %
+ ( paths.smbconf, setup_path("provision.smb.conf.dc")))
+ assert(paths.netlogon is not None)
+
+ if paths.sysvol is None:
+ message("Existing smb.conf does not have a [sysvol] share, but you are configuring a DC.")
+ message("Please either remove %s or see the template at %s" %
+ (paths.smbconf, setup_path("provision.smb.conf.dc")))
+ assert(paths.sysvol is not None)
+
+ policy_path = os.path.join(paths.sysvol, names.dnsdomain, "Policies",
+ "{" + policyguid + "}")
+ os.makedirs(policy_path, 0755)
+ open(os.path.join(policy_path, "GPT.INI"), 'w').write("")
+ os.makedirs(os.path.join(policy_path, "Machine"), 0755)
+ os.makedirs(os.path.join(policy_path, "User"), 0755)
+ if not os.path.isdir(paths.netlogon):
+ os.makedirs(paths.netlogon, 0755)
+
+ if samdb_fill == FILL_FULL:
+ setup_name_mappings(samdb, idmap, str(domainsid), names.domaindn,
+ root_uid=root_uid, nobody_uid=nobody_uid,
+ users_gid=users_gid, wheel_gid=wheel_gid)
+
+ message("Setting up sam.ldb rootDSE marking as synchronized")
+ setup_modify_ldif(samdb, setup_path("provision_rootdse_modify.ldif"))
+
+ # Only make a zone file on the first DC, it should be replicated with DNS replication
+ if serverrole == "domain controller":
+ secrets_ldb = Ldb(paths.secrets, session_info=session_info,
+ credentials=credentials, lp=lp)
+ secretsdb_become_dc(secrets_ldb, setup_path, domain=domain, realm=names.realm,
+ netbiosname=names.netbiosname, domainsid=domainsid,
+ keytab_path=paths.keytab, samdb_url=paths.samdb,
+ dns_keytab_path=paths.dns_keytab, dnspass=dnspass,
+ machinepass=machinepass, dnsdomain=names.dnsdomain)
+
+ samdb = SamDB(paths.samdb, session_info=session_info,
+ credentials=credentials, lp=lp)
+
+ domainguid = samdb.searchone(basedn=domaindn, attribute="objectGUID")
+ assert isinstance(domainguid, str)
+ hostguid = samdb.searchone(basedn=domaindn, attribute="objectGUID",
+ expression="(&(objectClass=computer)(cn=%s))" % names.hostname,
+ scope=SCOPE_SUBTREE)
+ assert isinstance(hostguid, str)
+
+ create_zone_file(paths.dns, setup_path, dnsdomain=names.dnsdomain,
+ domaindn=names.domaindn, hostip=hostip,
+ hostip6=hostip6, hostname=names.hostname,
+ dnspass=dnspass, realm=names.realm,
+ domainguid=domainguid, hostguid=hostguid)
+
+ create_named_conf(paths.namedconf, setup_path, realm=names.realm,
+ dnsdomain=names.dnsdomain, private_dir=paths.private_dir)
+
+ create_named_txt(paths.namedtxt, setup_path, realm=names.realm,
+ dnsdomain=names.dnsdomain, private_dir=paths.private_dir,
+ keytab_name=paths.dns_keytab)
+ message("See %s for an example configuration include file for BIND" % paths.namedconf)
+ message("and %s for further documentation required for secure DNS updates" % paths.namedtxt)
+
+ create_krb5_conf(paths.krb5conf, setup_path, dnsdomain=names.dnsdomain,
+ hostname=names.hostname, realm=names.realm)
+ message("A Kerberos configuration suitable for Samba 4 has been generated at %s" % paths.krb5conf)
+
+ create_phpldapadmin_config(paths.phpldapadminconfig, setup_path,
+ ldapi_url)
+
+ message("Please install the phpLDAPadmin configuration located at %s into /etc/phpldapadmin/config.php" % paths.phpldapadminconfig)
+
+ message("Once the above files are installed, your Samba4 server will be ready to use")
+ message("Server Role: %s" % serverrole)
+ message("Hostname: %s" % names.hostname)
+ message("NetBIOS Domain: %s" % names.domain)
+ message("DNS Domain: %s" % names.dnsdomain)
+ message("DOMAIN SID: %s" % str(domainsid))
+ message("Admin password: %s" % adminpass)
+
+ result = ProvisionResult()
+ result.domaindn = domaindn
+ result.paths = paths
+ result.lp = lp
+ result.samdb = samdb
+ return result
+
+
+def provision_become_dc(setup_dir=None,
+ smbconf=None, targetdir=None, realm=None,
+ rootdn=None, domaindn=None, schemadn=None, configdn=None,
+ serverdn=None,
+ domain=None, hostname=None, domainsid=None,
+ adminpass=None, krbtgtpass=None, domainguid=None,
+ policyguid=None, invocationid=None, machinepass=None,
+ dnspass=None, root=None, nobody=None, nogroup=None, users=None,
+ wheel=None, backup=None, aci=None, serverrole=None,
+ ldap_backend=None, ldap_backend_type=None, sitename=None):
+
+ def message(text):
+ """print a message if quiet is not set."""
+ print text
+
+ return provision(setup_dir, message, system_session(), None,
+ smbconf=smbconf, targetdir=targetdir, samdb_fill=FILL_DRS, realm=realm,
+ rootdn=rootdn, domaindn=domaindn, schemadn=schemadn, configdn=configdn, serverdn=serverdn,
+ domain=domain, hostname=hostname, hostip="127.0.0.1", domainsid=domainsid, machinepass=machinepass, serverrole="domain controller", sitename=sitename)
+
+
+def setup_db_config(setup_path, dbdir):
+ """Setup a Berkeley database.
+
+ :param setup_path: Setup path function.
+ :param dbdir: Database directory."""
+ if not os.path.isdir(os.path.join(dbdir, "bdb-logs")):
+ os.makedirs(os.path.join(dbdir, "bdb-logs"), 0700)
+ if not os.path.isdir(os.path.join(dbdir, "tmp")):
+ os.makedirs(os.path.join(dbdir, "tmp"), 0700)
+
+ setup_file(setup_path("DB_CONFIG"), os.path.join(dbdir, "DB_CONFIG"),
+ {"LDAPDBDIR": dbdir})
+
+
+
+def provision_backend(setup_dir=None, message=None,
+ smbconf=None, targetdir=None, realm=None,
+ rootdn=None, domaindn=None, schemadn=None, configdn=None,
+ domain=None, hostname=None, adminpass=None, root=None, serverrole=None,
+ ldap_backend_type=None, ldap_backend_port=None,
+ ol_mmr_urls=None):
+
+ def setup_path(file):
+ return os.path.join(setup_dir, file)
+
+ if hostname is None:
+ hostname = socket.gethostname().split(".")[0].lower()
+
+ if root is None:
+ root = findnss(pwd.getpwnam, ["root"])[0]
+
+ if adminpass is None:
+ adminpass = misc.random_password(12)
+
+ if targetdir is not None:
+ if (not os.path.exists(os.path.join(targetdir, "etc"))):
+ os.makedirs(os.path.join(targetdir, "etc"))
+ smbconf = os.path.join(targetdir, "etc", "smb.conf")
+
+ # only install a new smb.conf if there isn't one there already
+ if not os.path.exists(smbconf):
+ make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole,
+ targetdir)
+
+ lp = param.LoadParm()
+ lp.load(smbconf)
+
+ names = guess_names(lp=lp, hostname=hostname, domain=domain,
+ dnsdomain=realm, serverrole=serverrole,
+ rootdn=rootdn, domaindn=domaindn, configdn=configdn,
+ schemadn=schemadn)
+
+ paths = provision_paths_from_lp(lp, names.dnsdomain)
+
+ if not os.path.isdir(paths.ldapdir):
+ os.makedirs(paths.ldapdir, 0700)
+ schemadb_path = os.path.join(paths.ldapdir, "schema-tmp.ldb")
+ try:
+ os.unlink(schemadb_path)
+ except:
+ pass
+
+ schemadb = Ldb(schemadb_path, lp=lp)
+
+ prefixmap = open(setup_path("prefixMap.txt"), 'r').read()
+
+ setup_add_ldif(schemadb, setup_path("provision_schema_basedn.ldif"),
+ {"SCHEMADN": names.schemadn,
+ "ACI": "#",
+ })
+ setup_modify_ldif(schemadb,
+ setup_path("provision_schema_basedn_modify.ldif"), \
+ {"SCHEMADN": names.schemadn,
+ "NETBIOSNAME": names.netbiosname,
+ "DEFAULTSITE": DEFAULTSITE,
+ "CONFIGDN": names.configdn,
+ "SERVERDN": names.serverdn,
+ "PREFIXMAP_B64": b64encode(prefixmap)
+ })
+
+ setup_add_ldif(schemadb, setup_path("schema_samba4.ldif"),
+ {"SCHEMADN": names.schemadn })
+ setup_add_ldif(schemadb, setup_path("schema.ldif"),
+ {"SCHEMADN": names.schemadn})
+
+ if ldap_backend_type == "fedora-ds":
+ if ldap_backend_port is not None:
+ serverport = "ServerPort=%d" % ldap_backend_port
+ else:
+ serverport = ""
+
+ setup_file(setup_path("fedorads.inf"), paths.fedoradsinf,
+ {"ROOT": root,
+ "HOSTNAME": hostname,
+ "DNSDOMAIN": names.dnsdomain,
+ "LDAPDIR": paths.ldapdir,
+ "DOMAINDN": names.domaindn,
+ "LDAPMANAGERDN": names.ldapmanagerdn,
+ "LDAPMANAGERPASS": adminpass,
+ "SERVERPORT": serverport})
+
+ setup_file(setup_path("fedorads-partitions.ldif"), paths.fedoradspartitions,
+ {"CONFIGDN": names.configdn,
+ "SCHEMADN": names.schemadn,
+ })
+
+ mapping = "schema-map-fedora-ds-1.0"
+ backend_schema = "99_ad.ldif"
+
+ slapdcommand="Initailise Fedora DS with: setup-ds.pl --file=%s" % paths.fedoradsinf
+
+ ldapuser = "--simple-bind-dn=" + names.ldapmanagerdn
+
+ elif ldap_backend_type == "openldap":
+ attrs = ["linkID", "lDAPDisplayName"]
+ res = schemadb.search(expression="(&(&(linkID=*)(!(linkID:1.2.840.113556.1.4.803:=1)))(objectclass=attributeSchema))", base=names.schemadn, scope=SCOPE_SUBTREE, attrs=attrs)
+
+ memberof_config = "# Generated from schema in %s\n" % schemadb_path
+ refint_attributes = ""
+ for i in range (0, len(res)):
+ expression = "(&(objectclass=attributeSchema)(linkID=%d))" % (int(res[i]["linkID"][0])+1)
+ target = schemadb.searchone(basedn=names.schemadn,
+ expression=expression,
+ attribute="lDAPDisplayName",
+ scope=SCOPE_SUBTREE)
+ if target is not None:
+ refint_attributes = refint_attributes + " " + target + " " + res[i]["lDAPDisplayName"][0]
+
+ memberof_config += read_and_sub_file(setup_path("memberof.conf"),
+ { "MEMBER_ATTR" : str(res[i]["lDAPDisplayName"][0]),
+ "MEMBEROF_ATTR" : str(target) })
+
+ refint_config = read_and_sub_file(setup_path("refint.conf"),
+ { "LINK_ATTRS" : refint_attributes})
+
+# generate serverids, ldap-urls and syncrepl-blocks for mmr hosts
+ mmr_on_config = ""
+ mmr_replicator_acl = ""
+ mmr_serverids_config = ""
+ mmr_syncrepl_schema_config = ""
+ mmr_syncrepl_config_config = ""
+ mmr_syncrepl_user_config = ""
+
+ if ol_mmr_urls is not None:
+ # For now, make these equal
+ mmr_pass = adminpass
+
+ url_list=filter(None,ol_mmr_urls.split(' '))
+ if (len(url_list) == 1):
+ url_list=filter(None,ol_mmr_urls.split(','))
+
+
+ mmr_on_config = "MirrorMode On"
+ mmr_replicator_acl = " by dn=cn=replicator,cn=samba read"
+ serverid=0
+ for url in url_list:
+ serverid=serverid+1
+ mmr_serverids_config += read_and_sub_file(setup_path("mmr_serverids.conf"),
+ { "SERVERID" : str(serverid),
+ "LDAPSERVER" : url })
+ rid=serverid*10
+ rid=rid+1
+ mmr_syncrepl_schema_config += read_and_sub_file(setup_path("mmr_syncrepl.conf"),
+ { "RID" : str(rid),
+ "MMRDN": names.schemadn,
+ "LDAPSERVER" : url,
+ "MMR_PASSWORD": mmr_pass})
+
+ rid=rid+1
+ mmr_syncrepl_config_config += read_and_sub_file(setup_path("mmr_syncrepl.conf"),
+ { "RID" : str(rid),
+ "MMRDN": names.configdn,
+ "LDAPSERVER" : url,
+ "MMR_PASSWORD": mmr_pass})
+
+ rid=rid+1
+ mmr_syncrepl_user_config += read_and_sub_file(setup_path("mmr_syncrepl.conf"),
+ { "RID" : str(rid),
+ "MMRDN": names.domaindn,
+ "LDAPSERVER" : url,
+ "MMR_PASSWORD": mmr_pass })
+
+
+ setup_file(setup_path("slapd.conf"), paths.slapdconf,
+ {"DNSDOMAIN": names.dnsdomain,
+ "LDAPDIR": paths.ldapdir,
+ "DOMAINDN": names.domaindn,
+ "CONFIGDN": names.configdn,
+ "SCHEMADN": names.schemadn,
+ "MEMBEROF_CONFIG": memberof_config,
+ "MIRRORMODE": mmr_on_config,
+ "REPLICATOR_ACL": mmr_replicator_acl,
+ "MMR_SERVERIDS_CONFIG": mmr_serverids_config,
+ "MMR_SYNCREPL_SCHEMA_CONFIG": mmr_syncrepl_schema_config,
+ "MMR_SYNCREPL_CONFIG_CONFIG": mmr_syncrepl_config_config,
+ "MMR_SYNCREPL_USER_CONFIG": mmr_syncrepl_user_config,
+ "REFINT_CONFIG": refint_config})
+ setup_file(setup_path("modules.conf"), paths.modulesconf,
+ {"REALM": names.realm})
+
+ setup_db_config(setup_path, os.path.join(paths.ldapdir, "db", "user"))
+ setup_db_config(setup_path, os.path.join(paths.ldapdir, "db", "config"))
+ setup_db_config(setup_path, os.path.join(paths.ldapdir, "db", "schema"))
+
+ if not os.path.exists(os.path.join(paths.ldapdir, "db", "samba", "cn=samba")):
+ os.makedirs(os.path.join(paths.ldapdir, "db", "samba", "cn=samba"), 0700)
+
+ setup_file(setup_path("cn=samba.ldif"),
+ os.path.join(paths.ldapdir, "db", "samba", "cn=samba.ldif"),
+ { "UUID": str(uuid.uuid4()),
+ "LDAPTIME": timestring(int(time.time()))} )
+ setup_file(setup_path("cn=samba-admin.ldif"),
+ os.path.join(paths.ldapdir, "db", "samba", "cn=samba", "cn=samba-admin.ldif"),
+ {"LDAPADMINPASS_B64": b64encode(adminpass),
+ "UUID": str(uuid.uuid4()),
+ "LDAPTIME": timestring(int(time.time()))} )
+
+ if ol_mmr_urls is not None:
+ setup_file(setup_path("cn=replicator.ldif"),
+ os.path.join(paths.ldapdir, "db", "samba", "cn=samba", "cn=replicator.ldif"),
+ {"MMR_PASSWORD_B64": b64encode(mmr_pass),
+ "UUID": str(uuid.uuid4()),
+ "LDAPTIME": timestring(int(time.time()))} )
+
+
+
+ mapping = "schema-map-openldap-2.3"
+ backend_schema = "backend-schema.schema"
+
+ ldapi_uri = "ldapi://" + urllib.quote(os.path.join(paths.private_dir, "ldap", "ldapi"), safe="")
+ if ldap_backend_port is not None:
+ server_port_string = " -h ldap://0.0.0.0:%d" % ldap_backend_port
+ else:
+ server_port_string = ""
+
+ slapdcommand="Start slapd with: slapd -f " + paths.ldapdir + "/slapd.conf -h " + ldapi_uri + server_port_string
+
+ ldapuser = "--username=samba-admin"
+
+
+ schema_command = "bin/ad2oLschema --option=convert:target=" + ldap_backend_type + " -I " + setup_path(mapping) + " -H tdb://" + schemadb_path + " -O " + os.path.join(paths.ldapdir, backend_schema)
+
+ os.system(schema_command)
+
+ message("Your %s Backend for Samba4 is now configured, and is ready to be started" % ldap_backend_type)
+ message("Server Role: %s" % serverrole)
+ message("Hostname: %s" % names.hostname)
+ message("DNS Domain: %s" % names.dnsdomain)
+ message("Base DN: %s" % names.domaindn)
+
+ if ldap_backend_type == "openldap":
+ message("LDAP admin user: samba-admin")
+ else:
+ message("LDAP admin DN: %s" % names.ldapmanagerdn)
+
+ message("LDAP admin password: %s" % adminpass)
+ message(slapdcommand)
+ message("Run provision with: --ldap-backend=ldapi --ldap-backend-type=" + ldap_backend_type + " --password=" + adminpass + " " + ldapuser)
+
+def create_phpldapadmin_config(path, setup_path, ldapi_uri):
+ """Create a PHP LDAP admin configuration file.
+
+ :param path: Path to write the configuration to.
+ :param setup_path: Function to generate setup paths.
+ """
+ setup_file(setup_path("phpldapadmin-config.php"), path,
+ {"S4_LDAPI_URI": ldapi_uri})
+
+
+def create_zone_file(path, setup_path, dnsdomain, domaindn,
+ hostip, hostip6, hostname, dnspass, realm, domainguid, hostguid):
+ """Write out a DNS zone file, from the info in the current database.
+
+ :param path: Path of the new zone file.
+ :param setup_path: Setup path function.
+ :param dnsdomain: DNS Domain name
+ :param domaindn: DN of the Domain
+ :param hostip: Local IPv4 IP
+ :param hostip6: Local IPv6 IP
+ :param hostname: Local hostname
+ :param dnspass: Password for DNS
+ :param realm: Realm name
+ :param domainguid: GUID of the domain.
+ :param hostguid: GUID of the host.
+ """
+ assert isinstance(domainguid, str)
+
+ if hostip6 is not None:
+ hostip6_base_line = " IN AAAA " + hostip6
+ hostip6_host_line = hostname + " IN AAAA " + hostip6
+ else:
+ hostip6_base_line = ""
+ hostip6_host_line = ""
+
+ setup_file(setup_path("provision.zone"), path, {
+ "DNSPASS_B64": b64encode(dnspass),
+ "HOSTNAME": hostname,
+ "DNSDOMAIN": dnsdomain,
+ "REALM": realm,
+ "HOSTIP": hostip,
+ "DOMAINGUID": domainguid,
+ "DATESTRING": time.strftime("%Y%m%d%H"),
+ "DEFAULTSITE": DEFAULTSITE,
+ "HOSTGUID": hostguid,
+ "HOSTIP6_BASE_LINE": hostip6_base_line,
+ "HOSTIP6_HOST_LINE": hostip6_host_line,
+ })
+
+
+def create_named_conf(path, setup_path, realm, dnsdomain,
+ private_dir):
+ """Write out a file containing zone statements suitable for inclusion in a
+ named.conf file (including GSS-TSIG configuration).
+
+ :param path: Path of the new named.conf file.
+ :param setup_path: Setup path function.
+ :param realm: Realm name
+ :param dnsdomain: DNS Domain name
+ :param private_dir: Path to private directory
+ :param keytab_name: File name of DNS keytab file
+ """
+
+ setup_file(setup_path("named.conf"), path, {
+ "DNSDOMAIN": dnsdomain,
+ "REALM": realm,
+ "REALM_WC": "*." + ".".join(realm.split(".")[1:]),
+ "PRIVATE_DIR": private_dir
+ })
+
+def create_named_txt(path, setup_path, realm, dnsdomain,
+ private_dir, keytab_name):
+ """Write out a file containing zone statements suitable for inclusion in a
+ named.conf file (including GSS-TSIG configuration).
+
+ :param path: Path of the new named.conf file.
+ :param setup_path: Setup path function.
+ :param realm: Realm name
+ :param dnsdomain: DNS Domain name
+ :param private_dir: Path to private directory
+ :param keytab_name: File name of DNS keytab file
+ """
+
+ setup_file(setup_path("named.txt"), path, {
+ "DNSDOMAIN": dnsdomain,
+ "REALM": realm,
+ "DNS_KEYTAB": keytab_name,
+ "DNS_KEYTAB_ABS": os.path.join(private_dir, keytab_name),
+ "PRIVATE_DIR": private_dir
+ })
+
+def create_krb5_conf(path, setup_path, dnsdomain, hostname, realm):
+ """Write out a file containing zone statements suitable for inclusion in a
+ named.conf file (including GSS-TSIG configuration).
+
+ :param path: Path of the new named.conf file.
+ :param setup_path: Setup path function.
+ :param dnsdomain: DNS Domain name
+ :param hostname: Local hostname
+ :param realm: Realm name
+ """
+
+ setup_file(setup_path("krb5.conf"), path, {
+ "DNSDOMAIN": dnsdomain,
+ "HOSTNAME": hostname,
+ "REALM": realm,
+ })
+
+
+def load_schema(setup_path, samdb, schemadn, netbiosname, configdn, sitename,
+ serverdn, servername):
+ """Load schema for the SamDB.
+
+ :param samdb: Load a schema into a SamDB.
+ :param setup_path: Setup path function.
+ :param schemadn: DN of the schema
+ :param netbiosname: NetBIOS name of the host.
+ :param configdn: DN of the configuration
+ :param serverdn: DN of the server
+ :param servername: Host name of the server
+ """
+ schema_data = open(setup_path("schema.ldif"), 'r').read()
+ schema_data += open(setup_path("schema_samba4.ldif"), 'r').read()
+ schema_data = substitute_var(schema_data, {"SCHEMADN": schemadn})
+ check_all_substituted(schema_data)
+ prefixmap = open(setup_path("prefixMap.txt"), 'r').read()
+ prefixmap = b64encode(prefixmap)
+
+ head_data = open(setup_path("provision_schema_basedn_modify.ldif"), 'r').read()
+ head_data = substitute_var(head_data, {
+ "SCHEMADN": schemadn,
+ "NETBIOSNAME": netbiosname,
+ "CONFIGDN": configdn,
+ "DEFAULTSITE": sitename,
+ "PREFIXMAP_B64": prefixmap,
+ "SERVERDN": serverdn,
+ "SERVERNAME": servername,
+ })
+ check_all_substituted(head_data)
+ samdb.attach_schema_from_ldif(head_data, schema_data)
+
diff --git a/source4/scripting/python/samba/samba3.py b/source4/scripting/python/samba/samba3.py
new file mode 100644
index 0000000000..0e0c29dac8
--- /dev/null
+++ b/source4/scripting/python/samba/samba3.py
@@ -0,0 +1,711 @@
+#!/usr/bin/python
+
+# Unix SMB/CIFS implementation.
+# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+"""Support for reading Samba 3 data files."""
+
+__docformat__ = "restructuredText"
+
+REGISTRY_VALUE_PREFIX = "SAMBA_REGVAL"
+REGISTRY_DB_VERSION = 1
+
+import os
+import tdb
+
+
+class TdbDatabase(object):
+ """Simple Samba 3 TDB database reader."""
+ def __init__(self, file):
+ """Open a file.
+
+ :param file: Path of the file to open.
+ """
+ self.tdb = tdb.Tdb(file, flags=os.O_RDONLY)
+ self._check_version()
+
+ def _check_version(self):
+ pass
+
+ def close(self):
+ """Close resources associated with this object."""
+ self.tdb.close()
+
+
+class Registry(TdbDatabase):
+ """Simple read-only support for reading the Samba3 registry.
+
+ :note: This object uses the same syntax for registry key paths as
+ Samba 3. This particular format uses forward slashes for key path
+ separators and abbreviations for the predefined key names.
+ e.g.: HKLM/Software/Bar.
+ """
+ def __len__(self):
+ """Return the number of keys."""
+ return len(self.keys())
+
+ def keys(self):
+ """Return list with all the keys."""
+ return [k.rstrip("\x00") for k in self.tdb.keys() if not k.startswith(REGISTRY_VALUE_PREFIX)]
+
+ def subkeys(self, key):
+ """Retrieve the subkeys for the specified key.
+
+ :param key: Key path.
+ :return: list with key names
+ """
+ data = self.tdb.get("%s\x00" % key)
+ if data is None:
+ return []
+ import struct
+ (num, ) = struct.unpack("<L", data[0:4])
+ keys = data[4:].split("\0")
+ assert keys[-1] == ""
+ keys.pop()
+ assert len(keys) == num
+ return keys
+
+ def values(self, key):
+ """Return a dictionary with the values set for a specific key.
+
+ :param key: Key to retrieve values for.
+ :return: Dictionary with value names as key, tuple with type and
+ data as value."""
+ data = self.tdb.get("%s/%s\x00" % (REGISTRY_VALUE_PREFIX, key))
+ if data is None:
+ return {}
+ ret = {}
+ import struct
+ (num, ) = struct.unpack("<L", data[0:4])
+ data = data[4:]
+ for i in range(num):
+ # Value name
+ (name, data) = data.split("\0", 1)
+
+ (type, ) = struct.unpack("<L", data[0:4])
+ data = data[4:]
+ (value_len, ) = struct.unpack("<L", data[0:4])
+ data = data[4:]
+
+ ret[name] = (type, data[:value_len])
+ data = data[value_len:]
+
+ return ret
+
+
+class PolicyDatabase(TdbDatabase):
+ """Samba 3 Account Policy database reader."""
+ def __init__(self, file):
+ """Open a policy database
+
+ :param file: Path to the file to open.
+ """
+ super(PolicyDatabase, self).__init__(file)
+ self.min_password_length = self.tdb.fetch_uint32("min password length\x00")
+ self.password_history = self.tdb.fetch_uint32("password history\x00")
+ self.user_must_logon_to_change_password = self.tdb.fetch_uint32("user must logon to change pasword\x00")
+ self.maximum_password_age = self.tdb.fetch_uint32("maximum password age\x00")
+ self.minimum_password_age = self.tdb.fetch_uint32("minimum password age\x00")
+ self.lockout_duration = self.tdb.fetch_uint32("lockout duration\x00")
+ self.reset_count_minutes = self.tdb.fetch_uint32("reset count minutes\x00")
+ self.bad_lockout_minutes = self.tdb.fetch_uint32("bad lockout minutes\x00")
+ self.disconnect_time = self.tdb.fetch_int32("disconnect time\x00")
+ self.refuse_machine_password_change = self.tdb.fetch_uint32("refuse machine password change\x00")
+
+ # FIXME: Read privileges as well
+
+
+GROUPDB_DATABASE_VERSION_V1 = 1 # native byte format.
+GROUPDB_DATABASE_VERSION_V2 = 2 # le format.
+
+GROUP_PREFIX = "UNIXGROUP/"
+
+# Alias memberships are stored reverse, as memberships. The performance
+# critical operation is to determine the aliases a SID is member of, not
+# listing alias members. So we store a list of alias SIDs a SID is member of
+# hanging of the member as key.
+MEMBEROF_PREFIX = "MEMBEROF/"
+
+class GroupMappingDatabase(TdbDatabase):
+ """Samba 3 group mapping database reader."""
+ def _check_version(self):
+ assert self.tdb.fetch_int32("INFO/version\x00") in (GROUPDB_DATABASE_VERSION_V1, GROUPDB_DATABASE_VERSION_V2)
+
+ def groupsids(self):
+ """Retrieve the SIDs for the groups in this database.
+
+ :return: List with sids as strings.
+ """
+ for k in self.tdb.keys():
+ if k.startswith(GROUP_PREFIX):
+ yield k[len(GROUP_PREFIX):].rstrip("\0")
+
+ def get_group(self, sid):
+ """Retrieve the group mapping information for a particular group.
+
+ :param sid: SID of the group
+ :return: None if the group can not be found, otherwise
+ a tuple with gid, sid_name_use, the NT name and comment.
+ """
+ data = self.tdb.get("%s%s\0" % (GROUP_PREFIX, sid))
+ if data is None:
+ return data
+ import struct
+ (gid, sid_name_use) = struct.unpack("<lL", data[0:8])
+ (nt_name, comment, _) = data[8:].split("\0")
+ return (gid, sid_name_use, nt_name, comment)
+
+ def aliases(self):
+ """Retrieve the aliases in this database."""
+ for k in self.tdb.keys():
+ if k.startswith(MEMBEROF_PREFIX):
+ yield k[len(MEMBEROF_PREFIX):].rstrip("\0")
+
+
+# High water mark keys
+IDMAP_HWM_GROUP = "GROUP HWM\0"
+IDMAP_HWM_USER = "USER HWM\0"
+
+IDMAP_GROUP_PREFIX = "GID "
+IDMAP_USER_PREFIX = "UID "
+
+# idmap version determines auto-conversion
+IDMAP_VERSION_V2 = 2
+
+class IdmapDatabase(TdbDatabase):
+ """Samba 3 ID map database reader."""
+ def _check_version(self):
+ assert self.tdb.fetch_int32("IDMAP_VERSION\0") == IDMAP_VERSION_V2
+
+ def uids(self):
+ """Retrieve a list of all uids in this database."""
+ for k in self.tdb.keys():
+ if k.startswith(IDMAP_USER_PREFIX):
+ yield int(k[len(IDMAP_USER_PREFIX):].rstrip("\0"))
+
+ def gids(self):
+ """Retrieve a list of all gids in this database."""
+ for k in self.tdb.keys():
+ if k.startswith(IDMAP_GROUP_PREFIX):
+ yield int(k[len(IDMAP_GROUP_PREFIX):].rstrip("\0"))
+
+ def get_user_sid(self, uid):
+ """Retrieve the SID associated with a particular uid.
+
+ :param uid: UID to retrieve SID for.
+ :return: A SID or None if no mapping was found.
+ """
+ data = self.tdb.get("%s%d\0" % (IDMAP_USER_PREFIX, uid))
+ if data is None:
+ return data
+ return data.rstrip("\0")
+
+ def get_group_sid(self, gid):
+ data = self.tdb.get("%s%d\0" % (IDMAP_GROUP_PREFIX, gid))
+ if data is None:
+ return data
+ return data.rstrip("\0")
+
+ def get_user_hwm(self):
+ """Obtain the user high-water mark."""
+ return self.tdb.fetch_uint32(IDMAP_HWM_USER)
+
+ def get_group_hwm(self):
+ """Obtain the group high-water mark."""
+ return self.tdb.fetch_uint32(IDMAP_HWM_GROUP)
+
+
+class SecretsDatabase(TdbDatabase):
+ """Samba 3 Secrets database reader."""
+ def get_auth_password(self):
+ return self.tdb.get("SECRETS/AUTH_PASSWORD")
+
+ def get_auth_domain(self):
+ return self.tdb.get("SECRETS/AUTH_DOMAIN")
+
+ def get_auth_user(self):
+ return self.tdb.get("SECRETS/AUTH_USER")
+
+ def get_domain_guid(self, host):
+ return self.tdb.get("SECRETS/DOMGUID/%s" % host)
+
+ def ldap_dns(self):
+ for k in self.tdb.keys():
+ if k.startswith("SECRETS/LDAP_BIND_PW/"):
+ yield k[len("SECRETS/LDAP_BIND_PW/"):].rstrip("\0")
+
+ def domains(self):
+ """Iterate over domains in this database.
+
+ :return: Iterator over the names of domains in this database.
+ """
+ for k in self.tdb.keys():
+ if k.startswith("SECRETS/SID/"):
+ yield k[len("SECRETS/SID/"):].rstrip("\0")
+
+ def get_ldap_bind_pw(self, host):
+ return self.tdb.get("SECRETS/LDAP_BIND_PW/%s" % host)
+
+ def get_afs_keyfile(self, host):
+ return self.tdb.get("SECRETS/AFS_KEYFILE/%s" % host)
+
+ def get_machine_sec_channel_type(self, host):
+ return self.tdb.fetch_uint32("SECRETS/MACHINE_SEC_CHANNEL_TYPE/%s" % host)
+
+ def get_machine_last_change_time(self, host):
+ return self.tdb.fetch_uint32("SECRETS/MACHINE_LAST_CHANGE_TIME/%s" % host)
+
+ def get_machine_password(self, host):
+ return self.tdb.get("SECRETS/MACHINE_PASSWORD/%s" % host)
+
+ def get_machine_acc(self, host):
+ return self.tdb.get("SECRETS/$MACHINE.ACC/%s" % host)
+
+ def get_domtrust_acc(self, host):
+ return self.tdb.get("SECRETS/$DOMTRUST.ACC/%s" % host)
+
+ def trusted_domains(self):
+ for k in self.tdb.keys():
+ if k.startswith("SECRETS/$DOMTRUST.ACC/"):
+ yield k[len("SECRETS/$DOMTRUST.ACC/"):].rstrip("\0")
+
+ def get_random_seed(self):
+ return self.tdb.get("INFO/random_seed")
+
+ def get_sid(self, host):
+ return self.tdb.get("SECRETS/SID/%s" % host.upper())
+
+
+SHARE_DATABASE_VERSION_V1 = 1
+SHARE_DATABASE_VERSION_V2 = 2
+
+class ShareInfoDatabase(TdbDatabase):
+ """Samba 3 Share Info database reader."""
+ def _check_version(self):
+ assert self.tdb.fetch_int32("INFO/version\0") in (SHARE_DATABASE_VERSION_V1, SHARE_DATABASE_VERSION_V2)
+
+ def get_secdesc(self, name):
+ """Obtain the security descriptor on a particular share.
+
+ :param name: Name of the share
+ """
+ secdesc = self.tdb.get("SECDESC/%s" % name)
+ # FIXME: Run ndr_pull_security_descriptor
+ return secdesc
+
+
+class Shares(object):
+ """Container for share objects."""
+ def __init__(self, lp, shareinfo):
+ self.lp = lp
+ self.shareinfo = shareinfo
+
+ def __len__(self):
+ """Number of shares."""
+ return len(self.lp) - 1
+
+ def __iter__(self):
+ """Iterate over the share names."""
+ return self.lp.__iter__()
+
+
+ACB_DISABLED = 0x00000001
+ACB_HOMDIRREQ = 0x00000002
+ACB_PWNOTREQ = 0x00000004
+ACB_TEMPDUP = 0x00000008
+ACB_NORMAL = 0x00000010
+ACB_MNS = 0x00000020
+ACB_DOMTRUST = 0x00000040
+ACB_WSTRUST = 0x00000080
+ACB_SVRTRUST = 0x00000100
+ACB_PWNOEXP = 0x00000200
+ACB_AUTOLOCK = 0x00000400
+ACB_ENC_TXT_PWD_ALLOWED = 0x00000800
+ACB_SMARTCARD_REQUIRED = 0x00001000
+ACB_TRUSTED_FOR_DELEGATION = 0x00002000
+ACB_NOT_DELEGATED = 0x00004000
+ACB_USE_DES_KEY_ONLY = 0x00008000
+ACB_DONT_REQUIRE_PREAUTH = 0x00010000
+ACB_PW_EXPIRED = 0x00020000
+ACB_NO_AUTH_DATA_REQD = 0x00080000
+
+acb_info_mapping = {
+ 'N': ACB_PWNOTREQ, # 'N'o password.
+ 'D': ACB_DISABLED, # 'D'isabled.
+ 'H': ACB_HOMDIRREQ, # 'H'omedir required.
+ 'T': ACB_TEMPDUP, # 'T'emp account.
+ 'U': ACB_NORMAL, # 'U'ser account (normal).
+ 'M': ACB_MNS, # 'M'NS logon user account. What is this ?
+ 'W': ACB_WSTRUST, # 'W'orkstation account.
+ 'S': ACB_SVRTRUST, # 'S'erver account.
+ 'L': ACB_AUTOLOCK, # 'L'ocked account.
+ 'X': ACB_PWNOEXP, # No 'X'piry on password
+ 'I': ACB_DOMTRUST, # 'I'nterdomain trust account.
+ ' ': 0
+ }
+
+def decode_acb(text):
+ """Decode a ACB field.
+
+ :param text: ACB text
+ :return: integer with flags set.
+ """
+ assert not "[" in text and not "]" in text
+ ret = 0
+ for x in text:
+ ret |= acb_info_mapping[x]
+ return ret
+
+
+class SAMUser(object):
+ """Samba 3 SAM User.
+
+ :note: Unknown or unset fields are set to None.
+ """
+ def __init__(self, name, uid=None, lm_password=None, nt_password=None, acct_ctrl=None,
+ last_change_time=None, nt_username=None, fullname=None, logon_time=None, logoff_time=None,
+ acct_desc=None, group_rid=None, bad_password_count=None, logon_count=None,
+ domain=None, dir_drive=None, munged_dial=None, homedir=None, logon_script=None,
+ profile_path=None, workstations=None, kickoff_time=None, bad_password_time=None,
+ pass_last_set_time=None, pass_can_change_time=None, pass_must_change_time=None,
+ user_rid=None, unknown_6=None, nt_password_history=None,
+ unknown_str=None, hours=None, logon_divs=None):
+ self.username = name
+ self.uid = uid
+ self.lm_password = lm_password
+ self.nt_password = nt_password
+ self.acct_ctrl = acct_ctrl
+ self.pass_last_set_time = last_change_time
+ self.nt_username = nt_username
+ self.fullname = fullname
+ self.logon_time = logon_time
+ self.logoff_time = logoff_time
+ self.acct_desc = acct_desc
+ self.group_rid = group_rid
+ self.bad_password_count = bad_password_count
+ self.logon_count = logon_count
+ self.domain = domain
+ self.dir_drive = dir_drive
+ self.munged_dial = munged_dial
+ self.homedir = homedir
+ self.logon_script = logon_script
+ self.profile_path = profile_path
+ self.workstations = workstations
+ self.kickoff_time = kickoff_time
+ self.bad_password_time = bad_password_time
+ self.pass_can_change_time = pass_can_change_time
+ self.pass_must_change_time = pass_must_change_time
+ self.user_rid = user_rid
+ self.unknown_6 = unknown_6
+ self.nt_password_history = nt_password_history
+ self.unknown_str = unknown_str
+ self.hours = hours
+ self.logon_divs = logon_divs
+
+ def __eq__(self, other):
+ if not isinstance(other, SAMUser):
+ return False
+ return self.__dict__ == other.__dict__
+
+
+class SmbpasswdFile(object):
+ """Samba 3 smbpasswd file reader."""
+ def __init__(self, file):
+ self.users = {}
+ f = open(file, 'r')
+ for l in f.readlines():
+ if len(l) == 0 or l[0] == "#":
+ continue # Skip comments and blank lines
+ parts = l.split(":")
+ username = parts[0]
+ uid = int(parts[1])
+ acct_ctrl = 0
+ last_change_time = None
+ if parts[2] == "NO PASSWORD":
+ acct_ctrl |= ACB_PWNOTREQ
+ lm_password = None
+ elif parts[2][0] in ("*", "X"):
+ # No password set
+ lm_password = None
+ else:
+ lm_password = parts[2]
+
+ if parts[3][0] in ("*", "X"):
+ # No password set
+ nt_password = None
+ else:
+ nt_password = parts[3]
+
+ if parts[4][0] == '[':
+ assert "]" in parts[4]
+ acct_ctrl |= decode_acb(parts[4][1:-1])
+ if parts[5].startswith("LCT-"):
+ last_change_time = int(parts[5][len("LCT-"):], 16)
+ else: # old style file
+ if username[-1] == "$":
+ acct_ctrl &= ~ACB_NORMAL
+ acct_ctrl |= ACB_WSTRUST
+
+ self.users[username] = SAMUser(username, uid, lm_password, nt_password, acct_ctrl, last_change_time)
+
+ f.close()
+
+ def __len__(self):
+ return len(self.users)
+
+ def __getitem__(self, name):
+ return self.users[name]
+
+ def __iter__(self):
+ return iter(self.users)
+
+ def close(self): # For consistency
+ pass
+
+
+TDBSAM_FORMAT_STRING_V0 = "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
+TDBSAM_FORMAT_STRING_V1 = "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
+TDBSAM_FORMAT_STRING_V2 = "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
+TDBSAM_USER_PREFIX = "USER_"
+
+
+class LdapSam(object):
+ """Samba 3 LDAP passdb backend reader."""
+ def __init__(self, url):
+ self.ldap_url = ldap_url
+
+
+class TdbSam(TdbDatabase):
+ """Samba 3 TDB passdb backend reader."""
+ def _check_version(self):
+ self.version = self.tdb.fetch_uint32("INFO/version\0") or 0
+ assert self.version in (0, 1, 2)
+
+ def usernames(self):
+ """Iterate over the usernames in this Tdb database."""
+ for k in self.tdb.keys():
+ if k.startswith(TDBSAM_USER_PREFIX):
+ yield k[len(TDBSAM_USER_PREFIX):].rstrip("\0")
+
+ __iter__ = usernames
+
+ def __getitem__(self, name):
+ data = self.tdb["%s%s\0" % (TDBSAM_USER_PREFIX, name)]
+ user = SAMUser(name)
+ import struct
+
+ def unpack_string(data):
+ (length, ) = struct.unpack("<L", data[:4])
+ data = data[4:]
+ if length == 0:
+ return (None, data)
+ return (data[:length].rstrip("\0"), data[length:])
+
+ def unpack_int32(data):
+ (value, ) = struct.unpack("<l", data[:4])
+ return (value, data[4:])
+
+ def unpack_uint32(data):
+ (value, ) = struct.unpack("<L", data[:4])
+ return (value, data[4:])
+
+ def unpack_uint16(data):
+ (value, ) = struct.unpack("<H", data[:2])
+ return (value, data[2:])
+
+ (logon_time, data) = unpack_int32(data)
+ (logoff_time, data) = unpack_int32(data)
+ (kickoff_time, data) = unpack_int32(data)
+
+ if self.version > 0:
+ (bad_password_time, data) = unpack_int32(data)
+ if bad_password_time != 0:
+ user.bad_password_time = bad_password_time
+ (pass_last_set_time, data) = unpack_int32(data)
+ (pass_can_change_time, data) = unpack_int32(data)
+ (pass_must_change_time, data) = unpack_int32(data)
+
+ if logon_time != 0:
+ user.logon_time = logon_time
+ user.logoff_time = logoff_time
+ user.kickoff_time = kickoff_time
+ if pass_last_set_time != 0:
+ user.pass_last_set_time = pass_last_set_time
+ user.pass_can_change_time = pass_can_change_time
+
+ (user.username, data) = unpack_string(data)
+ (user.domain, data) = unpack_string(data)
+ (user.nt_username, data) = unpack_string(data)
+ (user.fullname, data) = unpack_string(data)
+ (user.homedir, data) = unpack_string(data)
+ (user.dir_drive, data) = unpack_string(data)
+ (user.logon_script, data) = unpack_string(data)
+ (user.profile_path, data) = unpack_string(data)
+ (user.acct_desc, data) = unpack_string(data)
+ (user.workstations, data) = unpack_string(data)
+ (user.unknown_str, data) = unpack_string(data)
+ (user.munged_dial, data) = unpack_string(data)
+
+ (user.user_rid, data) = unpack_int32(data)
+ (user.group_rid, data) = unpack_int32(data)
+
+ (user.lm_password, data) = unpack_string(data)
+ (user.nt_password, data) = unpack_string(data)
+
+ if self.version > 1:
+ (user.nt_password_history, data) = unpack_string(data)
+
+ (user.acct_ctrl, data) = unpack_uint16(data)
+ (_, data) = unpack_uint32(data) # remove_me field
+ (user.logon_divs, data) = unpack_uint16(data)
+ (hours, data) = unpack_string(data)
+ user.hours = []
+ for entry in hours:
+ for i in range(8):
+ user.hours.append(ord(entry) & (2 ** i) == (2 ** i))
+ (user.bad_password_count, data) = unpack_uint16(data)
+ (user.logon_count, data) = unpack_uint16(data)
+ (user.unknown_6, data) = unpack_uint32(data)
+ assert len(data) == 0
+ return user
+
+
+def shellsplit(text):
+ """Very simple shell-like line splitting.
+
+ :param text: Text to split.
+ :return: List with parts of the line as strings.
+ """
+ ret = list()
+ inquotes = False
+ current = ""
+ for c in text:
+ if c == "\"":
+ inquotes = not inquotes
+ elif c in ("\t", "\n", " ") and not inquotes:
+ ret.append(current)
+ current = ""
+ else:
+ current += c
+ if current != "":
+ ret.append(current)
+ return ret
+
+
+class WinsDatabase(object):
+ """Samba 3 WINS database reader."""
+ def __init__(self, file):
+ self.entries = {}
+ f = open(file, 'r')
+ assert f.readline().rstrip("\n") == "VERSION 1 0"
+ for l in f.readlines():
+ if l[0] == "#": # skip comments
+ continue
+ entries = shellsplit(l.rstrip("\n"))
+ name = entries[0]
+ ttl = int(entries[1])
+ i = 2
+ ips = []
+ while "." in entries[i]:
+ ips.append(entries[i])
+ i+=1
+ nb_flags = int(entries[i][:-1], 16)
+ assert not name in self.entries, "Name %s exists twice" % name
+ self.entries[name] = (ttl, ips, nb_flags)
+ f.close()
+
+ def __getitem__(self, name):
+ return self.entries[name]
+
+ def __len__(self):
+ return len(self.entries)
+
+ def __iter__(self):
+ return iter(self.entries)
+
+ def items(self):
+ """Return the entries in this WINS database."""
+ return self.entries.items()
+
+ def close(self): # for consistency
+ pass
+
+
+class Samba3(object):
+ """Samba 3 configuration and state data reader."""
+ def __init__(self, libdir, smbconfpath):
+ """Open the configuration and data for a Samba 3 installation.
+
+ :param libdir: Library directory
+ :param smbconfpath: Path to the smb.conf file.
+ """
+ self.smbconfpath = smbconfpath
+ self.libdir = libdir
+ import param
+ self.lp = param.ParamFile()
+ self.lp.read(self.smbconfpath)
+
+ def libdir_path(self, path):
+ if path[0] == "/" or path[0] == ".":
+ return path
+ return os.path.join(self.libdir, path)
+
+ def get_conf(self):
+ return self.lp
+
+ def get_sam_db(self):
+ lp = self.get_conf()
+ backends = str(lp.get("passdb backend")).split(" ")
+ if ":" in backends[0]:
+ (name, location) = backends[0].split(":", 2)
+ else:
+ name = backends[0]
+ location = None
+ if name == "smbpasswd":
+ return SmbpasswdFile(self.libdir_path(location or "smbpasswd"))
+ elif name == "tdbsam":
+ return TdbSam(self.libdir_path(location or "passdb.tdb"))
+ elif name == "ldapsam":
+ if location is not None:
+ return LdapSam("ldap:%s" % location)
+ return LdapSam(lp.get("ldap server"))
+ else:
+ raise NotImplementedError("unsupported passdb backend %s" % backends[0])
+
+ def get_policy_db(self):
+ return PolicyDatabase(self.libdir_path("account_policy.tdb"))
+
+ def get_registry(self):
+ return Registry(self.libdir_path("registry.tdb"))
+
+ def get_secrets_db(self):
+ return SecretsDatabase(self.libdir_path("secrets.tdb"))
+
+ def get_shareinfo_db(self):
+ return ShareInfoDatabase(self.libdir_path("share_info.tdb"))
+
+ def get_idmap_db(self):
+ return IdmapDatabase(self.libdir_path("winbindd_idmap.tdb"))
+
+ def get_wins_db(self):
+ return WinsDatabase(self.libdir_path("wins.dat"))
+
+ def get_shares(self):
+ return Shares(self.get_conf(), self.get_shareinfo_db())
+
+ def get_groupmapping_db(self):
+ return GroupMappingDatabase(self.libdir_path("group_mapping.tdb"))
diff --git a/source4/scripting/python/samba/samdb.py b/source4/scripting/python/samba/samdb.py
new file mode 100644
index 0000000000..4a64c2f76d
--- /dev/null
+++ b/source4/scripting/python/samba/samdb.py
@@ -0,0 +1,227 @@
+#!/usr/bin/python
+
+# Unix SMB/CIFS implementation.
+# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008
+#
+# Based on the original in EJS:
+# Copyright (C) Andrew Tridgell <tridge@samba.org> 2005
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+"""Convenience functions for using the SAM."""
+
+import samba
+import misc
+import ldb
+from samba.idmap import IDmapDB
+import pwd
+import time
+
+__docformat__ = "restructuredText"
+
+class SamDB(samba.Ldb):
+ """The SAM database."""
+
+ def __init__(self, url=None, session_info=None, credentials=None,
+ modules_dir=None, lp=None):
+ """Open the Sam Database.
+
+ :param url: URL of the database.
+ """
+ self.lp = lp
+ super(SamDB, self).__init__(session_info=session_info, credentials=credentials,
+ modules_dir=modules_dir, lp=lp)
+ assert misc.dsdb_set_global_schema(self) == 0
+ if url:
+ self.connect(url)
+ else:
+ self.connect(lp.get("sam database"))
+
+ def connect(self, url):
+ super(SamDB, self).connect(misc.private_path(self.lp, url))
+
+ def add_foreign(self, domaindn, sid, desc):
+ """Add a foreign security principle."""
+ add = """
+dn: CN=%s,CN=ForeignSecurityPrincipals,%s
+objectClass: top
+objectClass: foreignSecurityPrincipal
+description: %s
+ """ % (sid, domaindn, desc)
+ # deliberately ignore errors from this, as the records may
+ # already exist
+ for msg in self.parse_ldif(add):
+ self.add(msg[1])
+
+ def enable_account(self, user_dn):
+ """Enable an account.
+
+ :param user_dn: Dn of the account to enable.
+ """
+ res = self.search(user_dn, ldb.SCOPE_BASE, None, ["userAccountControl"])
+ assert len(res) == 1
+ userAccountControl = res[0]["userAccountControl"][0]
+ userAccountControl = int(userAccountControl)
+ if (userAccountControl & 0x2):
+ userAccountControl = userAccountControl & ~0x2 # remove disabled bit
+ if (userAccountControl & 0x20):
+ userAccountControl = userAccountControl & ~0x20 # remove 'no password required' bit
+
+ mod = """
+dn: %s
+changetype: modify
+replace: userAccountControl
+userAccountControl: %u
+""" % (user_dn, userAccountControl)
+ self.modify_ldif(mod)
+
+ def domain_dn(self):
+ # find the DNs for the domain and the domain users group
+ res = self.search("", scope=ldb.SCOPE_BASE,
+ expression="(defaultNamingContext=*)",
+ attrs=["defaultNamingContext"])
+ assert(len(res) == 1 and res[0]["defaultNamingContext"] is not None)
+ return res[0]["defaultNamingContext"][0]
+
+ def newuser(self, username, unixname, password):
+ """add a new user record.
+
+ :param username: Name of the new user.
+ :param unixname: Name of the unix user to map to.
+ :param password: Password for the new user
+ """
+ # connect to the sam
+ self.transaction_start()
+
+ domain_dn = self.domain_dn()
+ assert(domain_dn is not None)
+ user_dn = "CN=%s,CN=Users,%s" % (username, domain_dn)
+
+ #
+ # the new user record. note the reliance on the samdb module to fill
+ # in a sid, guid etc
+ #
+ # now the real work
+ self.add({"dn": user_dn,
+ "sAMAccountName": username,
+ "userPassword": password,
+ "objectClass": "user"})
+
+ res = self.search(user_dn, scope=ldb.SCOPE_BASE,
+ expression="objectclass=*",
+ attrs=["objectSid"])
+ assert(len(res) == 1)
+ user_sid = self.schema_format_value("objectSid", res[0]["objectSid"][0])
+
+
+ try:
+ idmap = IDmapDB(lp=self.lp)
+
+ user = pwd.getpwnam(unixname)
+ # setup ID mapping for this UID
+
+ idmap.setup_name_mapping(user_sid, idmap.TYPE_UID, user[2])
+
+ except KeyError:
+ pass
+
+ # modify the userAccountControl to remove the disabled bit
+ self.enable_account(user_dn)
+ self.transaction_commit()
+
+ def setpassword(self, filter, password):
+ """Set a password on a user record
+
+ :param filter: LDAP filter to find the user (eg samccountname=name)
+ :param password: Password for the user
+ """
+ # connect to the sam
+ self.transaction_start()
+
+ # find the DNs for the domain
+ res = self.search("", scope=ldb.SCOPE_BASE,
+ expression="(defaultNamingContext=*)",
+ attrs=["defaultNamingContext"])
+ assert(len(res) == 1 and res[0]["defaultNamingContext"] is not None)
+ domain_dn = res[0]["defaultNamingContext"][0]
+ assert(domain_dn is not None)
+
+ res = self.search(domain_dn, scope=ldb.SCOPE_SUBTREE,
+ expression=filter,
+ attrs=[])
+ assert(len(res) == 1)
+ user_dn = res[0].dn
+
+ setpw = """
+dn: %s
+changetype: modify
+replace: userPassword
+userPassword: %s
+""" % (user_dn, password)
+
+ self.modify_ldif(setpw)
+
+ # modify the userAccountControl to remove the disabled bit
+ self.enable_account(user_dn)
+ self.transaction_commit()
+
+ def set_domain_sid(self, sid):
+ """Change the domain SID used by this SamDB.
+
+ :param sid: The new domain sid to use.
+ """
+ misc.samdb_set_domain_sid(self, sid)
+
+ def attach_schema_from_ldif(self, pf, df):
+ misc.dsdb_attach_schema_from_ldif_file(self, pf, df)
+
+ def set_invocation_id(self, invocation_id):
+ """Set the invocation id for this SamDB handle.
+
+ :param invocation_id: GUID of the invocation id.
+ """
+ misc.dsdb_set_ntds_invocation_id(self, invocation_id)
+
+ def setexpiry(self, user, expiry_seconds, noexpiry):
+ """Set the password expiry for a user
+
+ :param expiry_seconds: expiry time from now in seconds
+ :param noexpiry: if set, then don't expire password
+ """
+ self.transaction_start();
+ res = self.search(base=self.domain_dn(), scope=ldb.SCOPE_SUBTREE,
+ expression=("(samAccountName=%s)" % user),
+ attrs=["userAccountControl", "accountExpires"])
+ assert len(res) == 1
+ userAccountControl = int(res[0]["userAccountControl"][0])
+ accountExpires = int(res[0]["accountExpires"][0])
+ if noexpiry:
+ userAccountControl = userAccountControl | 0x10000
+ accountExpires = 0
+ else:
+ userAccountControl = userAccountControl & ~0x10000
+ accountExpires = misc.unix2nttime(expiry_seconds + int(time.time()))
+
+ mod = """
+dn: %s
+changetype: modify
+replace: userAccountControl
+userAccountControl: %u
+replace: accountExpires
+accountExpires: %u
+""" % (res[0].dn, userAccountControl, accountExpires)
+ # now change the database
+ self.modify_ldif(mod)
+ self.transaction_commit();
diff --git a/source4/scripting/python/samba/samr.py b/source4/scripting/python/samba/samr.py
new file mode 100644
index 0000000000..62a7c6eb3d
--- /dev/null
+++ b/source4/scripting/python/samba/samr.py
@@ -0,0 +1,759 @@
+import dcerpc
+
+def sid_to_string(sid):
+ """Convert a Python dictionary SID to a string SID."""
+
+ result = 'S-%d' % sid.sid_rev_num
+
+ result = result + '-%u' % \
+ (dcerpc.uint8_array_getitem(sid.id_auth, 5) +
+ (dcerpc.uint8_array_getitem(sid.id_auth, 4) << 8) +
+ (dcerpc.uint8_array_getitem(sid.id_auth, 3) << 16) +
+ (dcerpc.uint8_array_getitem(sid.id_auth, 2) << 24))
+
+ for i in range(0, sid.num_auths):
+ result = result + '-%u' % \
+ dcerpc.uint32_array_getitem(sid.sub_auths, i)
+
+ return result
+
+def string_to_sid(string):
+ """Convert a string SID to a Python dictionary SID. Throws a
+ ValueError if the SID string was badly formed."""
+
+ if string[0] != 'S':
+ raise ValueError('Bad SID format')
+
+ string = string[1:]
+
+ import re
+
+ match = re.match('-\d+', string)
+
+ if not match:
+ raise ValueError('Bad SID format')
+
+ try:
+ sid_rev_num = int(string[match.start()+1:match.end()])
+ except ValueError:
+ raise ValueError('Bad SID format')
+
+ string = string[match.end():]
+
+ match = re.match('-\d+', string)
+
+ if not match:
+ raise ValueError('Bad SID format')
+
+ try:
+ ia = int(string[match.start()+1:match.end()])
+ except ValueError:
+ raise ValueError('Bad SID format')
+
+ string = string[match.end():]
+
+ id_auth = [0, 0, (ia >> 24) & 0xff, (ia >> 16) & 0xff,
+ (ia >> 8) & 0xff, ia & 0xff]
+
+ num_auths = 0
+ sub_auths = []
+
+ while len(string):
+
+ match = re.match('-\d+', string)
+
+ if not match:
+ raise ValueError('Bad SID format')
+
+ try:
+ sa = int(string[match.start() + 1 : match.end()])
+ except ValueError:
+ raise ValueError('Bad SID format')
+
+ num_auths = num_auths + 1
+ sub_auths.append(int(sa))
+
+ string = string[match.end():]
+
+ sid = dcerpc.dom_sid()
+ sid.sid_rev_num = sid_rev_num
+ sid.id_auth = dcerpc.new_uint8_array(6)
+ for i in range(6):
+ dcerpc.uint8_array_setitem(sid.id_auth, i, id_auth[i])
+ sid.num_auths = num_auths
+ sid.sub_auths = dcerpc.new_uint32_array(num_auths)
+ for i in range(num_auths):
+ dcerpc.uint32_array_setitem(sid.sub_auths, i, sub_auths[i])
+
+ return sid
+
+def call_fn(fn, pipe, args):
+ """Wrap up a RPC call and throw an exception is an error was returned."""
+
+ result = fn(pipe, args);
+
+ if result & 0xc0000000L:
+ raise dcerpc.NTSTATUS(result, dcerpc.nt_errstr(result));
+
+ return result;
+
+
+class SamrHandle(object):
+
+ def __init__(self, pipe, handle):
+
+ self.pipe = pipe
+ self.handle = handle
+
+ def __del__(self):
+
+ if self.handle is not None:
+ self.Close()
+
+ def Close(self):
+
+ r = dcerpc.samr_Close()
+ r.data_in.handle = self.handle
+
+ call_fn(dcerpc.dcerpc_samr_Close, self.pipe, r)
+
+ self.handle = None
+
+ def QuerySecurity(self, sec_info = 7):
+
+ r = dcerpc.samr_QuerySecurity()
+ r.data_in.handle = self.handle
+ r.data_in.sec_info = sec_info
+
+ call_fn(dcerpc.dcerpc_samr_QuerySecurity, self.pipe, r)
+
+ return r.data_out.sdbuf
+
+ def SetSecurity(self, sdbuf, sec_info = 7):
+
+ r = dcerpc.samr_SetSecurity()
+ r.data_in.handle = self.handle
+ r.data_in.sec_info = sec_info
+ r.data_in.sdbuf = sdbuf
+
+ call_fn(dcerpc.dcerpc_samr_SetSecurity, self.pipe, r)
+
+
+class ConnectHandle(SamrHandle):
+
+ def EnumDomains(self):
+
+ r = dcerpc.samr_EnumDomains()
+ r.data_in.connect_handle = self.handle
+ r.data_in.resume_handle = 0
+ r.data_in.buf_size = -1
+
+ domains = []
+
+ while 1:
+
+ call_fn(dcerpc.dcerpc_samr_EnumDomains, self.pipe, r)
+
+ for i in range(r.data_out.sam.count):
+ domains.append(dcerpc.samr_SamEntry_array_getitem(
+ r.data_out.sam.entries, i).name.string)
+
+ # TODO: Handle more entries here
+
+ break
+
+ return domains
+
+ def LookupDomain(self, domain_name):
+
+ r = dcerpc.samr_LookupDomain()
+ r.data_in.connect_handle = self.handle
+ r.data_in.domain_name = dcerpc.samr_String()
+ r.data_in.domain_name.string = domain_name
+
+ call_fn(dcerpc.dcerpc_samr_LookupDomain, self.pipe, r)
+
+ return sid_to_string(r.data_out.sid);
+
+ def OpenDomain(self, domain_sid, access_mask = 0x02000000):
+
+ r = dcerpc.samr_OpenDomain()
+ r.data_in.connect_handle = self.handle
+ r.data_in.access_mask = access_mask
+ r.data_in.sid = string_to_sid(domain_sid)
+
+ call_fn(dcerpc.dcerpc_samr_OpenDomain, self.pipe, r)
+
+ return DomainHandle(self.pipe, r.data_out.domain_handle)
+
+ def Shutdown(self):
+
+ r = dcerpc.samr_Shutdown()
+ r.data_in.connect_handle = self.handle
+
+ call_fn(dcerpc.dcerpc_samr_Shutdown, self.pipe, r)
+
+ def GetDomPwInfo(self, domain_name):
+
+ r = dcerpc.samr_GetDomPwInfo()
+ r.data_in.domain_name = dcerpc.samr_String()
+ r.data_in.domain_name.string = domain_name
+
+ call_fn(dcerpc.dcerpc_samr_GetDomPwInfo, self.pipe, r)
+
+ return r.data_out.info
+
+
+ def SetBootKeyInformation(self, unknown1, unknown2, unknown3):
+
+ r = dcerpc.samr_GetBootKeyInformation()
+ r.data_in.connect_handle = self.handle
+ r.data_in.unknown1 = unknown1
+ r.data_in.unknown2 = unknown2
+ r.data_in.unknown3 = unknown3
+
+ call_fn(dcerpc.dcerpc_samr_SetBootKeyInformation, self.pipe, r)
+
+
+class DomainHandle(SamrHandle):
+
+ def QueryDomainInfo(self, level = 2):
+
+ r = dcerpc.samr_QueryDomainInfo()
+ r.data_in.domain_handle = self.handle
+ r.data_in.level = level
+
+ call_fn(dcerpc.dcerpc_samr_QueryDomainInfo, self.pipe, r)
+
+ return getattr(r.data_out.info, 'info%d' % level)
+
+ def QueryDomainInfo2(self, level = 2):
+
+ r = dcerpc.samr_QueryDomainInfo2()
+ r.data_in.domain_handle = self.handle
+ r.data_in.level = level
+
+ call_fn(dcerpc.dcerpc_samr_QueryDomainInfo2, self.pipe, r)
+
+ return getattr(r.data_out.info, 'info%d' % level)
+
+ def SetDomainInfo(self, level, info):
+
+ r = dcerpc.samr_SetDomainInfo()
+ r.data_in.domain_handle = self.handle
+ r.data_in.level = level
+ r.data_in.info = dcerpc.samr_DomainInfo()
+ setattr(r.data_in.info, 'info%d' % level, info)
+
+ call_fn(dcerpc.dcerpc_samr_SetDomainInfo, self.pipe, r)
+
+ def EnumDomainGroups(self):
+
+ r = dcerpc.samr_EnumDomainGroups()
+ r.data_in.domain_handle = self.handle
+ r.data_in.resume_handle = 0
+ r.data_in.max_size = 1000
+
+ call_fn(dcerpc.dcerpc_samr_EnumDomainGroups, self.pipe, r)
+
+ groups = []
+
+ if r.data_out.sam.entries:
+ for i in range(r.data_out.sam.count):
+ groups.append(dcerpc.samr_SamEntry_array_getitem(
+ r.data_out.sam.entries, i).name.string)
+
+ return groups
+
+ def EnumDomainAliases(self):
+
+ r = dcerpc.samr_EnumDomainAliases()
+ r.data_in.domain_handle = self.handle
+ r.data_in.resume_handle = 0
+ # acct_flags in SamrEnumerateAliasesInDomain has probably
+ # no meaning so use 0xffffffff like W2K
+ r.data_in.acct_flags = 0xffffffffL
+
+ call_fn(dcerpc.dcerpc_samr_EnumDomainAliases, self.pipe, r)
+
+ aliases = []
+
+ if r.data_out.sam.entries:
+ for i in range(r.data_out.sam.count):
+ aliases.append(dcerpc.samr_SamEntry_array_getitem(
+ r.data_out.sam.entries, i).name.string)
+
+ return aliases
+
+ def EnumDomainUsers(self, user_account_flags = 16):
+
+ r = dcerpc.samr_EnumDomainUsers()
+ r.data_in.domain_handle = self.handle
+ r.data_in.resume_handle = 0
+ r.data_in.acct_flags = user_account_flags
+ r.data_in.max_size = 1000
+
+ call_fn(dcerpc.dcerpc_samr_EnumDomainUsers, self.pipe, r)
+
+ users = []
+
+ if r.data_out.sam.entries:
+ for i in range(r.data_out.sam.count):
+ users.append(dcerpc.samr_SamEntry_array_getitem(
+ r.data_out.sam.entries, i).name.string)
+
+ return users
+
+ def CreateUser(self, account_name, access_mask = 0x02000000):
+
+ r = dcerpc.samr_CreateUser()
+ r.data_in.domain_handle = self.handle
+ r.data_in.account_name = dcerpc.samr_String()
+ r.data_in.account_name.string = account_name
+ r.data_in.access_mask = access_mask
+
+ call_fn(dcerpc.dcerpc_samr_CreateUser, self.pipe, r)
+
+ return (r.data_out.user_handle,
+ dcerpc.uint32_array_getitem(r.data_out.rid, 0))
+
+ def CreateUser2(self, account_name, acct_flags = 0x00000010,
+ access_mask = 0x02000000):
+
+ r = dcerpc.samr_CreateUser2()
+ r.data_in.domain_handle = self.handle
+ r.data_in.account_name = dcerpc.samr_String()
+ r.data_in.account_name.string = account_name
+ r.data_in.acct_flags = acct_flags
+ r.data_in.access_mask = access_mask
+
+ call_fn(dcerpc.dcerpc_samr_CreateUser2, self.pipe, r)
+
+ return (r.data_out.user_handle,
+ dcerpc.uint32_array_getitem(r.data_out.access_granted, 0),
+ dcerpc.uint32_array_getitem(r.data_out.rid, 0))
+
+ def OpenUser(self, rid, access_mask = 0x02000000):
+
+ r = dcerpc.samr_OpenUser()
+ r.data_in.domain_handle = self.handle
+ r.data_in.access_mask = access_mask
+ r.data_in.rid = rid
+
+ call_fn(dcerpc.dcerpc_samr_OpenUser, self.pipe, r)
+
+ return UserHandle(self.pipe, r.data_out.user_handle)
+
+ def OpenGroup(self, rid, access_mask = 0x02000000):
+
+ r = dcerpc.samr_OpenGroup()
+ r.data_in.domain_handle = self.handle
+ r.data_in.access_mask = access_mask
+ r.data_in.rid = rid
+
+ call_fn(dcerpc.dcerpc_samr_OpenGroup, self.pipe, r)
+
+ return GroupHandle(self.pipe, r.data_out.group_handle)
+
+ def OpenAlias(self, rid, access_mask = 0x02000000):
+
+ r = dcerpc.samr_OpenAlias()
+ r.data_in.domain_handle = self.handle
+ r.data_in.access_mask = access_mask
+ r.data_in.rid = rid
+
+ call_fn(dcerpc.dcerpc_samr_OpenAlias, self.pipe, r)
+
+ return AliasHandle(self.pipe, r.data_out.alias_handle)
+
+ def CreateDomAlias(self, alias_name, access_mask = 0x02000000):
+
+ r = dcerpc.samr_CreateDomAlias()
+ r.data_in.domain_handle = self.handle
+ r.data_in.alias_name = dcerpc.samr_String()
+ r.data_in.alias_name.string = alias_name
+ r.data_in.access_mask = access_mask
+
+ call_fn(dcerpc.dcerpc_samr_CreateDomAlias, self.pipe, r)
+
+ return (AliasHandle(self.pipe, r.data_out.alias_handle),
+ r.data_out.rid)
+
+ def RidToSid(self, rid):
+
+ r = dcerpc.samr_RidToSid()
+ r.data_in.domain_handle = self.handle
+ r.data_in.rid = rid
+
+ call_fn(dcerpc.dcerpc_samr_RidToSid, self.pipe, r)
+
+ return sid_to_string(r.data_out.sid)
+
+ def RemoveMemberFromForeignDomain(self, sid):
+
+ r = dcerpc.samr_RemoveMemberFromForeignDomain()
+ r.data_in.domain_handle = self.handle
+ r.data_in.sid = sid
+
+ call_fn(dcerpc.dcerpc_samr_RemoveMemberFromForeignDomain, self.pipe, r)
+
+ def LookupNames(self, names):
+
+ r = dcerpc.samr_LookupNames()
+ r.data_in.domain_handle = self.handle
+ r.data_in.num_names = len(names)
+ r.data_in.names = dcerpc.new_samr_String_array(len(names))
+
+ for i in range(len(names)):
+ s = dcerpc.samr_String()
+ s.string = names[i]
+ dcerpc.samr_String_array_setitem(r.data_in.names, i, s)
+
+ call_fn(dcerpc.dcerpc_samr_LookupNames, self.pipe, r)
+
+ return ([dcerpc.uint32_array_getitem(r.data_out.rids.ids, i)
+ for i in range(r.data_out.rids.count)],
+ [dcerpc.uint32_array_getitem(r.data_out.types.ids, i)
+ for i in range(r.data_out.types.count)])
+
+ def CreateDomainGroup(self, domain_name, access_mask = 0x02000000):
+
+ r = dcerpc.samr_CreateDomainGroup()
+ r.data_in.domain_handle = self.handle
+ r.data_in.name = dcerpc.samr_String()
+ r.data_in.name.string = domain_name
+ r.data_in.access_mask = access_mask
+
+ call_fn(dcerpc.dcerpc_samr_CreateDomainGroup, self.pipe, r)
+
+ def GetAliasMembership(self, sids):
+
+ r = dcerpc.samr_GetAliasMembership()
+ r.data_in.domain_handle = self.handle
+ r.data_in.sids = dcerpc.lsa_SidArray()
+ r.data_in.sids.num_sids = len(sids)
+ r.data_in.sids.sids = dcerpc.new_lsa_SidPtr_array(len(sids))
+
+ for i in range(len(sids)):
+ s = dcerpc.lsa_SidPtr()
+ s.sid = string_to_sid(sids[i])
+ dcerpc.lsa_SidPtr_array_setitem(r.data_in.sids.sids, i, s)
+
+ call_fn(dcerpc.dcerpc_samr_GetAliasMembership, self.pipe, r)
+
+ return [r.ids[x] for x in range(r.count)]
+
+ def QueryDisplayInfo(self, level):
+
+ # TODO: Handle more data returns
+
+ r = dcerpc.samr_QueryDisplayInfo()
+ r.data_in.domain_handle = self.handle
+ r.data_in.level = level
+ r.data_in.start_idx = 0
+ r.data_in.max_entries = 1000
+ r.data_in.buf_size = -1
+
+ call_fn(dcerpc.dcerpc_samr_QueryDisplayInfo, self.pipe, r)
+
+ # TODO: Return a mapping of the various samr_DispInfo
+ # structures here.
+
+ return getattr(r.data_out.info, 'info%d' % level)
+
+ def QueryDisplayInfo2(self, level):
+
+ # TODO: Handle more data returns
+
+ r = dcerpc.samr_QueryDisplayInfo2()
+ r.data_in.domain_handle = self.handle
+ r.data_in.level = level
+ r.data_in.start_idx = 0
+ r.data_in.max_entries = 1000
+ r.data_in.buf_size = -1
+
+ call_fn(dcerpc.dcerpc_samr_QueryDisplayInfo2, self.pipe, r)
+
+ # TODO: Return a mapping of the various samr_DispInfo
+ # structures here.
+
+ return getattr(r.data_out.info, 'info%d' % level)
+
+ def QueryDisplayInfo3(self, level):
+
+ # TODO: Handle more data returns
+
+ r = dcerpc.samr_QueryDisplayInfo3()
+ r.data_in.domain_handle = self.handle
+ r.data_in.level = level
+ r.data_in.start_idx = 0
+ r.data_in.max_entries = 1000
+ r.data_in.buf_size = -1
+
+ call_fn(dcerpc.dcerpc_samr_QueryDisplayInfo3, self.pipe, r)
+
+ # TODO: Return a mapping of the various samr_DispInfo
+ # structures here.
+
+ return getattr(r.data_out.info, 'info%d' % level)
+
+ def GetBootKeyInformation(self):
+
+ r = dcerpc.samr_GetBootKeyInformation()
+ r.data_in.domain_handle = self.handle
+
+ call_fn(dcerpc.dcerpc_samr_GetBootKeyInformation, self.pipe, r)
+
+ return r.data_out.unknown
+
+ def SetBootKeyInformation(self):
+
+ r = dcerpc.samr_GetBootKeyInformation()
+ r.data_in.domain_handle = self.handle
+
+ call_fn(dcerpc.dcerpc_samr_GetBootKeyInformation, self.pipe, r)
+
+ def TestPrivateFunctionsDomain(self):
+
+ r = dcerpc.samr_TestPrivateFunctionsDomain()
+ r.data_in.domain_handle = self.handle
+
+ call_fn(dcerpc.dcerpc_samr_TestPrivateFunctionsDomain, self.pipe, r)
+
+
+class UserHandle(SamrHandle):
+
+ def DeleteUser(self):
+
+ r = dcerpc.samr_DeleteUser()
+ r.data_in.user_handle = self.handle
+
+ call_fn(dcerpc.dcerpc_samr_DeleteUser, self.pipe, r)
+
+ self.handle = None
+
+ def GetUserPwInfo(self):
+
+ r = dcerpc.samr_GetUserPwInfo()
+ r.data_in.user_handle = self.handle
+
+ call_fn(dcerpc.dcerpc_samr_GetUserPwInfo, self.pipe, r)
+
+ return r.data_out.info
+
+ def QueryUserInfo(self, level):
+
+ r = dcerpc.samr_QueryUserInfo()
+ r.data_in.user_handle = self.handle
+ r.data_in.level = level
+
+ call_fn(dcerpc.dcerpc_samr_QueryUserInfo, self.pipe, r)
+
+ return r.data_out.info
+
+ def QueryUserInfo2(self, level):
+
+ r = dcerpc.samr_QueryUserInfo2()
+ r.data_in.user_handle = self.handle
+ r.data_in.level = level
+
+ call_fn(dcerpc.dcerpc_samr_QueryUserInfo2, self.pipe, r)
+
+ return r.data_out.info
+
+ def GetGroupsForUser(self):
+
+ r = dcerpc.samr_GetGroupsForUser()
+ r.data_in.user_handle = self.handle
+
+ call_fn(dcerpc.dcerpc_samr_GetGroupsForUser, self.pipe, r)
+
+ rid_types = [dcerpc.samr_RidType_array_getitem(r.data_out.rids.rid, x)
+ for x in range(r.data_out.rids.count)]
+
+ return [(x.rid, x.type) for x in rid_types]
+
+ def TestPrivateFunctionsUser(self):
+
+ r = dcerpc.samr_TestPrivateFunctionsUser()
+ r.data_in.user_handle = self.handle
+
+ call_fn(dcerpc.dcerpc_samr_TestPrivateFunctionsUser, self.pipe, r)
+
+
+class GroupHandle(SamrHandle):
+
+ def QueryGroupInfo(self, level):
+
+ r = dcerpc.samr_QueryGroupInfo()
+ r.data_in.group_handle = self.handle
+ r.data_in.level = level
+
+ call_fn(dcerpc.dcerpc_samr_QueryGroupInfo, self.pipe, r)
+
+ return r.data_out.info
+
+ def SetGroupInfo(self, level, info):
+
+ r = dcerpc.samr_SetGroupInfo()
+ r.data_in.group_handle = self.handle
+ r.data_in.level = level
+ r.data_in.info = info
+
+ call_fn(dcerpc.dcerpc_samr_SetGroupInfo, self.pipe, r)
+
+ def QueryGroupMember(self):
+
+ r = dcerpc.samr_QueryGroupMember()
+ r.data_in.group_handle = self.handle
+
+ call_fn(dcerpc.dcerpc_samr_QueryGroupMember, self.pipe, r)
+
+ return [(dcerpc.uint32_array_getitem(r.data_out.rids.rids, x),
+ dcerpc.uint32_array_getitem(r.data_out.rids.unknown, x))
+ for x in range(r.data_out.rids.count)]
+
+
+class AliasHandle(SamrHandle):
+
+ def DeleteDomAlias(self):
+
+ r = dcerpc.samr_DeleteDomAlias()
+ r.data_in.alias_handle = self.handle
+
+ call_fn(dcerpc.dcerpc_samr_DeleteDomAlias, self.pipe, r)
+
+ self.handle = None
+
+ def QueryAliasInfo(self, level = 1):
+
+ r = dcerpc.samr_QueryAliasInfo()
+ r.data_in.alias_handle = self.handle
+ r.data_in.level = level
+
+ call_fn(dcerpc.dcerpc_samr_QueryAliasInfo, self.pipe, r)
+
+ return r.data_out.info
+
+ def SetAliasInfo(self, level, info):
+
+ r = dcerpc.samr_SetAliasInfo()
+ r.data_in.alias_handle = self.handle
+ r.data_in.level = level
+ r.data_in.info = info
+
+ call_fn(dcerpc.dcerpc_samr_SetAliasInfo, self.pipe, r)
+
+ def AddAliasMember(self, sid):
+
+ r = dcerpc.samr_AddAliasMember()
+ r.data_in.alias_handle = self.handle
+ r.data_in.sid = string_to_sid(sid)
+
+ call_fn(dcerpc.dcerpc_samr_AddAliasMember, self.pipe, r)
+
+ def AddMultipleMembersToAlias(self, sids):
+
+ r = dcerpc.samr_AddMultipleMembersToAlias()
+ r.data_in.alias_handle = self.handle
+ r.data_in.sids = dcerpc.lsa_SidArray()
+ r.data_in.sids.num_sids = len(sids)
+ r.data_in.sids.sids = dcerpc.new_lsa_SidPtr_array(len(sids))
+
+ for i in range(len(sids)):
+ s = dcerpc.lsa_SidPtr()
+ s.sid = string_to_sid(sids[i])
+ dcerpc.lsa_SidPtr_array_setitem(r.data_in.sids.sids, i, s)
+
+ call_fn(dcerpc.dcerpc_samr_AddMultipleMembersToAlias, self.pipe, r)
+
+ def GetMembersInAlias(self):
+
+ r = dcerpc.samr_GetMembersInAlias()
+ r.data_in.alias_handle = self.handle
+
+ call_fn(dcerpc.dcerpc_samr_GetMembersInAlias, self.pipe, r)
+
+ return [
+ sid_to_string(
+ dcerpc.lsa_SidPtr_array_getitem(r.data_out.sids.sids, x).sid)
+ for x in range(r.data_out.sids.num_sids)]
+
+def Connect(pipe, access_mask = 0x02000000):
+
+ r = dcerpc.samr_Connect()
+ r.data_in.system_name = dcerpc.new_uint16_array(1)
+ dcerpc.uint16_array_setitem(r.data_in.system_name, 0, ord('\\'))
+ r.data_in.access_mask = access_mask
+
+ call_fn(dcerpc.dcerpc_samr_Connect, pipe, r)
+
+ return ConnectHandle(pipe, r.data_out.connect_handle)
+
+def Connect2(pipe, system_name = '', access_mask = 0x02000000):
+ """Connect to the SAMR pipe."""
+
+ r = dcerpc.samr_Connect2()
+ r.data_in.system_name = system_name
+ r.data_in.access_mask = access_mask
+
+ call_fn(dcerpc.dcerpc_samr_Connect2, pipe, r)
+
+ return ConnectHandle(pipe, r.data_out.connect_handle)
+
+def Connect3(pipe, system_name = '', access_mask = 0x02000000):
+
+ r = dcerpc.samr_Connect3()
+ r.data_in.system_name = system_name
+ r.data_in.unknown = 0
+ r.data_in.access_mask = access_mask
+
+ call_fn(dcerpc.dcerpc_samr_Connect3, pipe, r)
+
+ return ConnectHandle(pipe, r.data_out.connect_handle)
+
+
+def Connect4(pipe, system_name = '', access_mask = 0x02000000):
+
+ r = dcerpc.samr_Connect4()
+ r.data_in.system_name = system_name
+ r.data_in.unknown = 0
+ r.data_in.access_mask = access_mask
+
+ call_fn(dcerpc.dcerpc_samr_Connect4, pipe, r)
+
+ return ConnectHandle(pipe, r.data_out.connect_handle)
+
+def Connect5(pipe, system_name = '', access_mask = 0x02000000):
+
+ r = dcerpc.samr_Connect5()
+ r.data_in.system_name = system_name
+ r.data_in.access_mask = access_mask
+ r.data_in.level = 1
+ r.data_in.info = dcerpc.new_samr_ConnectInfo_array(1)
+ r.data_in.info.unknown1 = 0
+ r.data_in.info.unknown2 = 0
+
+ call_fn(dcerpc.dcerpc_samr_Connect5, pipe, r)
+
+ return ConnectHandle(pipe, r.data_out.connect_handle)
+
+# AddGroupMember
+# DeleteDomainGroup
+# DeleteGroupMember
+# SetMemberAttributesofGroup
+# AddAliasMember
+# DeleteAliasMember
+# GetMembersinAlias
+# SetUserInfo
+# ChangePasswordUser
+# GetDisplayEnumerationIndex
+# RemoveMemberFromForeignDomain
+# GetDisplayEnumerationIndex2
+# RemoveMultipleMembersFromAlias
+# OemChangePasswordUser2
+# ChangePasswordUser2
+# SetUserInfo2
+# ChangePasswordUser3
+# SetDsrmPassword
+# ValidatePassword
diff --git a/source4/scripting/python/samba/tests/__init__.py b/source4/scripting/python/samba/tests/__init__.py
new file mode 100644
index 0000000000..d827bfa004
--- /dev/null
+++ b/source4/scripting/python/samba/tests/__init__.py
@@ -0,0 +1,98 @@
+#!/usr/bin/python
+
+# Unix SMB/CIFS implementation.
+# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+"""Samba Python tests."""
+
+import os
+import ldb
+import samba
+import tempfile
+import unittest
+
+class LdbTestCase(unittest.TestCase):
+ """Trivial test case for running tests against a LDB."""
+ def setUp(self):
+ self.filename = os.tempnam()
+ self.ldb = samba.Ldb(self.filename)
+
+ def set_modules(self, modules=[]):
+ """Change the modules for this Ldb."""
+ m = ldb.Message()
+ m.dn = ldb.Dn(self.ldb, "@MODULES")
+ m["@LIST"] = ",".join(modules)
+ self.ldb.add(m)
+ self.ldb = samba.Ldb(self.filename)
+
+
+class TestCaseInTempDir(unittest.TestCase):
+ def setUp(self):
+ super(TestCaseInTempDir, self).setUp()
+ self.tempdir = tempfile.mkdtemp()
+
+ def tearDown(self):
+ super(TestCaseInTempDir, self).tearDown()
+ self.assertEquals([], os.listdir(self.tempdir))
+ os.rmdir(self.tempdir)
+
+
+class SubstituteVarTestCase(unittest.TestCase):
+ def test_empty(self):
+ self.assertEquals("", samba.substitute_var("", {}))
+
+ def test_nothing(self):
+ self.assertEquals("foo bar", samba.substitute_var("foo bar", {"bar": "bla"}))
+
+ def test_replace(self):
+ self.assertEquals("foo bla", samba.substitute_var("foo ${bar}", {"bar": "bla"}))
+
+ def test_broken(self):
+ self.assertEquals("foo ${bdkjfhsdkfh sdkfh ",
+ samba.substitute_var("foo ${bdkjfhsdkfh sdkfh ", {"bar": "bla"}))
+
+ def test_unknown_var(self):
+ self.assertEquals("foo ${bla} gsff",
+ samba.substitute_var("foo ${bla} gsff", {"bar": "bla"}))
+
+ def test_check_all_substituted(self):
+ samba.check_all_substituted("nothing to see here")
+ self.assertRaises(Exception, samba.check_all_substituted, "Not subsituted: ${FOOBAR}")
+
+
+class LdbExtensionTests(TestCaseInTempDir):
+ def test_searchone(self):
+ path = self.tempdir + "/searchone.ldb"
+ l = samba.Ldb(path)
+ try:
+ l.add({"dn": "foo=dc", "bar": "bla"})
+ self.assertEquals("bla", l.searchone(basedn=ldb.Dn(l, "foo=dc"), attribute="bar"))
+ finally:
+ del l
+ os.unlink(path)
+
+
+cmdline_loadparm = None
+cmdline_credentials = None
+
+class RpcInterfaceTestCase(unittest.TestCase):
+ def get_loadparm(self):
+ assert cmdline_loadparm is not None
+ return cmdline_loadparm
+
+ def get_credentials(self):
+ return cmdline_credentials
diff --git a/source4/scripting/python/samba/tests/dcerpc/__init__.py b/source4/scripting/python/samba/tests/dcerpc/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/source4/scripting/python/samba/tests/dcerpc/__init__.py
diff --git a/source4/scripting/python/samba/tests/dcerpc/bare.py b/source4/scripting/python/samba/tests/dcerpc/bare.py
new file mode 100644
index 0000000000..cd939b8098
--- /dev/null
+++ b/source4/scripting/python/samba/tests/dcerpc/bare.py
@@ -0,0 +1,48 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Unix SMB/CIFS implementation.
+# Copyright © Jelmer Vernooij <jelmer@samba.org> 2008
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+from samba.dcerpc import ClientConnection
+from unittest import TestCase
+from samba.tests import cmdline_loadparm
+
+
+class BareTestCase(TestCase):
+ def test_bare(self):
+ # Connect to the echo pipe
+ x = ClientConnection("ncalrpc:localhost[DEFAULT]",
+ ("60a15ec5-4de8-11d7-a637-005056a20182", 1), lp_ctx=cmdline_loadparm)
+ self.assertEquals("\x01\x00\x00\x00", x.request(0, chr(0) * 4))
+
+ def test_alter_context(self):
+ x = ClientConnection("ncalrpc:localhost[DEFAULT]",
+ ("12345778-1234-abcd-ef00-0123456789ac", 1), lp_ctx=cmdline_loadparm)
+ y = ClientConnection("ncalrpc:localhost",
+ ("60a15ec5-4de8-11d7-a637-005056a20182", 1),
+ basis_connection=x, lp_ctx=cmdline_loadparm)
+ x.alter_context(("60a15ec5-4de8-11d7-a637-005056a20182", 1))
+ # FIXME: self.assertEquals("\x01\x00\x00\x00", x.request(0, chr(0) * 4))
+
+ def test_two_connections(self):
+ x = ClientConnection("ncalrpc:localhost[DEFAULT]",
+ ("60a15ec5-4de8-11d7-a637-005056a20182", 1), lp_ctx=cmdline_loadparm)
+ y = ClientConnection("ncalrpc:localhost",
+ ("60a15ec5-4de8-11d7-a637-005056a20182", 1),
+ basis_connection=x, lp_ctx=cmdline_loadparm)
+ self.assertEquals("\x01\x00\x00\x00", y.request(0, chr(0) * 4))
diff --git a/source4/scripting/python/samba/tests/dcerpc/registry.py b/source4/scripting/python/samba/tests/dcerpc/registry.py
new file mode 100644
index 0000000000..526b2340cc
--- /dev/null
+++ b/source4/scripting/python/samba/tests/dcerpc/registry.py
@@ -0,0 +1,50 @@
+#!/usr/bin/python
+
+# Unix SMB/CIFS implementation.
+# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+from samba.dcerpc import winreg
+import unittest
+from samba.tests import RpcInterfaceTestCase
+
+
+class WinregTests(RpcInterfaceTestCase):
+ def setUp(self):
+ self.conn = winreg.winreg("ncalrpc:", self.get_loadparm(),
+ self.get_credentials())
+
+ def get_hklm(self):
+ return self.conn.OpenHKLM(None,
+ winreg.KEY_QUERY_VALUE | winreg.KEY_ENUMERATE_SUB_KEYS)
+
+ def test_hklm(self):
+ handle = self.conn.OpenHKLM(None,
+ winreg.KEY_QUERY_VALUE | winreg.KEY_ENUMERATE_SUB_KEYS)
+ self.conn.CloseKey(handle)
+
+ def test_getversion(self):
+ handle = self.get_hklm()
+ version = self.conn.GetVersion(handle)
+ self.assertEquals(int, version.__class__)
+ self.conn.CloseKey(handle)
+
+ def test_getkeyinfo(self):
+ handle = self.conn.OpenHKLM(None,
+ winreg.KEY_QUERY_VALUE | winreg.KEY_ENUMERATE_SUB_KEYS)
+ x = self.conn.QueryInfoKey(handle, winreg.String())
+ self.assertEquals(9, len(x)) # should return a 9-tuple
+ self.conn.CloseKey(handle)
diff --git a/source4/scripting/python/samba/tests/dcerpc/rpcecho.py b/source4/scripting/python/samba/tests/dcerpc/rpcecho.py
new file mode 100644
index 0000000000..12638e2397
--- /dev/null
+++ b/source4/scripting/python/samba/tests/dcerpc/rpcecho.py
@@ -0,0 +1,69 @@
+#!/usr/bin/python
+
+# Unix SMB/CIFS implementation.
+# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+from samba.dcerpc import echo
+from samba.ndr import ndr_pack, ndr_unpack
+import unittest
+from samba.tests import RpcInterfaceTestCase
+
+
+class RpcEchoTests(RpcInterfaceTestCase):
+ def setUp(self):
+ self.conn = echo.rpcecho("ncalrpc:", self.get_loadparm())
+
+ def test_two_contexts(self):
+ self.conn2 = echo.rpcecho("ncalrpc:", self.get_loadparm(), basis_connection=self.conn)
+ self.assertEquals(3, self.conn2.AddOne(2))
+
+ def test_abstract_syntax(self):
+ self.assertEquals(("60a15ec5-4de8-11d7-a637-005056a20182", 1),
+ self.conn.abstract_syntax)
+
+ def test_addone(self):
+ self.assertEquals(2, self.conn.AddOne(1))
+
+ def test_echodata(self):
+ self.assertEquals([1,2,3], self.conn.EchoData([1, 2, 3]))
+
+ def test_call(self):
+ self.assertEquals(u"foobar", self.conn.TestCall(u"foobar"))
+
+ def test_surrounding(self):
+ surrounding_struct = echo.Surrounding()
+ surrounding_struct.x = 4
+ surrounding_struct.surrounding = [1,2,3,4]
+ y = self.conn.TestSurrounding(surrounding_struct)
+ self.assertEquals(8 * [0], y.surrounding)
+
+ def test_manual_request(self):
+ self.assertEquals("\x01\x00\x00\x00", self.conn.request(0, chr(0) * 4))
+
+ def test_server_name(self):
+ self.assertEquals(None, self.conn.server_name)
+
+
+class NdrEchoTests(unittest.TestCase):
+ def test_info1_push(self):
+ x = echo.info1()
+ x.v = 42
+ self.assertEquals("\x2a", ndr_pack(x))
+
+ def test_info1_pull(self):
+ x = ndr_unpack(echo.info1, "\x42")
+ self.assertEquals(x.v, 66)
diff --git a/source4/scripting/python/samba/tests/dcerpc/sam.py b/source4/scripting/python/samba/tests/dcerpc/sam.py
new file mode 100644
index 0000000000..50e00a3f9e
--- /dev/null
+++ b/source4/scripting/python/samba/tests/dcerpc/sam.py
@@ -0,0 +1,46 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Unix SMB/CIFS implementation.
+# Copyright © Jelmer Vernooij <jelmer@samba.org> 2008
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+from samba.dcerpc import samr, security
+from samba.tests import RpcInterfaceTestCase
+
+# FIXME: Pidl should be doing this for us
+def toArray((handle, array, num_entries)):
+ ret = []
+ for x in range(num_entries):
+ ret.append((array.entries[x].idx, array.entries[x].name))
+ return ret
+
+
+class SamrTests(RpcInterfaceTestCase):
+ def setUp(self):
+ self.conn = samr.samr("ncalrpc:", self.get_loadparm())
+
+ def test_connect5(self):
+ (level, info, handle) = self.conn.Connect5(None, 0, 1, samr.ConnectInfo1())
+
+ def test_connect2(self):
+ handle = self.conn.Connect2(None, security.SEC_FLAG_MAXIMUM_ALLOWED)
+
+ def test_EnumDomains(self):
+ handle = self.conn.Connect2(None, security.SEC_FLAG_MAXIMUM_ALLOWED)
+ domains = toArray(self.conn.EnumDomains(handle, 0, -1))
+ self.conn.Close(handle)
+
diff --git a/source4/scripting/python/samba/tests/dcerpc/unix.py b/source4/scripting/python/samba/tests/dcerpc/unix.py
new file mode 100644
index 0000000000..aa47b71b16
--- /dev/null
+++ b/source4/scripting/python/samba/tests/dcerpc/unix.py
@@ -0,0 +1,37 @@
+#!/usr/bin/python
+
+# Unix SMB/CIFS implementation.
+# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+from samba.dcerpc import unixinfo
+from samba.tests import RpcInterfaceTestCase
+
+class UnixinfoTests(RpcInterfaceTestCase):
+ def setUp(self):
+ self.conn = unixinfo.unixinfo("ncalrpc:", self.get_loadparm())
+
+ def test_getpwuid(self):
+ infos = self.conn.GetPWUid(range(512))
+ self.assertEquals(512, len(infos))
+ self.assertEquals("/bin/false", infos[0].shell)
+ self.assertTrue(isinstance(infos[0].homedir, unicode))
+
+ def test_gidtosid(self):
+ self.conn.GidToSid(1000)
+
+ def test_uidtosid(self):
+ self.conn.UidToSid(1000)
diff --git a/source4/scripting/python/samba/tests/provision.py b/source4/scripting/python/samba/tests/provision.py
new file mode 100644
index 0000000000..352357f694
--- /dev/null
+++ b/source4/scripting/python/samba/tests/provision.py
@@ -0,0 +1,124 @@
+#!/usr/bin/python
+
+# Unix SMB/CIFS implementation.
+# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+import os
+from samba.provision import setup_secretsdb, secretsdb_become_dc, findnss
+import samba.tests
+from ldb import Dn
+from samba import param
+import unittest
+
+lp = samba.tests.cmdline_loadparm
+
+setup_dir = "setup"
+def setup_path(file):
+ return os.path.join(setup_dir, file)
+
+
+class ProvisionTestCase(samba.tests.TestCaseInTempDir):
+ """Some simple tests for individual functions in the provisioning code.
+ """
+ def test_setup_secretsdb(self):
+ path = os.path.join(self.tempdir, "secrets.ldb")
+ ldb = setup_secretsdb(path, setup_path, None, None, lp=lp)
+ try:
+ self.assertEquals("LSA Secrets",
+ ldb.searchone(basedn="CN=LSA Secrets", attribute="CN"))
+ finally:
+ del ldb
+ os.unlink(path)
+
+ def test_become_dc(self):
+ path = os.path.join(self.tempdir, "secrets.ldb")
+ secrets_ldb = setup_secretsdb(path, setup_path, None, None, lp=lp)
+ try:
+ secretsdb_become_dc(secrets_ldb, setup_path, domain="EXAMPLE",
+ realm="example", netbiosname="myhost",
+ domainsid="S-5-22", keytab_path="keytab.path",
+ samdb_url="ldap://url/",
+ dns_keytab_path="dns.keytab", dnspass="bla",
+ machinepass="machinepass", dnsdomain="example.com")
+ self.assertEquals(1,
+ len(secrets_ldb.search("samAccountName=krbtgt,flatname=EXAMPLE,CN=Principals")))
+ self.assertEquals("keytab.path",
+ secrets_ldb.searchone(basedn="flatname=EXAMPLE,CN=primary domains",
+ expression="(privateKeytab=*)",
+ attribute="privateKeytab"))
+ self.assertEquals("S-5-22",
+ secrets_ldb.searchone(basedn="flatname=EXAMPLE,CN=primary domains",
+ expression="objectSid=*", attribute="objectSid"))
+
+ finally:
+ del secrets_ldb
+ os.unlink(path)
+
+
+class FindNssTests(unittest.TestCase):
+ """Test findnss() function."""
+ def test_nothing(self):
+ def x(y):
+ raise KeyError
+ self.assertRaises(KeyError, findnss, x, [])
+
+ def test_first(self):
+ self.assertEquals("bla", findnss(lambda x: "bla", ["bla"]))
+
+ def test_skip_first(self):
+ def x(y):
+ if y != "bla":
+ raise KeyError
+ return "ha"
+ self.assertEquals("ha", findnss(x, ["bloe", "bla"]))
+
+
+class Disabled(object):
+ def test_setup_templatesdb(self):
+ raise NotImplementedError(self.test_setup_templatesdb)
+
+ def test_setup_registry(self):
+ raise NotImplementedError(self.test_setup_registry)
+
+ def test_setup_samdb_rootdse(self):
+ raise NotImplementedError(self.test_setup_samdb_rootdse)
+
+ def test_setup_samdb_partitions(self):
+ raise NotImplementedError(self.test_setup_samdb_partitions)
+
+ def test_create_phpldapadmin_config(self):
+ raise NotImplementedError(self.test_create_phpldapadmin_config)
+
+ def test_provision_dns(self):
+ raise NotImplementedError(self.test_provision_dns)
+
+ def test_provision_ldapbase(self):
+ raise NotImplementedError(self.test_provision_ldapbase)
+
+ def test_provision_guess(self):
+ raise NotImplementedError(self.test_provision_guess)
+
+ def test_join_domain(self):
+ raise NotImplementedError(self.test_join_domain)
+
+ def test_vampire(self):
+ raise NotImplementedError(self.test_vampire)
+
+ def test_erase_partitions(self):
+ raise NotImplementedError(self.test_erase_partitions)
+
+
diff --git a/source4/scripting/python/samba/tests/samba3.py b/source4/scripting/python/samba/tests/samba3.py
new file mode 100644
index 0000000000..1755cbdcf0
--- /dev/null
+++ b/source4/scripting/python/samba/tests/samba3.py
@@ -0,0 +1,210 @@
+#!/usr/bin/python
+
+# Unix SMB/CIFS implementation.
+# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+import unittest
+from samba.samba3 import (GroupMappingDatabase, Registry, PolicyDatabase, SecretsDatabase, TdbSam,
+ WinsDatabase, SmbpasswdFile, ACB_NORMAL, IdmapDatabase, SAMUser)
+import os
+
+DATADIR=os.path.join(os.path.dirname(__file__), "../../../../../testdata/samba3")
+print "Samba 3 data dir: %s" % DATADIR
+
+class RegistryTestCase(unittest.TestCase):
+ def setUp(self):
+ self.registry = Registry(os.path.join(DATADIR, "registry.tdb"))
+
+ def tearDown(self):
+ self.registry.close()
+
+ def test_length(self):
+ self.assertEquals(28, len(self.registry))
+
+ def test_keys(self):
+ self.assertTrue("HKLM" in self.registry.keys())
+
+ def test_subkeys(self):
+ self.assertEquals(["SOFTWARE", "SYSTEM"], self.registry.subkeys("HKLM"))
+
+ def test_values(self):
+ self.assertEquals({'DisplayName': (1L, 'E\x00v\x00e\x00n\x00t\x00 \x00L\x00o\x00g\x00\x00\x00'),
+ 'ErrorControl': (4L, '\x01\x00\x00\x00')},
+ self.registry.values("HKLM/SYSTEM/CURRENTCONTROLSET/SERVICES/EVENTLOG"))
+
+
+class PolicyTestCase(unittest.TestCase):
+ def setUp(self):
+ self.policy = PolicyDatabase(os.path.join(DATADIR, "account_policy.tdb"))
+
+ def test_policy(self):
+ self.assertEquals(self.policy.min_password_length, 5)
+ self.assertEquals(self.policy.minimum_password_age, 0)
+ self.assertEquals(self.policy.maximum_password_age, 999999999)
+ self.assertEquals(self.policy.refuse_machine_password_change, 0)
+ self.assertEquals(self.policy.reset_count_minutes, 0)
+ self.assertEquals(self.policy.disconnect_time, -1)
+ self.assertEquals(self.policy.user_must_logon_to_change_password, None)
+ self.assertEquals(self.policy.password_history, 0)
+ self.assertEquals(self.policy.lockout_duration, 0)
+ self.assertEquals(self.policy.bad_lockout_minutes, None)
+
+
+class GroupsTestCase(unittest.TestCase):
+ def setUp(self):
+ self.groupdb = GroupMappingDatabase(os.path.join(DATADIR, "group_mapping.tdb"))
+
+ def tearDown(self):
+ self.groupdb.close()
+
+ def test_group_length(self):
+ self.assertEquals(13, len(list(self.groupdb.groupsids())))
+
+ def test_get_group(self):
+ self.assertEquals((-1, 5L, 'Administrators', ''), self.groupdb.get_group("S-1-5-32-544"))
+
+ def test_groupsids(self):
+ sids = list(self.groupdb.groupsids())
+ self.assertTrue("S-1-5-32-544" in sids)
+
+ def test_alias_length(self):
+ self.assertEquals(0, len(list(self.groupdb.aliases())))
+
+
+class SecretsDbTestCase(unittest.TestCase):
+ def setUp(self):
+ self.secretsdb = SecretsDatabase(os.path.join(DATADIR, "secrets.tdb"))
+
+ def tearDown(self):
+ self.secretsdb.close()
+
+ def test_get_sid(self):
+ self.assertTrue(self.secretsdb.get_sid("BEDWYR") is not None)
+
+
+class TdbSamTestCase(unittest.TestCase):
+ def setUp(self):
+ self.samdb = TdbSam(os.path.join(DATADIR, "passdb.tdb"))
+
+ def tearDown(self):
+ self.samdb.close()
+
+ def test_usernames(self):
+ self.assertEquals(3, len(list(self.samdb.usernames())))
+
+ def test_getuser(self):
+ user = SAMUser("root")
+ user.logoff_time = 2147483647
+ user.kickoff_time = 2147483647
+ user.pass_can_change_time = 1125418267
+ user.username = "root"
+ user.uid = None
+ user.lm_password = 'U)\x02\x03\x1b\xed\xe9\xef\xaa\xd3\xb45\xb5\x14\x04\xee'
+ user.nt_password = '\x87\x8d\x80\x14`l\xda)gzD\xef\xa15?\xc7'
+ user.acct_ctrl = 16
+ user.pass_last_set_time = 1125418267
+ user.fullname = "root"
+ user.nt_username = ""
+ user.logoff_time = 2147483647
+ user.acct_desc = ""
+ user.group_rid = 1001
+ user.logon_count = 0
+ user.bad_password_count = 0
+ user.domain = "BEDWYR"
+ user.munged_dial = ""
+ user.workstations = ""
+ user.user_rid = 1000
+ user.kickoff_time = 2147483647
+ user.logoff_time = 2147483647
+ user.unknown_6 = 1260L
+ user.logon_divs = 0
+ user.hours = [True for i in range(168)]
+ other = self.samdb["root"]
+ for name in other.__dict__:
+ if other.__dict__[name] != user.__dict__[name]:
+ print "%s: %r != %r" % (name, other.__dict__[name], user.__dict__[name])
+ self.assertEquals(user, other)
+
+
+class WinsDatabaseTestCase(unittest.TestCase):
+ def setUp(self):
+ self.winsdb = WinsDatabase(os.path.join(DATADIR, "wins.dat"))
+
+ def test_length(self):
+ self.assertEquals(22, len(self.winsdb))
+
+ def test_first_entry(self):
+ self.assertEqual((1124185120, ["192.168.1.5"], 0x64), self.winsdb["ADMINISTRATOR#03"])
+
+ def tearDown(self):
+ self.winsdb.close()
+
+
+class SmbpasswdTestCase(unittest.TestCase):
+ def setUp(self):
+ self.samdb = SmbpasswdFile(os.path.join(DATADIR, "smbpasswd"))
+
+ def test_length(self):
+ self.assertEquals(3, len(self.samdb))
+
+ def test_get_user(self):
+ user = SAMUser("rootpw")
+ user.lm_password = "552902031BEDE9EFAAD3B435B51404EE"
+ user.nt_password = "878D8014606CDA29677A44EFA1353FC7"
+ user.acct_ctrl = ACB_NORMAL
+ user.pass_last_set_time = int(1125418267)
+ user.uid = 0
+ self.assertEquals(user, self.samdb["rootpw"])
+
+ def tearDown(self):
+ self.samdb.close()
+
+
+class IdmapDbTestCase(unittest.TestCase):
+ def setUp(self):
+ self.idmapdb = IdmapDatabase(os.path.join(DATADIR, "winbindd_idmap.tdb"))
+
+ def test_user_hwm(self):
+ self.assertEquals(10000, self.idmapdb.get_user_hwm())
+
+ def test_group_hwm(self):
+ self.assertEquals(10002, self.idmapdb.get_group_hwm())
+
+ def test_uids(self):
+ self.assertEquals(1, len(list(self.idmapdb.uids())))
+
+ def test_gids(self):
+ self.assertEquals(3, len(list(self.idmapdb.gids())))
+
+ def test_get_user_sid(self):
+ self.assertEquals("S-1-5-21-58189338-3053988021-627566699-501", self.idmapdb.get_user_sid(65534))
+
+ def test_get_group_sid(self):
+ self.assertEquals("S-1-5-21-2447931902-1787058256-3961074038-3007", self.idmapdb.get_group_sid(10001))
+
+ def tearDown(self):
+ self.idmapdb.close()
+
+
+class ShareInfoTestCase(unittest.TestCase):
+ def setUp(self):
+ self.shareinfodb = ShareInfoDatabase(os.path.join(DATADIR, "share_info.tdb"))
+
+ # FIXME: needs proper data so it can be tested
+
+ def tearDown(self):
+ self.shareinfodb.close()
diff --git a/source4/scripting/python/samba/tests/samdb.py b/source4/scripting/python/samba/tests/samdb.py
new file mode 100644
index 0000000000..97be5672ce
--- /dev/null
+++ b/source4/scripting/python/samba/tests/samdb.py
@@ -0,0 +1,84 @@
+#!/usr/bin/python
+
+# Unix SMB/CIFS implementation. Tests for SamDB
+# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+from samba.auth import system_session
+from samba.credentials import Credentials
+import os
+from samba.provision import setup_samdb, guess_names, setup_templatesdb, make_smbconf
+from samba.samdb import SamDB
+from samba.tests import cmdline_loadparm, TestCaseInTempDir
+from samba import security
+from unittest import TestCase
+import uuid
+from samba import param
+
+class SamDBTestCase(TestCaseInTempDir):
+ def setUp(self):
+ super(SamDBTestCase, self).setUp()
+ invocationid = str(uuid.uuid4())
+ domaindn = "DC=COM,DC=EXAMPLE"
+ self.domaindn = domaindn
+ configdn = "CN=Configuration," + domaindn
+ schemadn = "CN=Schema," + configdn
+ domainguid = str(uuid.uuid4())
+ policyguid = str(uuid.uuid4())
+ setup_path = lambda x: os.path.join("setup", x)
+ creds = Credentials()
+ creds.set_anonymous()
+ domainsid = security.random_sid()
+ hostguid = str(uuid.uuid4())
+ path = os.path.join(self.tempdir, "samdb.ldb")
+ session_info = system_session()
+
+ hostname="foo"
+ domain="EXAMPLE"
+ dnsdomain="example.com"
+ serverrole="domain controller"
+
+ smbconf = os.path.join(self.tempdir, "smb.conf")
+ make_smbconf(smbconf, setup_path, hostname, domain, dnsdomain, serverrole,
+ self.tempdir)
+
+ lp = param.LoadParm()
+ lp.load(smbconf)
+
+ names = guess_names(lp=lp, hostname=hostname,
+ domain=domain, dnsdomain=dnsdomain,
+ serverrole=serverrole,
+ domaindn=self.domaindn, configdn=configdn,
+ schemadn=schemadn)
+ setup_templatesdb(os.path.join(self.tempdir, "templates.ldb"),
+ setup_path, session_info=session_info,
+ credentials=creds, lp=cmdline_loadparm)
+ self.samdb = setup_samdb(path, setup_path, session_info, creds,
+ cmdline_loadparm, names,
+ lambda x: None, domainsid,
+ "# no aci", domainguid,
+ policyguid, False, "secret",
+ "secret", "secret", invocationid,
+ "secret", "domain controller")
+
+ def tearDown(self):
+ for f in ['templates.ldb', 'schema.ldb', 'configuration.ldb',
+ 'users.ldb', 'samdb.ldb', 'smb.conf']:
+ os.remove(os.path.join(self.tempdir, f))
+ super(SamDBTestCase, self).tearDown()
+
+ def test_add_foreign(self):
+ self.samdb.add_foreign(self.domaindn, "S-1-5-7", "Somedescription")
+
diff --git a/source4/scripting/python/samba/tests/upgrade.py b/source4/scripting/python/samba/tests/upgrade.py
new file mode 100644
index 0000000000..4dc86ace8a
--- /dev/null
+++ b/source4/scripting/python/samba/tests/upgrade.py
@@ -0,0 +1,37 @@
+#!/usr/bin/python
+
+# Unix SMB/CIFS implementation.
+# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+from samba import Ldb
+from samba.upgrade import import_wins
+from samba.tests import LdbTestCase
+
+class WinsUpgradeTests(LdbTestCase):
+ def test_upgrade(self):
+ winsdb = {
+ "FOO#20": (200, ["127.0.0.1", "127.0.0.2"], 0x60)
+ }
+ import_wins(self.ldb, winsdb)
+
+ self.assertEquals(['name=FOO,type=0x20'],
+ [str(m.dn) for m in self.ldb.search(expression="(objectClass=winsRecord)")])
+
+ def test_version(self):
+ import_wins(self.ldb, {})
+ self.assertEquals("VERSION",
+ self.ldb.search(expression="(objectClass=winsMaxVersion)")[0]["cn"])
diff --git a/source4/scripting/python/samba/torture/pytorture b/source4/scripting/python/samba/torture/pytorture
new file mode 100755
index 0000000000..e0123447e8
--- /dev/null
+++ b/source4/scripting/python/samba/torture/pytorture
@@ -0,0 +1,51 @@
+#!/usr/bin/python
+
+import sys
+from optparse import OptionParser
+
+# Parse command line
+
+parser = OptionParser()
+
+parser.add_option("-b", "--binding", action="store", type="string",
+ dest="binding")
+
+parser.add_option("-d", "--domain", action="store", type="string",
+ dest="domain")
+
+parser.add_option("-u", "--username", action="store", type="string",
+ dest="username")
+
+parser.add_option("-p", "--password", action="store", type="string",
+ dest="password")
+
+(options, args) = parser.parse_args()
+
+if not options.binding:
+ parser.error('You must supply a binding string')
+
+if not options.username or not options.password or not options.domain:
+ parser.error('You must supply a domain, username and password')
+
+binding = options.binding
+domain = options.domain
+username = options.username
+password = options.password
+
+if len(args) == 0:
+ parser.error('You must supply the name of a module to test')
+
+# Import and test
+
+for test in args:
+
+ try:
+ module = __import__('torture_%s' % test)
+ except ImportError:
+ print 'No such module "%s"' % test
+ sys.exit(1)
+
+ if not hasattr(module, 'runtests'):
+ print 'Module "%s" does not have a runtests function' % test
+
+ module.runtests(binding, (domain, username, password))
diff --git a/source4/scripting/python/samba/torture/spoolss.py b/source4/scripting/python/samba/torture/spoolss.py
new file mode 100644
index 0000000000..a75385e079
--- /dev/null
+++ b/source4/scripting/python/samba/torture/spoolss.py
@@ -0,0 +1,437 @@
+import sys, string
+import dcerpc
+
+
+def ResizeBufferCall(fn, pipe, r):
+
+ r['buffer'] = None
+ r['buf_size'] = 0
+
+ result = fn(pipe, r)
+
+ if result['result'] == dcerpc.WERR_INSUFFICIENT_BUFFER or \
+ result['result'] == dcerpc.WERR_MORE_DATA:
+ r['buffer'] = result['buf_size'] * '\x00'
+ r['buf_size'] = result['buf_size']
+
+ result = fn(pipe, r)
+
+ return result
+
+
+def test_OpenPrinterEx(pipe, printer):
+
+ print 'spoolss_OpenPrinterEx(%s)' % printer
+
+ printername = '\\\\%s' % dcerpc.dcerpc_server_name(pipe)
+
+ if printer is not None:
+ printername = printername + '\\%s' % printer
+
+ r = {}
+ r['printername'] = printername
+ r['datatype'] = None
+ r['devmode_ctr'] = {}
+ r['devmode_ctr']['size'] = 0
+ r['devmode_ctr']['devmode'] = None
+ r['access_mask'] = 0x02000000
+ r['level'] = 1
+ r['userlevel'] = {}
+ r['userlevel']['level1'] = {}
+ r['userlevel']['level1']['size'] = 0
+ r['userlevel']['level1']['client'] = None
+ r['userlevel']['level1']['user'] = None
+ r['userlevel']['level1']['build'] = 1381
+ r['userlevel']['level1']['major'] = 2
+ r['userlevel']['level1']['minor'] = 0
+ r['userlevel']['level1']['processor'] = 0
+
+ result = dcerpc.spoolss_OpenPrinterEx(pipe, r)
+
+ return result['handle']
+
+
+def test_ClosePrinter(pipe, handle):
+
+ r = {}
+ r['handle'] = handle
+
+ dcerpc.spoolss_ClosePrinter(pipe, r)
+
+
+def test_GetPrinter(pipe, handle):
+
+ r = {}
+ r['handle'] = handle
+
+ for level in [0, 1, 2, 3, 4, 5, 6, 7]:
+
+ print 'spoolss_GetPrinter(level = %d)' % level
+
+ r['level'] = level
+ r['buffer'] = None
+ r['buf_size'] = 0
+
+ result = ResizeBufferCall(dcerpc.spoolss_GetPrinter, pipe, r)
+
+
+def test_EnumForms(pipe, handle):
+
+ print 'spoolss_EnumForms()'
+
+ r = {}
+ r['handle'] = handle
+ r['level'] = 1
+ r['buffer'] = None
+ r['buf_size'] = 0
+
+ result = ResizeBufferCall(dcerpc.spoolss_EnumForms, pipe, r)
+
+ forms = dcerpc.unmarshall_spoolss_FormInfo_array(
+ result['buffer'], r['level'], result['count'])
+
+ for form in forms:
+
+ r = {}
+ r['handle'] = handle
+ r['formname'] = form['info1']['formname']
+ r['level'] = 1
+
+ result = ResizeBufferCall(dcerpc.spoolss_GetForm, pipe, r)
+
+
+def test_EnumPorts(pipe, handle):
+
+ print 'spoolss_EnumPorts()'
+
+ for level in [1, 2]:
+
+ r = {}
+ r['handle'] = handle
+ r['servername'] = None
+ r['level'] = level
+
+ result = ResizeBufferCall(dcerpc.spoolss_EnumPorts, pipe, r)
+
+ ports = dcerpc.unmarshall_spoolss_PortInfo_array(
+ result['buffer'], r['level'], result['count'])
+
+ if level == 1:
+ port_names = map(lambda x: x['info1']['port_name'], ports)
+
+
+def test_DeleteForm(pipe, handle, formname):
+
+ r = {}
+ r['handle'] = handle
+ r['formname'] = formname
+
+ dcerpc.spoolss_DeleteForm(pipe, r)
+
+
+def test_GetForm(pipe, handle, formname):
+
+ r = {}
+ r['handle'] = handle
+ r['formname'] = formname
+ r['level'] = 1
+
+ result = ResizeBufferCall(dcerpc.spoolss_GetForm, pipe, r)
+
+ return result['info']['info1']
+
+
+def test_SetForm(pipe, handle, form):
+
+ print 'spoolss_SetForm()'
+
+ r = {}
+ r['handle'] = handle
+ r['level'] = 1
+ r['formname'] = form['info1']['formname']
+ r['info'] = form
+
+ dcerpc.spoolss_SetForm(pipe, r)
+
+ newform = test_GetForm(pipe, handle, r['formname'])
+
+ if form['info1'] != newform:
+ print 'SetForm: mismatch: %s != %s' % \
+ (r['info']['info1'], f)
+ sys.exit(1)
+
+
+def test_AddForm(pipe, handle):
+
+ print 'spoolss_AddForm()'
+
+ formname = '__testform__'
+
+ r = {}
+ r['handle'] = handle
+ r['level'] = 1
+ r['info'] = {}
+ r['info']['info1'] = {}
+ r['info']['info1']['formname'] = formname
+ r['info']['info1']['flags'] = 0x0002
+ r['info']['info1']['width'] = 100
+ r['info']['info1']['length'] = 100
+ r['info']['info1']['left'] = 0
+ r['info']['info1']['top'] = 1000
+ r['info']['info1']['right'] = 2000
+ r['info']['info1']['bottom'] = 3000
+
+ try:
+ result = dcerpc.spoolss_AddForm(pipe, r)
+ except dcerpc.WERROR, arg:
+ if arg[0] == dcerpc.WERR_ALREADY_EXISTS:
+ test_DeleteForm(pipe, handle, formname)
+ result = dcerpc.spoolss_AddForm(pipe, r)
+
+ f = test_GetForm(pipe, handle, formname)
+
+ if r['info']['info1'] != f:
+ print 'AddForm: mismatch: %s != %s' % \
+ (r['info']['info1'], f)
+ sys.exit(1)
+
+ r['formname'] = formname
+
+ test_SetForm(pipe, handle, r['info'])
+
+ test_DeleteForm(pipe, handle, formname)
+
+
+def test_EnumJobs(pipe, handle):
+
+ print 'spoolss_EnumJobs()'
+
+ r = {}
+ r['handle'] = handle
+ r['firstjob'] = 0
+ r['numjobs'] = 0xffffffff
+ r['level'] = 1
+
+ result = ResizeBufferCall(dcerpc.spoolss_EnumJobs, pipe, r)
+
+ if result['buffer'] is None:
+ return
+
+ jobs = dcerpc.unmarshall_spoolss_JobInfo_array(
+ result['buffer'], r['level'], result['count'])
+
+ for job in jobs:
+
+ s = {}
+ s['handle'] = handle
+ s['job_id'] = job['info1']['job_id']
+ s['level'] = 1
+
+ result = ResizeBufferCall(dcerpc.spoolss_GetJob, pipe, s)
+
+ if result['info'] != job:
+ print 'EnumJobs: mismatch: %s != %s' % (result['info'], job)
+ sys.exit(1)
+
+
+ # TODO: AddJob, DeleteJob, ScheduleJob
+
+
+def test_EnumPrinterData(pipe, handle):
+
+ print 'test_EnumPrinterData()'
+
+ enum_index = 0
+
+ while 1:
+
+ r = {}
+ r['handle'] = handle
+ r['enum_index'] = enum_index
+
+ r['value_offered'] = 0
+ r['data_size'] = 0
+
+ result = dcerpc.spoolss_EnumPrinterData(pipe, r)
+
+ r['value_offered'] = result['value_needed']
+ r['data_size'] = result['data_size']
+
+ result = dcerpc.spoolss_EnumPrinterData(pipe, r)
+
+ if result['result'] == dcerpc.WERR_NO_MORE_ITEMS:
+ break
+
+ s = {}
+ s['handle'] = handle
+ s['value_name'] = result['value_name']
+
+ result2 = ResizeBufferCall(dcerpc.spoolss_GetPrinterData, pipe, s)
+
+ if result['buffer'][:result2['buf_size']] != result2['buffer']:
+ print 'EnumPrinterData/GetPrinterData mismatch'
+ sys.exit(1)
+
+ enum_index += 1
+
+
+def test_SetPrinterDataEx(pipe, handle):
+
+ valuename = '__printerdataextest__'
+ data = '12345'
+
+ r = {}
+ r['handle'] = handle
+ r['key_name'] = 'DsSpooler'
+ r['value_name'] = valuename
+ r['type'] = 3
+ r['buffer'] = data
+ r['buf_size'] = len(data)
+
+ result = dcerpc.spoolss_SetPrinterDataEx(pipe, r)
+
+
+def test_EnumPrinterDataEx(pipe, handle):
+
+ r = {}
+ r['handle'] = handle
+ r['key_name'] = 'DsSpooler'
+ r['buf_size'] = 0
+
+ result = dcerpc.spoolss_EnumPrinterDataEx(pipe, r)
+
+ if result['result'] == dcerpc.WERR_MORE_DATA:
+ r['buf_size'] = result['buf_size']
+
+ result = dcerpc.spoolss_EnumPrinterDataEx(pipe, r)
+
+ # TODO: test spoolss_GetPrinterDataEx()
+
+
+def test_SetPrinterData(pipe, handle):
+
+ print 'testing spoolss_SetPrinterData()'
+
+ valuename = '__printerdatatest__'
+ data = '12345'
+
+ r = {}
+ r['handle'] = handle
+ r['value_name'] = valuename
+ r['type'] = 3 # REG_BINARY
+ r['buffer'] = data
+ r['real_len'] = 5
+
+ dcerpc.spoolss_SetPrinterData(pipe, r)
+
+ s = {}
+ s['handle'] = handle
+ s['value_name'] = valuename
+
+ result = ResizeBufferCall(dcerpc.spoolss_GetPrinterData, pipe, r)
+
+ if result['buffer'] != data:
+ print 'SetPrinterData: mismatch'
+ sys.exit(1)
+
+ dcerpc.spoolss_DeletePrinterData(pipe, r)
+
+
+def test_EnumPrinters(pipe):
+
+ print 'testing spoolss_EnumPrinters()'
+
+ printer_names = None
+
+ r = {}
+ r['flags'] = 0x02
+ r['server'] = None
+
+ for level in [0, 1, 2, 4, 5]:
+
+ print 'test_EnumPrinters(level = %d)' % level
+
+ r['level'] = level
+
+ result = ResizeBufferCall(dcerpc.spoolss_EnumPrinters, pipe, r)
+
+ printers = dcerpc.unmarshall_spoolss_PrinterInfo_array(
+ result['buffer'], r['level'], result['count'])
+
+ if level == 2:
+ for p in printers:
+
+ # A nice check is for the specversion in the
+ # devicemode. This has always been observed to be
+ # 1025.
+
+ if p['info2']['devmode']['specversion'] != 1025:
+ print 'test_EnumPrinters: specversion != 1025'
+ sys.exit(1)
+
+ r['level'] = 1
+ result = ResizeBufferCall(dcerpc.spoolss_EnumPrinters, pipe, r)
+
+ for printer in dcerpc.unmarshall_spoolss_PrinterInfo_array(
+ result['buffer'], r['level'], result['count']):
+
+ if string.find(printer['info1']['name'], '\\\\') == 0:
+ print 'Skipping remote printer %s' % printer['info1']['name']
+ continue
+
+ printername = string.split(printer['info1']['name'], ',')[0]
+
+ handle = test_OpenPrinterEx(pipe, printername)
+
+ test_GetPrinter(pipe, handle)
+ test_EnumPorts(pipe, handle)
+ test_EnumForms(pipe, handle)
+ test_AddForm(pipe, handle)
+ test_EnumJobs(pipe, handle)
+ test_EnumPrinterData(pipe, handle)
+ test_EnumPrinterDataEx(pipe, handle)
+ test_SetPrinterData(pipe, handle)
+# test_SetPrinterDataEx(pipe, handle)
+ test_ClosePrinter(pipe, handle)
+
+
+def test_EnumPrinterDrivers(pipe):
+
+ print 'test spoolss_EnumPrinterDrivers()'
+
+ for level in [1, 2, 3]:
+
+ r = {}
+ r['server'] = None
+ r['environment'] = None
+ r['level'] = level
+
+ result = ResizeBufferCall(dcerpc.spoolss_EnumPrinterDrivers, pipe, r)
+
+ drivers = dcerpc.unmarshall_spoolss_DriverInfo_array(
+ result['buffer'], r['level'], result['count'])
+
+ if level == 1:
+ driver_names = map(lambda x: x['info1']['driver_name'], drivers)
+
+
+def test_PrintServer(pipe):
+
+ handle = test_OpenPrinterEx(pipe, None)
+
+ # EnumForms and AddForm tests return WERR_BADFID here (??)
+
+ test_ClosePrinter(pipe, handle)
+
+
+def runtests(binding, domain, username, password):
+
+ print 'Testing SPOOLSS pipe'
+
+ pipe = dcerpc.pipe_connect(binding,
+ dcerpc.DCERPC_SPOOLSS_UUID, dcerpc.DCERPC_SPOOLSS_VERSION,
+ domain, username, password)
+
+ test_EnumPrinters(pipe)
+ test_EnumPrinterDrivers(pipe)
+ test_PrintServer(pipe)
diff --git a/source4/scripting/python/samba/torture/torture_samr.py b/source4/scripting/python/samba/torture/torture_samr.py
new file mode 100755
index 0000000000..15c6dc1a76
--- /dev/null
+++ b/source4/scripting/python/samba/torture/torture_samr.py
@@ -0,0 +1,221 @@
+#!/usr/bin/python
+
+import sys
+import dcerpc, samr
+
+def test_Connect(pipe):
+
+ handle = samr.Connect(pipe)
+ handle = samr.Connect2(pipe)
+ handle = samr.Connect3(pipe)
+ handle = samr.Connect4(pipe)
+
+ # WIN2K3 only?
+
+ try:
+ handle = samr.Connect5(pipe)
+ except dcerpc.NTSTATUS, arg:
+ if arg[0] != 0xc00000d2L: # NT_STATUS_NET_WRITE_FAULT
+ raise
+
+ return handle
+
+def test_UserHandle(user_handle):
+
+ # QuerySecurity()/SetSecurity()
+
+ user_handle.SetSecurity(user_handle.QuerySecurity())
+
+ # GetUserPwInfo()
+
+ user_handle.GetUserPwInfo()
+
+ # GetUserInfo()
+
+ for level in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 20,
+ 21, 23, 24, 25, 26]:
+
+ try:
+ user_handle.QueryUserInfo(level)
+ user_handle.QueryUserInfo2(level)
+ except dcerpc.NTSTATUS, arg:
+ if arg[0] != 0xc0000003L: # NT_STATUS_INVALID_INFO_CLASS
+ raise
+
+ # GetGroupsForUser()
+
+ user_handle.GetGroupsForUser()
+
+ # TestPrivateFunctionsUser()
+
+ try:
+ user_handle.TestPrivateFunctionsUser()
+ except dcerpc.NTSTATUS, arg:
+ if arg[0] != 0xC0000002L:
+ raise
+
+def test_GroupHandle(group_handle):
+
+ # QuerySecurity()/SetSecurity()
+
+ group_handle.SetSecurity(group_handle.QuerySecurity())
+
+ # QueryGroupInfo()
+
+ for level in [1, 2, 3, 4, 5]:
+ info = group_handle.QueryGroupInfo(level)
+
+ # TODO: SetGroupinfo()
+
+ # QueryGroupMember()
+
+ group_handle.QueryGroupMember()
+
+def test_AliasHandle(alias_handle):
+
+ # QuerySecurity()/SetSecurity()
+
+ alias_handle.SetSecurity(alias_handle.QuerySecurity())
+
+ print alias_handle.GetMembersInAlias()
+
+def test_DomainHandle(name, sid, domain_handle):
+
+ print 'testing %s (%s)' % (name, sid)
+
+ # QuerySecurity()/SetSecurity()
+
+ domain_handle.SetSecurity(domain_handle.QuerySecurity())
+
+ # LookupNames(), none mapped
+
+ try:
+ domain_handle.LookupNames(['xxNONAMExx'])
+ except dcerpc.NTSTATUS, arg:
+ if arg[0] != 0xc0000073L:
+ raise dcerpc.NTSTATUS(arg)
+
+ # LookupNames(), some mapped
+
+ if name != 'Builtin':
+ domain_handle.LookupNames(['Administrator', 'xxNONAMExx'])
+
+ # QueryDomainInfo()/SetDomainInfo()
+
+ levels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13]
+ set_ok = [1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0]
+
+ for i in range(len(levels)):
+
+ info = domain_handle.QueryDomainInfo(level = levels[i])
+
+ try:
+ domain_handle.SetDomainInfo(levels[i], info)
+ except dcerpc.NTSTATUS, arg:
+ if not (arg[0] == 0xc0000003L and not set_ok[i]):
+ raise
+
+ # QueryDomainInfo2()
+
+ levels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13]
+
+ for i in range(len(levels)):
+ domain_handle.QueryDomainInfo2(level = levels[i])
+
+ # EnumDomainUsers
+
+ print 'testing users'
+
+ users = domain_handle.EnumDomainUsers()
+ rids = domain_handle.LookupNames(users)
+
+ for i in range(len(users)):
+ test_UserHandle(domain_handle.OpenUser(rids[0][i]))
+
+ # QueryDisplayInfo
+
+ for i in [1, 2, 3, 4, 5]:
+ domain_handle.QueryDisplayInfo(level = i)
+ domain_handle.QueryDisplayInfo2(level = i)
+ domain_handle.QueryDisplayInfo3(level = i)
+
+ # EnumDomainGroups
+
+ print 'testing groups'
+
+ groups = domain_handle.EnumDomainGroups()
+ rids = domain_handle.LookupNames(groups)
+
+ for i in range(len(groups)):
+ test_GroupHandle(domain_handle.OpenGroup(rids[0][i]))
+
+ # EnumDomainAliases
+
+ print 'testing aliases'
+
+ aliases = domain_handle.EnumDomainAliases()
+ rids = domain_handle.LookupNames(aliases)
+
+ for i in range(len(aliases)):
+ test_AliasHandle(domain_handle.OpenAlias(rids[0][i]))
+
+ # CreateUser
+ # CreateUser2
+ # CreateDomAlias
+ # RidToSid
+ # RemoveMemberFromForeignDomain
+ # CreateDomainGroup
+ # GetAliasMembership
+
+ # GetBootKeyInformation()
+
+ try:
+ domain_handle.GetBootKeyInformation()
+ except dcerpc.NTSTATUS, arg:
+ pass
+
+ # TestPrivateFunctionsDomain()
+
+ try:
+ domain_handle.TestPrivateFunctionsDomain()
+ except dcerpc.NTSTATUS, arg:
+ if arg[0] != 0xC0000002L:
+ raise
+
+def test_ConnectHandle(connect_handle):
+
+ print 'testing connect handle'
+
+ # QuerySecurity/SetSecurity
+
+ connect_handle.SetSecurity(connect_handle.QuerySecurity())
+
+ # Lookup bogus domain
+
+ try:
+ connect_handle.LookupDomain('xxNODOMAINxx')
+ except dcerpc.NTSTATUS, arg:
+ if arg[0] != 0xC00000DFL: # NT_STATUS_NO_SUCH_DOMAIN
+ raise
+
+ # Test all domains
+
+ for domain_name in connect_handle.EnumDomains():
+
+ connect_handle.GetDomPwInfo(domain_name)
+ sid = connect_handle.LookupDomain(domain_name)
+ domain_handle = connect_handle.OpenDomain(sid)
+
+ test_DomainHandle(domain_name, sid, domain_handle)
+
+ # TODO: Test Shutdown() function
+
+def runtests(binding, creds):
+
+ print 'Testing SAMR pipe'
+
+ pipe = dcerpc.pipe_connect(binding,
+ dcerpc.DCERPC_SAMR_UUID, int(dcerpc.DCERPC_SAMR_VERSION), creds)
+
+ handle = test_Connect(pipe)
+ test_ConnectHandle(handle)
diff --git a/source4/scripting/python/samba/torture/torture_tdb.py b/source4/scripting/python/samba/torture/torture_tdb.py
new file mode 100755
index 0000000000..7f97caf6cb
--- /dev/null
+++ b/source4/scripting/python/samba/torture/torture_tdb.py
@@ -0,0 +1,90 @@
+#!/usr/bin/python
+
+import sys, os
+import Tdb
+
+def fail(msg):
+ print 'FAILED:', msg
+ sys.exit(1)
+
+tdb_file = '/tmp/torture_tdb.tdb'
+
+# Create temporary tdb file
+
+t = Tdb.Tdb(tdb_file, flags = Tdb.CLEAR_IF_FIRST)
+
+# Check non-existent key throws KeyError exception
+
+try:
+ t['__none__']
+except KeyError:
+ pass
+else:
+ fail('non-existent key did not throw KeyError')
+
+# Check storing key
+
+t['bar'] = '1234'
+if t['bar'] != '1234':
+ fail('store key failed')
+
+# Check key exists
+
+if not t.has_key('bar'):
+ fail('has_key() failed for existing key')
+
+if t.has_key('__none__'):
+ fail('has_key() succeeded for non-existent key')
+
+# Delete key
+
+try:
+ del(t['__none__'])
+except KeyError:
+ pass
+else:
+ fail('delete of non-existent key did not throw KeyError')
+
+del t['bar']
+if t.has_key('bar'):
+ fail('delete of existing key did not delete key')
+
+# Clear all keys
+
+t.clear()
+if len(t) != 0:
+ fail('clear failed to remove all keys')
+
+# Other dict functions
+
+t['a'] = '1'
+t['ab'] = '12'
+t['abc'] = '123'
+
+if len(t) != 3:
+ fail('len method produced wrong value')
+
+keys = t.keys()
+values = t.values()
+items = t.items()
+
+if set(keys) != set(['a', 'ab', 'abc']):
+ fail('keys method produced wrong values')
+
+if set(values) != set(['1', '12', '123']):
+ fail('values method produced wrong values')
+
+if set(items) != set([('a', '1'), ('ab', '12'), ('abc', '123')]):
+ fail('values method produced wrong values')
+
+t.close()
+
+# Re-open read-only
+
+t = Tdb.Tdb(tdb_file, open_flags = os.O_RDONLY)
+t.keys()
+t.close()
+
+# Clean up
+
+os.unlink(tdb_file)
diff --git a/source4/scripting/python/samba/torture/winreg.py b/source4/scripting/python/samba/torture/winreg.py
new file mode 100755
index 0000000000..eb60b9847e
--- /dev/null
+++ b/source4/scripting/python/samba/torture/winreg.py
@@ -0,0 +1,165 @@
+#!/usr/bin/python
+
+import sys, dcerpc
+
+def test_OpenHKLM(pipe):
+
+ r = {}
+ r['unknown'] = {}
+ r['unknown']['unknown0'] = 0x9038
+ r['unknown']['unknown1'] = 0x0000
+ r['access_required'] = 0x02000000
+
+ result = dcerpc.winreg_OpenHKLM(pipe, r)
+
+ return result['handle']
+
+def test_QueryInfoKey(pipe, handle):
+
+ r = {}
+ r['handle'] = handle
+ r['class'] = {}
+ r['class']['name'] = None
+
+ return dcerpc.winreg_QueryInfoKey(pipe, r)
+
+def test_CloseKey(pipe, handle):
+
+ r = {}
+ r['handle'] = handle
+
+ dcerpc.winreg_CloseKey(pipe, r)
+
+def test_FlushKey(pipe, handle):
+
+ r = {}
+ r['handle'] = handle
+
+ dcerpc.winreg_FlushKey(pipe, r)
+
+def test_GetVersion(pipe, handle):
+
+ r = {}
+ r['handle'] = handle
+
+ dcerpc.winreg_GetVersion(pipe, r)
+
+def test_GetKeySecurity(pipe, handle):
+
+ r = {}
+ r['handle'] = handle
+ r['unknown'] = 4
+ r['size'] = None
+ r['data'] = {}
+ r['data']['max_len'] = 0
+ r['data']['data'] = ''
+
+ result = dcerpc.winreg_GetKeySecurity(pipe, r)
+
+ print result
+
+ if result['result'] == dcerpc.WERR_INSUFFICIENT_BUFFER:
+ r['size'] = {}
+ r['size']['max_len'] = result['data']['max_len']
+ r['size']['offset'] = 0
+ r['size']['len'] = result['data']['max_len']
+
+ result = dcerpc.winreg_GetKeySecurity(pipe, r)
+
+ print result
+
+ sys.exit(1)
+
+def test_Key(pipe, handle, name, depth = 0):
+
+ # Don't descend too far. Registries can be very deep.
+
+ if depth > 2:
+ return
+
+ try:
+ keyinfo = test_QueryInfoKey(pipe, handle)
+ except dcerpc.WERROR, arg:
+ if arg[0] == dcerpc.WERR_ACCESS_DENIED:
+ return
+
+ test_GetVersion(pipe, handle)
+
+ test_FlushKey(pipe, handle)
+
+ test_GetKeySecurity(pipe, handle)
+
+ # Enumerate values in this key
+
+ r = {}
+ r['handle'] = handle
+ r['name_in'] = {}
+ r['name_in']['len'] = 0
+ r['name_in']['max_len'] = (keyinfo['max_valnamelen'] + 1) * 2
+ r['name_in']['buffer'] = {}
+ r['name_in']['buffer']['max_len'] = keyinfo['max_valnamelen'] + 1
+ r['name_in']['buffer']['offset'] = 0
+ r['name_in']['buffer']['len'] = 0
+ r['type'] = 0
+ r['value_in'] = {}
+ r['value_in']['max_len'] = keyinfo['max_valbufsize']
+ r['value_in']['offset'] = 0
+ r['value_in']['len'] = 0
+ r['value_len1'] = keyinfo['max_valbufsize']
+ r['value_len2'] = 0
+
+ for i in range(0, keyinfo['num_values']):
+
+ r['enum_index'] = i
+
+ dcerpc.winreg_EnumValue(pipe, r)
+
+ # Recursively test subkeys of this key
+
+ r = {}
+ r['handle'] = handle
+ r['key_name_len'] = 0
+ r['unknown'] = 0x0414
+ r['in_name'] = {}
+ r['in_name']['unknown'] = 0x20a
+ r['in_name']['key_name'] = {}
+ r['in_name']['key_name']['name'] = None
+ r['class'] = {}
+ r['class']['name'] = None
+ r['last_changed_time'] = {}
+ r['last_changed_time']['low'] = 0
+ r['last_changed_time']['high'] = 0
+
+ for i in range(0, keyinfo['num_subkeys']):
+
+ r['enum_index'] = i
+
+ subkey = dcerpc.winreg_EnumKey(pipe, r)
+
+ s = {}
+ s['handle'] = handle
+ s['keyname'] = {}
+ s['keyname']['name'] = subkey['out_name']['name']
+ s['unknown'] = 0
+ s['access_mask'] = 0x02000000
+
+ result = dcerpc.winreg_OpenKey(pipe, s)
+
+ test_Key(pipe, result['handle'], name + '/' + s['keyname']['name'],
+ depth + 1)
+
+ test_CloseKey(pipe, result['handle'])
+
+ # Enumerate values
+
+def runtests(binding, domain, username, password):
+
+ print 'Testing WINREG pipe'
+
+ pipe = dcerpc.pipe_connect(binding,
+ dcerpc.DCERPC_WINREG_UUID, dcerpc.DCERPC_WINREG_VERSION,
+ domain, username, password)
+
+ handle = test_OpenHKLM(pipe)
+
+ test_Key(pipe, handle, 'HKLM')
diff --git a/source4/scripting/python/samba/upgrade.py b/source4/scripting/python/samba/upgrade.py
new file mode 100644
index 0000000000..0c83604e82
--- /dev/null
+++ b/source4/scripting/python/samba/upgrade.py
@@ -0,0 +1,437 @@
+#!/usr/bin/python
+#
+# backend code for upgrading from Samba3
+# Copyright Jelmer Vernooij 2005-2007
+# Released under the GNU GPL v3 or later
+#
+
+"""Support code for upgrading from Samba 3 to Samba 4."""
+
+__docformat__ = "restructuredText"
+
+from provision import findnss, provision, FILL_DRS
+import grp
+import ldb
+import time
+import pwd
+import uuid
+import registry
+from samba import Ldb
+from samba.samdb import SamDB
+
+def import_sam_policy(samldb, samba3_policy, domaindn):
+ """Import a Samba 3 policy database."""
+ samldb.modify_ldif("""
+dn: %s
+changetype: modify
+replace: minPwdLength
+minPwdLength: %d
+pwdHistoryLength: %d
+minPwdAge: %d
+maxPwdAge: %d
+lockoutDuration: %d
+samba3ResetCountMinutes: %d
+samba3UserMustLogonToChangePassword: %d
+samba3BadLockoutMinutes: %d
+samba3DisconnectTime: %d
+
+""" % (dn, policy.min_password_length,
+ policy.password_history, policy.minimum_password_age,
+ policy.maximum_password_age, policy.lockout_duration,
+ policy.reset_count_minutes, policy.user_must_logon_to_change_password,
+ policy.bad_lockout_minutes, policy.disconnect_time))
+
+
+def import_sam_account(samldb,acc,domaindn,domainsid):
+ """Import a Samba 3 SAM account.
+
+ :param samldb: Samba 4 SAM Database handle
+ :param acc: Samba 3 account
+ :param domaindn: Domain DN
+ :param domainsid: Domain SID."""
+ if acc.nt_username is None or acc.nt_username == "":
+ acc.nt_username = acc.username
+
+ if acc.fullname is None:
+ try:
+ acc.fullname = pwd.getpwnam(acc.username)[4].split(",")[0]
+ except KeyError:
+ pass
+
+ if acc.fullname is None:
+ acc.fullname = acc.username
+
+ assert acc.fullname is not None
+ assert acc.nt_username is not None
+
+ samldb.add({
+ "dn": "cn=%s,%s" % (acc.fullname, domaindn),
+ "objectClass": ["top", "user"],
+ "lastLogon": str(acc.logon_time),
+ "lastLogoff": str(acc.logoff_time),
+ "unixName": acc.username,
+ "sAMAccountName": acc.nt_username,
+ "cn": acc.nt_username,
+ "description": acc.acct_desc,
+ "primaryGroupID": str(acc.group_rid),
+ "badPwdcount": str(acc.bad_password_count),
+ "logonCount": str(acc.logon_count),
+ "samba3Domain": acc.domain,
+ "samba3DirDrive": acc.dir_drive,
+ "samba3MungedDial": acc.munged_dial,
+ "samba3Homedir": acc.homedir,
+ "samba3LogonScript": acc.logon_script,
+ "samba3ProfilePath": acc.profile_path,
+ "samba3Workstations": acc.workstations,
+ "samba3KickOffTime": str(acc.kickoff_time),
+ "samba3BadPwdTime": str(acc.bad_password_time),
+ "samba3PassLastSetTime": str(acc.pass_last_set_time),
+ "samba3PassCanChangeTime": str(acc.pass_can_change_time),
+ "samba3PassMustChangeTime": str(acc.pass_must_change_time),
+ "objectSid": "%s-%d" % (domainsid, acc.user_rid),
+ "lmPwdHash:": acc.lm_password,
+ "ntPwdHash:": acc.nt_password,
+ })
+
+
+def import_sam_group(samldb, sid, gid, sid_name_use, nt_name, comment, domaindn):
+ """Upgrade a SAM group.
+
+ :param samldb: SAM database.
+ :param gid: Group GID
+ :param sid_name_use: SID name use
+ :param nt_name: NT Group Name
+ :param comment: NT Group Comment
+ :param domaindn: Domain DN
+ """
+
+ if sid_name_use == 5: # Well-known group
+ return None
+
+ if nt_name in ("Domain Guests", "Domain Users", "Domain Admins"):
+ return None
+
+ if gid == -1:
+ gr = grp.getgrnam(nt_name)
+ else:
+ gr = grp.getgrgid(gid)
+
+ if gr is None:
+ unixname = "UNKNOWN"
+ else:
+ unixname = gr.gr_name
+
+ assert unixname is not None
+
+ samldb.add({
+ "dn": "cn=%s,%s" % (nt_name, domaindn),
+ "objectClass": ["top", "group"],
+ "description": comment,
+ "cn": nt_name,
+ "objectSid": sid,
+ "unixName": unixname,
+ "samba3SidNameUse": str(sid_name_use)
+ })
+
+
+def import_idmap(samdb,samba3_idmap,domaindn):
+ """Import idmap data.
+
+ :param samdb: SamDB handle.
+ :param samba3_idmap: Samba 3 IDMAP database to import from
+ :param domaindn: Domain DN.
+ """
+ samdb.add({
+ "dn": domaindn,
+ "userHwm": str(samba3_idmap.get_user_hwm()),
+ "groupHwm": str(samba3_idmap.get_group_hwm())})
+
+ for uid in samba3_idmap.uids():
+ samdb.add({"dn": "SID=%s,%s" % (samba3_idmap.get_user_sid(uid), domaindn),
+ "SID": samba3_idmap.get_user_sid(uid),
+ "type": "user",
+ "unixID": str(uid)})
+
+ for gid in samba3_idmap.uids():
+ samdb.add({"dn": "SID=%s,%s" % (samba3_idmap.get_group_sid(gid), domaindn),
+ "SID": samba3_idmap.get_group_sid(gid),
+ "type": "group",
+ "unixID": str(gid)})
+
+
+def import_wins(samba4_winsdb, samba3_winsdb):
+ """Import settings from a Samba3 WINS database.
+
+ :param samba4_winsdb: WINS database to import to
+ :param samba3_winsdb: WINS database to import from
+ """
+ version_id = 0
+
+ for (name, (ttl, ips, nb_flags)) in samba3_winsdb.items():
+ version_id+=1
+
+ type = int(name.split("#", 1)[1], 16)
+
+ if type == 0x1C:
+ rType = 0x2
+ elif type & 0x80:
+ if len(ips) > 1:
+ rType = 0x2
+ else:
+ rType = 0x1
+ else:
+ if len(ips) > 1:
+ rType = 0x3
+ else:
+ rType = 0x0
+
+ if ttl > time.time():
+ rState = 0x0 # active
+ else:
+ rState = 0x1 # released
+
+ nType = ((nb_flags & 0x60)>>5)
+
+ samba4_winsdb.add({"dn": "name=%s,type=0x%s" % tuple(name.split("#")),
+ "type": name.split("#")[1],
+ "name": name.split("#")[0],
+ "objectClass": "winsRecord",
+ "recordType": str(rType),
+ "recordState": str(rState),
+ "nodeType": str(nType),
+ "expireTime": ldb.timestring(ttl),
+ "isStatic": "0",
+ "versionID": str(version_id),
+ "address": ips})
+
+ samba4_winsdb.add({"dn": "cn=VERSION",
+ "cn": "VERSION",
+ "objectClass": "winsMaxVersion",
+ "maxVersion": str(version_id)})
+
+def upgrade_provision(samba3, setup_dir, message, credentials, session_info, smbconf, targetdir):
+ oldconf = samba3.get_conf()
+
+ if oldconf.get("domain logons") == "True":
+ serverrole = "domain controller"
+ else:
+ if oldconf.get("security") == "user":
+ serverrole = "standalone"
+ else:
+ serverrole = "member server"
+
+ domainname = oldconf.get("workgroup")
+ if domainname:
+ domainname = str(domainname)
+ realm = oldconf.get("realm")
+ netbiosname = oldconf.get("netbios name")
+
+ secrets_db = samba3.get_secrets_db()
+
+ if domainname is None:
+ domainname = secrets_db.domains()[0]
+ message("No domain specified in smb.conf file, assuming '%s'" % domainname)
+
+ if realm is None:
+ realm = domainname.lower()
+ message("No realm specified in smb.conf file, assuming '%s'\n" % realm)
+
+ domainguid = secrets_db.get_domain_guid(domainname)
+ domainsid = secrets_db.get_sid(domainname)
+ if domainsid is None:
+ message("Can't find domain secrets for '%s'; using random SID\n" % domainname)
+
+ if netbiosname is not None:
+ machinepass = secrets_db.get_machine_password(netbiosname)
+ else:
+ machinepass = None
+
+ result = provision(setup_dir=setup_dir, message=message,
+ samdb_fill=FILL_DRS, smbconf=smbconf, session_info=session_info,
+ credentials=credentials, realm=realm,
+ domain=domainname, domainsid=domainsid, domainguid=domainguid,
+ machinepass=machinepass, serverrole=serverrole, targetdir=targetdir)
+
+ import_wins(Ldb(result.paths.winsdb), samba3.get_wins_db())
+
+ # FIXME: import_registry(registry.Registry(), samba3.get_registry())
+
+ # FIXME: import_idmap(samdb,samba3.get_idmap_db(),domaindn)
+
+ groupdb = samba3.get_groupmapping_db()
+ for sid in groupdb.groupsids():
+ (gid, sid_name_use, nt_name, comment) = groupdb.get_group(sid)
+ # FIXME: import_sam_group(samdb, sid, gid, sid_name_use, nt_name, comment, domaindn)
+
+ # FIXME: Aliases
+
+ passdb = samba3.get_sam_db()
+ for name in passdb:
+ user = passdb[name]
+ #FIXME: import_sam_account(result.samdb, user, domaindn, domainsid)
+
+ if hasattr(passdb, 'ldap_url'):
+ message("Enabling Samba3 LDAP mappings for SAM database")
+
+ enable_samba3sam(result.samdb, passdb.ldap_url)
+
+
+def enable_samba3sam(samdb, ldapurl):
+ """Enable Samba 3 LDAP URL database.
+
+ :param samdb: SAM Database.
+ :param ldapurl: Samba 3 LDAP URL
+ """
+ samdb.modify_ldif("""
+dn: @MODULES
+changetype: modify
+replace: @LIST
+@LIST: samldb,operational,objectguid,rdn_name,samba3sam
+""")
+
+ samdb.add({"dn": "@MAP=samba3sam", "@MAP_URL": ldapurl})
+
+
+smbconf_keep = [
+ "dos charset",
+ "unix charset",
+ "display charset",
+ "comment",
+ "path",
+ "directory",
+ "workgroup",
+ "realm",
+ "netbios name",
+ "netbios aliases",
+ "netbios scope",
+ "server string",
+ "interfaces",
+ "bind interfaces only",
+ "security",
+ "auth methods",
+ "encrypt passwords",
+ "null passwords",
+ "obey pam restrictions",
+ "password server",
+ "smb passwd file",
+ "private dir",
+ "passwd chat",
+ "password level",
+ "lanman auth",
+ "ntlm auth",
+ "client NTLMv2 auth",
+ "client lanman auth",
+ "client plaintext auth",
+ "read only",
+ "hosts allow",
+ "hosts deny",
+ "log level",
+ "debuglevel",
+ "log file",
+ "smb ports",
+ "large readwrite",
+ "max protocol",
+ "min protocol",
+ "unicode",
+ "read raw",
+ "write raw",
+ "disable netbios",
+ "nt status support",
+ "announce version",
+ "announce as",
+ "max mux",
+ "max xmit",
+ "name resolve order",
+ "max wins ttl",
+ "min wins ttl",
+ "time server",
+ "unix extensions",
+ "use spnego",
+ "server signing",
+ "client signing",
+ "max connections",
+ "paranoid server security",
+ "socket options",
+ "strict sync",
+ "max print jobs",
+ "printable",
+ "print ok",
+ "printer name",
+ "printer",
+ "map system",
+ "map hidden",
+ "map archive",
+ "preferred master",
+ "prefered master",
+ "local master",
+ "browseable",
+ "browsable",
+ "wins server",
+ "wins support",
+ "csc policy",
+ "strict locking",
+ "preload",
+ "auto services",
+ "lock dir",
+ "lock directory",
+ "pid directory",
+ "socket address",
+ "copy",
+ "include",
+ "available",
+ "volume",
+ "fstype",
+ "panic action",
+ "msdfs root",
+ "host msdfs",
+ "winbind separator"]
+
+def upgrade_smbconf(oldconf,mark):
+ """Remove configuration variables not present in Samba4
+
+ :param oldconf: Old configuration structure
+ :param mark: Whether removed configuration variables should be
+ kept in the new configuration as "samba3:<name>"
+ """
+ data = oldconf.data()
+ newconf = param_init()
+
+ for s in data:
+ for p in data[s]:
+ keep = False
+ for k in smbconf_keep:
+ if smbconf_keep[k] == p:
+ keep = True
+ break
+
+ if keep:
+ newconf.set(s, p, oldconf.get(s, p))
+ elif mark:
+ newconf.set(s, "samba3:"+p, oldconf.get(s,p))
+
+ return newconf
+
+SAMBA3_PREDEF_NAMES = {
+ 'HKLM': registry.HKEY_LOCAL_MACHINE,
+}
+
+def import_registry(samba4_registry, samba3_regdb):
+ """Import a Samba 3 registry database into the Samba 4 registry.
+
+ :param samba4_registry: Samba 4 registry handle.
+ :param samba3_regdb: Samba 3 registry database handle.
+ """
+ def ensure_key_exists(keypath):
+ (predef_name, keypath) = keypath.split("/", 1)
+ predef_id = SAMBA3_PREDEF_NAMES[predef_name]
+ keypath = keypath.replace("/", "\\")
+ return samba4_registry.create_key(predef_id, keypath)
+
+ for key in samba3_regdb.keys():
+ key_handle = ensure_key_exists(key)
+ for subkey in samba3_regdb.subkeys(key):
+ ensure_key_exists(subkey)
+ for (value_name, (value_type, value_data)) in samba3_regdb.values(key).items():
+ key_handle.set_value(value_name, value_type, value_data)
+
+
diff --git a/source4/scripting/python/subunit/__init__.py b/source4/scripting/python/subunit/__init__.py
new file mode 100644
index 0000000000..406cd8765b
--- /dev/null
+++ b/source4/scripting/python/subunit/__init__.py
@@ -0,0 +1,388 @@
+#
+# subunit: extensions to python unittest to get test results from subprocesses.
+# Copyright (C) 2005 Robert Collins <robertc@robertcollins.net>
+# Copyright (C) 2007 Jelmer Vernooij <jelmer@samba.org>
+#
+# 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 3 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+import os
+from StringIO import StringIO
+import sys
+import unittest
+
+def test_suite():
+ import subunit.tests
+ return subunit.tests.test_suite()
+
+
+def join_dir(base_path, path):
+ """
+ Returns an absolute path to C{path}, calculated relative to the parent
+ of C{base_path}.
+
+ @param base_path: A path to a file or directory.
+ @param path: An absolute path, or a path relative to the containing
+ directory of C{base_path}.
+
+ @return: An absolute path to C{path}.
+ """
+ return os.path.join(os.path.dirname(os.path.abspath(base_path)), path)
+
+
+class TestProtocolServer(object):
+ """A class for receiving results from a TestProtocol client."""
+
+ OUTSIDE_TEST = 0
+ TEST_STARTED = 1
+ READING_FAILURE = 2
+ READING_ERROR = 3
+
+ def __init__(self, client, stream=sys.stdout):
+ """Create a TestProtocol server instance.
+
+ client should be an object that provides
+ - startTest
+ - addSuccess
+ - addFailure
+ - addError
+ - stopTest
+ methods, i.e. a TestResult.
+ """
+ self.state = TestProtocolServer.OUTSIDE_TEST
+ self.client = client
+ self._stream = stream
+
+ def _addError(self, offset, line):
+ if (self.state == TestProtocolServer.TEST_STARTED and
+ self.current_test_description == line[offset:-1]):
+ self.state = TestProtocolServer.OUTSIDE_TEST
+ self.current_test_description = None
+ self.client.addError(self._current_test, RemoteError(""))
+ self.client.stopTest(self._current_test)
+ self._current_test = None
+ elif (self.state == TestProtocolServer.TEST_STARTED and
+ self.current_test_description + " [" == line[offset:-1]):
+ self.state = TestProtocolServer.READING_ERROR
+ self._message = ""
+ else:
+ self.stdOutLineReceived(line)
+
+ def _addFailure(self, offset, line):
+ if (self.state == TestProtocolServer.TEST_STARTED and
+ self.current_test_description == line[offset:-1]):
+ self.state = TestProtocolServer.OUTSIDE_TEST
+ self.current_test_description = None
+ self.client.addFailure(self._current_test, RemoteError())
+ self.client.stopTest(self._current_test)
+ elif (self.state == TestProtocolServer.TEST_STARTED and
+ self.current_test_description + " [" == line[offset:-1]):
+ self.state = TestProtocolServer.READING_FAILURE
+ self._message = ""
+ else:
+ self.stdOutLineReceived(line)
+
+ def _addSuccess(self, offset, line):
+ if (self.state == TestProtocolServer.TEST_STARTED and
+ self.current_test_description == line[offset:-1]):
+ self.client.addSuccess(self._current_test)
+ self.client.stopTest(self._current_test)
+ self.current_test_description = None
+ self._current_test = None
+ self.state = TestProtocolServer.OUTSIDE_TEST
+ else:
+ self.stdOutLineReceived(line)
+
+ def _appendMessage(self, line):
+ if line[0:2] == " ]":
+ # quoted ] start
+ self._message += line[1:]
+ else:
+ self._message += line
+
+ def endQuote(self, line):
+ if self.state == TestProtocolServer.READING_FAILURE:
+ self.state = TestProtocolServer.OUTSIDE_TEST
+ self.current_test_description = None
+ self.client.addFailure(self._current_test,
+ RemoteError(self._message))
+ self.client.stopTest(self._current_test)
+ elif self.state == TestProtocolServer.READING_ERROR:
+ self.state = TestProtocolServer.OUTSIDE_TEST
+ self.current_test_description = None
+ self.client.addError(self._current_test,
+ RemoteError(self._message))
+ self.client.stopTest(self._current_test)
+ else:
+ self.stdOutLineReceived(line)
+
+ def lineReceived(self, line):
+ """Call the appropriate local method for the received line."""
+ if line == "]\n":
+ self.endQuote(line)
+ elif (self.state == TestProtocolServer.READING_FAILURE or
+ self.state == TestProtocolServer.READING_ERROR):
+ self._appendMessage(line)
+ else:
+ parts = line.split(None, 1)
+ if len(parts) == 2:
+ cmd, rest = parts
+ offset = len(cmd) + 1
+ cmd = cmd.strip(':')
+ if cmd in ('test', 'testing'):
+ self._startTest(offset, line)
+ elif cmd == 'error':
+ self._addError(offset, line)
+ elif cmd == 'failure':
+ self._addFailure(offset, line)
+ elif cmd in ('success', 'successful'):
+ self._addSuccess(offset, line)
+ else:
+ self.stdOutLineReceived(line)
+ else:
+ self.stdOutLineReceived(line)
+
+ def lostConnection(self):
+ """The input connection has finished."""
+ if self.state == TestProtocolServer.TEST_STARTED:
+ self.client.addError(self._current_test,
+ RemoteError("lost connection during test '%s'"
+ % self.current_test_description))
+ self.client.stopTest(self._current_test)
+ elif self.state == TestProtocolServer.READING_ERROR:
+ self.client.addError(self._current_test,
+ RemoteError("lost connection during "
+ "error report of test "
+ "'%s'" %
+ self.current_test_description))
+ self.client.stopTest(self._current_test)
+ elif self.state == TestProtocolServer.READING_FAILURE:
+ self.client.addError(self._current_test,
+ RemoteError("lost connection during "
+ "failure report of test "
+ "'%s'" %
+ self.current_test_description))
+ self.client.stopTest(self._current_test)
+
+ def readFrom(self, pipe):
+ for line in pipe.readlines():
+ self.lineReceived(line)
+ self.lostConnection()
+
+ def _startTest(self, offset, line):
+ """Internal call to change state machine. Override startTest()."""
+ if self.state == TestProtocolServer.OUTSIDE_TEST:
+ self.state = TestProtocolServer.TEST_STARTED
+ self._current_test = RemotedTestCase(line[offset:-1])
+ self.current_test_description = line[offset:-1]
+ self.client.startTest(self._current_test)
+ else:
+ self.stdOutLineReceived(line)
+
+ def stdOutLineReceived(self, line):
+ self._stream.write(line)
+
+
+class RemoteException(Exception):
+ """An exception that occured remotely to python."""
+
+ def __eq__(self, other):
+ try:
+ return self.args == other.args
+ except AttributeError:
+ return False
+
+
+class TestProtocolClient(unittest.TestResult):
+ """A class that looks like a TestResult and informs a TestProtocolServer."""
+
+ def __init__(self, stream):
+ super(TestProtocolClient, self).__init__()
+ self._stream = stream
+
+ def addError(self, test, error):
+ """Report an error in test test."""
+ self._stream.write("error: %s [\n" % (test.shortDescription() or str(test)))
+ for line in self._exc_info_to_string(error, test).splitlines():
+ self._stream.write("%s\n" % line)
+ self._stream.write("]\n")
+ super(TestProtocolClient, self).addError(test, error)
+
+ def addFailure(self, test, error):
+ """Report a failure in test test."""
+ self._stream.write("failure: %s [\n" % (test.shortDescription() or str(test)))
+ for line in self._exc_info_to_string(error, test).splitlines():
+ self._stream.write("%s\n" % line)
+ self._stream.write("]\n")
+ super(TestProtocolClient, self).addFailure(test, error)
+
+ def addSuccess(self, test):
+ """Report a success in a test."""
+ self._stream.write("successful: %s\n" % (test.shortDescription() or str(test)))
+ super(TestProtocolClient, self).addSuccess(test)
+
+ def startTest(self, test):
+ """Mark a test as starting its test run."""
+ self._stream.write("test: %s\n" % (test.shortDescription() or str(test)))
+ super(TestProtocolClient, self).startTest(test)
+
+
+def RemoteError(description=""):
+ if description == "":
+ description = "\n"
+ return (RemoteException, RemoteException(description), None)
+
+
+class RemotedTestCase(unittest.TestCase):
+ """A class to represent test cases run in child processes."""
+
+ def __eq__ (self, other):
+ try:
+ return self.__description == other.__description
+ except AttributeError:
+ return False
+
+ def __init__(self, description):
+ """Create a psuedo test case with description description."""
+ self.__description = description
+
+ def error(self, label):
+ raise NotImplementedError("%s on RemotedTestCases is not permitted." %
+ label)
+
+ def setUp(self):
+ self.error("setUp")
+
+ def tearDown(self):
+ self.error("tearDown")
+
+ def shortDescription(self):
+ return self.__description
+
+ def id(self):
+ return "%s.%s" % (self._strclass(), self.__description)
+
+ def __str__(self):
+ return "%s (%s)" % (self.__description, self._strclass())
+
+ def __repr__(self):
+ return "<%s description='%s'>" % \
+ (self._strclass(), self.__description)
+
+ def run(self, result=None):
+ if result is None: result = self.defaultTestResult()
+ result.startTest(self)
+ result.addError(self, RemoteError("Cannot run RemotedTestCases.\n"))
+ result.stopTest(self)
+
+ def _strclass(self):
+ cls = self.__class__
+ return "%s.%s" % (cls.__module__, cls.__name__)
+
+
+class ExecTestCase(unittest.TestCase):
+ """A test case which runs external scripts for test fixtures."""
+
+ def __init__(self, methodName='runTest'):
+ """Create an instance of the class that will use the named test
+ method when executed. Raises a ValueError if the instance does
+ not have a method with the specified name.
+ """
+ unittest.TestCase.__init__(self, methodName)
+ testMethod = getattr(self, methodName)
+ self.script = join_dir(sys.modules[self.__class__.__module__].__file__,
+ testMethod.__doc__)
+
+ def countTestCases(self):
+ return 1
+
+ def run(self, result=None):
+ if result is None: result = self.defaultTestResult()
+ self._run(result)
+
+ def debug(self):
+ """Run the test without collecting errors in a TestResult"""
+ self._run(unittest.TestResult())
+
+ def _run(self, result):
+ protocol = TestProtocolServer(result)
+ output = os.popen(self.script, mode='r')
+ protocol.readFrom(output)
+
+
+class IsolatedTestCase(unittest.TestCase):
+ """A TestCase which runs its tests in a forked process."""
+
+ def run(self, result=None):
+ if result is None: result = self.defaultTestResult()
+ run_isolated(unittest.TestCase, self, result)
+
+
+class IsolatedTestSuite(unittest.TestSuite):
+ """A TestCase which runs its tests in a forked process."""
+
+ def run(self, result=None):
+ if result is None: result = unittest.TestResult()
+ run_isolated(unittest.TestSuite, self, result)
+
+
+def run_isolated(klass, self, result):
+ """Run a test suite or case in a subprocess, using the run method on klass.
+ """
+ c2pread, c2pwrite = os.pipe()
+ # fixme - error -> result
+ # now fork
+ pid = os.fork()
+ if pid == 0:
+ # Child
+ # Close parent's pipe ends
+ os.close(c2pread)
+ # Dup fds for child
+ os.dup2(c2pwrite, 1)
+ # Close pipe fds.
+ os.close(c2pwrite)
+
+ # at this point, sys.stdin is redirected, now we want
+ # to filter it to escape ]'s.
+ ### XXX: test and write that bit.
+
+ result = TestProtocolClient(sys.stdout)
+ klass.run(self, result)
+ sys.stdout.flush()
+ sys.stderr.flush()
+ # exit HARD, exit NOW.
+ os._exit(0)
+ else:
+ # Parent
+ # Close child pipe ends
+ os.close(c2pwrite)
+ # hookup a protocol engine
+ protocol = TestProtocolServer(result)
+ protocol.readFrom(os.fdopen(c2pread, 'rU'))
+ os.waitpid(pid, 0)
+ # TODO return code evaluation.
+ return result
+
+
+class SubunitTestRunner(object):
+ def __init__(self, stream=sys.stdout):
+ self.stream = stream
+
+ def run(self, test):
+ "Run the given test case or test suite."
+ result = TestProtocolClient(self.stream)
+ test(result)
+ return result
+
diff --git a/source4/scripting/python/uuidmodule.c b/source4/scripting/python/uuidmodule.c
new file mode 100644
index 0000000000..98ef9adaa9
--- /dev/null
+++ b/source4/scripting/python/uuidmodule.c
@@ -0,0 +1,58 @@
+/*
+ Unix SMB/CIFS implementation.
+ Samba utility functions
+ Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include <Python.h>
+#include "librpc/ndr/libndr.h"
+
+static PyObject *uuid_random(PyObject *self, PyObject *args)
+{
+ struct GUID guid;
+ PyObject *pyobj;
+ char *str;
+
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+
+ guid = GUID_random();
+
+ str = GUID_string(NULL, &guid);
+ if (str == NULL) {
+ PyErr_SetString(PyExc_TypeError, "can't convert uuid to string");
+ return NULL;
+ }
+
+ pyobj = PyString_FromString(str);
+
+ talloc_free(str);
+
+ return pyobj;
+}
+
+static PyMethodDef methods[] = {
+ { "uuid4", (PyCFunction)uuid_random, METH_VARARGS, NULL},
+ { NULL, NULL }
+};
+
+void inituuid(void)
+{
+ PyObject *mod = Py_InitModule3("uuid", methods, "UUID helper routines");
+ if (mod == NULL)
+ return;
+}