diff options
| author | Volker Lendecke <vl@samba.org> | 2022-11-10 13:46:25 +0100 |
|---|---|---|
| committer | Jeremy Allison <jra@samba.org> | 2022-11-22 18:27:33 +0000 |
| commit | e7516fa9884dfa114703c1d532fa39dddd9bef47 (patch) | |
| tree | 91e4c72a18e4f1a8d65d030eaa3a9a758024d8df /libcli | |
| parent | d79566c782f308d470a6075593c3e8fb6b7bcad0 (diff) | |
| download | samba-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.c | 93 | ||||
| -rw-r--r-- | libcli/smb/reparse_symlink.h | 9 |
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, |
