r25598: Add missing become_root/unbecome_root around calls of add_aliases.
[samba.git] / source / python / py_smb.c
1 /* 
2    Python wrappers for DCERPC/SMB client routines.
3
4    Copyright (C) Tim Potter, 2002
5    
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.
10    
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.
15    
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/>.
18 */
19
20 #include "python/py_smb.h"
21
22 /* Create a new cli_state python object */
23
24 PyObject *new_cli_state_object(struct cli_state *cli)
25 {
26         cli_state_object *o;
27
28         o = PyObject_New(cli_state_object, &cli_state_type);
29
30         o->cli = cli;
31
32         return (PyObject*)o;
33 }
34
35 static PyObject *py_smb_connect(PyObject *self, PyObject *args, PyObject *kw)
36 {
37         static char *kwlist[] = { "server", NULL };
38         struct cli_state *cli;
39         char *server;
40         struct in_addr ip;
41
42         if (!PyArg_ParseTupleAndKeywords(args, kw, "s", kwlist, &server))
43                 return NULL;
44
45         if (!(cli = cli_initialise()))
46                 return NULL;
47
48         ZERO_STRUCT(ip);
49
50         if (!NT_STATUS_IS_OK(cli_connect(cli, server, &ip)))
51                 return NULL;
52
53         return new_cli_state_object(cli);
54 }
55
56 static PyObject *py_smb_session_request(PyObject *self, PyObject *args,
57                                         PyObject *kw)
58 {
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;
63         BOOL result;
64
65         if (!PyArg_ParseTupleAndKeywords(args, kw, "s|s", kwlist, &called_name, 
66                                          &calling_name))
67                 return NULL;
68
69         if (!calling_name)
70                 calling_name = global_myname();
71
72         make_nmb_name(&calling, calling_name, 0x00);
73         make_nmb_name(&called, called_name, 0x20);
74
75         result = cli_session_request(cli->cli, &calling, &called);
76
77         return Py_BuildValue("i", result);
78 }
79                                       
80 static PyObject *py_smb_negprot(PyObject *self, PyObject *args, PyObject *kw)
81 {
82         cli_state_object *cli = (cli_state_object *)self;
83         static char *kwlist[] = { NULL };
84         BOOL result;
85
86         if (!PyArg_ParseTupleAndKeywords(args, kw, "", kwlist))
87                 return NULL;
88
89         result = cli_negprot(cli->cli);
90
91         return Py_BuildValue("i", result);
92 }
93
94 static PyObject *py_smb_session_setup(PyObject *self, PyObject *args, 
95                                       PyObject *kw)
96 {
97         cli_state_object *cli = (cli_state_object *)self;
98         static char *kwlist[] = { "creds", NULL };
99         PyObject *creds;
100         char *username, *domain, *password, *errstr;
101         NTSTATUS result;
102
103         if (!PyArg_ParseTupleAndKeywords(args, kw, "|O", kwlist, &creds))
104                 return NULL;
105
106         if (!py_parse_creds(creds, &username, &domain, &password, &errstr)) {
107                 free(errstr);
108                 return NULL;
109         }
110
111         result = cli_session_setup(
112                 cli->cli, username, password, strlen(password) + 1,
113                 password, strlen(password) + 1, domain);
114
115         if (cli_is_error(cli->cli)) {
116                 PyErr_SetString(PyExc_RuntimeError, "session setup failed");
117                 return NULL;
118         }
119
120         return Py_BuildValue("i", NT_STATUS_IS_OK(result));
121 }
122
123 static PyObject *py_smb_tconx(PyObject *self, PyObject *args, PyObject *kw)
124 {
125         cli_state_object *cli = (cli_state_object *)self;
126         static char *kwlist[] = { "service", NULL };
127         char *service;
128         BOOL result;
129
130         if (!PyArg_ParseTupleAndKeywords(args, kw, "s", kwlist, &service))
131                 return NULL;
132
133         result = cli_send_tconX(
134                 cli->cli, service, strequal(service, "IPC$") ? "IPC" : 
135                 "?????", "", 1);
136
137         if (cli_is_error(cli->cli)) {
138                 PyErr_SetString(PyExc_RuntimeError, "tconx failed");
139                 return NULL;
140         }
141
142         return Py_BuildValue("i", result);
143 }
144
145 static PyObject *py_smb_nt_create_andx(PyObject *self, PyObject *args,
146                                        PyObject *kw)
147 {
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",
152                                   NULL };
153         char *filename;
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;
157         int result;
158
159         /* Parse parameters */
160
161         if (!PyArg_ParseTupleAndKeywords(
162                     args, kw, "si|iiii", kwlist, &filename, &desired_access,
163                     &file_attributes, &share_access, &create_disposition,
164                     &create_options))
165                 return NULL;
166
167         result = cli_nt_create_full(
168                 cli->cli, filename, 0, desired_access, file_attributes,
169                 share_access, create_disposition, create_options, 0);
170
171         if (cli_is_error(cli->cli)) {
172                 PyErr_SetString(PyExc_RuntimeError, "nt_create_andx failed");
173                 return NULL;
174         }
175
176         /* Return FID */
177
178         return PyInt_FromLong(result);
179 }
180
181 static PyObject *py_smb_open(PyObject *self, PyObject *args, PyObject *kw)
182 {
183         cli_state_object *cli = (cli_state_object *)self;
184         static char *kwlist[] = { "filename", "flags", 
185                                   "share_mode", NULL };
186         char *filename;
187         uint32 flags, share_mode = DENY_NONE;
188         int result;
189
190         /* Parse parameters */
191
192         if (!PyArg_ParseTupleAndKeywords(
193                     args, kw, "si|i", kwlist, &filename, &flags, &share_mode))
194                 return NULL;
195
196         result = cli_open(cli->cli, filename, flags, share_mode);
197
198         if (cli_is_error(cli->cli)) {
199                 PyErr_SetString(PyExc_RuntimeError, "open failed");
200                 return NULL;
201         }
202
203         /* Return FID */
204
205         return PyInt_FromLong(result);
206 }
207
208 static PyObject *py_smb_read(PyObject *self, PyObject *args, PyObject *kw)
209 {
210         cli_state_object *cli = (cli_state_object *)self;
211         static char *kwlist[] = { "fnum", "offset", "size", NULL };
212         int fnum, offset=0, size=0;
213         ssize_t result;
214         SMB_OFF_T fsize;
215         char *data;
216         PyObject *ret;
217
218         /* Parse parameters */
219
220         if (!PyArg_ParseTupleAndKeywords(
221                     args, kw, "i|ii", kwlist, &fnum, &offset, &size))
222                 return NULL;
223
224         if (!cli_qfileinfo(cli->cli, fnum, NULL, &fsize, NULL, NULL,
225                     NULL, NULL, NULL) &&
226             !cli_getattrE(cli->cli, fnum, NULL, &fsize, NULL, NULL, NULL)) {
227                 PyErr_SetString(PyExc_RuntimeError, "getattrib failed");
228                 return NULL;
229         }
230
231         if (offset < 0)
232                 offset = 0;
233
234         if (size < 1 || size > fsize - offset)
235                 size = fsize - offset;
236
237         if (!(data = SMB_XMALLOC_ARRAY(char, size))) {
238                 PyErr_SetString(PyExc_RuntimeError, "malloc failed");
239                 return NULL;
240         }
241
242         result = cli_read(cli->cli, fnum, data, (off_t) offset, (size_t) size);
243
244         if (result==-1 || cli_is_error(cli->cli)) {
245                 SAFE_FREE(data);
246                 PyErr_SetString(PyExc_RuntimeError, "read failed");
247                 return NULL;
248         }
249
250         /* Return a python string */
251
252         ret = Py_BuildValue("s#", data, result);
253         SAFE_FREE(data);
254
255         return ret;
256 }
257
258 static PyObject *py_smb_close(PyObject *self, PyObject *args,
259                               PyObject *kw)
260 {
261         cli_state_object *cli = (cli_state_object *)self;
262         static char *kwlist[] = { "fnum", NULL };
263         BOOL result;
264         int fnum;
265
266         /* Parse parameters */
267
268         if (!PyArg_ParseTupleAndKeywords(
269                     args, kw, "i", kwlist, &fnum))
270                 return NULL;
271
272         result = cli_close(cli->cli, fnum);
273
274         return PyInt_FromLong(result);
275 }
276
277 static PyObject *py_smb_unlink(PyObject *self, PyObject *args,
278                                PyObject *kw)
279 {
280         cli_state_object *cli = (cli_state_object *)self;
281         static char *kwlist[] = { "filename", NULL };
282         char *filename;
283         BOOL result;
284
285         /* Parse parameters */
286
287         if (!PyArg_ParseTupleAndKeywords(
288                     args, kw, "s", kwlist, &filename))
289                 return NULL;
290
291         result = cli_unlink(cli->cli, filename);
292
293         return PyInt_FromLong(result);
294 }
295
296 static PyObject *py_smb_query_secdesc(PyObject *self, PyObject *args,
297                                       PyObject *kw)
298 {
299         cli_state_object *cli = (cli_state_object *)self;
300         static char *kwlist[] = { "fnum", NULL };
301         PyObject *result = NULL;
302         SEC_DESC *secdesc = NULL;
303         int fnum;
304         TALLOC_CTX *mem_ctx = NULL;
305
306         /* Parse parameters */
307
308         if (!PyArg_ParseTupleAndKeywords(
309                     args, kw, "i", kwlist, &fnum))
310                 return NULL;
311
312         mem_ctx = talloc_init("py_smb_query_secdesc");
313
314         secdesc = cli_query_secdesc(cli->cli, fnum, mem_ctx);
315
316         if (cli_is_error(cli->cli)) {
317                 PyErr_SetString(PyExc_RuntimeError, "query_secdesc failed");
318                 goto done;
319         }
320
321         if (!secdesc) {
322                 Py_INCREF(Py_None);
323                 result = Py_None;
324                 goto done;
325         }
326
327         if (!py_from_SECDESC(&result, secdesc)) {
328                 PyErr_SetString(
329                         PyExc_TypeError,
330                         "Invalid security descriptor returned");
331                 goto done;
332         }
333
334  done:
335         talloc_destroy(mem_ctx);
336
337         return result;
338         
339 }
340
341 static PyObject *py_smb_set_secdesc(PyObject *self, PyObject *args,
342                                     PyObject *kw)
343 {
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;
348         SEC_DESC *secdesc;
349         TALLOC_CTX *mem_ctx = NULL;
350         int fnum;
351         BOOL err;
352
353         /* Parse parameters */
354
355         if (!PyArg_ParseTupleAndKeywords(
356                     args, kw, "iO", kwlist, &fnum, &py_secdesc))
357                 return NULL;
358
359         mem_ctx = talloc_init("py_smb_set_secdesc");
360
361         if (!py_to_SECDESC(&secdesc, py_secdesc, mem_ctx)) {
362                 PyErr_SetString(PyExc_TypeError, 
363                                 "Invalid security descriptor");
364                 goto done;
365         }
366
367         err = cli_set_secdesc(cli->cli, fnum, secdesc);
368
369         if (cli_is_error(cli->cli)) {
370                 PyErr_SetString(PyExc_RuntimeError, "set_secdesc failed");
371                 goto done;
372         }
373
374         result =  PyInt_FromLong(err);
375  done:
376         talloc_destroy(mem_ctx);
377
378         return result;
379 }
380
381 static PyMethodDef smb_hnd_methods[] = {
382
383         /* Session and connection handling */
384
385         { "session_request", (PyCFunction)py_smb_session_request, 
386           METH_VARARGS | METH_KEYWORDS, "Request a session" },
387
388         { "negprot", (PyCFunction)py_smb_negprot, 
389           METH_VARARGS | METH_KEYWORDS, "Protocol negotiation" },
390
391         { "session_setup", (PyCFunction)py_smb_session_setup,
392           METH_VARARGS | METH_KEYWORDS, "Session setup" },
393
394         { "tconx", (PyCFunction)py_smb_tconx,
395           METH_VARARGS | METH_KEYWORDS, "Tree connect" },
396
397         /* File operations */
398
399         { "nt_create_andx", (PyCFunction)py_smb_nt_create_andx,
400           METH_VARARGS | METH_KEYWORDS, "NT Create&X" },
401
402         { "open", (PyCFunction)py_smb_open,
403           METH_VARARGS | METH_KEYWORDS,
404           "Open a file\n"
405 "\n"
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"
409 "\n"
410 "Example:\n"
411 "\n"
412 ">>> fnum=conn.open(filename, os.O_RDONLY)" },
413
414         { "read", (PyCFunction)py_smb_read,
415           METH_VARARGS | METH_KEYWORDS,
416           "Read from an open file\n"
417 "\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"
421 "\n"
422 "Example:\n"
423 "\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" },
428
429         { "close", (PyCFunction)py_smb_close,
430           METH_VARARGS | METH_KEYWORDS, "Close" },
431
432         { "unlink", (PyCFunction)py_smb_unlink,
433           METH_VARARGS | METH_KEYWORDS, "Unlink" },
434
435         /* Security descriptors */
436
437         { "query_secdesc", (PyCFunction)py_smb_query_secdesc,
438           METH_VARARGS | METH_KEYWORDS, "Query security descriptor" },
439
440         { "set_secdesc", (PyCFunction)py_smb_set_secdesc,
441           METH_VARARGS | METH_KEYWORDS, "Set security descriptor" },
442
443         { NULL }
444 };
445
446 /*
447  * Method dispatch tables
448  */
449
450 static PyMethodDef smb_methods[] = {
451
452         { "connect", (PyCFunction)py_smb_connect, METH_VARARGS | METH_KEYWORDS,
453           "Connect to a host" },
454
455         /* Other stuff - this should really go into a samba config module
456            but for the moment let's leave it here. */
457
458         { "setup_logging", (PyCFunction)py_setup_logging, 
459           METH_VARARGS | METH_KEYWORDS, 
460           "Set up debug logging.\n"
461 "\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"
465 "\n"
466 "Example:\n"
467 "\n"
468 ">>> smb.setup_logging(interactive = 1)" },
469
470         { "get_debuglevel", (PyCFunction)get_debuglevel, 
471           METH_VARARGS, 
472           "Set the current debug level.\n"
473 "\n"
474 "Example:\n"
475 "\n"
476 ">>> smb.get_debuglevel()\n"
477 "0" },
478
479         { "set_debuglevel", (PyCFunction)set_debuglevel, 
480           METH_VARARGS, 
481           "Get the current debug level.\n"
482 "\n"
483 "Example:\n"
484 "\n"
485 ">>> smb.set_debuglevel(10)" },
486
487         { NULL }
488 };
489
490 static void py_cli_state_dealloc(PyObject* self)
491 {
492         cli_state_object *cli = (cli_state_object *)self;
493
494         if (cli->cli)
495                 cli_shutdown(cli->cli);
496
497         PyObject_Del(self);
498 }
499
500 static PyObject *py_cli_state_getattr(PyObject *self, char *attrname)
501 {
502         return Py_FindMethod(smb_hnd_methods, self, attrname);
503 }
504
505 PyTypeObject cli_state_type = {
506         PyObject_HEAD_INIT(NULL)
507         0,
508         "SMB client connection",
509         sizeof(cli_state_object),
510         0,
511         py_cli_state_dealloc, /*tp_dealloc*/
512         0,          /*tp_print*/
513         py_cli_state_getattr,          /*tp_getattr*/
514         0,          /*tp_setattr*/
515         0,          /*tp_compare*/
516         0,          /*tp_repr*/
517         0,          /*tp_as_number*/
518         0,          /*tp_as_sequence*/
519         0,          /*tp_as_mapping*/
520         0,          /*tp_hash */
521 };
522
523 /*
524  * Module initialisation 
525  */
526
527 void initsmb(void)
528 {
529         PyObject *module, *dict;
530
531         /* Initialise module */
532
533         module = Py_InitModule("smb", smb_methods);
534         dict = PyModule_GetDict(module);
535
536         /* Initialise policy handle object */
537
538         cli_state_type.ob_type = &PyType_Type;
539
540         /* Do samba initialisation */
541
542         py_samba_init();
543
544         setup_logging("smb", True);
545         DEBUGLEVEL = 3;
546 }