From ea6d5bc48bd14f8eaca665576d7094cce53be81a Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 4 Nov 2002 20:33:16 +0000 Subject: Sync with HEAD. (This used to be commit 0310e539bb41f569c7ae77b2d131e966adefa27b) --- source3/python/examples/tdbpack/test_tdbpack.py | 66 ++++---- source3/python/py_common.c | 7 +- source3/python/py_common_proto.h | 2 +- source3/python/py_lsa.c | 2 +- source3/python/py_samr.c | 3 +- source3/python/py_smb.c | 202 ++++++++++++++++++++++-- source3/python/py_spoolss_drivers.c | 6 +- source3/python/py_spoolss_ports.c | 2 +- source3/python/py_spoolss_printers.c | 6 +- source3/python/py_tdbpack.c | 34 ++-- source3/python/setup.py | 3 +- 11 files changed, 265 insertions(+), 68 deletions(-) (limited to 'source3/python') diff --git a/source3/python/examples/tdbpack/test_tdbpack.py b/source3/python/examples/tdbpack/test_tdbpack.py index 36fed881e3..659dc0efed 100755 --- a/source3/python/examples/tdbpack/test_tdbpack.py +++ b/source3/python/examples/tdbpack/test_tdbpack.py @@ -17,13 +17,12 @@ string, with one character per field.""" __author__ = 'Martin Pool ' import unittest -# import tdbutil +import oldtdbutil import samba.tdbpack -packer = samba.tdbpack.pack -unpacker = samba.tdbpack.unpack - - +both_unpackers = (samba.tdbpack.unpack, oldtdbutil.unpack) +both_packers = (samba.tdbpack.pack, oldtdbutil.pack) + class PackTests(unittest.TestCase): symm_cases = [('B', ['hello' * 51], '\xff\0\0\0' + 'hello' * 51), ('w', [42], '\x2a\0'), @@ -78,11 +77,13 @@ class PackTests(unittest.TestCase): def test_symmetric(self): """Cookbook of symmetric pack/unpack tests """ - for format, values, expected in self.symm_cases: - self.assertEquals(packer(format, values), expected) - out, rest = unpacker(format, expected) - self.assertEquals(rest, '') - self.assertEquals(list(values), list(out)) + for packer in both_packers: + for unpacker in both_unpackers: + for format, values, expected in self.symm_cases: + self.assertEquals(packer(format, values), expected) + out, rest = unpacker(format, expected) + self.assertEquals(rest, '') + self.assertEquals(list(values), list(out)) def test_pack(self): @@ -100,25 +101,30 @@ class PackTests(unittest.TestCase): # as if you called list() ] - for format, values, expected in cases: - self.assertEquals(packer(format, values), expected) + for packer in both_packers: + for format, values, expected in cases: + self.assertEquals(packer(format, values), expected) def test_unpack_extra(self): # Test leftover data - for format, values, packed in self.symm_cases: - out, rest = unpacker(format, packed + 'hello sailor!') - self.assertEquals(rest, 'hello sailor!') - self.assertEquals(list(values), list(out)) + for unpacker in both_unpackers: + for format, values, packed in self.symm_cases: + out, rest = unpacker(format, packed + 'hello sailor!') + self.assertEquals(rest, 'hello sailor!') + self.assertEquals(list(values), list(out)) def test_unpack(self): """Cookbook of tricky unpack tests""" cases = [ + # Apparently I couldn't think of any tests that weren't + # symmetric :-/ ] - for format, values, expected in cases: - out, rest = unpacker(format, expected) - self.assertEquals(rest, '') - self.assertEquals(list(values), list(out)) + for unpacker in both_unpackers: + for format, values, expected in cases: + out, rest = unpacker(format, expected) + self.assertEquals(rest, '') + self.assertEquals(list(values), list(out)) def test_pack_failures(self): @@ -141,7 +147,7 @@ class PackTests(unittest.TestCase): ('f', [2], TypeError), ('P', [None], TypeError), ('P', (), IndexError), - ('f', [packer], TypeError), + ('f', [hex], TypeError), ('fw', ['hello'], IndexError), ('f', [u'hello'], TypeError), ('B', [2], TypeError), @@ -153,10 +159,11 @@ class PackTests(unittest.TestCase): ('fQ', ['2'], IndexError), (2, [2], TypeError), ({}, {}, TypeError)] - for format, values, throwable_class in cases: - def do_pack(): - packer(format, values) - self.assertRaises(throwable_class, do_pack) + for packer in both_packers: + for format, values, throwable_class in cases: + def do_pack(): + packer(format, values) + self.assertRaises(throwable_class, do_pack) def test_unpack_failures(self): @@ -182,10 +189,11 @@ class PackTests(unittest.TestCase): ('B', 'foobar', IndexError), ('BB', '\x01\0\0\0a\x01', IndexError), ] - - for format, values, throwable_class in cases: - def do_unpack(): - unpacker(format, values) + + for unpacker in both_unpackers: + for format, values, throwable_class in cases: + def do_unpack(): + unpacker(format, values) self.assertRaises(throwable_class, do_unpack) diff --git a/source3/python/py_common.c b/source3/python/py_common.c index d15df234d1..364271d57c 100644 --- a/source3/python/py_common.c +++ b/source3/python/py_common.c @@ -218,7 +218,7 @@ BOOL py_parse_creds(PyObject *creds, char **username, char **domain, be freed by calling free(). */ struct cli_state *open_pipe_creds(char *server, PyObject *creds, - char *pipe_name, char **errstr) + int pipe_idx, char **errstr) { char *username, *password, *domain; struct cli_state *cli; @@ -240,10 +240,9 @@ struct cli_state *open_pipe_creds(char *server, PyObject *creds, return NULL; } - if (!cli_nt_session_open(cli, pipe_name)) { + if (!cli_nt_session_open(cli, pipe_idx)) { cli_shutdown(cli); - free(cli); - asprintf(errstr, "error opening %s", pipe_name); + asprintf(errstr, "error opening pipe index %d", pipe_idx); return NULL; } diff --git a/source3/python/py_common_proto.h b/source3/python/py_common_proto.h index 89f0f35fc9..b012c17e15 100644 --- a/source3/python/py_common_proto.h +++ b/source3/python/py_common_proto.h @@ -15,7 +15,7 @@ PyObject *py_setup_logging(PyObject *self, PyObject *args, PyObject *kw); BOOL py_parse_creds(PyObject *creds, char **username, char **domain, char **password, char **errstr); struct cli_state *open_pipe_creds(char *server, PyObject *creds, - char *pipe_name, char **errstr); + int pipe_idx, char **errstr); BOOL get_level_value(PyObject *dict, uint32 *level); /* The following definitions come from python/py_ntsec.c */ diff --git a/source3/python/py_lsa.c b/source3/python/py_lsa.c index 0584cf716b..d54a2289ef 100644 --- a/source3/python/py_lsa.c +++ b/source3/python/py_lsa.c @@ -78,7 +78,7 @@ static PyObject *lsa_open_policy(PyObject *self, PyObject *args, server += 2; - if (!(cli = open_pipe_creds(server, creds, PIPE_LSARPC, &errstr))) { + if (!(cli = open_pipe_creds(server, creds, PI_LSARPC, &errstr))) { PyErr_SetString(lsa_error, errstr); free(errstr); return NULL; diff --git a/source3/python/py_samr.c b/source3/python/py_samr.c index 917a90a2fb..92a2eaf063 100644 --- a/source3/python/py_samr.c +++ b/source3/python/py_samr.c @@ -393,7 +393,7 @@ static PyObject *samr_connect(PyObject *self, PyObject *args, PyObject *kw) return NULL; } - if (!(cli = open_pipe_creds(server, creds, PIPE_SAMR, &errstr))) { + if (!(cli = open_pipe_creds(server, creds, PI_SAMR, &errstr))) { PyErr_SetString(samr_error, errstr); free(errstr); return NULL; @@ -409,7 +409,6 @@ static PyObject *samr_connect(PyObject *self, PyObject *args, PyObject *kw) if (!NT_STATUS_IS_OK(ntstatus)) { cli_shutdown(cli); - SAFE_FREE(cli); PyErr_SetObject(samr_ntstatus, py_ntstatus_tuple(ntstatus)); goto done; } diff --git a/source3/python/py_smb.c b/source3/python/py_smb.c index 77d7bb32fc..41b8237a8a 100644 --- a/source3/python/py_smb.c +++ b/source3/python/py_smb.c @@ -97,12 +97,12 @@ static PyObject *py_smb_session_setup(PyObject *self, PyObject *args, PyObject *kw) { cli_state_object *cli = (cli_state_object *)self; - static char *kwlist[] = { "creds" }; + static char *kwlist[] = { "creds", NULL }; PyObject *creds; char *username, *domain, *password, *errstr; BOOL result; - if (!PyArg_ParseTupleAndKeywords(args, kw, "O", kwlist, &creds)) + if (!PyArg_ParseTupleAndKeywords(args, kw, "|O", kwlist, &creds)) return NULL; if (!py_parse_creds(creds, &username, &domain, &password, &errstr)) { @@ -114,35 +114,192 @@ static PyObject *py_smb_session_setup(PyObject *self, PyObject *args, cli->cli, username, password, strlen(password) + 1, password, strlen(password) + 1, domain); + if (cli_is_error(cli->cli)) { + PyErr_SetString(PyExc_RuntimeError, "session setup failed"); + return NULL; + } + return Py_BuildValue("i", result); } static PyObject *py_smb_tconx(PyObject *self, PyObject *args, PyObject *kw) { cli_state_object *cli = (cli_state_object *)self; - static char *kwlist[] = { "service", "creds" }; - PyObject *creds; - char *service, *username, *domain, *password, *errstr; + static char *kwlist[] = { "service", NULL }; + char *service; BOOL result; - if (!PyArg_ParseTupleAndKeywords(args, kw, "sO", kwlist, &service, - &creds)) + if (!PyArg_ParseTupleAndKeywords(args, kw, "s", kwlist, &service)) return NULL; - if (!py_parse_creds(creds, &username, &domain, &password, &errstr)) { - free(errstr); + result = cli_send_tconX( + cli->cli, service, strequal(service, "IPC$") ? "IPC" : + "?????", "", 1); + + if (cli_is_error(cli->cli)) { + PyErr_SetString(PyExc_RuntimeError, "tconx failed"); return NULL; } - result = cli_send_tconX( - cli->cli, service, strequal(service, "IPC$") ? "IPC" : "?????", - password, strlen(password) + 1); - return Py_BuildValue("i", result); } +static PyObject *py_smb_nt_create_andx(PyObject *self, PyObject *args, + PyObject *kw) +{ + cli_state_object *cli = (cli_state_object *)self; + static char *kwlist[] = { "filename", "desired_access", + "file_attributes", "share_access", + "create_disposition", NULL }; + char *filename; + uint32 desired_access, file_attributes = 0, + share_access = FILE_SHARE_READ | FILE_SHARE_WRITE, + create_disposition = FILE_EXISTS_OPEN, create_options = 0; + int result; + + /* Parse parameters */ + + if (!PyArg_ParseTupleAndKeywords( + args, kw, "si|iii", kwlist, &filename, &desired_access, + &file_attributes, &share_access, &create_disposition, + &create_options)) + return NULL; + + result = cli_nt_create_full( + cli->cli, filename, desired_access, file_attributes, + share_access, create_disposition, create_options); + + if (cli_is_error(cli->cli)) { + PyErr_SetString(PyExc_RuntimeError, "nt_create_andx failed"); + return NULL; + } + + /* Return FID */ + + return PyInt_FromLong(result); +} + +static PyObject *py_smb_close(PyObject *self, PyObject *args, + PyObject *kw) +{ + cli_state_object *cli = (cli_state_object *)self; + static char *kwlist[] = { "fnum", NULL }; + BOOL result; + int fnum; + + /* Parse parameters */ + + if (!PyArg_ParseTupleAndKeywords( + args, kw, "i", kwlist, &fnum)) + return NULL; + + result = cli_close(cli->cli, fnum); + + return PyInt_FromLong(result); +} + +static PyObject *py_smb_unlink(PyObject *self, PyObject *args, + PyObject *kw) +{ + cli_state_object *cli = (cli_state_object *)self; + static char *kwlist[] = { "filename", NULL }; + char *filename; + BOOL result; + + /* Parse parameters */ + + if (!PyArg_ParseTupleAndKeywords( + args, kw, "s", kwlist, &filename)) + return NULL; + + result = cli_unlink(cli->cli, filename); + + return PyInt_FromLong(result); +} + +static PyObject *py_smb_query_secdesc(PyObject *self, PyObject *args, + PyObject *kw) +{ + cli_state_object *cli = (cli_state_object *)self; + static char *kwlist[] = { "fnum", NULL }; + PyObject *result; + SEC_DESC *secdesc = NULL; + int fnum; + TALLOC_CTX *mem_ctx; + + /* Parse parameters */ + + if (!PyArg_ParseTupleAndKeywords( + args, kw, "i", kwlist, &fnum)) + return NULL; + + mem_ctx = talloc_init(); + + secdesc = cli_query_secdesc(cli->cli, fnum, mem_ctx); + + if (cli_is_error(cli->cli)) { + PyErr_SetString(PyExc_RuntimeError, "query_secdesc failed"); + return NULL; + } + + if (!secdesc) { + Py_INCREF(Py_None); + result = Py_None; + goto done; + } + + if (!py_from_SECDESC(&result, secdesc)) { + PyErr_SetString( + PyExc_TypeError, + "Invalid security descriptor returned"); + result = NULL; + goto done; + } + + done: + talloc_destroy(mem_ctx); + + return result; + +} + +static PyObject *py_smb_set_secdesc(PyObject *self, PyObject *args, + PyObject *kw) +{ + cli_state_object *cli = (cli_state_object *)self; + static char *kwlist[] = { "fnum", "security_descriptor", NULL }; + PyObject *py_secdesc; + SEC_DESC *secdesc; + TALLOC_CTX *mem_ctx = talloc_init(); + int fnum; + BOOL result; + + /* Parse parameters */ + + if (!PyArg_ParseTupleAndKeywords( + args, kw, "iO", kwlist, &fnum, &py_secdesc)) + return NULL; + + if (!py_to_SECDESC(&secdesc, py_secdesc, mem_ctx)) { + PyErr_SetString(PyExc_TypeError, + "Invalid security descriptor"); + return NULL; + } + + result = cli_set_secdesc(cli->cli, fnum, secdesc); + + if (cli_is_error(cli->cli)) { + PyErr_SetString(PyExc_RuntimeError, "set_secdesc failed"); + return NULL; + } + + return PyInt_FromLong(result); +} + static PyMethodDef smb_hnd_methods[] = { + /* Session and connection handling */ + { "session_request", (PyCFunction)py_smb_session_request, METH_VARARGS | METH_KEYWORDS, "Request a session" }, @@ -155,6 +312,25 @@ static PyMethodDef smb_hnd_methods[] = { { "tconx", (PyCFunction)py_smb_tconx, METH_VARARGS | METH_KEYWORDS, "Tree connect" }, + /* File operations */ + + { "nt_create_andx", (PyCFunction)py_smb_nt_create_andx, + METH_VARARGS | METH_KEYWORDS, "NT Create&X" }, + + { "close", (PyCFunction)py_smb_close, + METH_VARARGS | METH_KEYWORDS, "Close" }, + + { "unlink", (PyCFunction)py_smb_unlink, + METH_VARARGS | METH_KEYWORDS, "Unlink" }, + + /* Security descriptors */ + + { "query_secdesc", (PyCFunction)py_smb_query_secdesc, + METH_VARARGS | METH_KEYWORDS, "Query security descriptor" }, + + { "set_secdesc", (PyCFunction)py_smb_set_secdesc, + METH_VARARGS | METH_KEYWORDS, "Set security descriptor" }, + { NULL } }; diff --git a/source3/python/py_spoolss_drivers.c b/source3/python/py_spoolss_drivers.c index f1cf6aca99..6daa32d0f4 100644 --- a/source3/python/py_spoolss_drivers.c +++ b/source3/python/py_spoolss_drivers.c @@ -57,7 +57,7 @@ PyObject *spoolss_enumprinterdrivers(PyObject *self, PyObject *args, /* Call rpc function */ - if (!(cli = open_pipe_creds(server, creds, PIPE_SPOOLSS, &errstr))) { + if (!(cli = open_pipe_creds(server, creds, PI_SPOOLSS, &errstr))) { PyErr_SetString(spoolss_error, errstr); free(errstr); goto done; @@ -261,7 +261,7 @@ PyObject *spoolss_getprinterdriverdir(PyObject *self, PyObject *args, /* Call rpc function */ - if (!(cli = open_pipe_creds(server, creds, PIPE_SPOOLSS, &errstr))) { + if (!(cli = open_pipe_creds(server, creds, PI_SPOOLSS, &errstr))) { PyErr_SetString(spoolss_error, errstr); free(errstr); goto done; @@ -341,7 +341,7 @@ PyObject *spoolss_addprinterdriver(PyObject *self, PyObject *args, return NULL; } - if (!(cli = open_pipe_creds(server, creds, PIPE_SPOOLSS, &errstr))) { + if (!(cli = open_pipe_creds(server, creds, PI_SPOOLSS, &errstr))) { PyErr_SetString(spoolss_error, errstr); free(errstr); goto done; diff --git a/source3/python/py_spoolss_ports.c b/source3/python/py_spoolss_ports.c index fe6d7536d3..55716aca6e 100644 --- a/source3/python/py_spoolss_ports.c +++ b/source3/python/py_spoolss_ports.c @@ -53,7 +53,7 @@ PyObject *spoolss_enumports(PyObject *self, PyObject *args, PyObject *kw) return NULL; } - if (!(cli = open_pipe_creds(server, creds, PIPE_SPOOLSS, &errstr))) { + if (!(cli = open_pipe_creds(server, creds, PI_SPOOLSS, &errstr))) { PyErr_SetString(spoolss_error, errstr); free(errstr); goto done; diff --git a/source3/python/py_spoolss_printers.c b/source3/python/py_spoolss_printers.c index a300eada86..a96498dddc 100644 --- a/source3/python/py_spoolss_printers.c +++ b/source3/python/py_spoolss_printers.c @@ -56,7 +56,7 @@ PyObject *spoolss_openprinter(PyObject *self, PyObject *args, PyObject *kw) return NULL; } - if (!(cli = open_pipe_creds(server, creds, PIPE_SPOOLSS, &errstr))) { + if (!(cli = open_pipe_creds(server, creds, PI_SPOOLSS, &errstr))) { PyErr_SetString(spoolss_error, errstr); free(errstr); goto done; @@ -304,7 +304,7 @@ PyObject *spoolss_enumprinters(PyObject *self, PyObject *args, PyObject *kw) return NULL; } - if (!(cli = open_pipe_creds(server, creds, PIPE_SPOOLSS, &errstr))) { + if (!(cli = open_pipe_creds(server, creds, PI_SPOOLSS, &errstr))) { PyErr_SetString(spoolss_error, errstr); free(errstr); goto done; @@ -439,7 +439,7 @@ PyObject *spoolss_addprinterex(PyObject *self, PyObject *args, PyObject *kw) &PyDict_Type, &info, &PyDict_Type, &creds)) return NULL; - if (!(cli = open_pipe_creds(server, creds, PIPE_SPOOLSS, &errstr))) { + if (!(cli = open_pipe_creds(server, creds, PI_SPOOLSS, &errstr))) { PyErr_SetString(spoolss_error, errstr); free(errstr); goto done; diff --git a/source3/python/py_tdbpack.c b/source3/python/py_tdbpack.c index e5044943be..06aebe61eb 100644 --- a/source3/python/py_tdbpack.c +++ b/source3/python/py_tdbpack.c @@ -329,18 +329,35 @@ pytdbpack_calc_reqd_len(char *format_str, } +static PyObject *pytdbpack_bad_type(char ch, + const char *expected, + PyObject *val_obj) +{ + PyObject *r = PyObject_Repr(val_obj); + if (!r) + return NULL; + PyErr_Format(PyExc_TypeError, + "tdbpack: format '%c' requires %s, not %s", + ch, expected, PyString_AS_STRING(r)); + Py_DECREF(r); + return val_obj; +} + + /* - Calculate the number of bytes required to pack a single value. -*/ + * Calculate the number of bytes required to pack a single value. While doing + * this, also conduct some initial checks that the argument types are + * reasonable. + * + * Returns -1 on exception. + */ static int pytdbpack_calc_item_len(char ch, PyObject *val_obj) { if (ch == 'd' || ch == 'w') { if (!PyInt_Check(val_obj)) { - PyErr_Format(PyExc_TypeError, - "tdbpack: format '%c' requires an Int", - ch); + pytdbpack_bad_type(ch, "Int", val_obj); return -1; } if (ch == 'w') @@ -353,10 +370,7 @@ pytdbpack_calc_item_len(char ch, else if (ch == 'f' || ch == 'P' || ch == 'B') { /* nul-terminated 8-bit string */ if (!PyString_Check(val_obj)) { - PyErr_Format(PyExc_TypeError, - "tdbpack: format '%c' requires a String", - ch); - return -1; + pytdbpack_bad_type(ch, "String", val_obj); } if (ch == 'B') { @@ -371,7 +385,7 @@ pytdbpack_calc_item_len(char ch, } else { PyErr_Format(PyExc_ValueError, - __FUNCTION__ ": format character '%c' is not supported", + "tdbpack: format character '%c' is not supported", ch); return -1; diff --git a/source3/python/setup.py b/source3/python/setup.py index 6d03ca633a..bf62f3b877 100755 --- a/source3/python/setup.py +++ b/source3/python/setup.py @@ -157,7 +157,8 @@ setup( Extension(name = "smb", sources = [samba_srcdir + "python/py_smb.c", - samba_srcdir + "python/py_common.c"], + samba_srcdir + "python/py_common.c", + samba_srcdir + "python/py_ntsec.c"], libraries = lib_list, library_dirs = ["/usr/kerberos/lib"], extra_compile_args = flags_list, -- cgit