lib: remove unused function nttime_from_string()
[bbaumbach/samba-autobuild/.git] / source3 / libsmb / reparse_symlink.c
1 /*
2  * Unix SMB/CIFS implementation.
3  *
4  * Implementation of
5  * http://msdn.microsoft.com/en-us/library/cc232006%28v=PROT.13%29.aspx
6  *
7  * Copyright (C) Volker Lendecke 2011
8  *
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.
13  *
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.
18  *
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/>.
21  */
22
23 #include "includes.h"
24 #include "include/client.h"
25 #include "libsmb/proto.h"
26 #include "include/ntioctl.h"
27
28 bool symlink_reparse_buffer_marshall(
29         const char *substitute, const char *printname, uint32_t flags,
30         TALLOC_CTX *mem_ctx, uint8_t **pdst, size_t *pdstlen)
31 {
32         uint8_t *dst = NULL;
33         size_t dst_len;
34         uint8_t *subst_utf16 = NULL;
35         uint8_t *print_utf16 = NULL;
36         size_t subst_len = 0;
37         size_t print_len = 0;
38
39         if (substitute == NULL) {
40                 return false;
41         }
42         if (printname == NULL) {
43                 printname = substitute;
44         }
45
46         if (!convert_string_talloc(talloc_tos(), CH_UNIX, CH_UTF16,
47                                    substitute, strlen(substitute),
48                                    &subst_utf16, &subst_len)) {
49                 goto fail;
50         }
51         if (!convert_string_talloc(talloc_tos(), CH_UNIX, CH_UTF16,
52                                    printname, strlen(printname),
53                                    &print_utf16, &print_len)) {
54                 goto fail;
55         }
56         dst_len = 20 + subst_len + print_len;
57         dst = talloc_array(mem_ctx, uint8_t, dst_len);
58         if (dst == NULL) {
59                 goto fail;
60         }
61
62         SIVAL(dst, 0, IO_REPARSE_TAG_SYMLINK);     /* ReparseTag */
63         SSVAL(dst, 4, 12 + subst_len + print_len); /* ReparseDataLength */
64         SSVAL(dst, 6, 0);                          /* Reserved */
65         SSVAL(dst, 8, 0);                          /* SubstituteNameOffset */
66         SSVAL(dst, 10, subst_len);                 /* SubstituteNameLength */
67         SSVAL(dst, 12, subst_len);                 /* PrintNameOffset */
68         SSVAL(dst, 14, print_len);                 /* PrintNameLength */
69         SIVAL(dst, 16, flags);                     /* Flags */
70
71         if ((subst_utf16 != NULL) && (subst_len != 0)) {
72                 memcpy(dst + 20, subst_utf16, subst_len);
73                 TALLOC_FREE(subst_utf16);
74         }
75
76         if ((print_utf16 != NULL) && (print_len != 0)) {
77                 memcpy(dst + 20 + subst_len, print_utf16, print_len);
78                 TALLOC_FREE(print_utf16);
79         }
80
81         *pdst = dst;
82         *pdstlen = dst_len;
83         return true;
84 fail:
85         TALLOC_FREE(subst_utf16);
86         TALLOC_FREE(print_utf16);
87         return false;
88 }
89
90 bool symlink_reparse_buffer_parse(
91         const uint8_t *src, size_t srclen, TALLOC_CTX *mem_ctx,
92         char **psubstitute_name, char **pprint_name, uint32_t *pflags)
93 {
94         uint16_t reparse_data_length;
95         uint16_t substitute_name_offset, substitute_name_length;
96         uint16_t print_name_offset, print_name_length;
97         uint32_t flags;
98         char *substitute_name = NULL;
99         char *print_name = NULL;
100
101         if (srclen < 20) {
102                 DEBUG(10, ("srclen = %d, expected >= 20\n", (int)srclen));
103                 return false;
104         }
105         if (IVAL(src, 0) != IO_REPARSE_TAG_SYMLINK) {
106                 DEBUG(10, ("Got ReparseTag %8.8x, expected %8.8x\n",
107                            IVAL(src, 0), IO_REPARSE_TAG_SYMLINK));
108                 return false;
109         }
110
111         reparse_data_length     = SVAL(src, 4);
112         substitute_name_offset  = SVAL(src, 8);
113         substitute_name_length  = SVAL(src, 10);
114         print_name_offset       = SVAL(src, 12);
115         print_name_length       = SVAL(src, 14);
116         flags                   = IVAL(src, 16);
117
118         if (reparse_data_length < 12) {
119                 DEBUG(10, ("reparse_data_length = %d, expected >= 12\n",
120                            (int)reparse_data_length));
121                 return false;
122         }
123         if (trans_oob(srclen - 8, reparse_data_length, 0)) {
124                 DEBUG(10, ("reparse_data_length (%d) too large for "
125                            "src_len (%d)\n", (int)reparse_data_length,
126                            (int)srclen));
127                 return false;
128         }
129         if (trans_oob(reparse_data_length - 12, substitute_name_offset,
130                       substitute_name_length)) {
131                 DEBUG(10, ("substitute_name (%d/%d) does not fit in "
132                            "reparse_data_length (%d)\n",
133                            (int)substitute_name_offset,
134                            (int)substitute_name_length,
135                            (int)reparse_data_length - 12));
136                 return false;
137         }
138         if (trans_oob(reparse_data_length - 12, print_name_offset,
139                       print_name_length)) {
140                 DEBUG(10, ("print_name (%d/%d) does not fit in "
141                            "reparse_data_length (%d)\n",
142                            (int)print_name_offset,
143                            (int)print_name_length,
144                            (int)reparse_data_length - 12));
145                 return false;
146         }
147
148         if ((psubstitute_name != NULL) &&
149             !convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX,
150                                    src + 20 + substitute_name_offset,
151                                    substitute_name_length,
152                                    &substitute_name, NULL)) {
153                 DEBUG(10, ("convert_string_talloc for substitute_name "
154                            "failed\n"));
155                 return false;
156         }
157         if ((pprint_name != NULL) &&
158             !convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX,
159                                    src + 20 + print_name_offset,
160                                    print_name_length,
161                                    &print_name, NULL)) {
162                 DEBUG(10, ("convert_string_talloc for print_name "
163                            "failed\n"));
164                 TALLOC_FREE(substitute_name);
165                 return false;
166         }
167         if (psubstitute_name != NULL) {
168                 *psubstitute_name = substitute_name;
169         }
170         if (pprint_name != NULL) {
171                 *pprint_name = print_name;
172         }
173         if (pflags != NULL) {
174                 *pflags = flags;
175         }
176         return true;
177 }