r19058: Implement "user cannot change password", and complete "user must change
[Samba.git] / source / python / py_smb.c
blob2f5d1161d87d16f23539640a643123f0dc476006
1 /*
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)
27 cli_state_object *o;
29 o = PyObject_New(cli_state_object, &cli_state_type);
31 o->cli = cli;
33 return (PyObject*)o;
36 static PyObject *py_smb_connect(PyObject *self, PyObject *args, PyObject *kw)
38 static char *kwlist[] = { "server", NULL };
39 struct cli_state *cli;
40 char *server;
41 struct in_addr ip;
43 if (!PyArg_ParseTupleAndKeywords(args, kw, "s", kwlist, &server))
44 return NULL;
46 if (!(cli = cli_initialise()))
47 return NULL;
49 ZERO_STRUCT(ip);
51 if (!cli_connect(cli, server, &ip))
52 return NULL;
54 return new_cli_state_object(cli);
57 static PyObject *py_smb_session_request(PyObject *self, PyObject *args,
58 PyObject *kw)
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;
64 BOOL result;
66 if (!PyArg_ParseTupleAndKeywords(args, kw, "s|s", kwlist, &called_name,
67 &calling_name))
68 return NULL;
70 if (!calling_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 };
85 BOOL result;
87 if (!PyArg_ParseTupleAndKeywords(args, kw, "", kwlist))
88 return NULL;
90 result = cli_negprot(cli->cli);
92 return Py_BuildValue("i", result);
95 static PyObject *py_smb_session_setup(PyObject *self, PyObject *args,
96 PyObject *kw)
98 cli_state_object *cli = (cli_state_object *)self;
99 static char *kwlist[] = { "creds", NULL };
100 PyObject *creds;
101 char *username, *domain, *password, *errstr;
102 NTSTATUS result;
104 if (!PyArg_ParseTupleAndKeywords(args, kw, "|O", kwlist, &creds))
105 return NULL;
107 if (!py_parse_creds(creds, &username, &domain, &password, &errstr)) {
108 free(errstr);
109 return NULL;
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");
118 return NULL;
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 };
128 char *service;
129 BOOL result;
131 if (!PyArg_ParseTupleAndKeywords(args, kw, "s", kwlist, &service))
132 return NULL;
134 result = cli_send_tconX(
135 cli->cli, service, strequal(service, "IPC$") ? "IPC" :
136 "?????", "", 1);
138 if (cli_is_error(cli->cli)) {
139 PyErr_SetString(PyExc_RuntimeError, "tconx failed");
140 return NULL;
143 return Py_BuildValue("i", result);
146 static PyObject *py_smb_nt_create_andx(PyObject *self, PyObject *args,
147 PyObject *kw)
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",
153 NULL };
154 char *filename;
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;
158 int result;
160 /* Parse parameters */
162 if (!PyArg_ParseTupleAndKeywords(
163 args, kw, "si|iiii", kwlist, &filename, &desired_access,
164 &file_attributes, &share_access, &create_disposition,
165 &create_options))
166 return NULL;
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");
174 return NULL;
177 /* Return FID */
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 };
187 char *filename;
188 uint32 flags, share_mode = DENY_NONE;
189 int result;
191 /* Parse parameters */
193 if (!PyArg_ParseTupleAndKeywords(
194 args, kw, "si|i", kwlist, &filename, &flags, &share_mode))
195 return NULL;
197 result = cli_open(cli->cli, filename, flags, share_mode);
199 if (cli_is_error(cli->cli)) {
200 PyErr_SetString(PyExc_RuntimeError, "open failed");
201 return NULL;
204 /* Return FID */
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;
214 ssize_t result;
215 SMB_OFF_T fsize;
216 char *data;
217 PyObject *ret;
219 /* Parse parameters */
221 if (!PyArg_ParseTupleAndKeywords(
222 args, kw, "i|ii", kwlist, &fnum, &offset, &size))
223 return NULL;
225 if (!cli_qfileinfo(cli->cli, fnum, NULL, &fsize, NULL, NULL,
226 NULL, NULL, NULL) &&
227 !cli_getattrE(cli->cli, fnum, NULL, &fsize, NULL, NULL, NULL)) {
228 PyErr_SetString(PyExc_RuntimeError, "getattrib failed");
229 return NULL;
232 if (offset < 0)
233 offset = 0;
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");
240 return NULL;
243 result = cli_read(cli->cli, fnum, data, (off_t) offset, (size_t) size);
245 if (result==-1 || cli_is_error(cli->cli)) {
246 SAFE_FREE(data);
247 PyErr_SetString(PyExc_RuntimeError, "read failed");
248 return NULL;
251 /* Return a python string */
253 ret = Py_BuildValue("s#", data, result);
254 SAFE_FREE(data);
256 return ret;
259 static PyObject *py_smb_close(PyObject *self, PyObject *args,
260 PyObject *kw)
262 cli_state_object *cli = (cli_state_object *)self;
263 static char *kwlist[] = { "fnum", NULL };
264 BOOL result;
265 int fnum;
267 /* Parse parameters */
269 if (!PyArg_ParseTupleAndKeywords(
270 args, kw, "i", kwlist, &fnum))
271 return NULL;
273 result = cli_close(cli->cli, fnum);
275 return PyInt_FromLong(result);
278 static PyObject *py_smb_unlink(PyObject *self, PyObject *args,
279 PyObject *kw)
281 cli_state_object *cli = (cli_state_object *)self;
282 static char *kwlist[] = { "filename", NULL };
283 char *filename;
284 BOOL result;
286 /* Parse parameters */
288 if (!PyArg_ParseTupleAndKeywords(
289 args, kw, "s", kwlist, &filename))
290 return NULL;
292 result = cli_unlink(cli->cli, filename);
294 return PyInt_FromLong(result);
297 static PyObject *py_smb_query_secdesc(PyObject *self, PyObject *args,
298 PyObject *kw)
300 cli_state_object *cli = (cli_state_object *)self;
301 static char *kwlist[] = { "fnum", NULL };
302 PyObject *result = NULL;
303 SEC_DESC *secdesc = NULL;
304 int fnum;
305 TALLOC_CTX *mem_ctx = NULL;
307 /* Parse parameters */
309 if (!PyArg_ParseTupleAndKeywords(
310 args, kw, "i", kwlist, &fnum))
311 return NULL;
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");
319 goto done;
322 if (!secdesc) {
323 Py_INCREF(Py_None);
324 result = Py_None;
325 goto done;
328 if (!py_from_SECDESC(&result, secdesc)) {
329 PyErr_SetString(
330 PyExc_TypeError,
331 "Invalid security descriptor returned");
332 goto done;
335 done:
336 talloc_destroy(mem_ctx);
338 return result;
342 static PyObject *py_smb_set_secdesc(PyObject *self, PyObject *args,
343 PyObject *kw)
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;
349 SEC_DESC *secdesc;
350 TALLOC_CTX *mem_ctx = NULL;
351 int fnum;
352 BOOL err;
354 /* Parse parameters */
356 if (!PyArg_ParseTupleAndKeywords(
357 args, kw, "iO", kwlist, &fnum, &py_secdesc))
358 return NULL;
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");
365 goto done;
368 err = cli_set_secdesc(cli->cli, fnum, secdesc);
370 if (cli_is_error(cli->cli)) {
371 PyErr_SetString(PyExc_RuntimeError, "set_secdesc failed");
372 goto done;
375 result = PyInt_FromLong(err);
376 done:
377 talloc_destroy(mem_ctx);
379 return result;
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,
405 "Open a file\n"
406 "\n"
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"
410 "\n"
411 "Example:\n"
412 "\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"
418 "\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"
422 "\n"
423 "Example:\n"
424 "\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" },
444 { NULL }
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"
462 "\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"
466 "\n"
467 "Example:\n"
468 "\n"
469 ">>> smb.setup_logging(interactive = 1)" },
471 { "get_debuglevel", (PyCFunction)get_debuglevel,
472 METH_VARARGS,
473 "Set the current debug level.\n"
474 "\n"
475 "Example:\n"
476 "\n"
477 ">>> smb.get_debuglevel()\n"
478 "0" },
480 { "set_debuglevel", (PyCFunction)set_debuglevel,
481 METH_VARARGS,
482 "Get the current debug level.\n"
483 "\n"
484 "Example:\n"
485 "\n"
486 ">>> smb.set_debuglevel(10)" },
488 { NULL }
491 static void py_cli_state_dealloc(PyObject* self)
493 cli_state_object *cli = (cli_state_object *)self;
495 if (cli->cli)
496 cli_shutdown(cli->cli);
498 PyObject_Del(self);
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*/
513 0, /*tp_print*/
514 py_cli_state_getattr, /*tp_getattr*/
515 0, /*tp_setattr*/
516 0, /*tp_compare*/
517 0, /*tp_repr*/
518 0, /*tp_as_number*/
519 0, /*tp_as_sequence*/
520 0, /*tp_as_mapping*/
521 0, /*tp_hash */
525 * Module initialisation
528 void initsmb(void)
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 */
543 py_samba_init();
545 setup_logging("smb", True);
546 DEBUGLEVEL = 3;