#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,
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;
printname = substitute;
}
+ iov[0] = (struct iovec) { .iov_base = sbuf, .iov_len = sizeof(sbuf), };
+
ok = convert_string_talloc(
mem_ctx,
CH_UNIX,
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,
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;