*/
#include <Python.h>
+#include "python/py3compat.h"
#include <tevent.h>
#include <pytalloc.h>
#include "includes.h"
#include "libcli/security/security_descriptor.h"
#include "librpc/rpc/pyrpc_util.h"
-#ifndef Py_RETURN_NONE
-#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
-#endif
-
-staticforward PyTypeObject PySMB;
+static PyTypeObject PySMB;
void initsmb(void);
* Connect to SMB share using smb_full_connection
*/
static NTSTATUS do_smb_connect(TALLOC_CTX *mem_ctx, struct smb_private_data *spdata,
- const char *hostname, const char *service, struct smbcli_tree **tree)
+ const char *hostname, const char *service,
+ struct smbcli_options *options,
+ struct smbcli_session_options *session_options,
+ struct smbcli_tree **tree)
{
struct smbcli_state *smb_state;
NTSTATUS status;
- struct smbcli_options options;
- struct smbcli_session_options session_options;
*tree = NULL;
smb_state = smbcli_state_init(mem_ctx);
- lpcfg_smbcli_options(spdata->lp_ctx, &options);
- lpcfg_smbcli_session_options(spdata->lp_ctx, &session_options);
-
status = smbcli_full_connection(mem_ctx, &smb_state, hostname,
lpcfg_smb_ports(spdata->lp_ctx),
service,
spdata->creds,
lpcfg_resolve_context(spdata->lp_ctx),
spdata->ev_ctx,
- &options,
- &session_options,
+ options,
+ session_options,
lpcfg_gensec_settings(mem_ctx, spdata->lp_ctx));
if (NT_STATUS_IS_OK(status)) {
/*
* Read SMB file and return the contents of the file as python string
*/
-static PyObject * py_smb_loadfile(pytalloc_Object *self, PyObject *args)
+static PyObject * py_smb_loadfile(PyObject *self, PyObject *args)
{
struct smb_composite_loadfile io;
const char *filename;
io.in.fname = filename;
- spdata = self->ptr;
- status = smb_composite_loadfile(spdata->tree, self->talloc_ctx, &io);
+ spdata = pytalloc_get_ptr(self);
+ status = smb_composite_loadfile(spdata->tree, pytalloc_get_mem_ctx(self), &io);
PyErr_NTSTATUS_IS_ERR_RAISE(status);
- return Py_BuildValue("s#", io.out.data, io.out.size);
+ return Py_BuildValue(PYARG_BYTES_LEN, io.out.data, io.out.size);
}
/*
* Create a SMB file with given string as the contents
*/
-static PyObject * py_smb_savefile(pytalloc_Object *self, PyObject *args)
+static PyObject * py_smb_savefile(PyObject *self, PyObject *args)
{
struct smb_composite_savefile io;
const char *filename;
- char *data;
+ char *data = NULL;
+ Py_ssize_t size = 0;
NTSTATUS status;
struct smb_private_data *spdata;
- if (!PyArg_ParseTuple(args, "ss:savefile", &filename, &data)) {
+ if (!PyArg_ParseTuple(args, "s"PYARG_BYTES_LEN":savefile", &filename, &data, &size )) {
return NULL;
}
io.in.fname = filename;
io.in.data = (unsigned char *)data;
- io.in.size = strlen(data);
+ io.in.size = size;
- spdata = self->ptr;
+ spdata = pytalloc_get_ptr(self);
status = smb_composite_savefile(spdata->tree, &io);
PyErr_NTSTATUS_IS_ERR_RAISE(status);
dict = PyDict_New();
if(dict) {
- PyDict_SetItemString(dict, "name", PyString_FromString(f->name));
+ PyDict_SetItemString(dict, "name", PyStr_FromString(f->name));
/* Windows does not always return short_name */
if (f->short_name) {
- PyDict_SetItemString(dict, "short_name", PyString_FromString(f->short_name));
+ PyDict_SetItemString(dict, "short_name", PyStr_FromString(f->short_name));
} else {
PyDict_SetItemString(dict, "short_name", Py_None);
}
/*
* List the directory contents for specified directory (Ignore '.' and '..' dirs)
*/
-static PyObject *py_smb_list(pytalloc_Object *self, PyObject *args, PyObject *kwargs)
+static PyObject *py_smb_list(PyObject *self, PyObject *args, PyObject *kwargs)
{
struct smb_private_data *spdata;
PyObject *py_dirlist;
}
if (user_mask == NULL) {
- mask = talloc_asprintf(self->talloc_ctx, "%s\\*", base_dir);
+ mask = talloc_asprintf(pytalloc_get_mem_ctx(self), "%s\\*", base_dir);
} else {
- mask = talloc_asprintf(self->talloc_ctx, "%s\\%s", base_dir, user_mask);
+ mask = talloc_asprintf(pytalloc_get_mem_ctx(self), "%s\\%s", base_dir, user_mask);
}
dos_format(mask);
- spdata = self->ptr;
+ spdata = pytalloc_get_ptr(self);
if((py_dirlist = PyList_New(0)) == NULL) {
PyErr_NoMemory();
/*
* Create a directory
*/
-static PyObject *py_smb_mkdir(pytalloc_Object *self, PyObject *args)
+static PyObject *py_smb_mkdir(PyObject *self, PyObject *args)
{
NTSTATUS status;
const char *dirname;
return NULL;
}
- spdata = self->ptr;
+ spdata = pytalloc_get_ptr(self);
status = smbcli_mkdir(spdata->tree, dirname);
PyErr_NTSTATUS_IS_ERR_RAISE(status);
/*
* Remove a directory
*/
-static PyObject *py_smb_rmdir(pytalloc_Object *self, PyObject *args)
+static PyObject *py_smb_rmdir(PyObject *self, PyObject *args)
{
NTSTATUS status;
const char *dirname;
return NULL;
}
- spdata = self->ptr;
+ spdata = pytalloc_get_ptr(self);
status = smbcli_rmdir(spdata->tree, dirname);
PyErr_NTSTATUS_IS_ERR_RAISE(status);
Py_RETURN_NONE;
}
+/*
+ * Remove a directory and all its contents
+ */
+static PyObject *py_smb_deltree(PyObject *self, PyObject *args)
+{
+ int status;
+ const char *dirname;
+ struct smb_private_data *spdata;
+
+ if (!PyArg_ParseTuple(args, "s:deltree", &dirname)) {
+ return NULL;
+ }
+
+ spdata = pytalloc_get_ptr(self);
+ status = smbcli_deltree(spdata->tree, dirname);
+ if (status <= 0) {
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
/*
* Check existence of a path
*/
-static PyObject *py_smb_chkpath(pytalloc_Object *self, PyObject *args)
+static PyObject *py_smb_chkpath(PyObject *self, PyObject *args)
{
NTSTATUS status;
const char *path;
return NULL;
}
- spdata = self->ptr;
+ spdata = pytalloc_get_ptr(self);
status = smbcli_chkpath(spdata->tree, path);
if (NT_STATUS_IS_OK(status)) {
/*
* Read ACL on a given file/directory as a security descriptor object
*/
-static PyObject *py_smb_getacl(pytalloc_Object *self, PyObject *args, PyObject *kwargs)
+static PyObject *py_smb_getacl(PyObject *self, PyObject *args, PyObject *kwargs)
{
NTSTATUS status;
union smb_open io;
union smb_fileinfo fio;
struct smb_private_data *spdata;
const char *filename;
- int sinfo = 0;
+ uint32_t sinfo = 0;
+ int access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
int fnum;
- if (!PyArg_ParseTuple(args, "s|i:get_acl", &filename, &sinfo)) {
+ if (!PyArg_ParseTuple(args, "s|Ii:get_acl", &filename, &sinfo, &access_mask)) {
return NULL;
}
ZERO_STRUCT(io);
- spdata = self->ptr;
+ spdata = pytalloc_get_ptr(self);
io.generic.level = RAW_OPEN_NTCREATEX;
io.ntcreatex.in.root_fid.fnum = 0;
io.ntcreatex.in.flags = 0;
- io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ io.ntcreatex.in.access_mask = access_mask;
io.ntcreatex.in.create_options = 0;
io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
io.ntcreatex.in.security_flags = 0;
io.ntcreatex.in.fname = filename;
- status = smb_raw_open(spdata->tree, self->talloc_ctx, &io);
+ status = smb_raw_open(spdata->tree, pytalloc_get_mem_ctx(self), &io);
PyErr_NTSTATUS_IS_ERR_RAISE(status);
fnum = io.ntcreatex.out.file.fnum;
SECINFO_PROTECTED_SACL |
SECINFO_UNPROTECTED_SACL;
- status = smb_raw_query_secdesc(spdata->tree, self->talloc_ctx, &fio);
+ status = smb_raw_query_secdesc(spdata->tree, pytalloc_get_mem_ctx(self), &fio);
smbcli_close(spdata->tree, fnum);
PyErr_NTSTATUS_IS_ERR_RAISE(status);
return py_return_ndr_struct("samba.dcerpc.security", "descriptor",
- self->talloc_ctx, fio.query_secdesc.out.sd);
+ pytalloc_get_mem_ctx(self), fio.query_secdesc.out.sd);
}
/*
* Set ACL on file/directory using given security descriptor object
*/
-static PyObject *py_smb_setacl(pytalloc_Object *self, PyObject *args, PyObject *kwargs)
+static PyObject *py_smb_setacl(PyObject *self, PyObject *args, PyObject *kwargs)
{
NTSTATUS status;
union smb_open io;
return NULL;
}
- spdata = self->ptr;
+ spdata = pytalloc_get_ptr(self);
sd = pytalloc_get_type(py_sd, struct security_descriptor);
if (!sd) {
ZERO_STRUCT(io);
- spdata = self->ptr;
+ spdata = pytalloc_get_ptr(self);
io.generic.level = RAW_OPEN_NTCREATEX;
io.ntcreatex.in.root_fid.fnum = 0;
io.ntcreatex.in.security_flags = 0;
io.ntcreatex.in.fname = filename;
- status = smb_raw_open(spdata->tree, self->talloc_ctx, &io);
+ status = smb_raw_open(spdata->tree, pytalloc_get_mem_ctx(self), &io);
PyErr_NTSTATUS_IS_ERR_RAISE(status);
fnum = io.ntcreatex.out.file.fnum;
/*
* Open the file with the parameters passed in and return an object if OK
*/
-static PyObject *py_open_file(pytalloc_Object *self, PyObject *args, PyObject *kwargs)
+static PyObject *py_open_file(PyObject *self, PyObject *args, PyObject *kwargs)
{
NTSTATUS status;
union smb_open io;
ZERO_STRUCT(io);
- spdata = self->ptr;
+ spdata = pytalloc_get_ptr(self);
mem_ctx = talloc_new(NULL);
/*
* Close the file based on the fnum passed in
*/
-static PyObject *py_close_file(pytalloc_Object *self, PyObject *args, PyObject *kwargs)
+static PyObject *py_close_file(PyObject *self, PyObject *args, PyObject *kwargs)
{
struct smb_private_data *spdata;
int fnum;
return NULL;
}
- spdata = self->ptr;
+ spdata = pytalloc_get_ptr(self);
/*
* Should check the status ...
}
static PyMethodDef py_smb_methods[] = {
- { "loadfile", (PyCFunction)py_smb_loadfile, METH_VARARGS,
- "loadfile(path) -> file contents as a string\n\n \
- Read contents of a file." },
- { "savefile", (PyCFunction)py_smb_savefile, METH_VARARGS,
- "savefile(path, str) -> None\n\n \
- Write string str to file." },
+ { "loadfile", py_smb_loadfile, METH_VARARGS,
+ "loadfile(path) -> file contents as a "
+ PY_DESC_PY3_BYTES
+ "\n\n Read contents of a file." },
+ { "savefile", py_smb_savefile, METH_VARARGS,
+ "savefile(path, str) -> None\n\n Write "
+ PY_DESC_PY3_BYTES
+ " str to file." },
{ "list", (PyCFunction)py_smb_list, METH_VARARGS|METH_KEYWORDS,
- "list(path) -> directory contents as a dictionary\n\n \
+ "list(path, access_mask='*', attribs=DEFAULT_ATTRS) -> \
+directory contents as a dictionary\n \
+ DEFAULT_ATTRS: FILE_ATTRIBUTE_SYSTEM | \
+FILE_ATTRIBUTE_DIRECTORY | \
+FILE_ATTRIBUTE_ARCHIVE\n\n \
List contents of a directory. The keys are, \n \
\tname: Long name of the directory item\n \
\tshort_name: Short name of the directory item\n \
\tsize: File size in bytes\n \
\tattrib: Attributes\n \
\tmtime: Modification time\n" },
- { "mkdir", (PyCFunction)py_smb_mkdir, METH_VARARGS,
+ { "mkdir", py_smb_mkdir, METH_VARARGS,
"mkdir(path) -> None\n\n \
Create a directory." },
- { "rmdir", (PyCFunction)py_smb_rmdir, METH_VARARGS,
+ { "rmdir", py_smb_rmdir, METH_VARARGS,
"rmdir(path) -> None\n\n \
Delete a directory." },
- { "chkpath", (PyCFunction)py_smb_chkpath, METH_VARARGS,
+ { "deltree", py_smb_deltree, METH_VARARGS,
+ "deltree(path) -> None\n\n \
+ Delete a directory and all its contents." },
+ { "chkpath", py_smb_chkpath, METH_VARARGS,
"chkpath(path) -> True or False\n\n \
Return true if path exists, false otherwise." },
{ "get_acl", (PyCFunction)py_smb_getacl, METH_VARARGS,
{
PyObject *py_creds = Py_None;
PyObject *py_lp = Py_None;
- const char *kwnames[] = { "hostname", "service", "creds", "lp", NULL };
+ const char *kwnames[] = { "hostname", "service", "creds", "lp",
+ "ntlmv2_auth", "use_spnego", NULL };
const char *hostname = NULL;
const char *service = NULL;
- pytalloc_Object *smb;
+ PyObject *smb;
struct smb_private_data *spdata;
NTSTATUS status;
+ TALLOC_CTX *frame = NULL;
+ struct smbcli_options options;
+ struct smbcli_session_options session_options;
+ uint8_t ntlmv2_auth = 0xFF;
+ uint8_t use_spnego = 0xFF;
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "zz|OO",
- discard_const_p(char *, kwnames),
- &hostname, &service, &py_creds, &py_lp)) {
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "zz|OObb",
+ discard_const_p(char *, kwnames),
+ &hostname, &service, &py_creds, &py_lp,
+ &ntlmv2_auth, &use_spnego)) {
return NULL;
}
- smb = (pytalloc_Object *)type->tp_alloc(type, 0);
- if (smb == NULL) {
- PyErr_NoMemory();
- return NULL;
- }
- smb->talloc_ctx = talloc_new(NULL);
- if (smb->talloc_ctx == NULL) {
- PyErr_NoMemory();
- return NULL;
- }
+ frame = talloc_stackframe();
- spdata = talloc_zero(smb->talloc_ctx, struct smb_private_data);
+ spdata = talloc_zero(frame, struct smb_private_data);
if (spdata == NULL) {
PyErr_NoMemory();
- Py_DECREF(smb);
+ TALLOC_FREE(frame);
return NULL;
}
- spdata->lp_ctx = lpcfg_from_py_object(smb->talloc_ctx, py_lp);
+ spdata->lp_ctx = lpcfg_from_py_object(spdata, py_lp);
if (spdata->lp_ctx == NULL) {
- Py_DECREF(smb);
+ PyErr_SetString(PyExc_TypeError, "Expected loadparm context");
+ TALLOC_FREE(frame);
+ return NULL;
+ }
+
+ spdata->creds = cli_credentials_from_py_object(py_creds);
+ if (spdata->creds == NULL) {
+ PyErr_SetString(PyExc_TypeError, "Expected credentials");
+ TALLOC_FREE(frame);
return NULL;
}
- spdata->creds = PyCredentials_AsCliCredentials(py_creds);
- spdata->ev_ctx = s4_event_context_init(smb->talloc_ctx);
+ spdata->ev_ctx = s4_event_context_init(spdata);
if (spdata->ev_ctx == NULL) {
PyErr_NoMemory();
- Py_DECREF(smb);
+ TALLOC_FREE(frame);
return NULL;
}
- status = do_smb_connect(smb->talloc_ctx, spdata, hostname, service, &spdata->tree);
+ lpcfg_smbcli_options(spdata->lp_ctx, &options);
+ lpcfg_smbcli_session_options(spdata->lp_ctx, &session_options);
+
+ if (ntlmv2_auth != 0xFF) {
+ session_options.ntlmv2_auth = ntlmv2_auth;
+ }
+ if (use_spnego != 0xFF) {
+ options.use_spnego = use_spnego;
+ }
+
+ status = do_smb_connect(spdata, spdata, hostname, service,
+ &options,
+ &session_options,
+ &spdata->tree);
PyErr_NTSTATUS_IS_ERR_RAISE(status);
if (spdata->tree == NULL) {
- Py_DECREF(smb);
+ TALLOC_FREE(frame);
return NULL;
}
- smb->ptr = spdata;
- return (PyObject *)smb;
+ smb = pytalloc_steal(type, spdata);
+ TALLOC_FREE(frame);
+ return smb;
}
static PyTypeObject PySMB = {
.tp_name = "smb.SMB",
- .tp_basicsize = sizeof(pytalloc_Object),
.tp_new = py_smb_new,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_methods = py_smb_methods,
};
-void initsmb(void)
-{
- PyObject *m;
- PyTypeObject *talloc_type = pytalloc_GetObjectType();
- if (talloc_type == NULL) {
- return;
- }
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ .m_name = "smb",
+ .m_doc = "SMB File I/O support",
+ .m_size = -1,
+ .m_methods = NULL,
+};
- PySMB.tp_base = talloc_type;
+void initsmb(void);
+
+MODULE_INIT_FUNC(smb)
+{
+ PyObject *m = NULL;
- if (PyType_Ready(&PySMB) < 0) {
- return;
+ if (pytalloc_BaseObject_PyType_Ready(&PySMB) < 0) {
+ return m;
}
- m = Py_InitModule3("smb", NULL, "SMB File I/O support");
+ m = PyModule_Create(&moduledef);
if (m == NULL) {
- return;
+ return m;
}
Py_INCREF(&PySMB);
ADD_FLAGS(FILE_ATTRIBUTE_NONINDEXED);
ADD_FLAGS(FILE_ATTRIBUTE_ENCRYPTED);
ADD_FLAGS(FILE_ATTRIBUTE_ALL_MASK);
+ return m;
}