2 * Unix SMB/CIFS implementation.
5 * http://msdn.microsoft.com/en-us/library/cc232006%28v=PROT.13%29.aspx
7 * Copyright (C) Volker Lendecke 2011
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "reparse_symlink.h"
25 #include "lib/util/charset/charset.h"
26 #include "lib/util/byteorder.h"
27 #include "libcli/smb/smb_constants.h"
28 #include "libcli/smb/smb_util.h"
29 #include "lib/util/debug.h"
31 bool symlink_reparse_buffer_marshall(
32 const char *substitute
, const char *printname
, uint32_t flags
,
33 TALLOC_CTX
*mem_ctx
, uint8_t **pdst
, size_t *pdstlen
)
37 uint8_t *subst_utf16
= NULL
;
38 uint8_t *print_utf16
= NULL
;
44 if (substitute
== NULL
) {
47 if (printname
== NULL
) {
48 printname
= substitute
;
51 ok
= convert_string_talloc(
63 ok
= convert_string_talloc(
75 dst_len
= subst_len
+ 20;
80 if (dst_len
< print_len
) {
83 dst
= talloc_array(mem_ctx
, uint8_t, dst_len
);
88 SIVAL(dst
, 0, IO_REPARSE_TAG_SYMLINK
); /* ReparseTag */
89 SSVAL(dst
, 4, 12 + subst_len
+ print_len
); /* ReparseDataLength */
90 SSVAL(dst
, 6, 0); /* Reserved */
91 SSVAL(dst
, 8, 0); /* SubstituteNameOffset */
92 SSVAL(dst
, 10, subst_len
); /* SubstituteNameLength */
93 SSVAL(dst
, 12, subst_len
); /* PrintNameOffset */
94 SSVAL(dst
, 14, print_len
); /* PrintNameLength */
95 SIVAL(dst
, 16, flags
); /* Flags */
97 if ((subst_utf16
!= NULL
) && (subst_len
!= 0)) {
98 memcpy(dst
+ 20, subst_utf16
, subst_len
);
101 if ((print_utf16
!= NULL
) && (print_len
!= 0)) {
102 memcpy(dst
+ 20 + subst_len
, print_utf16
, print_len
);
110 TALLOC_FREE(subst_utf16
);
111 TALLOC_FREE(print_utf16
);
115 struct symlink_reparse_struct
*symlink_reparse_buffer_parse(
116 TALLOC_CTX
*mem_ctx
, const uint8_t *src
, size_t srclen
)
118 struct symlink_reparse_struct
*result
= NULL
;
119 uint16_t reparse_data_length
;
120 uint16_t substitute_name_offset
, substitute_name_length
;
121 uint16_t print_name_offset
, print_name_length
;
125 DEBUG(10, ("srclen = %d, expected >= 20\n", (int)srclen
));
128 if (IVAL(src
, 0) != IO_REPARSE_TAG_SYMLINK
) {
129 DEBUG(10, ("Got ReparseTag %8.8x, expected %8.8x\n",
130 IVAL(src
, 0), IO_REPARSE_TAG_SYMLINK
));
134 reparse_data_length
= SVAL(src
, 4);
135 substitute_name_offset
= SVAL(src
, 8);
136 substitute_name_length
= SVAL(src
, 10);
137 print_name_offset
= SVAL(src
, 12);
138 print_name_length
= SVAL(src
, 14);
140 if (reparse_data_length
< 12) {
141 DEBUG(10, ("reparse_data_length = %d, expected >= 12\n",
142 (int)reparse_data_length
));
145 if (smb_buffer_oob(srclen
- 8, reparse_data_length
, 0)) {
146 DEBUG(10, ("reparse_data_length (%d) too large for "
147 "src_len (%d)\n", (int)reparse_data_length
,
151 if (smb_buffer_oob(reparse_data_length
- 12, substitute_name_offset
,
152 substitute_name_length
)) {
153 DEBUG(10, ("substitute_name (%d/%d) does not fit in "
154 "reparse_data_length (%d)\n",
155 (int)substitute_name_offset
,
156 (int)substitute_name_length
,
157 (int)reparse_data_length
- 12));
160 if (smb_buffer_oob(reparse_data_length
- 12, print_name_offset
,
161 print_name_length
)) {
162 DEBUG(10, ("print_name (%d/%d) does not fit in "
163 "reparse_data_length (%d)\n",
164 (int)print_name_offset
,
165 (int)print_name_length
,
166 (int)reparse_data_length
- 12));
170 result
= talloc_zero(mem_ctx
, struct symlink_reparse_struct
);
171 if (result
== NULL
) {
172 DBG_DEBUG("talloc failed\n");
176 ok
= convert_string_talloc(
180 src
+ 20 + substitute_name_offset
,
181 substitute_name_length
,
182 &result
->substitute_name
,
185 DEBUG(10, ("convert_string_talloc for substitute_name "
190 ok
= convert_string_talloc(
194 src
+ 20 + print_name_offset
,
199 DEBUG(10, ("convert_string_talloc for print_name "
204 result
->unparsed_path_length
= SVAL(src
, 6);
205 result
->flags
= IVAL(src
, 16);