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 2 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, write to the Free Software 18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19*/ 20 21#include "python/py_smb.h" 22 23/* Create a new cli_state python object */ 24 25PyObject *new_cli_state_object(struct cli_state *cli) 26{ 27 cli_state_object *o; 28 29 o = PyObject_New(cli_state_object, &cli_state_type); 30 31 o->cli = cli; 32 33 return (PyObject*)o; 34} 35 36static PyObject *py_smb_connect(PyObject *self, PyObject *args, PyObject *kw) 37{ 38 static char *kwlist[] = { "server", NULL }; 39 struct cli_state *cli; 40 char *server; 41 struct in_addr ip; 42 43 if (!PyArg_ParseTupleAndKeywords(args, kw, "s", kwlist, &server)) 44 return NULL; 45 46 if (!(cli = cli_initialise())) 47 return NULL; 48 49 ZERO_STRUCT(ip); 50 51 if (!cli_connect(cli, server, &ip)) 52 return NULL; 53 54 return new_cli_state_object(cli); 55} 56 57static PyObject *py_smb_session_request(PyObject *self, PyObject *args, 58 PyObject *kw) 59{ 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; 65 66 if (!PyArg_ParseTupleAndKeywords(args, kw, "s|s", kwlist, &called_name, 67 &calling_name)) 68 return NULL; 69 70 if (!calling_name) 71 calling_name = global_myname(); 72 73 make_nmb_name(&calling, calling_name, 0x00); 74 make_nmb_name(&called, called_name, 0x20); 75 76 result = cli_session_request(cli->cli, &calling, &called); 77 78 return Py_BuildValue("i", result); 79} 80 81static PyObject *py_smb_negprot(PyObject *self, PyObject *args, PyObject *kw) 82{ 83 cli_state_object *cli = (cli_state_object *)self; 84 static char *kwlist[] = { NULL }; 85 BOOL result; 86 87 if (!PyArg_ParseTupleAndKeywords(args, kw, "", kwlist)) 88 return NULL; 89 90 result = cli_negprot(cli->cli); 91 92 return Py_BuildValue("i", result); 93} 94 95static PyObject *py_smb_session_setup(PyObject *self, PyObject *args, 96 PyObject *kw) 97{ 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; 103 104 if (!PyArg_ParseTupleAndKeywords(args, kw, "|O", kwlist, &creds)) 105 return NULL; 106 107 if (!py_parse_creds(creds, &username, &domain, &password, &errstr)) { 108 free(errstr); 109 return NULL; 110 } 111 112 result = cli_session_setup( 113 cli->cli, username, password, strlen(password) + 1, 114 password, strlen(password) + 1, domain); 115 116 if (cli_is_error(cli->cli)) { 117 PyErr_SetString(PyExc_RuntimeError, "session setup failed"); 118 return NULL; 119 } 120 121 return Py_BuildValue("i", NT_STATUS_IS_OK(result)); 122} 123 124static PyObject *py_smb_tconx(PyObject *self, PyObject *args, PyObject *kw) 125{ 126 cli_state_object *cli = (cli_state_object *)self; 127 static char *kwlist[] = { "service", NULL }; 128 char *service; 129 BOOL result; 130 131 if (!PyArg_ParseTupleAndKeywords(args, kw, "s", kwlist, &service)) 132 return NULL; 133 134 result = cli_send_tconX( 135 cli->cli, service, strequal(service, "IPC$") ? "IPC" : 136 "?????", "", 1); 137 138 if (cli_is_error(cli->cli)) { 139 PyErr_SetString(PyExc_RuntimeError, "tconx failed"); 140 return NULL; 141 } 142 143 return Py_BuildValue("i", result); 144} 145 146static PyObject *py_smb_nt_create_andx(PyObject *self, PyObject *args, 147 PyObject *kw) 148{ 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; 159 160 /* Parse parameters */ 161 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; 167 168 result = cli_nt_create_full( 169 cli->cli, filename, 0, desired_access, file_attributes, 170 share_access, create_disposition, create_options, 0); 171 172 if (cli_is_error(cli->cli)) { 173 PyErr_SetString(PyExc_RuntimeError, "nt_create_andx failed"); 174 return NULL; 175 } 176 177 /* Return FID */ 178 179 return PyInt_FromLong(result); 180} 181 182static PyObject *py_smb_open(PyObject *self, PyObject *args, PyObject *kw) 183{ 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; 190 191 /* Parse parameters */ 192 193 if (!PyArg_ParseTupleAndKeywords( 194 args, kw, "si|i", kwlist, &filename, &flags, &share_mode)) 195 return NULL; 196 197 result = cli_open(cli->cli, filename, flags, share_mode); 198 199 if (cli_is_error(cli->cli)) { 200 PyErr_SetString(PyExc_RuntimeError, "open failed"); 201 return NULL; 202 } 203 204 /* Return FID */ 205 206 return PyInt_FromLong(result); 207} 208 209static PyObject *py_smb_read(PyObject *self, PyObject *args, PyObject *kw) 210{ 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; 218 219 /* Parse parameters */ 220 221 if (!PyArg_ParseTupleAndKeywords( 222 args, kw, "i|ii", kwlist, &fnum, &offset, &size)) 223 return NULL; 224 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; 230 } 231 232 if (offset < 0) 233 offset = 0; 234 235 if (size < 1 || size > fsize - offset) 236 size = fsize - offset; 237 238 if (!(data = SMB_XMALLOC_ARRAY(char, size))) { 239 PyErr_SetString(PyExc_RuntimeError, "malloc failed"); 240 return NULL; 241 } 242 243 result = cli_read(cli->cli, fnum, data, (off_t) offset, (size_t) size); 244 245 if (result==-1 || cli_is_error(cli->cli)) { 246 SAFE_FREE(data); 247 PyErr_SetString(PyExc_RuntimeError, "read failed"); 248 return NULL; 249 } 250 251 /* Return a python string */ 252 253 ret = Py_BuildValue("s#", data, result); 254 SAFE_FREE(data); 255 256 return ret; 257} 258 259static PyObject *py_smb_close(PyObject *self, PyObject *args, 260 PyObject *kw) 261{ 262 cli_state_object *cli = (cli_state_object *)self; 263 static char *kwlist[] = { "fnum", NULL }; 264 BOOL result; 265 int fnum; 266 267 /* Parse parameters */ 268 269 if (!PyArg_ParseTupleAndKeywords( 270 args, kw, "i", kwlist, &fnum)) 271 return NULL; 272 273 result = cli_close(cli->cli, fnum); 274 275 return PyInt_FromLong(result); 276} 277 278static PyObject *py_smb_unlink(PyObject *self, PyObject *args, 279 PyObject *kw) 280{ 281 cli_state_object *cli = (cli_state_object *)self; 282 static char *kwlist[] = { "filename", NULL }; 283 char *filename; 284 BOOL result; 285 286 /* Parse parameters */ 287 288 if (!PyArg_ParseTupleAndKeywords( 289 args, kw, "s", kwlist, &filename)) 290 return NULL; 291 292 result = cli_unlink(cli->cli, filename); 293 294 return PyInt_FromLong(result); 295} 296 297static PyObject *py_smb_query_secdesc(PyObject *self, PyObject *args, 298 PyObject *kw) 299{ 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; 306 307 /* Parse parameters */ 308 309 if (!PyArg_ParseTupleAndKeywords( 310 args, kw, "i", kwlist, &fnum)) 311 return NULL; 312 313 mem_ctx = talloc_init("py_smb_query_secdesc"); 314 315 secdesc = cli_query_secdesc(cli->cli, fnum, mem_ctx); 316 317 if (cli_is_error(cli->cli)) { 318 PyErr_SetString(PyExc_RuntimeError, "query_secdesc failed"); 319 goto done; 320 } 321 322 if (!secdesc) { 323 Py_INCREF(Py_None); 324 result = Py_None; 325 goto done; 326 } 327 328 if (!py_from_SECDESC(&result, secdesc)) { 329 PyErr_SetString( 330 PyExc_TypeError, 331 "Invalid security descriptor returned"); 332 goto done; 333 } 334 335 done: 336 talloc_destroy(mem_ctx); 337 338 return result; 339 340} 341 342static PyObject *py_smb_set_secdesc(PyObject *self, PyObject *args, 343 PyObject *kw) 344{ 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; 353 354 /* Parse parameters */ 355 356 if (!PyArg_ParseTupleAndKeywords( 357 args, kw, "iO", kwlist, &fnum, &py_secdesc)) 358 return NULL; 359 360 mem_ctx = talloc_init("py_smb_set_secdesc"); 361 362 if (!py_to_SECDESC(&secdesc, py_secdesc, mem_ctx)) { 363 PyErr_SetString(PyExc_TypeError, 364 "Invalid security descriptor"); 365 goto done; 366 } 367 368 err = cli_set_secdesc(cli->cli, fnum, secdesc); 369 370 if (cli_is_error(cli->cli)) { 371 PyErr_SetString(PyExc_RuntimeError, "set_secdesc failed"); 372 goto done; 373 } 374 375 result = PyInt_FromLong(err); 376 done: 377 talloc_destroy(mem_ctx); 378 379 return result; 380} 381 382static PyMethodDef smb_hnd_methods[] = { 383 384 /* Session and connection handling */ 385 386 { "session_request", (PyCFunction)py_smb_session_request, 387 METH_VARARGS | METH_KEYWORDS, "Request a session" }, 388 389 { "negprot", (PyCFunction)py_smb_negprot, 390 METH_VARARGS | METH_KEYWORDS, "Protocol negotiation" }, 391 392 { "session_setup", (PyCFunction)py_smb_session_setup, 393 METH_VARARGS | METH_KEYWORDS, "Session setup" }, 394 395 { "tconx", (PyCFunction)py_smb_tconx, 396 METH_VARARGS | METH_KEYWORDS, "Tree connect" }, 397 398 /* File operations */ 399 400 { "nt_create_andx", (PyCFunction)py_smb_nt_create_andx, 401 METH_VARARGS | METH_KEYWORDS, "NT Create&X" }, 402 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)" }, 414 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" }, 429 430 { "close", (PyCFunction)py_smb_close, 431 METH_VARARGS | METH_KEYWORDS, "Close" }, 432 433 { "unlink", (PyCFunction)py_smb_unlink, 434 METH_VARARGS | METH_KEYWORDS, "Unlink" }, 435 436 /* Security descriptors */ 437 438 { "query_secdesc", (PyCFunction)py_smb_query_secdesc, 439 METH_VARARGS | METH_KEYWORDS, "Query security descriptor" }, 440 441 { "set_secdesc", (PyCFunction)py_smb_set_secdesc, 442 METH_VARARGS | METH_KEYWORDS, "Set security descriptor" }, 443 444 { NULL } 445}; 446 447/* 448 * Method dispatch tables 449 */ 450 451static PyMethodDef smb_methods[] = { 452 453 { "connect", (PyCFunction)py_smb_connect, METH_VARARGS | METH_KEYWORDS, 454 "Connect to a host" }, 455 456 /* Other stuff - this should really go into a samba config module 457 but for the moment let's leave it here. */ 458 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)" }, 470 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" }, 479 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)" }, 487 488 { NULL } 489}; 490 491static void py_cli_state_dealloc(PyObject* self) 492{ 493 cli_state_object *cli = (cli_state_object *)self; 494 495 if (cli->cli) 496 cli_shutdown(cli->cli); 497 498 PyObject_Del(self); 499} 500 501static PyObject *py_cli_state_getattr(PyObject *self, char *attrname) 502{ 503 return Py_FindMethod(smb_hnd_methods, self, attrname); 504} 505 506PyTypeObject cli_state_type = { 507 PyObject_HEAD_INIT(NULL) 508 0, 509 "SMB client connection", 510 sizeof(cli_state_object), 511 0, 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 */ 522}; 523 524/* 525 * Module initialisation 526 */ 527 528void initsmb(void) 529{ 530 PyObject *module, *dict; 531 532 /* Initialise module */ 533 534 module = Py_InitModule("smb", smb_methods); 535 dict = PyModule_GetDict(module); 536 537 /* Initialise policy handle object */ 538 539 cli_state_type.ob_type = &PyType_Type; 540 541 /* Do samba initialisation */ 542 543 py_samba_init(); 544 545 setup_logging("smb", True); 546 DEBUGLEVEL = 3; 547} 548