summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/cli_np_tstream.c2
-rw-r--r--source3/libsmb/cli_smb2_fnum.c4
-rw-r--r--source3/libsmb/cli_smb2_fnum.h2
-rw-r--r--source3/libsmb/clifile.c73
-rw-r--r--source3/libsmb/cliquota.c2
-rw-r--r--source3/libsmb/clisymlink.c4
-rw-r--r--source3/libsmb/libsmb_context.c17
-rw-r--r--source3/libsmb/libsmb_setget.c17
-rw-r--r--source3/libsmb/libsmb_xattr.c6
-rw-r--r--source3/libsmb/proto.h14
-rw-r--r--source3/libsmb/pylibsmb.c2
11 files changed, 117 insertions, 26 deletions
diff --git a/source3/libsmb/cli_np_tstream.c b/source3/libsmb/cli_np_tstream.c
index f3a9962f823..bf9a0c370a8 100644
--- a/source3/libsmb/cli_np_tstream.c
+++ b/source3/libsmb/cli_np_tstream.c
@@ -204,7 +204,7 @@ static void tstream_cli_np_open_done(struct tevent_req *subreq)
NTSTATUS status;
if (state->is_smb1) {
- status = cli_ntcreate_recv(subreq, &state->fnum);
+ status = cli_ntcreate_recv(subreq, &state->fnum, NULL);
} else {
status = smb2cli_create_recv(subreq,
&state->fid_persistent,
diff --git a/source3/libsmb/cli_smb2_fnum.c b/source3/libsmb/cli_smb2_fnum.c
index 1e2047ef676..8eb776a1324 100644
--- a/source3/libsmb/cli_smb2_fnum.c
+++ b/source3/libsmb/cli_smb2_fnum.c
@@ -163,7 +163,7 @@ NTSTATUS cli_smb2_create_fnum(struct cli_state *cli,
uint32_t create_disposition,
uint32_t create_options,
uint16_t *pfid,
- struct smb2_create_returns *cr)
+ struct smb_create_returns *cr)
{
NTSTATUS status;
struct smb2_hnd h;
@@ -660,7 +660,7 @@ NTSTATUS cli_smb2_qpathinfo_basic(struct cli_state *cli,
uint32_t *attributes)
{
NTSTATUS status;
- struct smb2_create_returns cr;
+ struct smb_create_returns cr;
uint16_t fnum = 0xffff;
size_t namelen = strlen(name);
diff --git a/source3/libsmb/cli_smb2_fnum.h b/source3/libsmb/cli_smb2_fnum.h
index a5cae25a2ba..61a0f6851ee 100644
--- a/source3/libsmb/cli_smb2_fnum.h
+++ b/source3/libsmb/cli_smb2_fnum.h
@@ -34,7 +34,7 @@ NTSTATUS cli_smb2_create_fnum(struct cli_state *cli,
uint32_t create_disposition,
uint32_t create_options,
uint16_t *pfid,
- struct smb2_create_returns *cr);
+ struct smb_create_returns *cr);
NTSTATUS cli_smb2_close_fnum(struct cli_state *cli, uint16_t fnum);
NTSTATUS cli_smb2_mkdir(struct cli_state *cli, const char *dirname);
diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index 424354b9638..70b769d1bd8 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -1795,6 +1795,7 @@ NTSTATUS cli_nt_delete_on_close(struct cli_state *cli, uint16_t fnum, bool flag)
struct cli_ntcreate_state {
uint16_t vwv[24];
uint16_t fnum;
+ struct smb_create_returns cr;
};
static void cli_ntcreate_done(struct tevent_req *subreq);
@@ -1880,17 +1881,29 @@ static void cli_ntcreate_done(struct tevent_req *subreq)
uint8_t *bytes;
NTSTATUS status;
- status = cli_smb_recv(subreq, state, NULL, 3, &wct, &vwv,
+ status = cli_smb_recv(subreq, state, NULL, 34, &wct, &vwv,
&num_bytes, &bytes);
TALLOC_FREE(subreq);
if (tevent_req_nterror(req, status)) {
return;
}
+ state->cr.oplock_level = CVAL(vwv+2, 0);
state->fnum = SVAL(vwv+2, 1);
+ state->cr.create_action = IVAL(vwv+3, 1);
+ state->cr.creation_time = BVAL(vwv+5, 1);
+ state->cr.last_access_time = BVAL(vwv+9, 1);
+ state->cr.last_write_time = BVAL(vwv+13, 1);
+ state->cr.change_time = BVAL(vwv+17, 1);
+ state->cr.file_attributes = IVAL(vwv+21, 1);
+ state->cr.allocation_size = BVAL(vwv+23, 1);
+ state->cr.end_of_file = BVAL(vwv+27, 1);
+
tevent_req_done(req);
}
-NTSTATUS cli_ntcreate_recv(struct tevent_req *req, uint16_t *pfnum)
+NTSTATUS cli_ntcreate_recv(struct tevent_req *req,
+ uint16_t *pfnum,
+ struct smb_create_returns *cr)
{
struct cli_ntcreate_state *state = tevent_req_data(
req, struct cli_ntcreate_state);
@@ -1900,6 +1913,9 @@ NTSTATUS cli_ntcreate_recv(struct tevent_req *req, uint16_t *pfnum)
return status;
}
*pfnum = state->fnum;
+ if (cr != NULL) {
+ *cr = state->cr;
+ }
return NT_STATUS_OK;
}
@@ -1912,7 +1928,8 @@ NTSTATUS cli_ntcreate(struct cli_state *cli,
uint32_t CreateDisposition,
uint32_t CreateOptions,
uint8_t SecurityFlags,
- uint16_t *pfid)
+ uint16_t *pfid,
+ struct smb_create_returns *cr)
{
TALLOC_CTX *frame = NULL;
struct tevent_context *ev;
@@ -1929,7 +1946,7 @@ NTSTATUS cli_ntcreate(struct cli_state *cli,
CreateDisposition,
CreateOptions,
pfid,
- NULL);
+ cr);
}
frame = talloc_stackframe();
@@ -1962,7 +1979,7 @@ NTSTATUS cli_ntcreate(struct cli_state *cli,
goto fail;
}
- status = cli_ntcreate_recv(req, pfid);
+ status = cli_ntcreate_recv(req, pfid, cr);
fail:
TALLOC_FREE(frame);
return status;
@@ -1970,6 +1987,7 @@ NTSTATUS cli_ntcreate(struct cli_state *cli,
struct cli_nttrans_create_state {
uint16_t fnum;
+ struct smb_create_returns cr;
};
static void cli_nttrans_create_done(struct tevent_req *subreq);
@@ -2082,12 +2100,24 @@ static void cli_nttrans_create_done(struct tevent_req *subreq)
if (tevent_req_nterror(req, status)) {
return;
}
+ state->cr.oplock_level = CVAL(param, 0);
state->fnum = SVAL(param, 2);
+ state->cr.create_action = IVAL(param, 4);
+ state->cr.creation_time = BVAL(param, 12);
+ state->cr.last_access_time = BVAL(param, 20);
+ state->cr.last_write_time = BVAL(param, 28);
+ state->cr.change_time = BVAL(param, 36);
+ state->cr.file_attributes = IVAL(param, 44);
+ state->cr.allocation_size = BVAL(param, 48);
+ state->cr.end_of_file = BVAL(param, 56);
+
TALLOC_FREE(param);
tevent_req_done(req);
}
-NTSTATUS cli_nttrans_create_recv(struct tevent_req *req, uint16_t *fnum)
+NTSTATUS cli_nttrans_create_recv(struct tevent_req *req,
+ uint16_t *fnum,
+ struct smb_create_returns *cr)
{
struct cli_nttrans_create_state *state = tevent_req_data(
req, struct cli_nttrans_create_state);
@@ -2097,6 +2127,9 @@ NTSTATUS cli_nttrans_create_recv(struct tevent_req *req, uint16_t *fnum)
return status;
}
*fnum = state->fnum;
+ if (cr != NULL) {
+ *cr = state->cr;
+ }
return NT_STATUS_OK;
}
@@ -2112,7 +2145,8 @@ NTSTATUS cli_nttrans_create(struct cli_state *cli,
struct security_descriptor *secdesc,
struct ea_struct *eas,
int num_eas,
- uint16_t *pfid)
+ uint16_t *pfid,
+ struct smb_create_returns *cr)
{
TALLOC_CTX *frame = talloc_stackframe();
struct tevent_context *ev;
@@ -2141,7 +2175,7 @@ NTSTATUS cli_nttrans_create(struct cli_state *cli,
if (!tevent_req_poll_ntstatus(req, ev, &status)) {
goto fail;
}
- status = cli_nttrans_create_recv(req, pfid);
+ status = cli_nttrans_create_recv(req, pfid, cr);
fail:
TALLOC_FREE(frame);
return status;
@@ -2353,6 +2387,7 @@ NTSTATUS cli_open(struct cli_state *cli, const char *fname, int flags,
unsigned int openfn = 0;
unsigned int dos_deny = 0;
uint32_t access_mask, share_mode, create_disposition, create_options;
+ struct smb_create_returns cr;
/* Do the initial mapping into OpenX parameters. */
if (flags & O_CREAT) {
@@ -2433,7 +2468,8 @@ NTSTATUS cli_open(struct cli_state *cli, const char *fname, int flags,
create_disposition,
create_options,
0,
- pfnum);
+ pfnum,
+ &cr);
/* Try and cope will all varients of "we don't do this call"
and fall back to openX. */
@@ -2450,6 +2486,25 @@ NTSTATUS cli_open(struct cli_state *cli, const char *fname, int flags,
goto try_openx;
}
+ if (NT_STATUS_IS_OK(status) &&
+ (create_options & FILE_NON_DIRECTORY_FILE) &&
+ (cr.file_attributes & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ /*
+ * Some (broken) servers return a valid handle
+ * for directories even if FILE_NON_DIRECTORY_FILE
+ * is set. Just close the handle and set the
+ * error explicitly to NT_STATUS_FILE_IS_A_DIRECTORY.
+ */
+ status = cli_close(cli, *pfnum);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ status = NT_STATUS_FILE_IS_A_DIRECTORY;
+ /* Set this so libsmbclient can retrieve it. */
+ cli->raw_status = status;
+ }
+
return status;
try_openx:
diff --git a/source3/libsmb/cliquota.c b/source3/libsmb/cliquota.c
index 9136506e48c..21dc72e35c9 100644
--- a/source3/libsmb/cliquota.c
+++ b/source3/libsmb/cliquota.c
@@ -29,7 +29,7 @@ NTSTATUS cli_get_quota_handle(struct cli_state *cli, uint16_t *quota_fnum)
return cli_ntcreate(cli, FAKE_FILE_NAME_QUOTA_WIN32,
0x00000016, DESIRED_ACCESS_PIPE,
0x00000000, FILE_SHARE_READ|FILE_SHARE_WRITE,
- FILE_OPEN, 0x00000000, 0x03, quota_fnum);
+ FILE_OPEN, 0x00000000, 0x03, quota_fnum, NULL);
}
void free_ntquota_list(SMB_NTQUOTA_LIST **qt_list)
diff --git a/source3/libsmb/clisymlink.c b/source3/libsmb/clisymlink.c
index 338f932c4e7..eacae85d01d 100644
--- a/source3/libsmb/clisymlink.c
+++ b/source3/libsmb/clisymlink.c
@@ -90,7 +90,7 @@ static void cli_symlink_create_done(struct tevent_req *subreq)
size_t data_len;
NTSTATUS status;
- status = cli_ntcreate_recv(subreq, &state->fnum);
+ status = cli_ntcreate_recv(subreq, &state->fnum, NULL);
TALLOC_FREE(subreq);
if (tevent_req_nterror(req, status)) {
return;
@@ -275,7 +275,7 @@ static void cli_readlink_opened(struct tevent_req *subreq)
req, struct cli_readlink_state);
NTSTATUS status;
- status = cli_ntcreate_recv(subreq, &state->fnum);
+ status = cli_ntcreate_recv(subreq, &state->fnum, NULL);
TALLOC_FREE(subreq);
if (tevent_req_nterror(req, status)) {
return;
diff --git a/source3/libsmb/libsmb_context.c b/source3/libsmb/libsmb_context.c
index c2b88f56927..ffa4d2de921 100644
--- a/source3/libsmb/libsmb_context.c
+++ b/source3/libsmb/libsmb_context.c
@@ -560,6 +560,7 @@ SMBCCTX *
smbc_init_context(SMBCCTX *context)
{
int pid;
+ TALLOC_CTX *frame;
if (!context) {
errno = EBADF;
@@ -571,11 +572,14 @@ smbc_init_context(SMBCCTX *context)
return NULL;
}
+ frame = talloc_stackframe();
+
if ((!smbc_getFunctionAuthData(context) &&
!smbc_getFunctionAuthDataWithContext(context)) ||
smbc_getDebug(context) < 0 ||
smbc_getDebug(context) > 100) {
+ TALLOC_FREE(frame);
errno = EINVAL;
return NULL;
@@ -594,6 +598,7 @@ smbc_init_context(SMBCCTX *context)
}
if (!user) {
+ TALLOC_FREE(frame);
errno = ENOMEM;
return NULL;
}
@@ -602,6 +607,7 @@ smbc_init_context(SMBCCTX *context)
SAFE_FREE(user);
if (!smbc_getUser(context)) {
+ TALLOC_FREE(frame);
errno = ENOMEM;
return NULL;
}
@@ -624,6 +630,7 @@ smbc_init_context(SMBCCTX *context)
pid = getpid();
netbios_name = (char *)SMB_MALLOC(17);
if (!netbios_name) {
+ TALLOC_FREE(frame);
errno = ENOMEM;
return NULL;
}
@@ -632,6 +639,7 @@ smbc_init_context(SMBCCTX *context)
}
if (!netbios_name) {
+ TALLOC_FREE(frame);
errno = ENOMEM;
return NULL;
}
@@ -640,6 +648,7 @@ smbc_init_context(SMBCCTX *context)
SAFE_FREE(netbios_name);
if (!smbc_getNetbiosName(context)) {
+ TALLOC_FREE(frame);
errno = ENOMEM;
return NULL;
}
@@ -659,6 +668,7 @@ smbc_init_context(SMBCCTX *context)
}
if (!workgroup) {
+ TALLOC_FREE(frame);
errno = ENOMEM;
return NULL;
}
@@ -667,6 +677,7 @@ smbc_init_context(SMBCCTX *context)
SAFE_FREE(workgroup);
if (!smbc_getWorkgroup(context)) {
+ TALLOC_FREE(frame);
errno = ENOMEM;
return NULL;
}
@@ -692,6 +703,7 @@ smbc_init_context(SMBCCTX *context)
smb_panic("error unlocking 'initialized_ctx_count'");
}
+ TALLOC_FREE(frame);
return context;
}
@@ -727,12 +739,15 @@ void smbc_set_credentials_with_fallback(SMBCCTX *context,
smbc_bool use_kerberos = false;
const char *signing_state = "off";
struct user_auth_info *auth_info = NULL;
+ TALLOC_CTX *frame;
if (! context) {
return;
}
+ frame = talloc_stackframe();
+
if (! workgroup || ! *workgroup) {
workgroup = smbc_getWorkgroup(context);
}
@@ -749,6 +764,7 @@ void smbc_set_credentials_with_fallback(SMBCCTX *context,
if (! auth_info) {
DEBUG(0, ("smbc_set_credentials_with_fallback: allocation fail\n"));
+ TALLOC_FREE(frame);
return;
}
@@ -777,4 +793,5 @@ void smbc_set_credentials_with_fallback(SMBCCTX *context,
TALLOC_FREE(context->internal->auth_info);
context->internal->auth_info = auth_info;
+ TALLOC_FREE(frame);
}
diff --git a/source3/libsmb/libsmb_setget.c b/source3/libsmb/libsmb_setget.c
index b8adcca18b9..3255b522bb0 100644
--- a/source3/libsmb/libsmb_setget.c
+++ b/source3/libsmb/libsmb_setget.c
@@ -91,9 +91,11 @@ void
smbc_setDebug(SMBCCTX *c, int debug)
{
char buf[32];
+ TALLOC_CTX *frame = talloc_stackframe();
snprintf(buf, sizeof(buf), "%d", debug);
c->debug = debug;
lp_set_cmdline("log level", buf);
+ TALLOC_FREE(frame);
}
/**
@@ -139,10 +141,15 @@ smbc_setPort(SMBCCTX *c, uint16_t port)
smbc_bool
smbc_getOptionDebugToStderr(SMBCCTX *c)
{
+ smbc_bool ret;
+ TALLOC_CTX *frame = talloc_stackframe();
+
/* Because this is a global concept, it is better to check
* what is really set, rather than what we wanted set
* (particularly as you cannot go back to stdout). */
- return debug_get_output_is_stderr();
+ ret = debug_get_output_is_stderr();
+ TALLOC_FREE(frame);
+ return ret;
}
/** Set whether to log to standard error instead of standard output.
@@ -154,6 +161,7 @@ smbc_getOptionDebugToStderr(SMBCCTX *c)
void
smbc_setOptionDebugToStderr(SMBCCTX *c, smbc_bool b)
{
+ TALLOC_CTX *frame = talloc_stackframe();
if (b) {
/*
* We do not have a unique per-thread debug state? For
@@ -164,6 +172,7 @@ smbc_setOptionDebugToStderr(SMBCCTX *c, smbc_bool b)
*/
setup_logging("libsmbclient", DEBUG_STDERR);
}
+ TALLOC_FREE(frame);
}
/**
@@ -498,7 +507,11 @@ smbc_setOptionUseNTHash(SMBCCTX *c, smbc_bool b)
smbc_get_auth_data_fn
smbc_getFunctionAuthData(SMBCCTX *c)
{
- return c->callbacks.auth_fn;
+ smbc_get_auth_data_fn ret;
+ TALLOC_CTX *frame = talloc_stackframe();
+ ret = c->callbacks.auth_fn;
+ TALLOC_FREE(frame);
+ return ret;
}
/** Set the function for obtaining authentication data */
diff --git a/source3/libsmb/libsmb_xattr.c b/source3/libsmb/libsmb_xattr.c
index 7d34290b65d..8e6590a5367 100644
--- a/source3/libsmb/libsmb_xattr.c
+++ b/source3/libsmb/libsmb_xattr.c
@@ -904,7 +904,7 @@ cacl_get(SMBCCTX *context,
status = cli_ntcreate(targetcli, targetpath, 0,
CREATE_ACCESS_READ, 0,
FILE_SHARE_READ|FILE_SHARE_WRITE,
- FILE_OPEN, 0x0, 0x0, &fnum);
+ FILE_OPEN, 0x0, 0x0, &fnum, NULL);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5, ("cacl_get failed to open %s: %s\n",
targetpath, nt_errstr(status)));
@@ -1563,7 +1563,7 @@ cacl_set(SMBCCTX *context,
status = cli_ntcreate(targetcli, targetpath, 0, CREATE_ACCESS_READ, 0,
FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN,
- 0x0, 0x0, &fnum);
+ 0x0, 0x0, &fnum, NULL);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5, ("cacl_set failed to open %s: %s\n",
targetpath, nt_errstr(status)));
@@ -1671,7 +1671,7 @@ cacl_set(SMBCCTX *context,
status = cli_ntcreate(targetcli, targetpath, 0,
WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS, 0,
FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN,
- 0x0, 0x0, &fnum);
+ 0x0, 0x0, &fnum, NULL);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5, ("cacl_set failed to open %s: %s\n",
targetpath, nt_errstr(status)));
diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h
index a1389ff4655..525625cd300 100644
--- a/source3/libsmb/proto.h
+++ b/source3/libsmb/proto.h
@@ -356,7 +356,9 @@ struct tevent_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx,
uint32_t CreateDisposition,
uint32_t CreateOptions,
uint8_t SecurityFlags);
-NTSTATUS cli_ntcreate_recv(struct tevent_req *req, uint16_t *pfnum);
+NTSTATUS cli_ntcreate_recv(struct tevent_req *req,
+ uint16_t *pfnum,
+ struct smb_create_returns *cr);
NTSTATUS cli_ntcreate(struct cli_state *cli,
const char *fname,
uint32_t CreatFlags,
@@ -366,7 +368,8 @@ NTSTATUS cli_ntcreate(struct cli_state *cli,
uint32_t CreateDisposition,
uint32_t CreateOptions,
uint8_t SecurityFlags,
- uint16_t *pfid);
+ uint16_t *pfid,
+ struct smb_create_returns *cr);
uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2, const char *str,
size_t str_len, size_t *pconverted_size);
uint8_t *smb_bytes_push_bytes(uint8_t *buf, uint8_t prefix,
@@ -600,7 +603,9 @@ struct tevent_req *cli_nttrans_create_send(TALLOC_CTX *mem_ctx,
struct security_descriptor *secdesc,
struct ea_struct *eas,
int num_eas);
-NTSTATUS cli_nttrans_create_recv(struct tevent_req *req, uint16_t *fnum);
+NTSTATUS cli_nttrans_create_recv(struct tevent_req *req,
+ uint16_t *fnum,
+ struct smb_create_returns *cr);
NTSTATUS cli_nttrans_create(struct cli_state *cli,
const char *fname,
uint32_t CreatFlags,
@@ -613,7 +618,8 @@ NTSTATUS cli_nttrans_create(struct cli_state *cli,
struct security_descriptor *secdesc,
struct ea_struct *eas,
int num_eas,
- uint16_t *pfid);
+ uint16_t *pfid,
+ struct smb_create_returns *cr);
/* The following definitions come from libsmb/clifsinfo.c */
diff --git a/source3/libsmb/pylibsmb.c b/source3/libsmb/pylibsmb.c
index ae0d6943d0f..e3a5ac7d18a 100644
--- a/source3/libsmb/pylibsmb.c
+++ b/source3/libsmb/pylibsmb.c
@@ -609,7 +609,7 @@ static PyObject *py_cli_create(struct py_cli_state *self, PyObject *args,
if (!py_tevent_req_wait_exc(self->ev, req)) {
return NULL;
}
- status = cli_ntcreate_recv(req, &fnum);
+ status = cli_ntcreate_recv(req, &fnum, NULL);
TALLOC_FREE(req);
if (!NT_STATUS_IS_OK(status)) {