#include "trans2.h"
#include "../libcli/smb/smbXcli_base.h"
#include "cli_smb2_fnum.h"
+#include "lib/util/string_wrappers.h"
#include <gnutls/gnutls.h>
#include <gnutls/crypto.h>
return (cli->rap_error == 0);
}
-/****************************************************************************
- Send a qpathinfo call.
-****************************************************************************/
-
-struct cli_qpathinfo1_state {
- struct cli_state *cli;
- uint32_t num_data;
- uint8_t *data;
-};
-
-static void cli_qpathinfo1_done(struct tevent_req *subreq);
-
-struct tevent_req *cli_qpathinfo1_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct cli_state *cli,
- const char *fname)
-{
- struct tevent_req *req = NULL, *subreq = NULL;
- struct cli_qpathinfo1_state *state = NULL;
-
- req = tevent_req_create(mem_ctx, &state, struct cli_qpathinfo1_state);
- if (req == NULL) {
- return NULL;
- }
- state->cli = cli;
- subreq = cli_qpathinfo_send(state, ev, cli, fname, SMB_INFO_STANDARD,
- 22, CLI_BUFFER_SIZE);
- if (tevent_req_nomem(subreq, req)) {
- return tevent_req_post(req, ev);
- }
- tevent_req_set_callback(subreq, cli_qpathinfo1_done, req);
- return req;
-}
-
-static void cli_qpathinfo1_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- struct cli_qpathinfo1_state *state = tevent_req_data(
- req, struct cli_qpathinfo1_state);
- NTSTATUS status;
-
- status = cli_qpathinfo_recv(subreq, state, &state->data,
- &state->num_data);
- TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return;
- }
- tevent_req_done(req);
-}
-
-NTSTATUS cli_qpathinfo1_recv(struct tevent_req *req,
- time_t *change_time,
- time_t *access_time,
- time_t *write_time,
- off_t *size,
- uint32_t *pattr)
-{
- struct cli_qpathinfo1_state *state = tevent_req_data(
- req, struct cli_qpathinfo1_state);
- NTSTATUS status;
-
- time_t (*date_fn)(const void *buf, int serverzone);
-
- if (tevent_req_is_nterror(req, &status)) {
- return status;
- }
-
- if (state->cli->win95) {
- date_fn = make_unix_date;
- } else {
- date_fn = make_unix_date2;
- }
-
- if (change_time) {
- *change_time = date_fn(state->data+0, smb1cli_conn_server_time_zone(state->cli->conn));
- }
- if (access_time) {
- *access_time = date_fn(state->data+4, smb1cli_conn_server_time_zone(state->cli->conn));
- }
- if (write_time) {
- *write_time = date_fn(state->data+8, smb1cli_conn_server_time_zone(state->cli->conn));
- }
- if (size) {
- *size = IVAL(state->data, 12);
- }
- if (pattr) {
- *pattr = SVAL(state->data, l1_attrFile);
- }
- return NT_STATUS_OK;
-}
-
-NTSTATUS cli_qpathinfo1(struct cli_state *cli,
- const char *fname,
- time_t *change_time,
- time_t *access_time,
- time_t *write_time,
- off_t *size,
- uint32_t *pattr)
-{
- TALLOC_CTX *frame = talloc_stackframe();
- struct tevent_context *ev;
- struct tevent_req *req;
- NTSTATUS status = NT_STATUS_NO_MEMORY;
-
- if (smbXcli_conn_has_async_calls(cli->conn)) {
- /*
- * Can't use sync call while an async call is in flight
- */
- status = NT_STATUS_INVALID_PARAMETER;
- goto fail;
- }
- ev = samba_tevent_context_init(frame);
- if (ev == NULL) {
- goto fail;
- }
- req = cli_qpathinfo1_send(frame, ev, cli, fname);
- if (req == NULL) {
- goto fail;
- }
- if (!tevent_req_poll_ntstatus(req, ev, &status)) {
- goto fail;
- }
- status = cli_qpathinfo1_recv(req, change_time, access_time,
- write_time, size, pattr);
- fail:
- TALLOC_FREE(frame);
- return status;
-}
-
static void prep_basic_information_buf(
uint8_t buf[40],
struct timespec create_time,
****************************************************************************/
struct cli_qpathinfo2_state {
- uint32_t num_data;
- uint8_t *data;
+ struct timespec create_time;
+ struct timespec access_time;
+ struct timespec write_time;
+ struct timespec change_time;
+ off_t size;
+ uint32_t attr;
+ SMB_INO_T ino;
};
+static void cli_qpathinfo2_done2(struct tevent_req *subreq);
static void cli_qpathinfo2_done(struct tevent_req *subreq);
struct tevent_req *cli_qpathinfo2_send(TALLOC_CTX *mem_ctx,
if (req == NULL) {
return NULL;
}
+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
+ subreq = cli_smb2_qpathinfo_send(state,
+ ev,
+ cli,
+ fname,
+ FSCC_FILE_ALL_INFORMATION,
+ 0x60,
+ UINT16_MAX);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, cli_qpathinfo2_done2, req);
+ return req;
+ }
subreq = cli_qpathinfo_send(state, ev, cli, fname,
SMB_QUERY_FILE_ALL_INFO,
68, CLI_BUFFER_SIZE);
return req;
}
+static void cli_qpathinfo2_done2(struct tevent_req *subreq)
+{
+ struct tevent_req *req =
+ tevent_req_callback_data(subreq, struct tevent_req);
+ struct cli_qpathinfo2_state *state =
+ tevent_req_data(req, struct cli_qpathinfo2_state);
+ uint8_t *rdata = NULL;
+ uint32_t num_rdata;
+ NTSTATUS status;
+
+ status = cli_smb2_qpathinfo_recv(subreq, state, &rdata, &num_rdata);
+ TALLOC_FREE(subreq);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+ state->create_time = interpret_long_date(BVAL(rdata, 0x0));
+ state->access_time = interpret_long_date(BVAL(rdata, 0x8));
+ state->write_time = interpret_long_date(BVAL(rdata, 0x10));
+ state->change_time = interpret_long_date(BVAL(rdata, 0x18));
+ state->attr = PULL_LE_U32(rdata, 0x20);
+ state->size = PULL_LE_U64(rdata, 0x30);
+ state->ino = PULL_LE_U64(rdata, 0x40);
+
+ tevent_req_done(req);
+}
+
static void cli_qpathinfo2_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(
subreq, struct tevent_req);
struct cli_qpathinfo2_state *state = tevent_req_data(
req, struct cli_qpathinfo2_state);
+ uint8_t *data = NULL;
+ uint32_t num_data;
NTSTATUS status;
- status = cli_qpathinfo_recv(subreq, state, &state->data,
- &state->num_data);
+ status = cli_qpathinfo_recv(subreq, state, &data, &num_data);
TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
+ if (tevent_req_nterror(req, status)) {
return;
}
+
+ state->create_time = interpret_long_date(BVAL(data, 0));
+ state->access_time = interpret_long_date(BVAL(data, 8));
+ state->write_time = interpret_long_date(BVAL(data, 16));
+ state->change_time = interpret_long_date(BVAL(data, 24));
+ state->attr = PULL_LE_U32(data, 32);
+ state->size = PULL_LE_U64(data, 48);
+
+ /*
+ * SMB1 qpathinfo2 uses SMB_QUERY_FILE_ALL_INFO which doesn't
+ * return an inode number (fileid). We can't change this to
+ * one of the FILE_ID info levels as only Win2003 and above
+ * support these [MS-SMB: 2.2.2.3.1] and the SMB1 code needs
+ * to support older servers.
+ */
+ state->ino = 0;
+
+ TALLOC_FREE(data);
+
tevent_req_done(req);
}
}
if (create_time) {
- *create_time = interpret_long_date((char *)state->data+0);
+ *create_time = state->create_time;
}
if (access_time) {
- *access_time = interpret_long_date((char *)state->data+8);
+ *access_time = state->access_time;
}
if (write_time) {
- *write_time = interpret_long_date((char *)state->data+16);
+ *write_time = state->write_time;
}
if (change_time) {
- *change_time = interpret_long_date((char *)state->data+24);
+ *change_time = state->change_time;
}
if (pattr) {
- /* SMB_QUERY_FILE_ALL_INFO returns 32-bit attributes. */
- *pattr = IVAL(state->data, 32);
+ *pattr = state->attr;
}
if (size) {
- *size = IVAL2_TO_SMB_BIG_UINT(state->data,48);
+ *size = state->size;
}
if (ino) {
- /*
- * SMB1 qpathinfo2 uses SMB_QUERY_FILE_ALL_INFO
- * which doesn't return an inode number (fileid).
- * We can't change this to one of the FILE_ID
- * info levels as only Win2003 and above support
- * these [MS-SMB: 2.2.2.3.1] and the SMB1 code
- * needs to support older servers.
- */
- *ino = 0;
+ *ino = state->ino;
}
return NT_STATUS_OK;
}
off_t *size, uint32_t *pattr,
SMB_INO_T *ino)
{
- TALLOC_CTX *frame = NULL;
- struct tevent_context *ev;
- struct tevent_req *req;
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct tevent_context *ev = NULL;
+ struct tevent_req *req = NULL;
NTSTATUS status = NT_STATUS_NO_MEMORY;
- if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
- return cli_smb2_qpathinfo2(cli,
- fname,
- create_time,
- access_time,
- write_time,
- change_time,
- size,
- pattr,
- ino);
- }
-
- frame = talloc_stackframe();
-
if (smbXcli_conn_has_async_calls(cli->conn)) {
/*
* Can't use sync call while an async call is in flight
};
static void cli_qpathinfo_streams_done(struct tevent_req *subreq);
+static void cli_qpathinfo_streams_done2(struct tevent_req *subreq);
struct tevent_req *cli_qpathinfo_streams_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
if (req == NULL) {
return NULL;
}
+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
+ subreq = cli_smb2_qpathinfo_send(state,
+ ev,
+ cli,
+ fname,
+ FSCC_FILE_STREAM_INFORMATION,
+ 0,
+ CLI_BUFFER_SIZE);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq,
+ cli_qpathinfo_streams_done2,
+ req);
+ return req;
+ }
subreq = cli_qpathinfo_send(state, ev, cli, fname,
SMB_FILE_STREAM_INFORMATION,
0, CLI_BUFFER_SIZE);
status = cli_qpathinfo_recv(subreq, state, &state->data,
&state->num_data);
- TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return;
- }
- tevent_req_done(req);
+ tevent_req_simple_finish_ntstatus(subreq, status);
+}
+
+static void cli_qpathinfo_streams_done2(struct tevent_req *subreq)
+{
+ struct tevent_req *req =
+ tevent_req_callback_data(subreq, struct tevent_req);
+ struct cli_qpathinfo_streams_state *state =
+ tevent_req_data(req, struct cli_qpathinfo_streams_state);
+ NTSTATUS status;
+
+ status = cli_smb2_qpathinfo_recv(subreq,
+ state,
+ &state->data,
+ &state->num_data);
+ tevent_req_simple_finish_ntstatus(subreq, status);
}
NTSTATUS cli_qpathinfo_streams_recv(struct tevent_req *req,
struct tevent_req *req;
NTSTATUS status = NT_STATUS_NO_MEMORY;
- if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
- return cli_smb2_qpathinfo_streams(cli,
- fname,
- mem_ctx,
- pnum_streams,
- pstreams);
- }
-
frame = talloc_stackframe();
if (smbXcli_conn_has_async_calls(cli->conn)) {
Send a qfileinfo QUERY_FILE_NAME_INFO call.
****************************************************************************/
-NTSTATUS cli_qfilename(struct cli_state *cli, uint16_t fnum,
- TALLOC_CTX *mem_ctx, char **_name)
-{
- uint16_t recv_flags2;
- uint8_t *rdata;
- uint32_t num_rdata;
- NTSTATUS status;
- char *name = NULL;
- uint32_t namelen;
-
- status = cli_qfileinfo(talloc_tos(), cli, fnum,
- SMB_QUERY_FILE_NAME_INFO,
- 4, CLI_BUFFER_SIZE, &recv_flags2,
- &rdata, &num_rdata);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- namelen = IVAL(rdata, 0);
- if (namelen > (num_rdata - 4)) {
- TALLOC_FREE(rdata);
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
- }
-
- pull_string_talloc(mem_ctx,
- (const char *)rdata,
- recv_flags2,
- &name,
- rdata + 4,
- namelen,
- STR_UNICODE);
- if (name == NULL) {
- status = map_nt_error_from_unix(errno);
- TALLOC_FREE(rdata);
- return status;
- }
-
- *_name = name;
- TALLOC_FREE(rdata);
- return NT_STATUS_OK;
-}
-
struct cli_qfileinfo_basic_state {
uint32_t attr;
off_t size;
return;
}
- state->create_time = interpret_long_date((char *)rdata+0);
- state->access_time = interpret_long_date((char *)rdata+8);
- state->write_time = interpret_long_date((char *)rdata+16);
- state->change_time = interpret_long_date((char *)rdata+24);
+ state->create_time = interpret_long_date(BVAL(rdata, 0));
+ state->access_time = interpret_long_date(BVAL(rdata, 8));
+ state->write_time = interpret_long_date(BVAL(rdata, 16));
+ state->change_time = interpret_long_date(BVAL(rdata, 24));
state->attr = PULL_LE_U32(rdata, 32);
state->size = PULL_LE_U64(rdata,48);
state->ino = PULL_LE_U32(rdata, 64);
return;
}
- state->create_time = interpret_long_date(
- (const char *)outbuf.data + 0x0);
- state->access_time = interpret_long_date(
- (const char *)outbuf.data + 0x8);
- state->write_time = interpret_long_date(
- (const char *)outbuf.data + 0x10);
- state->change_time = interpret_long_date(
- (const char *)outbuf.data + 0x18);
+ state->create_time = interpret_long_date(BVAL(outbuf.data, 0x0));
+ state->access_time = interpret_long_date(BVAL(outbuf.data, 0x8));
+ state->write_time = interpret_long_date(BVAL(outbuf.data, 0x10));
+ state->change_time = interpret_long_date(BVAL(outbuf.data, 0x18));
state->attr = IVAL(outbuf.data, 0x20);
state->size = BVAL(outbuf.data, 0x30);
state->ino = BVAL(outbuf.data, 0x40);
status = cli_qpathinfo_recv(subreq, state, &state->data,
&state->num_data);
TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
+ if (tevent_req_nterror(req, status)) {
return;
}
tevent_req_done(req);
return status;
}
- sbuf->st_ex_btime = interpret_long_date((char *)state->data);
- sbuf->st_ex_atime = interpret_long_date((char *)state->data+8);
- sbuf->st_ex_mtime = interpret_long_date((char *)state->data+16);
- sbuf->st_ex_ctime = interpret_long_date((char *)state->data+24);
+ sbuf->st_ex_btime = interpret_long_date(BVAL(state->data, 0));
+ sbuf->st_ex_atime = interpret_long_date(BVAL(state->data, 8));
+ sbuf->st_ex_mtime = interpret_long_date(BVAL(state->data, 16));
+ sbuf->st_ex_ctime = interpret_long_date(BVAL(state->data, 24));
*attributes = IVAL(state->data, 32);
return NT_STATUS_OK;
}