r25598: Add missing become_root/unbecome_root around calls of add_aliases.
[samba.git] / source / python / py_smb.c
index c206e6ba9b4934692fac951566dbed980e51b4c3..17b2a2d5aa13782b35f07e517089f7dea0a5f798 100644 (file)
@@ -5,7 +5,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "python/py_smb.h"
 
-/* 
- * Exceptions raised by this module 
- */
+/* Create a new cli_state python object */
+
+PyObject *new_cli_state_object(struct cli_state *cli)
+{
+       cli_state_object *o;
+
+       o = PyObject_New(cli_state_object, &cli_state_type);
+
+       o->cli = cli;
+
+       return (PyObject*)o;
+}
+
+static PyObject *py_smb_connect(PyObject *self, PyObject *args, PyObject *kw)
+{
+       static char *kwlist[] = { "server", NULL };
+       struct cli_state *cli;
+       char *server;
+       struct in_addr ip;
+
+       if (!PyArg_ParseTupleAndKeywords(args, kw, "s", kwlist, &server))
+               return NULL;
+
+       if (!(cli = cli_initialise()))
+               return NULL;
+
+       ZERO_STRUCT(ip);
+
+       if (!NT_STATUS_IS_OK(cli_connect(cli, server, &ip)))
+               return NULL;
+
+       return new_cli_state_object(cli);
+}
+
+static PyObject *py_smb_session_request(PyObject *self, PyObject *args,
+                                       PyObject *kw)
+{
+       cli_state_object *cli = (cli_state_object *)self;
+       static char *kwlist[] = { "called", "calling", NULL };
+       char *calling_name = NULL, *called_name;
+       struct nmb_name calling, called;
+       BOOL result;
+
+       if (!PyArg_ParseTupleAndKeywords(args, kw, "s|s", kwlist, &called_name, 
+                                        &calling_name))
+               return NULL;
+
+       if (!calling_name)
+               calling_name = global_myname();
+
+       make_nmb_name(&calling, calling_name, 0x00);
+       make_nmb_name(&called, called_name, 0x20);
+
+       result = cli_session_request(cli->cli, &calling, &called);
+
+       return Py_BuildValue("i", result);
+}
+                                     
+static PyObject *py_smb_negprot(PyObject *self, PyObject *args, PyObject *kw)
+{
+       cli_state_object *cli = (cli_state_object *)self;
+       static char *kwlist[] = { NULL };
+       BOOL result;
+
+       if (!PyArg_ParseTupleAndKeywords(args, kw, "", kwlist))
+               return NULL;
+
+       result = cli_negprot(cli->cli);
+
+       return Py_BuildValue("i", result);
+}
+
+static PyObject *py_smb_session_setup(PyObject *self, PyObject *args, 
+                                     PyObject *kw)
+{
+       cli_state_object *cli = (cli_state_object *)self;
+       static char *kwlist[] = { "creds", NULL };
+       PyObject *creds;
+       char *username, *domain, *password, *errstr;
+       NTSTATUS result;
+
+       if (!PyArg_ParseTupleAndKeywords(args, kw, "|O", kwlist, &creds))
+               return NULL;
+
+       if (!py_parse_creds(creds, &username, &domain, &password, &errstr)) {
+               free(errstr);
+               return NULL;
+       }
+
+       result = cli_session_setup(
+               cli->cli, username, password, strlen(password) + 1,
+               password, strlen(password) + 1, domain);
+
+       if (cli_is_error(cli->cli)) {
+               PyErr_SetString(PyExc_RuntimeError, "session setup failed");
+               return NULL;
+       }
+
+       return Py_BuildValue("i", NT_STATUS_IS_OK(result));
+}
+
+static PyObject *py_smb_tconx(PyObject *self, PyObject *args, PyObject *kw)
+{
+       cli_state_object *cli = (cli_state_object *)self;
+       static char *kwlist[] = { "service", NULL };
+       char *service;
+       BOOL result;
+
+       if (!PyArg_ParseTupleAndKeywords(args, kw, "s", kwlist, &service))
+               return NULL;
+
+       result = cli_send_tconX(
+               cli->cli, service, strequal(service, "IPC$") ? "IPC" : 
+               "?????", "", 1);
+
+       if (cli_is_error(cli->cli)) {
+               PyErr_SetString(PyExc_RuntimeError, "tconx failed");
+               return NULL;
+       }
+
+       return Py_BuildValue("i", result);
+}
+
+static PyObject *py_smb_nt_create_andx(PyObject *self, PyObject *args,
+                                      PyObject *kw)
+{
+       cli_state_object *cli = (cli_state_object *)self;
+       static char *kwlist[] = { "filename", "desired_access", 
+                                 "file_attributes", "share_access",
+                                 "create_disposition", "create_options",
+                                 NULL };
+       char *filename;
+       uint32 desired_access, file_attributes = 0, 
+               share_access = FILE_SHARE_READ | FILE_SHARE_WRITE,
+               create_disposition = OPENX_FILE_EXISTS_OPEN, create_options = 0;
+       int result;
+
+       /* Parse parameters */
+
+       if (!PyArg_ParseTupleAndKeywords(
+                   args, kw, "si|iiii", kwlist, &filename, &desired_access,
+                   &file_attributes, &share_access, &create_disposition,
+                   &create_options))
+               return NULL;
+
+       result = cli_nt_create_full(
+               cli->cli, filename, 0, desired_access, file_attributes,
+               share_access, create_disposition, create_options, 0);
+
+       if (cli_is_error(cli->cli)) {
+               PyErr_SetString(PyExc_RuntimeError, "nt_create_andx failed");
+               return NULL;
+       }
+
+       /* Return FID */
+
+       return PyInt_FromLong(result);
+}
+
+static PyObject *py_smb_open(PyObject *self, PyObject *args, PyObject *kw)
+{
+       cli_state_object *cli = (cli_state_object *)self;
+       static char *kwlist[] = { "filename", "flags", 
+                                 "share_mode", NULL };
+       char *filename;
+       uint32 flags, share_mode = DENY_NONE;
+       int result;
+
+       /* Parse parameters */
+
+       if (!PyArg_ParseTupleAndKeywords(
+                   args, kw, "si|i", kwlist, &filename, &flags, &share_mode))
+               return NULL;
+
+       result = cli_open(cli->cli, filename, flags, share_mode);
+
+       if (cli_is_error(cli->cli)) {
+               PyErr_SetString(PyExc_RuntimeError, "open failed");
+               return NULL;
+       }
+
+       /* Return FID */
+
+       return PyInt_FromLong(result);
+}
+
+static PyObject *py_smb_read(PyObject *self, PyObject *args, PyObject *kw)
+{
+       cli_state_object *cli = (cli_state_object *)self;
+       static char *kwlist[] = { "fnum", "offset", "size", NULL };
+       int fnum, offset=0, size=0;
+       ssize_t result;
+       SMB_OFF_T fsize;
+       char *data;
+       PyObject *ret;
+
+       /* Parse parameters */
+
+       if (!PyArg_ParseTupleAndKeywords(
+                   args, kw, "i|ii", kwlist, &fnum, &offset, &size))
+               return NULL;
+
+       if (!cli_qfileinfo(cli->cli, fnum, NULL, &fsize, NULL, NULL,
+                   NULL, NULL, NULL) &&
+           !cli_getattrE(cli->cli, fnum, NULL, &fsize, NULL, NULL, NULL)) {
+               PyErr_SetString(PyExc_RuntimeError, "getattrib failed");
+               return NULL;
+       }
+
+       if (offset < 0)
+               offset = 0;
+
+       if (size < 1 || size > fsize - offset)
+               size = fsize - offset;
+
+       if (!(data = SMB_XMALLOC_ARRAY(char, size))) {
+               PyErr_SetString(PyExc_RuntimeError, "malloc failed");
+               return NULL;
+       }
 
-PyObject *smb_ntstatus;                /* This exception is raised when a RPC call
-                                  returns a status code other than
-                                  NT_STATUS_OK */
+       result = cli_read(cli->cli, fnum, data, (off_t) offset, (size_t) size);
 
+       if (result==-1 || cli_is_error(cli->cli)) {
+               SAFE_FREE(data);
+               PyErr_SetString(PyExc_RuntimeError, "read failed");
+               return NULL;
+       }
+
+       /* Return a python string */
+
+       ret = Py_BuildValue("s#", data, result);
+       SAFE_FREE(data);
+
+       return ret;
+}
+
+static PyObject *py_smb_close(PyObject *self, PyObject *args,
+                             PyObject *kw)
+{
+       cli_state_object *cli = (cli_state_object *)self;
+       static char *kwlist[] = { "fnum", NULL };
+       BOOL result;
+       int fnum;
+
+       /* Parse parameters */
+
+       if (!PyArg_ParseTupleAndKeywords(
+                   args, kw, "i", kwlist, &fnum))
+               return NULL;
+
+       result = cli_close(cli->cli, fnum);
+
+       return PyInt_FromLong(result);
+}
+
+static PyObject *py_smb_unlink(PyObject *self, PyObject *args,
+                              PyObject *kw)
+{
+       cli_state_object *cli = (cli_state_object *)self;
+       static char *kwlist[] = { "filename", NULL };
+       char *filename;
+       BOOL result;
+
+       /* Parse parameters */
+
+       if (!PyArg_ParseTupleAndKeywords(
+                   args, kw, "s", kwlist, &filename))
+               return NULL;
+
+       result = cli_unlink(cli->cli, filename);
+
+       return PyInt_FromLong(result);
+}
+
+static PyObject *py_smb_query_secdesc(PyObject *self, PyObject *args,
+                                     PyObject *kw)
+{
+       cli_state_object *cli = (cli_state_object *)self;
+       static char *kwlist[] = { "fnum", NULL };
+       PyObject *result = NULL;
+       SEC_DESC *secdesc = NULL;
+       int fnum;
+       TALLOC_CTX *mem_ctx = NULL;
+
+       /* Parse parameters */
+
+       if (!PyArg_ParseTupleAndKeywords(
+                   args, kw, "i", kwlist, &fnum))
+               return NULL;
+
+       mem_ctx = talloc_init("py_smb_query_secdesc");
+
+       secdesc = cli_query_secdesc(cli->cli, fnum, mem_ctx);
+
+       if (cli_is_error(cli->cli)) {
+               PyErr_SetString(PyExc_RuntimeError, "query_secdesc failed");
+               goto done;
+       }
+
+       if (!secdesc) {
+               Py_INCREF(Py_None);
+               result = Py_None;
+               goto done;
+       }
+
+       if (!py_from_SECDESC(&result, secdesc)) {
+               PyErr_SetString(
+                       PyExc_TypeError,
+                       "Invalid security descriptor returned");
+               goto done;
+       }
+
+ done:
+       talloc_destroy(mem_ctx);
+
+       return result;
+       
+}
+
+static PyObject *py_smb_set_secdesc(PyObject *self, PyObject *args,
+                                   PyObject *kw)
+{
+       cli_state_object *cli = (cli_state_object *)self;
+       static char *kwlist[] = { "fnum", "security_descriptor", NULL };
+       PyObject *result = NULL;
+       PyObject *py_secdesc;
+       SEC_DESC *secdesc;
+       TALLOC_CTX *mem_ctx = NULL;
+       int fnum;
+       BOOL err;
+
+       /* Parse parameters */
+
+       if (!PyArg_ParseTupleAndKeywords(
+                   args, kw, "iO", kwlist, &fnum, &py_secdesc))
+               return NULL;
+
+       mem_ctx = talloc_init("py_smb_set_secdesc");
+
+       if (!py_to_SECDESC(&secdesc, py_secdesc, mem_ctx)) {
+               PyErr_SetString(PyExc_TypeError, 
+                               "Invalid security descriptor");
+               goto done;
+       }
+
+       err = cli_set_secdesc(cli->cli, fnum, secdesc);
+
+       if (cli_is_error(cli->cli)) {
+               PyErr_SetString(PyExc_RuntimeError, "set_secdesc failed");
+               goto done;
+       }
+
+       result =  PyInt_FromLong(err);
+ done:
+       talloc_destroy(mem_ctx);
+
+       return result;
+}
+
+static PyMethodDef smb_hnd_methods[] = {
+
+       /* Session and connection handling */
+
+       { "session_request", (PyCFunction)py_smb_session_request, 
+         METH_VARARGS | METH_KEYWORDS, "Request a session" },
+
+       { "negprot", (PyCFunction)py_smb_negprot, 
+         METH_VARARGS | METH_KEYWORDS, "Protocol negotiation" },
+
+       { "session_setup", (PyCFunction)py_smb_session_setup,
+         METH_VARARGS | METH_KEYWORDS, "Session setup" },
+
+       { "tconx", (PyCFunction)py_smb_tconx,
+         METH_VARARGS | METH_KEYWORDS, "Tree connect" },
+
+       /* File operations */
+
+       { "nt_create_andx", (PyCFunction)py_smb_nt_create_andx,
+         METH_VARARGS | METH_KEYWORDS, "NT Create&X" },
+
+       { "open", (PyCFunction)py_smb_open,
+         METH_VARARGS | METH_KEYWORDS,
+         "Open a file\n"
+"\n"
+"This function returns a fnum handle to an open file.  The file is\n"
+"opened with flags and optional share mode.  If unspecified, the\n"
+"default share mode is DENY_NONE\n"
+"\n"
+"Example:\n"
+"\n"
+">>> fnum=conn.open(filename, os.O_RDONLY)" },
+
+       { "read", (PyCFunction)py_smb_read,
+         METH_VARARGS | METH_KEYWORDS,
+         "Read from an open file\n"
+"\n"
+"This function returns a string read from an open file starting at\n"
+"offset for size bytes (until EOF is reached).  If unspecified, the\n"
+"default offset is 0, and default size is the remainder of the file.\n"
+"\n"
+"Example:\n"
+"\n"
+">>> conn.read(fnum)           # read entire file\n"
+">>> conn.read(fnum,5)         # read entire file from offset 5\n"
+">>> conn.read(fnum,size=64)   # read 64 bytes from start of file\n"
+">>> conn.read(fnum,4096,1024) # read 1024 bytes from offset 4096\n" },
+
+       { "close", (PyCFunction)py_smb_close,
+         METH_VARARGS | METH_KEYWORDS, "Close" },
+
+       { "unlink", (PyCFunction)py_smb_unlink,
+         METH_VARARGS | METH_KEYWORDS, "Unlink" },
+
+       /* Security descriptors */
+
+       { "query_secdesc", (PyCFunction)py_smb_query_secdesc,
+         METH_VARARGS | METH_KEYWORDS, "Query security descriptor" },
+
+       { "set_secdesc", (PyCFunction)py_smb_set_secdesc,
+         METH_VARARGS | METH_KEYWORDS, "Set security descriptor" },
+
+       { NULL }
+};
 
 /*
  * Method dispatch tables
  */
 
 static PyMethodDef smb_methods[] = {
-       { NULL }
-};
 
-/* Create a new cli_state python object */
+       { "connect", (PyCFunction)py_smb_connect, METH_VARARGS | METH_KEYWORDS,
+         "Connect to a host" },
 
-PyObject *new_cli_state_object(struct cli_state *cli)
-{
-       cli_state_object *o;
+       /* Other stuff - this should really go into a samba config module
+          but for the moment let's leave it here. */
 
-       o = PyObject_New(cli_state_object, &cli_state_type);
+       { "setup_logging", (PyCFunction)py_setup_logging, 
+         METH_VARARGS | METH_KEYWORDS, 
+         "Set up debug logging.\n"
+"\n"
+"Initialises Samba's debug logging system.  One argument is expected which\n"
+"is a boolean specifying whether debugging is interactive and sent to stdout\n"
+"or logged to a file.\n"
+"\n"
+"Example:\n"
+"\n"
+">>> smb.setup_logging(interactive = 1)" },
 
-       o->cli = cli;
+       { "get_debuglevel", (PyCFunction)get_debuglevel, 
+         METH_VARARGS, 
+         "Set the current debug level.\n"
+"\n"
+"Example:\n"
+"\n"
+">>> smb.get_debuglevel()\n"
+"0" },
 
-       return (PyObject*)o;
-}
+       { "set_debuglevel", (PyCFunction)set_debuglevel, 
+         METH_VARARGS, 
+         "Get the current debug level.\n"
+"\n"
+"Example:\n"
+"\n"
+">>> smb.set_debuglevel(10)" },
+
+       { NULL }
+};
 
 static void py_cli_state_dealloc(PyObject* self)
 {
+       cli_state_object *cli = (cli_state_object *)self;
+
+       if (cli->cli)
+               cli_shutdown(cli->cli);
+
        PyObject_Del(self);
 }
 
 static PyObject *py_cli_state_getattr(PyObject *self, char *attrname)
 {
-       return Py_FindMethod(smb_methods, self, attrname);
+       return Py_FindMethod(smb_hnd_methods, self, attrname);
 }
 
 PyTypeObject cli_state_type = {
@@ -91,9 +533,6 @@ void initsmb(void)
        module = Py_InitModule("smb", smb_methods);
        dict = PyModule_GetDict(module);
 
-       smb_ntstatus = PyErr_NewException("smb.ntstatus", NULL, NULL);
-       PyDict_SetItemString(dict, "ntstatus", smb_ntstatus);
-
        /* Initialise policy handle object */
 
        cli_state_type.ob_type = &PyType_Type;
@@ -103,5 +542,5 @@ void initsmb(void)
        py_samba_init();
 
        setup_logging("smb", True);
-       DEBUGLEVEL = 10;
+       DEBUGLEVEL = 3;
 }