summaryrefslogtreecommitdiff
path: root/libcli
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2022-11-10 13:46:25 +0100
committerJeremy Allison <jra@samba.org>2022-11-22 18:27:33 +0000
commite7516fa9884dfa114703c1d532fa39dddd9bef47 (patch)
tree91e4c72a18e4f1a8d65d030eaa3a9a758024d8df /libcli
parentd79566c782f308d470a6075593c3e8fb6b7bcad0 (diff)
downloadsamba-e7516fa9884dfa114703c1d532fa39dddd9bef47.tar.gz
samba-e7516fa9884dfa114703c1d532fa39dddd9bef47.tar.bz2
samba-e7516fa9884dfa114703c1d532fa39dddd9bef47.zip
libsmb: Factor out reparse_buffer_marshall from symlink_reparse_buffer_marshall()
Make it easier to play with reparse points Signed-off-by: Volker Lendecke <vl@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'libcli')
-rw-r--r--libcli/smb/reparse_symlink.c93
-rw-r--r--libcli/smb/reparse_symlink.h9
2 files changed, 80 insertions, 22 deletions
diff --git a/libcli/smb/reparse_symlink.c b/libcli/smb/reparse_symlink.c
index 31a438013fc..51570b563e4 100644
--- a/libcli/smb/reparse_symlink.c
+++ b/libcli/smb/reparse_symlink.c
@@ -28,6 +28,39 @@
#include "libcli/smb/smb_util.h"
#include "lib/util/debug.h"
+ssize_t reparse_buffer_marshall(
+ uint32_t reparse_tag,
+ uint16_t reserved,
+ const struct iovec *iov,
+ int iovlen,
+ uint8_t *buf,
+ size_t buflen)
+{
+ ssize_t reparse_data_length = iov_buflen(iov, iovlen);
+ size_t needed;
+
+ if (reparse_data_length == -1) {
+ return -1;
+ }
+ if (reparse_data_length > UINT16_MAX) {
+ return -1;
+ }
+
+ needed = reparse_data_length + 8;
+ if (needed < reparse_data_length) {
+ return -1;
+ }
+
+ if (buflen >= needed) {
+ PUSH_LE_U32(buf, 0, reparse_tag);
+ PUSH_LE_U16(buf, 4, reparse_data_length);
+ PUSH_LE_U16(buf, 6, reserved);
+ iov_buf(iov, iovlen, buf+8, buflen-8);
+ }
+
+ return needed;
+}
+
bool symlink_reparse_buffer_marshall(
const char *substitute,
const char *printname,
@@ -37,8 +70,10 @@ bool symlink_reparse_buffer_marshall(
uint8_t **pdst,
size_t *pdstlen)
{
+ uint8_t sbuf[12];
+ struct iovec iov[3];
uint8_t *dst = NULL;
- size_t dst_len;
+ ssize_t dst_len;
uint8_t *subst_utf16 = NULL;
uint8_t *print_utf16 = NULL;
size_t subst_len = 0;
@@ -53,6 +88,8 @@ bool symlink_reparse_buffer_marshall(
printname = substitute;
}
+ iov[0] = (struct iovec) { .iov_base = sbuf, .iov_len = sizeof(sbuf), };
+
ok = convert_string_talloc(
mem_ctx,
CH_UNIX,
@@ -64,6 +101,12 @@ bool symlink_reparse_buffer_marshall(
if (!ok) {
goto fail;
}
+ if (subst_len > UINT16_MAX) {
+ goto fail;
+ }
+ iov[1] = (struct iovec) {
+ .iov_base = subst_utf16, .iov_len = subst_len,
+ };
ok = convert_string_talloc(
mem_ctx,
@@ -76,36 +119,42 @@ bool symlink_reparse_buffer_marshall(
if (!ok) {
goto fail;
}
-
- dst_len = subst_len + 20;
- if (dst_len < 20) {
+ if (print_len > UINT16_MAX) {
goto fail;
}
- dst_len += print_len;
- if (dst_len < print_len) {
+ iov[2] = (struct iovec) {
+ .iov_base = print_utf16, .iov_len = print_len,
+ };
+
+ PUSH_LE_U16(sbuf, 0, 0); /* SubstituteNameOffset */
+ PUSH_LE_U16(sbuf, 2, subst_len); /* SubstituteNameLength */
+ PUSH_LE_U16(sbuf, 4, subst_len); /* PrintNameOffset */
+ PUSH_LE_U16(sbuf, 6, print_len); /* PrintNameLength */
+ PUSH_LE_U32(sbuf, 8, flags); /* Flags */
+
+ dst_len = reparse_buffer_marshall(
+ IO_REPARSE_TAG_SYMLINK,
+ unparsed_path_length,
+ iov,
+ ARRAY_SIZE(iov),
+ NULL,
+ 0);
+ if (dst_len == -1) {
goto fail;
}
+
dst = talloc_array(mem_ctx, uint8_t, dst_len);
if (dst == NULL) {
goto fail;
}
- SIVAL(dst, 0, IO_REPARSE_TAG_SYMLINK); /* ReparseTag */
- SSVAL(dst, 4, 12 + subst_len + print_len); /* ReparseDataLength */
- SSVAL(dst, 6, unparsed_path_length); /* Reserved */
- SSVAL(dst, 8, 0); /* SubstituteNameOffset */
- SSVAL(dst, 10, subst_len); /* SubstituteNameLength */
- SSVAL(dst, 12, subst_len); /* PrintNameOffset */
- SSVAL(dst, 14, print_len); /* PrintNameLength */
- SIVAL(dst, 16, flags); /* Flags */
-
- if ((subst_utf16 != NULL) && (subst_len != 0)) {
- memcpy(dst + 20, subst_utf16, subst_len);
- }
-
- if ((print_utf16 != NULL) && (print_len != 0)) {
- memcpy(dst + 20 + subst_len, print_utf16, print_len);
- }
+ reparse_buffer_marshall(
+ IO_REPARSE_TAG_SYMLINK,
+ unparsed_path_length,
+ iov,
+ ARRAY_SIZE(iov),
+ dst,
+ dst_len);
*pdst = dst;
*pdstlen = dst_len;
diff --git a/libcli/smb/reparse_symlink.h b/libcli/smb/reparse_symlink.h
index 7791d71663e..2f57a592eec 100644
--- a/libcli/smb/reparse_symlink.h
+++ b/libcli/smb/reparse_symlink.h
@@ -25,6 +25,7 @@
#include "replace.h"
#include <talloc.h>
+#include "lib/util/iov_buf.h"
struct symlink_reparse_struct {
uint16_t unparsed_path_length; /* reserved for the reparse point */
@@ -33,6 +34,14 @@ struct symlink_reparse_struct {
uint32_t flags;
};
+ssize_t reparse_buffer_marshall(
+ uint32_t reparse_tag,
+ uint16_t reserved,
+ const struct iovec *iov,
+ int iovlen,
+ uint8_t *buf,
+ size_t buflen);
+
bool symlink_reparse_buffer_marshall(
const char *substitute,
const char *printname,