2 Python wrappers for DCERPC/SMB client routines.
4 Copyright (C) Tim Potter, 2002
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "python/py_smb.h"
22 /* Create a new cli_state python object */
24 PyObject *new_cli_state_object(struct cli_state *cli)
28 o = PyObject_New(cli_state_object, &cli_state_type);
35 static PyObject *py_smb_connect(PyObject *self, PyObject *args, PyObject *kw)
37 static char *kwlist[] = { "server", NULL };
38 struct cli_state *cli;
42 if (!PyArg_ParseTupleAndKeywords(args, kw, "s", kwlist, &server))
45 if (!(cli = cli_initialise()))
50 if (!NT_STATUS_IS_OK(cli_connect(cli, server, &ip)))
53 return new_cli_state_object(cli);
56 static PyObject *py_smb_session_request(PyObject *self, PyObject *args,
59 cli_state_object *cli = (cli_state_object *)self;
60 static char *kwlist[] = { "called", "calling", NULL };
61 char *calling_name = NULL, *called_name;
62 struct nmb_name calling, called;
65 if (!PyArg_ParseTupleAndKeywords(args, kw, "s|s", kwlist, &called_name,
70 calling_name = global_myname();
72 make_nmb_name(&calling, calling_name, 0x00);
73 make_nmb_name(&called, called_name, 0x20);
75 result = cli_session_request(cli->cli, &calling, &called);
77 return Py_BuildValue("i", result);
80 static PyObject *py_smb_negprot(PyObject *self, PyObject *args, PyObject *kw)
82 cli_state_object *cli = (cli_state_object *)self;
83 static char *kwlist[] = { NULL };
86 if (!PyArg_ParseTupleAndKeywords(args, kw, "", kwlist))
89 result = cli_negprot(cli->cli);
91 return Py_BuildValue("i", result);
94 static PyObject *py_smb_session_setup(PyObject *self, PyObject *args,
97 cli_state_object *cli = (cli_state_object *)self;
98 static char *kwlist[] = { "creds", NULL };
100 char *username, *domain, *password, *errstr;
103 if (!PyArg_ParseTupleAndKeywords(args, kw, "|O", kwlist, &creds))
106 if (!py_parse_creds(creds, &username, &domain, &password, &errstr)) {
111 result = cli_session_setup(
112 cli->cli, username, password, strlen(password) + 1,
113 password, strlen(password) + 1, domain);
115 if (cli_is_error(cli->cli)) {
116 PyErr_SetString(PyExc_RuntimeError, "session setup failed");
120 return Py_BuildValue("i", NT_STATUS_IS_OK(result));
123 static PyObject *py_smb_tconx(PyObject *self, PyObject *args, PyObject *kw)
125 cli_state_object *cli = (cli_state_object *)self;
126 static char *kwlist[] = { "service", NULL };
130 if (!PyArg_ParseTupleAndKeywords(args, kw, "s", kwlist, &service))
133 result = cli_send_tconX(
134 cli->cli, service, strequal(service, "IPC$") ? "IPC" :
137 if (cli_is_error(cli->cli)) {
138 PyErr_SetString(PyExc_RuntimeError, "tconx failed");
142 return Py_BuildValue("i", result);
145 static PyObject *py_smb_nt_create_andx(PyObject *self, PyObject *args,
148 cli_state_object *cli = (cli_state_object *)self;
149 static char *kwlist[] = { "filename", "desired_access",
150 "file_attributes", "share_access",
151 "create_disposition", "create_options",
154 uint32 desired_access, file_attributes = 0,
155 share_access = FILE_SHARE_READ | FILE_SHARE_WRITE,
156 create_disposition = OPENX_FILE_EXISTS_OPEN, create_options = 0;
159 /* Parse parameters */
161 if (!PyArg_ParseTupleAndKeywords(
162 args, kw, "si|iiii", kwlist, &filename, &desired_access,
163 &file_attributes, &share_access, &create_disposition,
167 result = cli_nt_create_full(
168 cli->cli, filename, 0, desired_access, file_attributes,
169 share_access, create_disposition, create_options, 0);
171 if (cli_is_error(cli->cli)) {
172 PyErr_SetString(PyExc_RuntimeError, "nt_create_andx failed");
178 return PyInt_FromLong(result);
181 static PyObject *py_smb_open(PyObject *self, PyObject *args, PyObject *kw)
183 cli_state_object *cli = (cli_state_object *)self;
184 static char *kwlist[] = { "filename", "flags",
185 "share_mode", NULL };
187 uint32 flags, share_mode = DENY_NONE;
190 /* Parse parameters */
192 if (!PyArg_ParseTupleAndKeywords(
193 args, kw, "si|i", kwlist, &filename, &flags, &share_mode))
196 result = cli_open(cli->cli, filename, flags, share_mode);
198 if (cli_is_error(cli->cli)) {
199 PyErr_SetString(PyExc_RuntimeError, "open failed");
205 return PyInt_FromLong(result);
208 static PyObject *py_smb_read(PyObject *self, PyObject *args, PyObject *kw)
210 cli_state_object *cli = (cli_state_object *)self;
211 static char *kwlist[] = { "fnum", "offset", "size", NULL };
212 int fnum, offset=0, size=0;
218 /* Parse parameters */
220 if (!PyArg_ParseTupleAndKeywords(
221 args, kw, "i|ii", kwlist, &fnum, &offset, &size))
224 if (!cli_qfileinfo(cli->cli, fnum, NULL, &fsize, NULL, NULL,
226 !cli_getattrE(cli->cli, fnum, NULL, &fsize, NULL, NULL, NULL)) {
227 PyErr_SetString(PyExc_RuntimeError, "getattrib failed");
234 if (size < 1 || size > fsize - offset)
235 size = fsize - offset;
237 if (!(data = SMB_XMALLOC_ARRAY(char, size))) {
238 PyErr_SetString(PyExc_RuntimeError, "malloc failed");
242 result = cli_read(cli->cli, fnum, data, (off_t) offset, (size_t) size);
244 if (result==-1 || cli_is_error(cli->cli)) {
246 PyErr_SetString(PyExc_RuntimeError, "read failed");
250 /* Return a python string */
252 ret = Py_BuildValue("s#", data, result);
258 static PyObject *py_smb_close(PyObject *self, PyObject *args,
261 cli_state_object *cli = (cli_state_object *)self;
262 static char *kwlist[] = { "fnum", NULL };
266 /* Parse parameters */
268 if (!PyArg_ParseTupleAndKeywords(
269 args, kw, "i", kwlist, &fnum))
272 result = cli_close(cli->cli, fnum);
274 return PyInt_FromLong(result);
277 static PyObject *py_smb_unlink(PyObject *self, PyObject *args,
280 cli_state_object *cli = (cli_state_object *)self;
281 static char *kwlist[] = { "filename", NULL };
285 /* Parse parameters */
287 if (!PyArg_ParseTupleAndKeywords(
288 args, kw, "s", kwlist, &filename))
291 result = cli_unlink(cli->cli, filename);
293 return PyInt_FromLong(result);
296 static PyObject *py_smb_query_secdesc(PyObject *self, PyObject *args,
299 cli_state_object *cli = (cli_state_object *)self;
300 static char *kwlist[] = { "fnum", NULL };
301 PyObject *result = NULL;
302 SEC_DESC *secdesc = NULL;
304 TALLOC_CTX *mem_ctx = NULL;
306 /* Parse parameters */
308 if (!PyArg_ParseTupleAndKeywords(
309 args, kw, "i", kwlist, &fnum))
312 mem_ctx = talloc_init("py_smb_query_secdesc");
314 secdesc = cli_query_secdesc(cli->cli, fnum, mem_ctx);
316 if (cli_is_error(cli->cli)) {
317 PyErr_SetString(PyExc_RuntimeError, "query_secdesc failed");
327 if (!py_from_SECDESC(&result, secdesc)) {
330 "Invalid security descriptor returned");
335 talloc_destroy(mem_ctx);
341 static PyObject *py_smb_set_secdesc(PyObject *self, PyObject *args,
344 cli_state_object *cli = (cli_state_object *)self;
345 static char *kwlist[] = { "fnum", "security_descriptor", NULL };
346 PyObject *result = NULL;
347 PyObject *py_secdesc;
349 TALLOC_CTX *mem_ctx = NULL;
353 /* Parse parameters */
355 if (!PyArg_ParseTupleAndKeywords(
356 args, kw, "iO", kwlist, &fnum, &py_secdesc))
359 mem_ctx = talloc_init("py_smb_set_secdesc");
361 if (!py_to_SECDESC(&secdesc, py_secdesc, mem_ctx)) {
362 PyErr_SetString(PyExc_TypeError,
363 "Invalid security descriptor");
367 err = cli_set_secdesc(cli->cli, fnum, secdesc);
369 if (cli_is_error(cli->cli)) {
370 PyErr_SetString(PyExc_RuntimeError, "set_secdesc failed");
374 result = PyInt_FromLong(err);
376 talloc_destroy(mem_ctx);
381 static PyMethodDef smb_hnd_methods[] = {
383 /* Session and connection handling */
385 { "session_request", (PyCFunction)py_smb_session_request,
386 METH_VARARGS | METH_KEYWORDS, "Request a session" },
388 { "negprot", (PyCFunction)py_smb_negprot,
389 METH_VARARGS | METH_KEYWORDS, "Protocol negotiation" },
391 { "session_setup", (PyCFunction)py_smb_session_setup,
392 METH_VARARGS | METH_KEYWORDS, "Session setup" },
394 { "tconx", (PyCFunction)py_smb_tconx,
395 METH_VARARGS | METH_KEYWORDS, "Tree connect" },
397 /* File operations */
399 { "nt_create_andx", (PyCFunction)py_smb_nt_create_andx,
400 METH_VARARGS | METH_KEYWORDS, "NT Create&X" },
402 { "open", (PyCFunction)py_smb_open,
403 METH_VARARGS | METH_KEYWORDS,
406 "This function returns a fnum handle to an open file. The file is\n"
407 "opened with flags and optional share mode. If unspecified, the\n"
408 "default share mode is DENY_NONE\n"
412 ">>> fnum=conn.open(filename, os.O_RDONLY)" },
414 { "read", (PyCFunction)py_smb_read,
415 METH_VARARGS | METH_KEYWORDS,
416 "Read from an open file\n"
418 "This function returns a string read from an open file starting at\n"
419 "offset for size bytes (until EOF is reached). If unspecified, the\n"
420 "default offset is 0, and default size is the remainder of the file.\n"
424 ">>> conn.read(fnum) # read entire file\n"
425 ">>> conn.read(fnum,5) # read entire file from offset 5\n"
426 ">>> conn.read(fnum,size=64) # read 64 bytes from start of file\n"
427 ">>> conn.read(fnum,4096,1024) # read 1024 bytes from offset 4096\n" },
429 { "close", (PyCFunction)py_smb_close,
430 METH_VARARGS | METH_KEYWORDS, "Close" },
432 { "unlink", (PyCFunction)py_smb_unlink,
433 METH_VARARGS | METH_KEYWORDS, "Unlink" },
435 /* Security descriptors */
437 { "query_secdesc", (PyCFunction)py_smb_query_secdesc,
438 METH_VARARGS | METH_KEYWORDS, "Query security descriptor" },
440 { "set_secdesc", (PyCFunction)py_smb_set_secdesc,
441 METH_VARARGS | METH_KEYWORDS, "Set security descriptor" },
447 * Method dispatch tables
450 static PyMethodDef smb_methods[] = {
452 { "connect", (PyCFunction)py_smb_connect, METH_VARARGS | METH_KEYWORDS,
453 "Connect to a host" },
455 /* Other stuff - this should really go into a samba config module
456 but for the moment let's leave it here. */
458 { "setup_logging", (PyCFunction)py_setup_logging,
459 METH_VARARGS | METH_KEYWORDS,
460 "Set up debug logging.\n"
462 "Initialises Samba's debug logging system. One argument is expected which\n"
463 "is a boolean specifying whether debugging is interactive and sent to stdout\n"
464 "or logged to a file.\n"
468 ">>> smb.setup_logging(interactive = 1)" },
470 { "get_debuglevel", (PyCFunction)get_debuglevel,
472 "Set the current debug level.\n"
476 ">>> smb.get_debuglevel()\n"
479 { "set_debuglevel", (PyCFunction)set_debuglevel,
481 "Get the current debug level.\n"
485 ">>> smb.set_debuglevel(10)" },
490 static void py_cli_state_dealloc(PyObject* self)
492 cli_state_object *cli = (cli_state_object *)self;
495 cli_shutdown(cli->cli);
500 static PyObject *py_cli_state_getattr(PyObject *self, char *attrname)
502 return Py_FindMethod(smb_hnd_methods, self, attrname);
505 PyTypeObject cli_state_type = {
506 PyObject_HEAD_INIT(NULL)
508 "SMB client connection",
509 sizeof(cli_state_object),
511 py_cli_state_dealloc, /*tp_dealloc*/
513 py_cli_state_getattr, /*tp_getattr*/
518 0, /*tp_as_sequence*/
524 * Module initialisation
529 PyObject *module, *dict;
531 /* Initialise module */
533 module = Py_InitModule("smb", smb_methods);
534 dict = PyModule_GetDict(module);
536 /* Initialise policy handle object */
538 cli_state_type.ob_type = &PyType_Type;
540 /* Do samba initialisation */
544 setup_logging("smb", True);