#include "libcli/security/secdesc.h"
#include "../libcli/smb/smbXcli_base.h"
-/***********************************************************
- Common function for pushing stings, used by smb_bytes_push_str()
- and trans_bytes_push_str(). Only difference is the align_odd
- parameter setting.
-***********************************************************/
-
-static uint8_t *internal_bytes_push_str(uint8_t *buf, bool ucs2,
- const char *str, size_t str_len,
- bool align_odd,
- size_t *pconverted_size)
-{
- size_t buflen;
- char *converted;
- size_t converted_size;
-
- if (buf == NULL) {
- return NULL;
- }
-
- buflen = talloc_get_size(buf);
-
- if (ucs2 &&
- ((align_odd && (buflen % 2 == 0)) ||
- (!align_odd && (buflen % 2 == 1)))) {
- /*
- * We're pushing into an SMB buffer, align odd
- */
- buf = talloc_realloc(NULL, buf, uint8_t, buflen + 1);
- if (buf == NULL) {
- return NULL;
- }
- buf[buflen] = '\0';
- buflen += 1;
- }
-
- if (!convert_string_talloc(talloc_tos(), CH_UNIX,
- ucs2 ? CH_UTF16LE : CH_DOS,
- str, str_len, &converted,
- &converted_size)) {
- return NULL;
- }
-
- buf = talloc_realloc(NULL, buf, uint8_t,
- buflen + converted_size);
- if (buf == NULL) {
- TALLOC_FREE(converted);
- return NULL;
- }
-
- memcpy(buf + buflen, converted, converted_size);
-
- TALLOC_FREE(converted);
-
- if (pconverted_size) {
- *pconverted_size = converted_size;
- }
-
- return buf;
-}
-
-/***********************************************************
- Push a string into an SMB buffer, with odd byte alignment
- if it's a UCS2 string.
-***********************************************************/
-
-uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2,
- const char *str, size_t str_len,
- size_t *pconverted_size)
-{
- return internal_bytes_push_str(buf, ucs2, str, str_len,
- true, pconverted_size);
-}
-
-uint8_t *smb_bytes_push_bytes(uint8_t *buf, uint8_t prefix,
- const uint8_t *bytes, size_t num_bytes)
-{
- size_t buflen;
-
- if (buf == NULL) {
- return NULL;
- }
- buflen = talloc_get_size(buf);
-
- buf = talloc_realloc(NULL, buf, uint8_t,
- buflen + 1 + num_bytes);
- if (buf == NULL) {
- return NULL;
- }
- buf[buflen] = prefix;
- memcpy(&buf[buflen+1], bytes, num_bytes);
- return buf;
-}
-
-/***********************************************************
- Same as smb_bytes_push_str(), but without the odd byte
- align for ucs2 (we're pushing into a param or data block).
- static for now, although this will probably change when
- other modules use async trans calls.
-***********************************************************/
-
-uint8_t *trans2_bytes_push_str(uint8_t *buf, bool ucs2,
- const char *str, size_t str_len,
- size_t *pconverted_size)
-{
- return internal_bytes_push_str(buf, ucs2, str, str_len,
- false, pconverted_size);
-}
-
-uint8_t *trans2_bytes_push_bytes(uint8_t *buf,
- const uint8_t *bytes, size_t num_bytes)
-{
- size_t buflen;
-
- if (buf == NULL) {
- return NULL;
- }
- buflen = talloc_get_size(buf);
-
- buf = talloc_realloc(NULL, buf, uint8_t,
- buflen + num_bytes);
- if (buf == NULL) {
- return NULL;
- }
- memcpy(&buf[buflen], bytes, num_bytes);
- return buf;
-}
-
struct cli_setpathinfo_state {
uint16_t setup;
uint8_t *param;
return tevent_req_post(req, ev);
}
- if (clistr_is_previous_version_path(path) &&
+ if (clistr_is_previous_version_path(path, NULL, NULL, NULL) &&
!INFO_LEVEL_IS_UNIX(level)) {
additional_flags2 = FLAGS2_REPARSE_PATH;
}
Rename a file.
****************************************************************************/
-static void cli_rename_done(struct tevent_req *subreq);
+static struct tevent_req *cli_cifs_rename_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct cli_state *cli,
+ const char *fname_src,
+ const char *fname_dst,
+ bool replace);
+
+static struct tevent_req *cli_smb1_rename_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct cli_state *cli,
+ const char *fname_src,
+ const char *fname_dst,
+ bool replace);
+
+struct tevent_req *cli_rename_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct cli_state *cli,
+ const char *fname_src,
+ const char *fname_dst,
+ bool replace)
+{
+ if (replace && smbXcli_conn_support_passthrough(cli->conn)) {
+ return cli_smb1_rename_send(mem_ctx, ev, cli, fname_src,
+ fname_dst, replace);
+ } else {
+ return cli_cifs_rename_send(mem_ctx, ev, cli, fname_src,
+ fname_dst, replace);
+ }
+}
+
+struct cli_smb1_rename_state {
+ uint8_t *data;
+};
+
+static void cli_smb1_rename_done(struct tevent_req *subreq);
+
+static struct tevent_req *cli_smb1_rename_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct cli_state *cli,
+ const char *fname_src,
+ const char *fname_dst,
+ bool replace)
+{
+ NTSTATUS status;
+ struct tevent_req *req = NULL, *subreq = NULL;
+ struct cli_smb1_rename_state *state = NULL;
+ smb_ucs2_t *converted_str = NULL;
+ size_t converted_size_bytes = 0;
+
+ req = tevent_req_create(mem_ctx, &state, struct cli_smb1_rename_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ if (!push_ucs2_talloc(talloc_tos(), &converted_str, fname_dst,
+ &converted_size_bytes)) {
+ status = NT_STATUS_INVALID_PARAMETER;
+ goto fail;
+ }
+
+ /* W2K8 insists the dest name is not null
+ terminated. Remove the last 2 zero bytes
+ and reduce the name length. */
+
+ if (converted_size_bytes < 2) {
+ status = NT_STATUS_INVALID_PARAMETER;
+ goto fail;
+ }
+ converted_size_bytes -= 2;
+
+ state->data =
+ talloc_zero_array(state, uint8_t, 12 + converted_size_bytes);
+ if (state->data == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
+
+ if (replace) {
+ SCVAL(state->data, 0, 1);
+ }
+
+ SIVAL(state->data, 8, converted_size_bytes);
+ memcpy(state->data + 12, converted_str, converted_size_bytes);
+
+ TALLOC_FREE(converted_str);
+
+ subreq = cli_setpathinfo_send(
+ state, ev, cli, SMB_FILE_RENAME_INFORMATION, fname_src, state->data,
+ talloc_get_size(state->data));
+ if (tevent_req_nomem(subreq, req)) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
+ tevent_req_set_callback(subreq, cli_smb1_rename_done, req);
+ return req;
+
+fail:
+ TALLOC_FREE(converted_str);
+ tevent_req_nterror(req, status);
+ return tevent_req_post(req, ev);
+}
+
+static void cli_smb1_rename_done(struct tevent_req *subreq)
+{
+ NTSTATUS status = cli_setpathinfo_recv(subreq);
+ tevent_req_simple_finish_ntstatus(subreq, status);
+}
+
+static void cli_cifs_rename_done(struct tevent_req *subreq);
-struct cli_rename_state {
+struct cli_cifs_rename_state {
uint16_t vwv[1];
};
-struct tevent_req *cli_rename_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct cli_state *cli,
- const char *fname_src,
- const char *fname_dst)
+static struct tevent_req *cli_cifs_rename_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct cli_state *cli,
+ const char *fname_src,
+ const char *fname_dst,
+ bool replace)
{
struct tevent_req *req = NULL, *subreq = NULL;
- struct cli_rename_state *state = NULL;
+ struct cli_cifs_rename_state *state = NULL;
uint8_t additional_flags = 0;
uint16_t additional_flags2 = 0;
uint8_t *bytes = NULL;
- req = tevent_req_create(mem_ctx, &state, struct cli_rename_state);
+ req = tevent_req_create(mem_ctx, &state, struct cli_cifs_rename_state);
if (req == NULL) {
return NULL;
}
+ if (replace) {
+ /*
+ * CIFS doesn't support replace
+ */
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return tevent_req_post(req, ev);
+ }
+
SSVAL(state->vwv+0, 0, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY);
bytes = talloc_array(state, uint8_t, 1);
return tevent_req_post(req, ev);
}
- if (clistr_is_previous_version_path(fname_src)) {
+ if (clistr_is_previous_version_path(fname_src, NULL, NULL, NULL)) {
additional_flags2 = FLAGS2_REPARSE_PATH;
}
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
- tevent_req_set_callback(subreq, cli_rename_done, req);
+ tevent_req_set_callback(subreq, cli_cifs_rename_done, req);
return req;
}
-static void cli_rename_done(struct tevent_req *subreq)
+static void cli_cifs_rename_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(
subreq, struct tevent_req);
return tevent_req_simple_recv_ntstatus(req);
}
-NTSTATUS cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
+NTSTATUS cli_rename(struct cli_state *cli,
+ const char *fname_src,
+ const char *fname_dst,
+ bool replace)
{
TALLOC_CTX *frame = NULL;
struct tevent_context *ev;
NTSTATUS status = NT_STATUS_OK;
if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
- return cli_smb2_rename(cli,
- fname_src,
- fname_dst);
+ return cli_smb2_rename(cli, fname_src, fname_dst, replace);
}
frame = talloc_stackframe();
goto fail;
}
- req = cli_rename_send(frame, ev, cli, fname_src, fname_dst);
+ req = cli_rename_send(frame, ev, cli, fname_src, fname_dst, replace);
if (req == NULL) {
status = NT_STATUS_NO_MEMORY;
goto fail;
struct tevent_req *req = NULL, *subreq = NULL;
struct cli_ntrename_internal_state *state = NULL;
uint8_t additional_flags = 0;
+ uint16_t additional_flags2 = 0;
uint8_t *bytes = NULL;
req = tevent_req_create(mem_ctx, &state,
return tevent_req_post(req, ev);
}
+ if (clistr_is_previous_version_path(fname_src, NULL, NULL, NULL)) {
+ additional_flags2 = FLAGS2_REPARSE_PATH;
+ }
+
bytes = talloc_realloc(state, bytes, uint8_t,
talloc_get_size(bytes)+1);
if (tevent_req_nomem(bytes, req)) {
return tevent_req_post(req, ev);
}
- subreq = cli_smb_send(state, ev, cli, SMBntrename, additional_flags, 0,
- 4, state->vwv, talloc_get_size(bytes), bytes);
+ subreq = cli_smb_send(state, ev, cli, SMBntrename, additional_flags,
+ additional_flags2,
+ 4, state->vwv, talloc_get_size(bytes), bytes);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
struct tevent_req *req = NULL, *subreq = NULL;
struct cli_unlink_state *state = NULL;
uint8_t additional_flags = 0;
+ uint16_t additional_flags2 = 0;
uint8_t *bytes = NULL;
req = tevent_req_create(mem_ctx, &state, struct cli_unlink_state);
return tevent_req_post(req, ev);
}
- subreq = cli_smb_send(state, ev, cli, SMBunlink, additional_flags, 0,
+ if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
+ additional_flags2 = FLAGS2_REPARSE_PATH;
+ }
+
+ subreq = cli_smb_send(state, ev, cli, SMBunlink, additional_flags,
+ additional_flags2,
1, state->vwv, talloc_get_size(bytes), bytes);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
struct tevent_req *req = NULL, *subreq = NULL;
struct cli_mkdir_state *state = NULL;
uint8_t additional_flags = 0;
+ uint16_t additional_flags2 = 0;
uint8_t *bytes = NULL;
req = tevent_req_create(mem_ctx, &state, struct cli_mkdir_state);
return tevent_req_post(req, ev);
}
- subreq = cli_smb_send(state, ev, cli, SMBmkdir, additional_flags, 0,
- 0, NULL, talloc_get_size(bytes), bytes);
+ if (clistr_is_previous_version_path(dname, NULL, NULL, NULL)) {
+ additional_flags2 = FLAGS2_REPARSE_PATH;
+ }
+
+ subreq = cli_smb_send(state, ev, cli, SMBmkdir, additional_flags,
+ additional_flags2,
+ 0, NULL, talloc_get_size(bytes), bytes);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
struct tevent_req *req = NULL, *subreq = NULL;
struct cli_rmdir_state *state = NULL;
uint8_t additional_flags = 0;
+ uint16_t additional_flags2 = 0;
uint8_t *bytes = NULL;
req = tevent_req_create(mem_ctx, &state, struct cli_rmdir_state);
return tevent_req_post(req, ev);
}
- subreq = cli_smb_send(state, ev, cli, SMBrmdir, additional_flags, 0,
- 0, NULL, talloc_get_size(bytes), bytes);
+ if (clistr_is_previous_version_path(dname, NULL, NULL, NULL)) {
+ additional_flags2 = FLAGS2_REPARSE_PATH;
+ }
+
+ subreq = cli_smb_send(state, ev, cli, SMBrmdir, additional_flags,
+ additional_flags2,
+ 0, NULL, talloc_get_size(bytes), bytes);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
uint16_t *vwv;
uint8_t *bytes;
size_t converted_len;
+ uint16_t additional_flags2 = 0;
req = tevent_req_create(mem_ctx, &state, struct cli_ntcreate1_state);
if (req == NULL) {
fname, strlen(fname)+1,
&converted_len);
+ if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
+ additional_flags2 = FLAGS2_REPARSE_PATH;
+ }
+
/* sigh. this copes with broken netapp filer behaviour */
bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, NULL);
SSVAL(vwv+2, 1, converted_len);
- subreq = cli_smb_send(state, ev, cli, SMBntcreateX, 0, 0, 24, vwv,
- talloc_get_size(bytes), bytes);
+ subreq = cli_smb_send(state, ev, cli, SMBntcreateX, 0,
+ additional_flags2, 24, vwv,
+ talloc_get_size(bytes), bytes);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
size_t secdesc_len;
NTSTATUS status;
size_t converted_len;
+ uint16_t additional_flags2 = 0;
req = tevent_req_create(mem_ctx,
&state, struct cli_nttrans_create_state);
return tevent_req_post(req, ev);
}
+ if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
+ additional_flags2 = FLAGS2_REPARSE_PATH;
+ }
+
SIVAL(param, 0, CreatFlags);
SIVAL(param, 4, 0x0); /* RootDirectoryFid */
SIVAL(param, 8, DesiredAccess);
SCVAL(param, 52, SecurityFlags);
subreq = cli_trans_send(state, ev, cli,
- 0, /* additional_flags2 */
+ additional_flags2, /* additional_flags2 */
SMBnttrans,
NULL, -1, /* name, fid */
NT_TRANSACT_CREATE, 0,
unsigned openfn;
unsigned accessmode;
uint8_t additional_flags;
+ uint16_t additional_flags2 = 0;
uint8_t *bytes;
req = tevent_req_create(mem_ctx, &state, struct cli_openx_state);
return tevent_req_post(req, ev);
}
+ if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
+ additional_flags2 = FLAGS2_REPARSE_PATH;
+ }
+
state->bytes.iov_base = (void *)bytes;
state->bytes.iov_len = talloc_get_size(bytes);
subreq = cli_smb_req_create(state, ev, cli, SMBopenX, additional_flags,
- 0, 15, state->vwv, 1, &state->bytes);
+ additional_flags2, 15, state->vwv, 1, &state->bytes);
if (subreq == NULL) {
TALLOC_FREE(req);
return NULL;
NTSTATUS cli_ftruncate(struct cli_state *cli, uint16_t fnum, uint64_t size)
{
- TALLOC_CTX *frame = talloc_stackframe();
+ TALLOC_CTX *frame = NULL;
struct tevent_context *ev = NULL;
struct tevent_req *req = NULL;
NTSTATUS status = NT_STATUS_OK;
+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
+ return cli_smb2_ftruncate(cli, fnum, size);
+ }
+
+ frame = talloc_stackframe();
+
if (smbXcli_conn_has_async_calls(cli->conn)) {
/*
* Can't use sync call while an async call is in flight
struct tevent_req *req = NULL, *subreq = NULL;
struct cli_getatr_state *state = NULL;
uint8_t additional_flags = 0;
+ uint16_t additional_flags2 = 0;
uint8_t *bytes = NULL;
req = tevent_req_create(mem_ctx, &state, struct cli_getatr_state);
return tevent_req_post(req, ev);
}
- subreq = cli_smb_send(state, ev, cli, SMBgetatr, additional_flags, 0,
- 0, NULL, talloc_get_size(bytes), bytes);
+ if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
+ additional_flags2 = FLAGS2_REPARSE_PATH;
+ }
+
+ subreq = cli_smb_send(state, ev, cli, SMBgetatr, additional_flags,
+ additional_flags2,
+ 0, NULL, talloc_get_size(bytes), bytes);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
struct tevent_req *req = NULL, *subreq = NULL;
struct cli_setatr_state *state = NULL;
uint8_t additional_flags = 0;
+ uint16_t additional_flags2 = 0;
uint8_t *bytes = NULL;
req = tevent_req_create(mem_ctx, &state, struct cli_setatr_state);
return tevent_req_post(req, ev);
}
- subreq = cli_smb_send(state, ev, cli, SMBsetatr, additional_flags, 0,
- 8, state->vwv, talloc_get_size(bytes), bytes);
+ if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
+ additional_flags2 = FLAGS2_REPARSE_PATH;
+ }
+
+ subreq = cli_smb_send(state, ev, cli, SMBsetatr, additional_flags,
+ additional_flags2,
+ 8, state->vwv, talloc_get_size(bytes), bytes);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
}
/****************************************************************************
- Check for existance of a dir.
+ Check for existence of a dir.
****************************************************************************/
static void cli_chkpath_done(struct tevent_req *subreq);
struct tevent_req *req = NULL, *subreq = NULL;
struct cli_chkpath_state *state = NULL;
uint8_t additional_flags = 0;
+ uint16_t additional_flags2 = 0;
uint8_t *bytes = NULL;
req = tevent_req_create(mem_ctx, &state, struct cli_chkpath_state);
return tevent_req_post(req, ev);
}
- subreq = cli_smb_send(state, ev, cli, SMBcheckpath, additional_flags, 0,
- 0, NULL, talloc_get_size(bytes), bytes);
+ if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
+ additional_flags2 = FLAGS2_REPARSE_PATH;
+ }
+
+ subreq = cli_smb_send(state, ev, cli, SMBcheckpath, additional_flags,
+ additional_flags2,
+ 0, NULL, talloc_get_size(bytes), bytes);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
struct tevent_req *req = NULL, *subreq = NULL;
struct ctemp_state *state = NULL;
uint8_t additional_flags = 0;
+ uint16_t additional_flags2 = 0;
uint8_t *bytes = NULL;
req = tevent_req_create(mem_ctx, &state, struct ctemp_state);
return tevent_req_post(req, ev);
}
- subreq = cli_smb_send(state, ev, cli, SMBctemp, additional_flags, 0,
- 3, state->vwv, talloc_get_size(bytes), bytes);
+ if (clistr_is_previous_version_path(path, NULL, NULL, NULL)) {
+ additional_flags2 = FLAGS2_REPARSE_PATH;
+ }
+
+ subreq = cli_smb_send(state, ev, cli, SMBctemp, additional_flags,
+ additional_flags2,
+ 3, state->vwv, talloc_get_size(bytes), bytes);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
memcpy(p+4+ea_namelen+1, ea_val, ea_len);
}
+ /*
+ * FIXME - if we want to do previous version path
+ * processing on an EA set call we need to turn this
+ * into calls to cli_trans_send()/cli_trans_recv()
+ * with a temporary event context, as cli_trans_send()
+ * have access to the additional_flags2 needed to
+ * send @GMT- paths. JRA.
+ */
+
status = cli_trans(talloc_tos(), cli, SMBtrans2, NULL, -1, 0, 0,
setup, 1, 0,
param, param_len, 2,
return tevent_req_post(req, ev);
}
- if (clistr_is_previous_version_path(fname) &&
+ if (clistr_is_previous_version_path(fname, NULL, NULL, NULL) &&
!INFO_LEVEL_IS_UNIX(level)) {
additional_flags2 = FLAGS2_REPARSE_PATH;
}
subreq = cli_trans_send(
state, ev, cli, 0, SMBnttrans, NULL, 0, NT_TRANSACT_IOCTL, 0,
- state->setup, ARRAY_SIZE(state->setup), 0,
+ state->setup, ARRAY_SIZE(state->setup),
+ ARRAY_SIZE(state->setup),
NULL, 0, 0,
NULL, 0, ret_size);
if (tevent_req_nomem(subreq, req)) {
{
struct cli_shadow_copy_data_state *state = tevent_req_data(
req, struct cli_shadow_copy_data_state);
- char **names;
- int i, num_names;
+ char **names = NULL;
+ uint32_t i, num_names;
uint32_t dlength;
+ uint8_t *endp = NULL;
NTSTATUS status;
if (tevent_req_is_nterror(req, &status)) {
return status;
}
+
+ if (state->num_data < 16) {
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+
num_names = IVAL(state->data, 4);
dlength = IVAL(state->data, 8);
+ if (num_names > 0x7FFFFFFF) {
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+
if (!state->get_names) {
- *pnum_names = num_names;
+ *pnum_names = (int)num_names;
return NT_STATUS_OK;
}
- if (dlength+12 > state->num_data) {
+ if (dlength + 12 < 12) {
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+ if (dlength + 12 > state->num_data) {
return NT_STATUS_INVALID_NETWORK_RESPONSE;
}
+ if (state->num_data + (2 * sizeof(SHADOW_COPY_LABEL)) <
+ state->num_data) {
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+
names = talloc_array(mem_ctx, char *, num_names);
if (names == NULL) {
return NT_STATUS_NO_MEMORY;
}
+ endp = state->data + state->num_data;
+
for (i=0; i<num_names; i++) {
bool ret;
uint8_t *src;
size_t converted_size;
src = state->data + 12 + i * 2 * sizeof(SHADOW_COPY_LABEL);
+
+ if (src + (2 * sizeof(SHADOW_COPY_LABEL)) > endp) {
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+
ret = convert_string_talloc(
names, CH_UTF16LE, CH_UNIX,
src, 2 * sizeof(SHADOW_COPY_LABEL),
return NT_STATUS_INVALID_NETWORK_RESPONSE;
}
}
- *pnum_names = num_names;
+ *pnum_names = (int)num_names;
*pnames = names;
return NT_STATUS_OK;
}
uint16_t fnum, bool get_names,
char ***pnames, int *pnum_names)
{
- TALLOC_CTX *frame = talloc_stackframe();
+ TALLOC_CTX *frame = NULL;
struct tevent_context *ev;
struct tevent_req *req;
NTSTATUS status = NT_STATUS_NO_MEMORY;
+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
+ return cli_smb2_shadow_copy_data(mem_ctx,
+ cli,
+ fnum,
+ get_names,
+ pnames,
+ pnum_names);
+ }
+
+ frame = talloc_stackframe();
+
if (smbXcli_conn_has_async_calls(cli->conn)) {
/*
* Can't use sync call while an async call is in flight