From: Volker Lendecke Date: Thu, 10 Nov 2022 12:46:25 +0000 (+0100) Subject: libsmb: Factor out reparse_buffer_marshall from symlink_reparse_buffer_marshall() X-Git-Tag: talloc-2.4.0~500 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e7516fa9884dfa114703c1d532fa39dddd9bef47;p=thirdparty%2Fsamba.git libsmb: Factor out reparse_buffer_marshall from symlink_reparse_buffer_marshall() Make it easier to play with reparse points Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- 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 +#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,