s3: Add symlink reparse point marshalling routines
authorVolker Lendecke <vl@samba.org>
Thu, 23 Jun 2011 13:33:58 +0000 (15:33 +0200)
committerVolker Lendecke <vl@samba.org>
Fri, 24 Jun 2011 19:24:17 +0000 (21:24 +0200)
source3/Makefile.in
source3/libsmb/proto.h
source3/libsmb/reparse_symlink.c [new file with mode: 0644]
source3/wscript_build

index 59f9032ea2bff5425ca925c5194da7824e4ba6d1..2763277bbcef2d0e91b5a0279c37272ab52b26d3 100644 (file)
@@ -590,6 +590,7 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \
             libsmb/clikrb5.o ../libcli/auth/krb5_wrap.o libsmb/clispnego.o \
             ../libcli/auth/spnego_parse.o \
             ../lib/util/asn1.o \
+            libsmb/reparse_symlink.o \
             libsmb/clirap.o libsmb/clierror.o libsmb/climessage.o \
             libsmb/clireadwrite.o libsmb/clilist.o libsmb/cliprint.o \
             libsmb/clitrans.o libsmb/clisecdesc.o libsmb/clidgram.o \
index f88a891d5853792a7ea75a87fb03adf6b3106b03..4d820d6bc676e4e9fc487aa486cdcbdaf0bacee2 100644 (file)
@@ -851,4 +851,13 @@ bool client_is_signing_allowed(struct cli_state *cli);
 bool client_is_signing_mandatory(struct cli_state *cli);
 void cli_set_signing_negotiated(struct cli_state *cli);
 
+/* The following definitions come from libsmb/reparse_symlink.c  */
+
+bool symlink_reparse_buffer_marshall(
+       const char *substitute, const char *printname, uint32_t flags,
+       TALLOC_CTX *mem_ctx, uint8_t **pdst, size_t *pdstlen);
+bool symlink_reparse_buffer_parse(
+       const uint8_t *src, size_t srclen, TALLOC_CTX *mem_ctx,
+       char **psubstitute_name, char **pprint_name, uint32_t *pflags);
+
 #endif /* _LIBSMB_PROTO_H_ */
diff --git a/source3/libsmb/reparse_symlink.c b/source3/libsmb/reparse_symlink.c
new file mode 100644 (file)
index 0000000..9c158ee
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Unix SMB/CIFS implementation.
+ *
+ * Implementation of
+ * http://msdn.microsoft.com/en-us/library/cc232006%28v=PROT.13%29.aspx
+ *
+ * Copyright (C) Volker Lendecke 2011
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+#include "include/client.h"
+#include "libsmb/proto.h"
+#include "include/ntioctl.h"
+
+bool symlink_reparse_buffer_marshall(
+       const char *substitute, const char *printname, uint32_t flags,
+       TALLOC_CTX *mem_ctx, uint8_t **pdst, size_t *pdstlen)
+{
+       uint8_t *dst = NULL;
+       size_t dst_len;
+       uint8_t *subst_utf16 = NULL;
+       uint8_t *print_utf16 = NULL;
+       size_t subst_len = 0;
+       size_t print_len = 0;
+
+       if (substitute == NULL) {
+               return false;
+       }
+       if (printname == NULL) {
+               printname = substitute;
+       }
+
+       if (!convert_string_talloc(talloc_tos(), CH_UNIX, CH_UTF16,
+                                  substitute, strlen(substitute),
+                                  &subst_utf16, &subst_len)) {
+               goto fail;
+       }
+       if (!convert_string_talloc(talloc_tos(), CH_UNIX, CH_UTF16,
+                                  printname, strlen(printname),
+                                  &print_utf16, &print_len)) {
+               goto fail;
+       }
+       dst_len = 20 + subst_len + print_len;
+       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, 0);                          /* 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);
+               TALLOC_FREE(subst_utf16);
+       }
+
+       if ((print_utf16 != NULL) && (print_len != 0)) {
+               memcpy(dst + 20 + subst_len, print_utf16, print_len);
+               TALLOC_FREE(print_utf16);
+       }
+
+       *pdst = dst;
+       *pdstlen = dst_len;
+       return true;
+fail:
+       TALLOC_FREE(subst_utf16);
+       TALLOC_FREE(print_utf16);
+       return false;
+}
+
+bool symlink_reparse_buffer_parse(
+       const uint8_t *src, size_t srclen, TALLOC_CTX *mem_ctx,
+       char **psubstitute_name, char **pprint_name, uint32_t *pflags)
+{
+       uint16_t reparse_data_length;
+       uint16_t substitute_name_offset, substitute_name_length;
+       uint16_t print_name_offset, print_name_length;
+       uint32_t flags;
+       char *substitute_name = NULL;
+       char *print_name = NULL;
+
+       if (srclen < 20) {
+               DEBUG(10, ("srclen = %d, expected >= 20\n", (int)srclen));
+               return false;
+       }
+       if (IVAL(src, 0) != IO_REPARSE_TAG_SYMLINK) {
+               DEBUG(10, ("Got ReparseTag %8.8x, expected %8.8x\n",
+                          IVAL(src, 0), IO_REPARSE_TAG_SYMLINK));
+               return false;
+       }
+
+       reparse_data_length     = SVAL(src, 4);
+       substitute_name_offset  = SVAL(src, 8);
+       substitute_name_length  = SVAL(src, 10);
+       print_name_offset       = SVAL(src, 12);
+       print_name_length       = SVAL(src, 14);
+       flags                   = IVAL(src, 16);
+
+       if (reparse_data_length < 12) {
+               DEBUG(10, ("reparse_data_length = %d, expected >= 12\n",
+                          (int)reparse_data_length));
+               return false;
+       }
+       if (trans_oob(srclen - 8, reparse_data_length, 0)) {
+               DEBUG(10, ("reparse_data_length (%d) too large for "
+                          "src_len (%d)\n", (int)reparse_data_length,
+                          (int)srclen));
+               return false;
+       }
+       if (trans_oob(reparse_data_length - 12, substitute_name_offset,
+                     substitute_name_length)) {
+               DEBUG(10, ("substitute_name (%d/%d) does not fit in "
+                          "reparse_data_length (%d)\n",
+                          (int)substitute_name_offset,
+                          (int)substitute_name_length,
+                          (int)reparse_data_length - 12));
+               return false;
+       }
+       if (trans_oob(reparse_data_length - 12, print_name_offset,
+                     print_name_length)) {
+               DEBUG(10, ("print_name (%d/%d) does not fit in "
+                          "reparse_data_length (%d)\n",
+                          (int)print_name_offset,
+                          (int)print_name_length,
+                          (int)reparse_data_length - 12));
+               return false;
+       }
+
+       if ((psubstitute_name != NULL) &&
+           !convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX,
+                                  src + 20 + substitute_name_offset,
+                                  substitute_name_length,
+                                  &substitute_name, NULL)) {
+               DEBUG(10, ("convert_string_talloc for substitute_name "
+                          "failed\n"));
+               return false;
+       }
+       if ((pprint_name != NULL) &&
+           !convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX,
+                                  src + 20 + print_name_offset,
+                                  print_name_length,
+                                  &print_name, NULL)) {
+               DEBUG(10, ("convert_string_talloc for print_name "
+                          "failed\n"));
+               TALLOC_FREE(substitute_name);
+               return false;
+       }
+       if (psubstitute_name != NULL) {
+               *psubstitute_name = substitute_name;
+       }
+       if (pprint_name != NULL) {
+               *pprint_name = print_name;
+       }
+       return true;
+}
index 5563b3a4e917481a39ded6ab7634602596c2873d..d071053d5e654f07ad73ce522ac80e623783a450 100755 (executable)
@@ -137,6 +137,7 @@ LIBSMB_SRC = '''libsmb/clientgen.c libsmb/cliconnect.c libsmb/clifile.c
              libsmb/clioplock.c libsmb/clirap2.c
              libsmb/smb_seal.c libsmb/async_smb.c  libsmb/read_smb.c
              libsmb/cli_np_tstream.c
+             libsmb/reparse_symlink.c
              libsmb/smbsock_connect.c'''
 
 LIBMSRPC_SRC = '''