]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
libsmb: Factor out reparse_buffer_marshall from symlink_reparse_buffer_marshall()
authorVolker Lendecke <vl@samba.org>
Thu, 10 Nov 2022 12:46:25 +0000 (13:46 +0100)
committerJeremy Allison <jra@samba.org>
Tue, 22 Nov 2022 18:27:33 +0000 (18:27 +0000)
Make it easier to play with reparse points

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
libcli/smb/reparse_symlink.c
libcli/smb/reparse_symlink.h

index 31a438013fcaa75145e5c85f07259588a6d4ab25..51570b563e44609c142aefb4828d19ea3e7c081e 100644 (file)
 #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;
index 7791d71663e97915769535b05a6d9028460b9802..2f57a592eec57379627d912798fdd9a16bc585a7 100644 (file)
@@ -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,