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 2 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, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "python/py_smb.h"
23 /* Create a new cli_state python object */
25 PyObject
*new_cli_state_object(struct cli_state
*cli
)
29 o
= PyObject_New(cli_state_object
, &cli_state_type
);
36 static PyObject
*py_smb_connect(PyObject
*self
, PyObject
*args
, PyObject
*kw
)
38 static char *kwlist
[] = { "server", NULL
};
39 struct cli_state
*cli
;
43 if (!PyArg_ParseTupleAndKeywords(args
, kw
, "s", kwlist
, &server
))
46 if (!(cli
= cli_initialise()))
51 if (!cli_connect(cli
, server
, &ip
))
54 return new_cli_state_object(cli
);
57 static PyObject
*py_smb_session_request(PyObject
*self
, PyObject
*args
,
60 cli_state_object
*cli
= (cli_state_object
*)self
;
61 static char *kwlist
[] = { "called", "calling", NULL
};
62 char *calling_name
= NULL
, *called_name
;
63 struct nmb_name calling
, called
;
66 if (!PyArg_ParseTupleAndKeywords(args
, kw
, "s|s", kwlist
, &called_name
,
71 calling_name
= global_myname();
73 make_nmb_name(&calling
, calling_name
, 0x00);
74 make_nmb_name(&called
, called_name
, 0x20);
76 result
= cli_session_request(cli
->cli
, &calling
, &called
);
78 return Py_BuildValue("i", result
);
81 static PyObject
*py_smb_negprot(PyObject
*self
, PyObject
*args
, PyObject
*kw
)
83 cli_state_object
*cli
= (cli_state_object
*)self
;
84 static char *kwlist
[] = { NULL
};
87 if (!PyArg_ParseTupleAndKeywords(args
, kw
, "", kwlist
))
90 result
= cli_negprot(cli
->cli
);
92 return Py_BuildValue("i", result
);
95 static PyObject
*py_smb_session_setup(PyObject
*self
, PyObject
*args
,
98 cli_state_object
*cli
= (cli_state_object
*)self
;
99 static char *kwlist
[] = { "creds", NULL
};
101 char *username
, *domain
, *password
, *errstr
;
104 if (!PyArg_ParseTupleAndKeywords(args
, kw
, "|O", kwlist
, &creds
))
107 if (!py_parse_creds(creds
, &username
, &domain
, &password
, &errstr
)) {
112 result
= cli_session_setup(
113 cli
->cli
, username
, password
, strlen(password
) + 1,
114 password
, strlen(password
) + 1, domain
);
116 if (cli_is_error(cli
->cli
)) {
117 PyErr_SetString(PyExc_RuntimeError
, "session setup failed");
121 return Py_BuildValue("i", NT_STATUS_IS_OK(result
));
124 static PyObject
*py_smb_tconx(PyObject
*self
, PyObject
*args
, PyObject
*kw
)
126 cli_state_object
*cli
= (cli_state_object
*)self
;
127 static char *kwlist
[] = { "service", NULL
};
131 if (!PyArg_ParseTupleAndKeywords(args
, kw
, "s", kwlist
, &service
))
134 result
= cli_send_tconX(
135 cli
->cli
, service
, strequal(service
, "IPC$") ? "IPC" :
138 if (cli_is_error(cli
->cli
)) {
139 PyErr_SetString(PyExc_RuntimeError
, "tconx failed");
143 return Py_BuildValue("i", result
);
146 static PyObject
*py_smb_nt_create_andx(PyObject
*self
, PyObject
*args
,
149 cli_state_object
*cli
= (cli_state_object
*)self
;
150 static char *kwlist
[] = { "filename", "desired_access",
151 "file_attributes", "share_access",
152 "create_disposition", "create_options",
155 uint32 desired_access
, file_attributes
= 0,
156 share_access
= FILE_SHARE_READ
| FILE_SHARE_WRITE
,
157 create_disposition
= OPENX_FILE_EXISTS_OPEN
, create_options
= 0;
160 /* Parse parameters */
162 if (!PyArg_ParseTupleAndKeywords(
163 args
, kw
, "si|iiii", kwlist
, &filename
, &desired_access
,
164 &file_attributes
, &share_access
, &create_disposition
,
168 result
= cli_nt_create_full(
169 cli
->cli
, filename
, 0, desired_access
, file_attributes
,
170 share_access
, create_disposition
, create_options
, 0);
172 if (cli_is_error(cli
->cli
)) {
173 PyErr_SetString(PyExc_RuntimeError
, "nt_create_andx failed");
179 return PyInt_FromLong(result
);
182 static PyObject
*py_smb_open(PyObject
*self
, PyObject
*args
, PyObject
*kw
)
184 cli_state_object
*cli
= (cli_state_object
*)self
;
185 static char *kwlist
[] = { "filename", "flags",
186 "share_mode", NULL
};
188 uint32 flags
, share_mode
= DENY_NONE
;
191 /* Parse parameters */
193 if (!PyArg_ParseTupleAndKeywords(
194 args
, kw
, "si|i", kwlist
, &filename
, &flags
, &share_mode
))
197 result
= cli_open(cli
->cli
, filename
, flags
, share_mode
);
199 if (cli_is_error(cli
->cli
)) {
200 PyErr_SetString(PyExc_RuntimeError
, "open failed");
206 return PyInt_FromLong(result
);
209 static PyObject
*py_smb_read(PyObject
*self
, PyObject
*args
, PyObject
*kw
)
211 cli_state_object
*cli
= (cli_state_object
*)self
;
212 static char *kwlist
[] = { "fnum", "offset", "size", NULL
};
213 int fnum
, offset
=0, size
=0;
219 /* Parse parameters */
221 if (!PyArg_ParseTupleAndKeywords(
222 args
, kw
, "i|ii", kwlist
, &fnum
, &offset
, &size
))
225 if (!cli_qfileinfo(cli
->cli
, fnum
, NULL
, &fsize
, NULL
, NULL
,
227 !cli_getattrE(cli
->cli
, fnum
, NULL
, &fsize
, NULL
, NULL
, NULL
)) {
228 PyErr_SetString(PyExc_RuntimeError
, "getattrib failed");
235 if (size
< 1 || size
> fsize
- offset
)
236 size
= fsize
- offset
;
238 if (!(data
= SMB_XMALLOC_ARRAY(char, size
))) {
239 PyErr_SetString(PyExc_RuntimeError
, "malloc failed");
243 result
= cli_read(cli
->cli
, fnum
, data
, (off_t
) offset
, (size_t) size
);
245 if (result
==-1 || cli_is_error(cli
->cli
)) {
247 PyErr_SetString(PyExc_RuntimeError
, "read failed");
251 /* Return a python string */
253 ret
= Py_BuildValue("s#", data
, result
);
259 static PyObject
*py_smb_close(PyObject
*self
, PyObject
*args
,
262 cli_state_object
*cli
= (cli_state_object
*)self
;
263 static char *kwlist
[] = { "fnum", NULL
};
267 /* Parse parameters */
269 if (!PyArg_ParseTupleAndKeywords(
270 args
, kw
, "i", kwlist
, &fnum
))
273 result
= cli_close(cli
->cli
, fnum
);
275 return PyInt_FromLong(result
);
278 static PyObject
*py_smb_unlink(PyObject
*self
, PyObject
*args
,
281 cli_state_object
*cli
= (cli_state_object
*)self
;
282 static char *kwlist
[] = { "filename", NULL
};
286 /* Parse parameters */
288 if (!PyArg_ParseTupleAndKeywords(
289 args
, kw
, "s", kwlist
, &filename
))
292 result
= cli_unlink(cli
->cli
, filename
);
294 return PyInt_FromLong(result
);
297 static PyObject
*py_smb_query_secdesc(PyObject
*self
, PyObject
*args
,
300 cli_state_object
*cli
= (cli_state_object
*)self
;
301 static char *kwlist
[] = { "fnum", NULL
};
302 PyObject
*result
= NULL
;
303 SEC_DESC
*secdesc
= NULL
;
305 TALLOC_CTX
*mem_ctx
= NULL
;
307 /* Parse parameters */
309 if (!PyArg_ParseTupleAndKeywords(
310 args
, kw
, "i", kwlist
, &fnum
))
313 mem_ctx
= talloc_init("py_smb_query_secdesc");
315 secdesc
= cli_query_secdesc(cli
->cli
, fnum
, mem_ctx
);
317 if (cli_is_error(cli
->cli
)) {
318 PyErr_SetString(PyExc_RuntimeError
, "query_secdesc failed");
328 if (!py_from_SECDESC(&result
, secdesc
)) {
331 "Invalid security descriptor returned");
336 talloc_destroy(mem_ctx
);
342 static PyObject
*py_smb_set_secdesc(PyObject
*self
, PyObject
*args
,
345 cli_state_object
*cli
= (cli_state_object
*)self
;
346 static char *kwlist
[] = { "fnum", "security_descriptor", NULL
};
347 PyObject
*result
= NULL
;
348 PyObject
*py_secdesc
;
350 TALLOC_CTX
*mem_ctx
= NULL
;
354 /* Parse parameters */
356 if (!PyArg_ParseTupleAndKeywords(
357 args
, kw
, "iO", kwlist
, &fnum
, &py_secdesc
))
360 mem_ctx
= talloc_init("py_smb_set_secdesc");
362 if (!py_to_SECDESC(&secdesc
, py_secdesc
, mem_ctx
)) {
363 PyErr_SetString(PyExc_TypeError
,
364 "Invalid security descriptor");
368 err
= cli_set_secdesc(cli
->cli
, fnum
, secdesc
);
370 if (cli_is_error(cli
->cli
)) {
371 PyErr_SetString(PyExc_RuntimeError
, "set_secdesc failed");
375 result
= PyInt_FromLong(err
);
377 talloc_destroy(mem_ctx
);
382 static PyMethodDef smb_hnd_methods
[] = {
384 /* Session and connection handling */
386 { "session_request", (PyCFunction
)py_smb_session_request
,
387 METH_VARARGS
| METH_KEYWORDS
, "Request a session" },
389 { "negprot", (PyCFunction
)py_smb_negprot
,
390 METH_VARARGS
| METH_KEYWORDS
, "Protocol negotiation" },
392 { "session_setup", (PyCFunction
)py_smb_session_setup
,
393 METH_VARARGS
| METH_KEYWORDS
, "Session setup" },
395 { "tconx", (PyCFunction
)py_smb_tconx
,
396 METH_VARARGS
| METH_KEYWORDS
, "Tree connect" },
398 /* File operations */
400 { "nt_create_andx", (PyCFunction
)py_smb_nt_create_andx
,
401 METH_VARARGS
| METH_KEYWORDS
, "NT Create&X" },
403 { "open", (PyCFunction
)py_smb_open
,
404 METH_VARARGS
| METH_KEYWORDS
,
407 "This function returns a fnum handle to an open file. The file is\n"
408 "opened with flags and optional share mode. If unspecified, the\n"
409 "default share mode is DENY_NONE\n"
413 ">>> fnum=conn.open(filename, os.O_RDONLY)" },
415 { "read", (PyCFunction
)py_smb_read
,
416 METH_VARARGS
| METH_KEYWORDS
,
417 "Read from an open file\n"
419 "This function returns a string read from an open file starting at\n"
420 "offset for size bytes (until EOF is reached). If unspecified, the\n"
421 "default offset is 0, and default size is the remainder of the file.\n"
425 ">>> conn.read(fnum) # read entire file\n"
426 ">>> conn.read(fnum,5) # read entire file from offset 5\n"
427 ">>> conn.read(fnum,size=64) # read 64 bytes from start of file\n"
428 ">>> conn.read(fnum,4096,1024) # read 1024 bytes from offset 4096\n" },
430 { "close", (PyCFunction
)py_smb_close
,
431 METH_VARARGS
| METH_KEYWORDS
, "Close" },
433 { "unlink", (PyCFunction
)py_smb_unlink
,
434 METH_VARARGS
| METH_KEYWORDS
, "Unlink" },
436 /* Security descriptors */
438 { "query_secdesc", (PyCFunction
)py_smb_query_secdesc
,
439 METH_VARARGS
| METH_KEYWORDS
, "Query security descriptor" },
441 { "set_secdesc", (PyCFunction
)py_smb_set_secdesc
,
442 METH_VARARGS
| METH_KEYWORDS
, "Set security descriptor" },
448 * Method dispatch tables
451 static PyMethodDef smb_methods
[] = {
453 { "connect", (PyCFunction
)py_smb_connect
, METH_VARARGS
| METH_KEYWORDS
,
454 "Connect to a host" },
456 /* Other stuff - this should really go into a samba config module
457 but for the moment let's leave it here. */
459 { "setup_logging", (PyCFunction
)py_setup_logging
,
460 METH_VARARGS
| METH_KEYWORDS
,
461 "Set up debug logging.\n"
463 "Initialises Samba's debug logging system. One argument is expected which\n"
464 "is a boolean specifying whether debugging is interactive and sent to stdout\n"
465 "or logged to a file.\n"
469 ">>> smb.setup_logging(interactive = 1)" },
471 { "get_debuglevel", (PyCFunction
)get_debuglevel
,
473 "Set the current debug level.\n"
477 ">>> smb.get_debuglevel()\n"
480 { "set_debuglevel", (PyCFunction
)set_debuglevel
,
482 "Get the current debug level.\n"
486 ">>> smb.set_debuglevel(10)" },
491 static void py_cli_state_dealloc(PyObject
* self
)
493 cli_state_object
*cli
= (cli_state_object
*)self
;
496 cli_shutdown(cli
->cli
);
501 static PyObject
*py_cli_state_getattr(PyObject
*self
, char *attrname
)
503 return Py_FindMethod(smb_hnd_methods
, self
, attrname
);
506 PyTypeObject cli_state_type
= {
507 PyObject_HEAD_INIT(NULL
)
509 "SMB client connection",
510 sizeof(cli_state_object
),
512 py_cli_state_dealloc
, /*tp_dealloc*/
514 py_cli_state_getattr
, /*tp_getattr*/
519 0, /*tp_as_sequence*/
525 * Module initialisation
530 PyObject
*module
, *dict
;
532 /* Initialise module */
534 module
= Py_InitModule("smb", smb_methods
);
535 dict
= PyModule_GetDict(module
);
537 /* Initialise policy handle object */
539 cli_state_type
.ob_type
= &PyType_Type
;
541 /* Do samba initialisation */
545 setup_logging("smb", True
);