#include "python/modules.h"
#include "libcli/smb/smbXcli_base.h"
#include "libcli/smb/smb2_negotiate_context.h"
-#include "libcli/smb/reparse_symlink.h"
+#include "libcli/smb/reparse.h"
#include "libsmb/libsmb.h"
#include "libcli/security/security.h"
#include "system/select.h"
PyObject *v = NULL;
v = Py_BuildValue(
- "{sLsLsLsLsLsLsLsLsL}",
+ "{sLsLsLsLsLsLsLsLsLsL}",
"oplock_level",
(unsigned long long)r->oplock_level,
+ "flags",
+ (unsigned long long)r->flags,
"create_action",
(unsigned long long)r->create_action,
"creation_time",
}
if (smbXcli_conn_protocol(self->cli->conn) >= PROTOCOL_SMB2_02) {
+ struct cli_smb2_create_flags cflags = {
+ .batch_oplock = (CreateFlags & REQUEST_BATCH_OPLOCK),
+ .exclusive_oplock = (CreateFlags & REQUEST_OPLOCK),
+ };
+
req = cli_smb2_create_fnum_send(
NULL,
self->ev,
self->cli,
fname,
- CreateFlags,
+ cflags,
ImpersonationLevel,
DesiredAccess,
FileAttributes,
goto nomem;
}
- v = PyTuple_New(3);
- if (v == NULL) {
- goto nomem;
- }
- ret = PyTuple_SetItem(v, 0, Py_BuildValue("I", (unsigned)fnum));
- if (ret == -1) {
- status = NT_STATUS_INTERNAL_ERROR;
- goto fail;
- }
- ret = PyTuple_SetItem(v, 1, py_cr);
- if (ret == -1) {
- status = NT_STATUS_INTERNAL_ERROR;
- goto fail;
- }
- ret = PyTuple_SetItem(v, 2, py_create_contexts_out);
- if (ret == -1) {
- status = NT_STATUS_INTERNAL_ERROR;
- goto fail;
- }
-
+ v = Py_BuildValue("(IOO)",
+ (unsigned)fnum,
+ py_cr,
+ py_create_contexts_out);
return v;
nomem:
status = NT_STATUS_NO_MEMORY;
{
struct tevent_req *req;
int fnum;
+ int flags = 0;
NTSTATUS status;
- if (!PyArg_ParseTuple(args, "i", &fnum)) {
+ if (!PyArg_ParseTuple(args, "i|i", &fnum, &flags)) {
return NULL;
}
- req = cli_close_send(NULL, self->ev, self->cli, fnum);
+ req = cli_close_send(NULL, self->ev, self->cli, fnum, flags);
if (!py_tevent_req_wait_exc(self, req)) {
return NULL;
}
PyErr_NTSTATUS_NOT_OK_RAISE(status);
/* close the file handle */
- req = cli_close_send(NULL, self->ev, self->cli, fnum);
+ req = cli_close_send(NULL, self->ev, self->cli, fnum, 0);
if (!py_tevent_req_wait_exc(self, req)) {
return NULL;
}
}
/* close the file handle */
- req = cli_close_send(NULL, self->ev, self->cli, fnum);
+ req = cli_close_send(NULL, self->ev, self->cli, fnum, 0);
if (!py_tevent_req_wait_exc(self, req)) {
Py_XDECREF(result);
return NULL;
static void py_cli_notify_state_dealloc(struct py_cli_notify_state *self)
{
TALLOC_FREE(self->req);
- if (self->py_cli_state != NULL) {
- Py_DECREF(self->py_cli_state);
- self->py_cli_state = NULL;
- }
+ Py_CLEAR(self->py_cli_state);
Py_TYPE(self)->tp_free(self);
}
ok = py_tevent_req_wait_exc(py_cli_state, req);
self->req = NULL;
- Py_DECREF(self->py_cli_state);
- self->py_cli_state = NULL;
+ Py_CLEAR(self->py_cli_state);
if (!ok) {
return NULL;
}
.tp_methods = py_cli_notify_state_methods,
};
+/*
+ * Helper to add posix directory listing entries to an overall Python list
+ */
+static NTSTATUS list_posix_helper(struct file_info *finfo,
+ const char *mask, void *state)
+{
+ PyObject *result = (PyObject *)state;
+ PyObject *file = NULL;
+ PyObject *size = NULL;
+ int ret;
+
+ size = PyLong_FromUnsignedLongLong(finfo->size);
+ /*
+ * Build a dictionary representing the file info.
+ * Note: Windows does not always return short_name (so it may be None)
+ */
+ file = Py_BuildValue("{s:s,s:i,s:s,s:O,s:l,s:i,s:i,s:i,s:s,s:s}",
+ "name", finfo->name,
+ "attrib", (int)finfo->attr,
+ "short_name", finfo->short_name,
+ "size", size,
+ "mtime",
+ convert_timespec_to_time_t(finfo->mtime_ts),
+ "perms", finfo->st_ex_mode,
+ "ino", finfo->ino,
+ "dev", finfo->st_ex_dev,
+ "owner_sid",
+ dom_sid_string(finfo, &finfo->owner_sid),
+ "group_sid",
+ dom_sid_string(finfo, &finfo->group_sid));
+
+ Py_CLEAR(size);
+
+ if (file == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ret = PyList_Append(result, file);
+ Py_CLEAR(file);
+ if (ret == -1) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ return NT_STATUS_OK;
+}
+
/*
* Helper to add directory listing entries to an overall Python list
*/
return NT_STATUS_NO_MEMORY;
}
+ if (finfo->attr & FILE_ATTRIBUTE_REPARSE_POINT) {
+ unsigned long tag = finfo->reparse_tag;
+
+ ret = PyDict_SetItemString(
+ file,
+ "reparse_tag",
+ PyLong_FromUnsignedLong(tag));
+ if (ret == -1) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ }
+
ret = PyList_Append(result, file);
Py_CLEAR(file);
if (ret == -1) {
PyObject *result = NULL;
const char *kwlist[] = { "directory", "mask", "attribs", "posix",
"info_level", NULL };
+ NTSTATUS (*callback_fn)(struct file_info *, const char *, void *) =
+ &list_helper;
if (!ParseTupleAndKeywords(args, kwds, "z|sIpI:list", kwlist,
&base_dir, &user_mask, &attribute,
}
}
+ if (posix) {
+ callback_fn = &list_posix_helper;
+ }
status = do_listing(self, base_dir, user_mask, attribute,
- info_level, posix, list_helper, result);
+ info_level, posix, callback_fn, result);
if (!NT_STATUS_IS_OK(status)) {
Py_XDECREF(result);
Py_RETURN_NONE;
}
+static PyObject *py_smb_smb1_stat(
+ struct py_cli_state *self, PyObject *args)
+{
+ NTSTATUS status;
+ const char *fname = NULL;
+ struct tevent_req *req = NULL;
+ struct stat_ex sbuf = { .st_ex_nlink = 0, };
+
+ if (!PyArg_ParseTuple(args, "s:smb1_stat", &fname)) {
+ return NULL;
+ }
+
+ req = cli_posix_stat_send(NULL, self->ev, self->cli, fname);
+ if (!py_tevent_req_wait_exc(self, req)) {
+ return NULL;
+ }
+ status = cli_posix_stat_recv(req, &sbuf);
+ TALLOC_FREE(req);
+ if (!NT_STATUS_IS_OK(status)) {
+ PyErr_SetNTSTATUS(status);
+ return NULL;
+ }
+
+ return Py_BuildValue(
+ "{sLsLsLsLsLsLsLsLsLsLsLsLsLsLsLsLsLsLsLsL}",
+ "dev",
+ (unsigned long long)sbuf.st_ex_dev,
+ "ino",
+ (unsigned long long)sbuf.st_ex_ino,
+ "mode",
+ (unsigned long long)sbuf.st_ex_mode,
+ "nlink",
+ (unsigned long long)sbuf.st_ex_nlink,
+ "uid",
+ (unsigned long long)sbuf.st_ex_uid,
+ "gid",
+ (unsigned long long)sbuf.st_ex_gid,
+ "rdev",
+ (unsigned long long)sbuf.st_ex_size,
+ "atime_sec",
+ (unsigned long long)sbuf.st_ex_atime.tv_sec,
+ "atime_nsec",
+ (unsigned long long)sbuf.st_ex_atime.tv_nsec,
+ "mtime_sec",
+ (unsigned long long)sbuf.st_ex_mtime.tv_sec,
+ "mtime_nsec",
+ (unsigned long long)sbuf.st_ex_mtime.tv_nsec,
+ "ctime_sec",
+ (unsigned long long)sbuf.st_ex_ctime.tv_sec,
+ "ctime_nsec",
+ (unsigned long long)sbuf.st_ex_ctime.tv_nsec,
+ "btime_sec",
+ (unsigned long long)sbuf.st_ex_btime.tv_sec,
+ "btime_nsec",
+ (unsigned long long)sbuf.st_ex_btime.tv_nsec,
+ "cached_dos_attributes",
+ (unsigned long long)sbuf.cached_dos_attributes,
+ "blksize",
+ (unsigned long long)sbuf.st_ex_blksize,
+ "blocks",
+ (unsigned long long)sbuf.st_ex_blocks,
+ "flags",
+ (unsigned long long)sbuf.st_ex_flags,
+ "iflags",
+ (unsigned long long)sbuf.st_ex_iflags);
+}
+
+static PyObject *py_cli_mknod(
+ struct py_cli_state *self, PyObject *args, PyObject *kwds)
+{
+ char *fname = NULL;
+ int mode = 0, major = 0, minor = 0, dev = 0;
+ struct tevent_req *req = NULL;
+ static const char *kwlist[] = {
+ "fname", "mode", "major", "minor", NULL,
+ };
+ NTSTATUS status;
+ bool ok;
+
+ ok = ParseTupleAndKeywords(
+ args,
+ kwds,
+ "sI|II:mknod",
+ kwlist,
+ &fname,
+ &mode,
+ &major,
+ &minor);
+ if (!ok) {
+ return NULL;
+ }
+
+#if defined(HAVE_MAKEDEV)
+ dev = makedev(major, minor);
+#endif
+
+ req = cli_mknod_send(
+ NULL, self->ev, self->cli, fname, mode, dev);
+ if (!py_tevent_req_wait_exc(self, req)) {
+ return NULL;
+ }
+ status = cli_mknod_recv(req);
+ TALLOC_FREE(req);
+ if (!NT_STATUS_IS_OK(status)) {
+ PyErr_SetNTSTATUS(status);
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
static PyObject *py_cli_fsctl(
struct py_cli_state *self, PyObject *args, PyObject *kwds)
{
METH_VARARGS,
"smb1_symlink(target, newname) -> None",
},
+ { "smb1_stat",
+ (PyCFunction)py_smb_smb1_stat,
+ METH_VARARGS,
+ "smb1_stat(path) -> stat info",
+ },
{ "fsctl",
(PyCFunction)py_cli_fsctl,
METH_VARARGS|METH_KEYWORDS,
"fsctl(fnum, ctl_code, in_bytes, max_out) -> out_bytes",
},
+ { "mknod",
+ PY_DISCARD_FUNC_SIG(PyCFunction, py_cli_mknod),
+ METH_VARARGS|METH_KEYWORDS,
+ "mknod(path, mode | major, minor)",
+ },
{ NULL, NULL, 0, NULL }
};
ADD_FLAGS(FSCTL_LMR_SET_LINK_TRACKING_INFORMATION);
ADD_FLAGS(FSCTL_QUERY_NETWORK_INTERFACE_INFO);
+ ADD_FLAGS(SYMLINK_ERROR_TAG);
+ ADD_FLAGS(SYMLINK_FLAG_RELATIVE);
+ ADD_FLAGS(SYMLINK_ADMIN);
+ ADD_FLAGS(SYMLINK_UNTRUSTED);
+ ADD_FLAGS(SYMLINK_TRUST_UNKNOWN);
+ ADD_FLAGS(SYMLINK_TRUST_MASK);
+
+ ADD_FLAGS(IO_REPARSE_TAG_SYMLINK);
+ ADD_FLAGS(IO_REPARSE_TAG_MOUNT_POINT);
+ ADD_FLAGS(IO_REPARSE_TAG_HSM);
+ ADD_FLAGS(IO_REPARSE_TAG_SIS);
+ ADD_FLAGS(IO_REPARSE_TAG_DFS);
+ ADD_FLAGS(IO_REPARSE_TAG_NFS);
+
#define ADD_STRING(val) PyModule_AddObject(m, #val, PyBytes_FromString(val))
ADD_STRING(SMB2_CREATE_TAG_EXTA);
ADD_STRING(SMB2_CREATE_TAG_APP_INSTANCE_ID);
ADD_STRING(SVHDX_OPEN_DEVICE_CONTEXT);
ADD_STRING(SMB2_CREATE_TAG_POSIX);
+ ADD_FLAGS(SMB2_FIND_POSIX_INFORMATION);
+ ADD_FLAGS(FILE_SUPERSEDE);
+ ADD_FLAGS(FILE_OPEN);
+ ADD_FLAGS(FILE_CREATE);
+ ADD_FLAGS(FILE_OPEN_IF);
+ ADD_FLAGS(FILE_OVERWRITE);
+ ADD_FLAGS(FILE_OVERWRITE_IF);
+ ADD_FLAGS(FILE_DIRECTORY_FILE);
return m;
}