From f76697ce89606aa4e5ba1bb13f1fda6e33998695 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 24 May 2008 18:57:15 +0200 Subject: Add convenience functions for packing/unpacking structs in python. (This used to be commit c5d7d48b32bcebf8a0495cbd4556e30587fa589f) --- source4/scripting/python/samba/ndr.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 source4/scripting/python/samba/ndr.py (limited to 'source4/scripting') diff --git a/source4/scripting/python/samba/ndr.py b/source4/scripting/python/samba/ndr.py new file mode 100644 index 0000000000..e93fbc3c2e --- /dev/null +++ b/source4/scripting/python/samba/ndr.py @@ -0,0 +1,27 @@ +#!/usr/bin/python + +# Unix SMB/CIFS implementation. +# Copyright © Jelmer Vernooij 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 . +# + +def ndr_pack(object): + return object.__ndr_pack__() + + +def ndr_unpack(cls, data): + object = cls() + object.__ndr_unpack__(data) + return object -- cgit From 05194ccdf875ee70cb9ee3f7c27147503d585a6d Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 24 May 2008 19:50:09 +0200 Subject: Add tests for new NDR pack/unpack functionality in Python DCE/RPC bindings. (This used to be commit 468d35827fd055c82c6d43d6ce6d3d561abed54d) --- source4/scripting/python/samba/ndr.py | 1 + source4/scripting/python/samba/tests/dcerpc/rpcecho.py | 12 ++++++++++++ 2 files changed, 13 insertions(+) (limited to 'source4/scripting') diff --git a/source4/scripting/python/samba/ndr.py b/source4/scripting/python/samba/ndr.py index e93fbc3c2e..e718ff3422 100644 --- a/source4/scripting/python/samba/ndr.py +++ b/source4/scripting/python/samba/ndr.py @@ -1,4 +1,5 @@ #!/usr/bin/python +# -*- coding: utf-8 -*- # Unix SMB/CIFS implementation. # Copyright © Jelmer Vernooij 2008 diff --git a/source4/scripting/python/samba/tests/dcerpc/rpcecho.py b/source4/scripting/python/samba/tests/dcerpc/rpcecho.py index 3b37f8a9bc..9157f83fc9 100644 --- a/source4/scripting/python/samba/tests/dcerpc/rpcecho.py +++ b/source4/scripting/python/samba/tests/dcerpc/rpcecho.py @@ -18,6 +18,7 @@ # from samba.dcerpc import echo +from samba.ndr import ndr_pack, ndr_unpack import unittest from samba.tests import RpcInterfaceTestCase @@ -40,3 +41,14 @@ class RpcEchoTests(RpcInterfaceTestCase): surrounding_struct.surrounding = [1,2,3,4] y = self.conn.TestSurrounding(surrounding_struct) self.assertEquals(8 * [0], y.surrounding) + + +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) -- cgit From 515b6ed5867bba8180bd0eeadbeab1c52bffc0ab Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 24 May 2008 20:00:37 +0200 Subject: Share struct used for interfaces in Python code. (This used to be commit 8501a3fc31e688dba696667a187821480e8cb714) --- source4/scripting/python/pyrpc.h | 39 --------------------------------------- 1 file changed, 39 deletions(-) delete mode 100644 source4/scripting/python/pyrpc.h (limited to 'source4/scripting') diff --git a/source4/scripting/python/pyrpc.h b/source4/scripting/python/pyrpc.h deleted file mode 100644 index 93d583c10a..0000000000 --- a/source4/scripting/python/pyrpc.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba utility functions - Copyright (C) Jelmer Vernooij 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 . -*/ - -#ifndef _PYRPC_H_ -#define _PYRPC_H_ - -#define PY_CHECK_TYPE(type, var, fail) \ - if (!type ## _Check(var)) {\ - PyErr_Format(PyExc_TypeError, "Expected type %s", type ## _Type.tp_name); \ - fail; \ - } - -#define dom_sid2_Type dom_sid_Type -#define dom_sid28_Type dom_sid_Type -#define dom_sid2_Check dom_sid_Check -#define dom_sid28_Check dom_sid_Check - -/* This macro is only provided by Python >= 2.3 */ -#ifndef PyAPI_DATA -# define PyAPI_DATA(RTYPE) extern RTYPE -#endif - -#endif /* _PYRPC_H_ */ -- cgit From f9c36fae757d197ee4de06f0ecf94ae13faad0de Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 24 May 2008 21:38:33 +0200 Subject: Export functions for setting NTSTATUS and WERRORs in python. (This used to be commit 4bcb92d2d49d90863b1e64b15d055517fbfd263c) --- source4/scripting/python/misc.i | 7 +++---- source4/scripting/python/misc_wrap.c | 6 ++++-- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'source4/scripting') diff --git a/source4/scripting/python/misc.i b/source4/scripting/python/misc.i index 56b862552a..1d331215b5 100644 --- a/source4/scripting/python/misc.i +++ b/source4/scripting/python/misc.i @@ -35,7 +35,7 @@ %import "../../auth/credentials/credentials.i" %import "../../param/param.i" %import "../../libcli/security/security.i" -%import "../../libcli/util/errors.i" +%include "../../libcli/util/errors.i" %feature("docstring") generate_random_str "S.random_password(len) -> string\n" \ "Generate random password with specified length."; @@ -97,7 +97,6 @@ bool dsdb_set_ntds_invocation_id(struct ldb_context *ldb, const char *guid) } %} -char *private_path(TALLOC_CTX* mem_ctx, - struct loadparm_context *lp_ctx, - const char *name); +char *private_path(TALLOC_CTX* mem_ctx, struct loadparm_context *lp_ctx, + const char *name); diff --git a/source4/scripting/python/misc_wrap.c b/source4/scripting/python/misc_wrap.c index 8c57237e5b..888918ef53 100644 --- a/source4/scripting/python/misc_wrap.c +++ b/source4/scripting/python/misc_wrap.c @@ -2554,6 +2554,9 @@ static swig_module_info swig_module = {swig_types, 27, 0, 0, 0, 0}; #include "librpc/ndr/libndr.h" +#include "libcli/util/pyerrors.h" + + SWIGINTERN int SWIG_AsVal_double (PyObject *obj, double *val) { @@ -3046,8 +3049,7 @@ SWIGINTERN PyObject *_wrap_dsdb_attach_schema_from_ldif_file(PyObject *SWIGUNUSE "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)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", W_ERROR_V(result), win_errstr(result)); - PyErr_SetObject(PyExc_RuntimeError, obj); + PyErr_SetWERROR(result); SWIG_fail; } else if (resultobj == NULL) { resultobj = Py_None; -- cgit From 75e7962d2efb1aa6e45ca999b1a93829406de540 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 24 May 2008 22:13:32 +0200 Subject: Add convenience functions for setting Python objects from errors. (This used to be commit f1de723b89251cbc8140b838941f304a34871bf3) --- source4/scripting/python/samba/tests/dcerpc/rpcecho.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source4/scripting') diff --git a/source4/scripting/python/samba/tests/dcerpc/rpcecho.py b/source4/scripting/python/samba/tests/dcerpc/rpcecho.py index 9157f83fc9..83279a0b30 100644 --- a/source4/scripting/python/samba/tests/dcerpc/rpcecho.py +++ b/source4/scripting/python/samba/tests/dcerpc/rpcecho.py @@ -42,6 +42,11 @@ class RpcEchoTests(RpcInterfaceTestCase): 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): -- cgit From 21ce0ff00688c560e60efd6c392c71f85229c9d4 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 24 May 2008 22:56:49 +0200 Subject: Allow connecting to a DCE/RPC interface with Python for which we don't have IDL. (This used to be commit e3178d522c95871f1db35d7e058906502387a553) --- .../scripting/python/samba/tests/dcerpc/bare.py | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 source4/scripting/python/samba/tests/dcerpc/bare.py (limited to 'source4/scripting') 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..dae1dedeb3 --- /dev/null +++ b/source4/scripting/python/samba/tests/dcerpc/bare.py @@ -0,0 +1,30 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Unix SMB/CIFS implementation. +# Copyright © Jelmer Vernooij 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 . +# + +from samba.dcerpc import ClientConnection +from unittest import TestCase + +class BareTestCase(TestCase): + def test_bare(self): + # Connect to the echo pipe + x = ClientConnection("ncalrpc:localhost[DEFAULT]", + ("60a15ec5-4de8-11d7-a637-005056a20182", 1)) + self.assertEquals("\x01\x00\x00\x00", x.request(0, chr(0) * 4)) + -- cgit From a2446e5f8550582c0d4353bb85874dea17cf1d98 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 25 May 2008 02:32:21 +0200 Subject: Add initial work for script that uses probing to figure out IDL. (This used to be commit 4e5687e813e50d0bc8d6314e389d1d7a0be2f8c1) --- source4/scripting/bin/autoidl.py | 161 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100755 source4/scripting/bin/autoidl.py (limited to 'source4/scripting') diff --git a/source4/scripting/bin/autoidl.py b/source4/scripting/bin/autoidl.py new file mode 100755 index 0000000000..eed4ba3a80 --- /dev/null +++ b/source4/scripting/bin/autoidl.py @@ -0,0 +1,161 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Unix SMB/CIFS implementation. +# Copyright © Jelmer Vernooij 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 . +# + +import sys + +MAX_OPNUM = 1000 +MAX_BASE_SIZE = 0x1000 +MAX_IFACE_VERSION = 1000 + +DCERPC_FAULT_OP_RNG_ERROR = 0x1c010002 +DCERPC_FAULT_NDR = 0x6f7 +NT_STATUS_NET_WRITE_FAULT = -1073741614 + + +sys.path.insert(0, "bin/python") + +from samba.dcerpc import ClientConnection + +def find_num_funcs(conn): + for i in xrange(MAX_OPNUM): + try: + conn.request(i, "") + except RuntimeError, (num, msg): + if num == DCERPC_FAULT_OP_RNG_ERROR: + return i + raise Exception("More than %d functions" % MAX_OPNUM) + +class Function: + def __init__(self, conn, opnum): + self.conn = conn + self.opnum = opnum + + def request(self, data): + assert isinstance(data, str) + self.conn.request(self.opnum, data) + + def valid_ndr(self, data): + try: + self.request(data) + except RuntimeError, (num, msg): + if num == DCERPC_FAULT_NDR: + return False + return True + + def find_base_request(self, start=""): + """Find the smallest possible request that we can do that is + valid. + + This generally means sending all zeroes so we get NULL pointers where + possible.""" + # TODO: Don't try with just 0's as there may be switch_is() variables + # for which 0 is not a valid value or variables with range() set + # See how much input bytes we need + for i in range(MAX_BASE_SIZE): + data = start + chr(0) * i + if self.valid_ndr(data): + return data + return None + + def check_decision_byte(self, base_request, i): + """Check whether the specified byte is a possible "decision" byte, + e.g. a byte that is part of a pointer, array size variable or + discriminant. + + Note that this function only checks if a byte is definitely a decision + byte. It may return False in some cases while the byte is actually + a decision byte.""" + data = list(base_request) + data[i] = chr(1) + return not self.valid_ndr("".join(data)) + + def find_deferrant_data(self, base_request, idx): + data = list(base_request) + data[idx*4] = chr(1) + # Just check that this is a pointer to something non-empty: + assert not self.valid_ndr("".join(data)) + + newdata = self.find_base_request("".join(data)) + + if newdata is None: + return None + + assert newdata.startswith(data) + + return newdata[len(data):] + + def find_idl(self): + base_request = self.find_base_request() + + if base_request is None: + raise Exception("Unable to determine base size for opnum %d" % self.opnum) + + print "\tBase request is %r" % base_request + + decision_byte_map = map(lambda x: self.check_decision_byte(base_request, x), range(len(base_request))) + + print decision_byte_map + + # find pointers + possible_pointers = map(all, + [decision_byte_map[i*4:(i+1)*4] for i in range(int(len(base_request)/4))]) + print possible_pointers + + pointer_deferrant_bases = map( + lambda x: self.find_deferrant_data(base_request, x) if possible_pointers[x] else None, range(len(possible_pointers))) + + print pointer_deferrant_bases + + +if len(sys.argv) < 3: + print "Usage: autoidl []" + sys.exit(1) + +(binding, uuid) = sys.argv[1:3] +if len(sys.argv) == 4: + version = sys.argv[3] +else: + version = None + +if version is None: + for i in range(MAX_IFACE_VERSION): + try: + conn = ClientConnection(binding, (uuid, i)) + except RuntimeError, (num, msg): + if num == NT_STATUS_NET_WRITE_FAULT: + continue + raise + else: + break +else: + conn = ClientConnection(binding, (uuid, version)) + +print "Figuring out number of connections...", +num_funcs = find_num_funcs(conn) +print "%d" % num_funcs + +# Figure out the syntax for each one +for i in range(num_funcs): + print "Function %d" % i + data = Function(conn, i) + try: + data.find_idl() + except Exception, e: + print "Error: %r" % e -- cgit From 928ecbaebbde00515d08fd530db7c99169c905ef Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 25 May 2008 04:23:03 +0200 Subject: Add support for secondary contexts from Python. (This used to be commit 16d1ad050546ae6500153438db8d3c857e6f3ad5) --- source4/scripting/python/samba/tests/dcerpc/bare.py | 13 +++++++++++++ source4/scripting/python/samba/tests/dcerpc/rpcecho.py | 4 ++++ 2 files changed, 17 insertions(+) (limited to 'source4/scripting') diff --git a/source4/scripting/python/samba/tests/dcerpc/bare.py b/source4/scripting/python/samba/tests/dcerpc/bare.py index dae1dedeb3..eea6744e42 100644 --- a/source4/scripting/python/samba/tests/dcerpc/bare.py +++ b/source4/scripting/python/samba/tests/dcerpc/bare.py @@ -28,3 +28,16 @@ class BareTestCase(TestCase): ("60a15ec5-4de8-11d7-a637-005056a20182", 1)) 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)) + # x.alter_context(("60a15ec5-4de8-11d7-a637-005056a20182", 1)) + # 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)) + y = ClientConnection("ncalrpc:localhost", + ("60a15ec5-4de8-11d7-a637-005056a20182", 1), + basis_connection=x) + self.assertEquals("\x01\x00\x00\x00", y.request(0, chr(0) * 4)) diff --git a/source4/scripting/python/samba/tests/dcerpc/rpcecho.py b/source4/scripting/python/samba/tests/dcerpc/rpcecho.py index 83279a0b30..7fd1bcc5b8 100644 --- a/source4/scripting/python/samba/tests/dcerpc/rpcecho.py +++ b/source4/scripting/python/samba/tests/dcerpc/rpcecho.py @@ -26,6 +26,10 @@ class RpcEchoTests(RpcInterfaceTestCase): def setUp(self): self.conn = echo.rpcecho("ncalrpc:", self.get_loadparm()) + def test_two_contexts(self): + self.conn2 = echo.rpcecho("ncalrpc", basis_connection=self.conn) + self.assertEquals(3, self.conn2.AddOne(2)) + def test_addone(self): self.assertEquals(2, self.conn.AddOne(1)) -- cgit From 74126bc6d0211a7674156dfda8ab13054b403a1d Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 25 May 2008 04:54:38 +0200 Subject: Expose transfer and abstract syntax. (This used to be commit a875e07a37568b7e51c290074d5e3834c2caa4d6) --- source4/scripting/python/samba/tests/dcerpc/bare.py | 13 ++++++++----- source4/scripting/python/samba/tests/dcerpc/rpcecho.py | 4 ++++ 2 files changed, 12 insertions(+), 5 deletions(-) (limited to 'source4/scripting') diff --git a/source4/scripting/python/samba/tests/dcerpc/bare.py b/source4/scripting/python/samba/tests/dcerpc/bare.py index eea6744e42..d75ffc381e 100644 --- a/source4/scripting/python/samba/tests/dcerpc/bare.py +++ b/source4/scripting/python/samba/tests/dcerpc/bare.py @@ -28,11 +28,14 @@ class BareTestCase(TestCase): ("60a15ec5-4de8-11d7-a637-005056a20182", 1)) 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)) - # x.alter_context(("60a15ec5-4de8-11d7-a637-005056a20182", 1)) - # 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)) + y = ClientConnection("ncalrpc:localhost", + ("60a15ec5-4de8-11d7-a637-005056a20182", 1), + basis_connection=x) + 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]", diff --git a/source4/scripting/python/samba/tests/dcerpc/rpcecho.py b/source4/scripting/python/samba/tests/dcerpc/rpcecho.py index 7fd1bcc5b8..68b7a42d52 100644 --- a/source4/scripting/python/samba/tests/dcerpc/rpcecho.py +++ b/source4/scripting/python/samba/tests/dcerpc/rpcecho.py @@ -30,6 +30,10 @@ class RpcEchoTests(RpcInterfaceTestCase): self.conn2 = echo.rpcecho("ncalrpc", 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)) -- cgit