1 | /*
|
---|
2 | Unix SMB/CIFS implementation.
|
---|
3 |
|
---|
4 | Copyright (C) Andrew Tridgell 2003
|
---|
5 | Copyright (C) Stefan Metzmacher 2006
|
---|
6 |
|
---|
7 | This program is free software; you can redistribute it and/or modify
|
---|
8 | it under the terms of the GNU General Public License as published by
|
---|
9 | the Free Software Foundation; either version 3 of the License, or
|
---|
10 | (at your option) any later version.
|
---|
11 |
|
---|
12 | This program is distributed in the hope that it will be useful,
|
---|
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
15 | GNU General Public License for more details.
|
---|
16 |
|
---|
17 | You should have received a copy of the GNU General Public License
|
---|
18 | along with this program. If not, see <http://www.gnu.org/licenses/>.
|
---|
19 | */
|
---|
20 |
|
---|
21 | #include "includes.h"
|
---|
22 | #include "smb_server/smb_server.h"
|
---|
23 | #include "librpc/gen_ndr/ndr_misc.h"
|
---|
24 | #include "libcli/raw/libcliraw.h"
|
---|
25 | #include "libcli/raw/raw_proto.h"
|
---|
26 |
|
---|
27 | #define BLOB_CHECK(cmd) do { \
|
---|
28 | NTSTATUS _status; \
|
---|
29 | _status = cmd; \
|
---|
30 | NT_STATUS_NOT_OK_RETURN(_status); \
|
---|
31 | } while (0)
|
---|
32 |
|
---|
33 | #define BLOB_CHECK_MIN_SIZE(blob, size) do { \
|
---|
34 | if ((blob)->length < (size)) { \
|
---|
35 | return NT_STATUS_INVALID_PARAMETER; \
|
---|
36 | } \
|
---|
37 | } while (0)
|
---|
38 |
|
---|
39 |
|
---|
40 | /* align the end of the blob on an 8 byte boundary */
|
---|
41 | #define BLOB_ALIGN(blob, alignment) do { \
|
---|
42 | if ((blob)->length & ((alignment)-1)) { \
|
---|
43 | uint8_t _pad = (alignment) - ((blob)->length & ((alignment)-1)); \
|
---|
44 | BLOB_CHECK(smbsrv_blob_fill_data(blob, blob, (blob)->length+_pad)); \
|
---|
45 | } \
|
---|
46 | } while (0)
|
---|
47 |
|
---|
48 | /* grow the data size of a trans2 reply */
|
---|
49 | NTSTATUS smbsrv_blob_grow_data(TALLOC_CTX *mem_ctx,
|
---|
50 | DATA_BLOB *blob,
|
---|
51 | uint32_t new_size)
|
---|
52 | {
|
---|
53 | if (new_size > blob->length) {
|
---|
54 | uint8_t *p;
|
---|
55 | p = talloc_realloc(mem_ctx, blob->data, uint8_t, new_size);
|
---|
56 | NT_STATUS_HAVE_NO_MEMORY(p);
|
---|
57 | blob->data = p;
|
---|
58 | }
|
---|
59 | blob->length = new_size;
|
---|
60 | return NT_STATUS_OK;
|
---|
61 | }
|
---|
62 |
|
---|
63 | /* grow the data, zero filling any new bytes */
|
---|
64 | NTSTATUS smbsrv_blob_fill_data(TALLOC_CTX *mem_ctx,
|
---|
65 | DATA_BLOB *blob,
|
---|
66 | uint32_t new_size)
|
---|
67 | {
|
---|
68 | uint32_t old_size = blob->length;
|
---|
69 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, new_size));
|
---|
70 | if (new_size > old_size) {
|
---|
71 | memset(blob->data + old_size, 0, new_size - old_size);
|
---|
72 | }
|
---|
73 | return NT_STATUS_OK;
|
---|
74 | }
|
---|
75 |
|
---|
76 | /*
|
---|
77 | pull a string from a blob in a trans2 request
|
---|
78 | */
|
---|
79 | size_t smbsrv_blob_pull_string(struct request_bufinfo *bufinfo,
|
---|
80 | const DATA_BLOB *blob,
|
---|
81 | uint16_t offset,
|
---|
82 | const char **str,
|
---|
83 | int flags)
|
---|
84 | {
|
---|
85 | *str = NULL;
|
---|
86 | /* we use STR_NO_RANGE_CHECK because the params are allocated
|
---|
87 | separately in a DATA_BLOB, so we need to do our own range
|
---|
88 | checking */
|
---|
89 | if (offset >= blob->length) {
|
---|
90 | return 0;
|
---|
91 | }
|
---|
92 |
|
---|
93 | return req_pull_string(bufinfo, str,
|
---|
94 | blob->data + offset,
|
---|
95 | blob->length - offset,
|
---|
96 | STR_NO_RANGE_CHECK | flags);
|
---|
97 | }
|
---|
98 |
|
---|
99 | /*
|
---|
100 | push a string into the data section of a trans2 request
|
---|
101 | return the number of bytes consumed in the output
|
---|
102 | */
|
---|
103 | size_t smbsrv_blob_push_string(TALLOC_CTX *mem_ctx,
|
---|
104 | DATA_BLOB *blob,
|
---|
105 | uint32_t len_offset,
|
---|
106 | uint32_t offset,
|
---|
107 | const char *str,
|
---|
108 | int dest_len,
|
---|
109 | int default_flags,
|
---|
110 | int flags)
|
---|
111 | {
|
---|
112 | int alignment = 0, ret = 0, pkt_len;
|
---|
113 |
|
---|
114 | /* we use STR_NO_RANGE_CHECK because the params are allocated
|
---|
115 | separately in a DATA_BLOB, so we need to do our own range
|
---|
116 | checking */
|
---|
117 | if (!str || offset >= blob->length) {
|
---|
118 | if (flags & STR_LEN8BIT) {
|
---|
119 | SCVAL(blob->data, len_offset, 0);
|
---|
120 | } else {
|
---|
121 | SIVAL(blob->data, len_offset, 0);
|
---|
122 | }
|
---|
123 | return 0;
|
---|
124 | }
|
---|
125 |
|
---|
126 | flags |= STR_NO_RANGE_CHECK;
|
---|
127 |
|
---|
128 | if (dest_len == -1 || (dest_len > blob->length - offset)) {
|
---|
129 | dest_len = blob->length - offset;
|
---|
130 | }
|
---|
131 |
|
---|
132 | if (!(flags & (STR_ASCII|STR_UNICODE))) {
|
---|
133 | flags |= default_flags;
|
---|
134 | }
|
---|
135 |
|
---|
136 | if ((offset&1) && (flags & STR_UNICODE) && !(flags & STR_NOALIGN)) {
|
---|
137 | alignment = 1;
|
---|
138 | if (dest_len > 0) {
|
---|
139 | SCVAL(blob->data + offset, 0, 0);
|
---|
140 | ret = push_string(blob->data + offset + 1, str, dest_len-1, flags);
|
---|
141 | }
|
---|
142 | } else {
|
---|
143 | ret = push_string(blob->data + offset, str, dest_len, flags);
|
---|
144 | }
|
---|
145 |
|
---|
146 | /* sometimes the string needs to be terminated, but the length
|
---|
147 | on the wire must not include the termination! */
|
---|
148 | pkt_len = ret;
|
---|
149 |
|
---|
150 | if ((flags & STR_LEN_NOTERM) && (flags & STR_TERMINATE)) {
|
---|
151 | if ((flags & STR_UNICODE) && ret >= 2) {
|
---|
152 | pkt_len = ret-2;
|
---|
153 | }
|
---|
154 | if ((flags & STR_ASCII) && ret >= 1) {
|
---|
155 | pkt_len = ret-1;
|
---|
156 | }
|
---|
157 | }
|
---|
158 |
|
---|
159 | if (flags & STR_LEN8BIT) {
|
---|
160 | SCVAL(blob->data, len_offset, pkt_len);
|
---|
161 | } else {
|
---|
162 | SIVAL(blob->data, len_offset, pkt_len);
|
---|
163 | }
|
---|
164 |
|
---|
165 | return ret + alignment;
|
---|
166 | }
|
---|
167 |
|
---|
168 | /*
|
---|
169 | append a string to the data section of a trans2 reply
|
---|
170 | len_offset points to the place in the packet where the length field
|
---|
171 | should go
|
---|
172 | */
|
---|
173 | NTSTATUS smbsrv_blob_append_string(TALLOC_CTX *mem_ctx,
|
---|
174 | DATA_BLOB *blob,
|
---|
175 | const char *str,
|
---|
176 | uint_t len_offset,
|
---|
177 | int default_flags,
|
---|
178 | int flags)
|
---|
179 | {
|
---|
180 | size_t ret;
|
---|
181 | uint32_t offset;
|
---|
182 | const int max_bytes_per_char = 3;
|
---|
183 |
|
---|
184 | offset = blob->length;
|
---|
185 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, offset + (2+strlen_m(str))*max_bytes_per_char));
|
---|
186 | ret = smbsrv_blob_push_string(mem_ctx, blob, len_offset, offset, str, -1, default_flags, flags);
|
---|
187 | if (ret < 0) {
|
---|
188 | return NT_STATUS_FOOBAR;
|
---|
189 | }
|
---|
190 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, offset + ret));
|
---|
191 | return NT_STATUS_OK;
|
---|
192 | }
|
---|
193 |
|
---|
194 | NTSTATUS smbsrv_push_passthru_fsinfo(TALLOC_CTX *mem_ctx,
|
---|
195 | DATA_BLOB *blob,
|
---|
196 | enum smb_fsinfo_level level,
|
---|
197 | union smb_fsinfo *fsinfo,
|
---|
198 | int default_str_flags)
|
---|
199 | {
|
---|
200 | uint_t i;
|
---|
201 | DATA_BLOB guid_blob;
|
---|
202 |
|
---|
203 | switch (level) {
|
---|
204 | case RAW_QFS_VOLUME_INFORMATION:
|
---|
205 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 18));
|
---|
206 |
|
---|
207 | push_nttime(blob->data, 0, fsinfo->volume_info.out.create_time);
|
---|
208 | SIVAL(blob->data, 8, fsinfo->volume_info.out.serial_number);
|
---|
209 | SSVAL(blob->data, 16, 0); /* padding */
|
---|
210 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
|
---|
211 | fsinfo->volume_info.out.volume_name.s,
|
---|
212 | 12, default_str_flags,
|
---|
213 | STR_UNICODE));
|
---|
214 |
|
---|
215 | return NT_STATUS_OK;
|
---|
216 |
|
---|
217 | case RAW_QFS_SIZE_INFORMATION:
|
---|
218 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 24));
|
---|
219 |
|
---|
220 | SBVAL(blob->data, 0, fsinfo->size_info.out.total_alloc_units);
|
---|
221 | SBVAL(blob->data, 8, fsinfo->size_info.out.avail_alloc_units);
|
---|
222 | SIVAL(blob->data, 16, fsinfo->size_info.out.sectors_per_unit);
|
---|
223 | SIVAL(blob->data, 20, fsinfo->size_info.out.bytes_per_sector);
|
---|
224 |
|
---|
225 | return NT_STATUS_OK;
|
---|
226 |
|
---|
227 | case RAW_QFS_DEVICE_INFORMATION:
|
---|
228 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 8));
|
---|
229 |
|
---|
230 | SIVAL(blob->data, 0, fsinfo->device_info.out.device_type);
|
---|
231 | SIVAL(blob->data, 4, fsinfo->device_info.out.characteristics);
|
---|
232 |
|
---|
233 | return NT_STATUS_OK;
|
---|
234 |
|
---|
235 | case RAW_QFS_ATTRIBUTE_INFORMATION:
|
---|
236 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 12));
|
---|
237 |
|
---|
238 | SIVAL(blob->data, 0, fsinfo->attribute_info.out.fs_attr);
|
---|
239 | SIVAL(blob->data, 4, fsinfo->attribute_info.out.max_file_component_length);
|
---|
240 | /* this must not be null terminated or win98 gets
|
---|
241 | confused! also note that w2k3 returns this as
|
---|
242 | unicode even when ascii is negotiated */
|
---|
243 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
|
---|
244 | fsinfo->attribute_info.out.fs_type.s,
|
---|
245 | 8, default_str_flags,
|
---|
246 | STR_UNICODE));
|
---|
247 | return NT_STATUS_OK;
|
---|
248 |
|
---|
249 |
|
---|
250 | case RAW_QFS_QUOTA_INFORMATION:
|
---|
251 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 48));
|
---|
252 |
|
---|
253 | SBVAL(blob->data, 0, fsinfo->quota_information.out.unknown[0]);
|
---|
254 | SBVAL(blob->data, 8, fsinfo->quota_information.out.unknown[1]);
|
---|
255 | SBVAL(blob->data, 16, fsinfo->quota_information.out.unknown[2]);
|
---|
256 | SBVAL(blob->data, 24, fsinfo->quota_information.out.quota_soft);
|
---|
257 | SBVAL(blob->data, 32, fsinfo->quota_information.out.quota_hard);
|
---|
258 | SBVAL(blob->data, 40, fsinfo->quota_information.out.quota_flags);
|
---|
259 |
|
---|
260 | return NT_STATUS_OK;
|
---|
261 |
|
---|
262 |
|
---|
263 | case RAW_QFS_FULL_SIZE_INFORMATION:
|
---|
264 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 32));
|
---|
265 |
|
---|
266 | SBVAL(blob->data, 0, fsinfo->full_size_information.out.total_alloc_units);
|
---|
267 | SBVAL(blob->data, 8, fsinfo->full_size_information.out.call_avail_alloc_units);
|
---|
268 | SBVAL(blob->data, 16, fsinfo->full_size_information.out.actual_avail_alloc_units);
|
---|
269 | SIVAL(blob->data, 24, fsinfo->full_size_information.out.sectors_per_unit);
|
---|
270 | SIVAL(blob->data, 28, fsinfo->full_size_information.out.bytes_per_sector);
|
---|
271 |
|
---|
272 | return NT_STATUS_OK;
|
---|
273 |
|
---|
274 | case RAW_QFS_OBJECTID_INFORMATION: {
|
---|
275 | enum ndr_err_code ndr_err;
|
---|
276 |
|
---|
277 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 64));
|
---|
278 |
|
---|
279 | ndr_err = ndr_push_struct_blob(&guid_blob, mem_ctx, NULL,
|
---|
280 | &fsinfo->objectid_information.out.guid,
|
---|
281 | (ndr_push_flags_fn_t)ndr_push_GUID);
|
---|
282 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
---|
283 | BLOB_CHECK(ndr_map_error2ntstatus(ndr_err));
|
---|
284 | }
|
---|
285 |
|
---|
286 | memcpy(blob->data, guid_blob.data, guid_blob.length);
|
---|
287 |
|
---|
288 | for (i=0;i<6;i++) {
|
---|
289 | SBVAL(blob->data, 16 + 8*i, fsinfo->objectid_information.out.unknown[i]);
|
---|
290 | }
|
---|
291 |
|
---|
292 | return NT_STATUS_OK;
|
---|
293 | }
|
---|
294 | default:
|
---|
295 | return NT_STATUS_INVALID_LEVEL;
|
---|
296 | }
|
---|
297 |
|
---|
298 | return NT_STATUS_INVALID_LEVEL;
|
---|
299 | }
|
---|
300 |
|
---|
301 | NTSTATUS smbsrv_push_passthru_fileinfo(TALLOC_CTX *mem_ctx,
|
---|
302 | DATA_BLOB *blob,
|
---|
303 | enum smb_fileinfo_level level,
|
---|
304 | union smb_fileinfo *st,
|
---|
305 | int default_str_flags)
|
---|
306 | {
|
---|
307 | uint_t i;
|
---|
308 | size_t list_size;
|
---|
309 |
|
---|
310 | switch (level) {
|
---|
311 | case RAW_FILEINFO_BASIC_INFORMATION:
|
---|
312 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 40));
|
---|
313 |
|
---|
314 | push_nttime(blob->data, 0, st->basic_info.out.create_time);
|
---|
315 | push_nttime(blob->data, 8, st->basic_info.out.access_time);
|
---|
316 | push_nttime(blob->data, 16, st->basic_info.out.write_time);
|
---|
317 | push_nttime(blob->data, 24, st->basic_info.out.change_time);
|
---|
318 | SIVAL(blob->data, 32, st->basic_info.out.attrib);
|
---|
319 | SIVAL(blob->data, 36, 0); /* padding */
|
---|
320 | return NT_STATUS_OK;
|
---|
321 |
|
---|
322 | case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:
|
---|
323 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 56));
|
---|
324 |
|
---|
325 | push_nttime(blob->data, 0, st->network_open_information.out.create_time);
|
---|
326 | push_nttime(blob->data, 8, st->network_open_information.out.access_time);
|
---|
327 | push_nttime(blob->data, 16, st->network_open_information.out.write_time);
|
---|
328 | push_nttime(blob->data, 24, st->network_open_information.out.change_time);
|
---|
329 | SBVAL(blob->data, 32, st->network_open_information.out.alloc_size);
|
---|
330 | SBVAL(blob->data, 40, st->network_open_information.out.size);
|
---|
331 | SIVAL(blob->data, 48, st->network_open_information.out.attrib);
|
---|
332 | SIVAL(blob->data, 52, 0); /* padding */
|
---|
333 | return NT_STATUS_OK;
|
---|
334 |
|
---|
335 | case RAW_FILEINFO_STANDARD_INFORMATION:
|
---|
336 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 24));
|
---|
337 |
|
---|
338 | SBVAL(blob->data, 0, st->standard_info.out.alloc_size);
|
---|
339 | SBVAL(blob->data, 8, st->standard_info.out.size);
|
---|
340 | SIVAL(blob->data, 16, st->standard_info.out.nlink);
|
---|
341 | SCVAL(blob->data, 20, st->standard_info.out.delete_pending);
|
---|
342 | SCVAL(blob->data, 21, st->standard_info.out.directory);
|
---|
343 | SSVAL(blob->data, 22, 0); /* padding */
|
---|
344 | return NT_STATUS_OK;
|
---|
345 |
|
---|
346 | case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
|
---|
347 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 8));
|
---|
348 |
|
---|
349 | SIVAL(blob->data, 0, st->attribute_tag_information.out.attrib);
|
---|
350 | SIVAL(blob->data, 4, st->attribute_tag_information.out.reparse_tag);
|
---|
351 | return NT_STATUS_OK;
|
---|
352 |
|
---|
353 | case RAW_FILEINFO_EA_INFORMATION:
|
---|
354 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 4));
|
---|
355 |
|
---|
356 | SIVAL(blob->data, 0, st->ea_info.out.ea_size);
|
---|
357 | return NT_STATUS_OK;
|
---|
358 |
|
---|
359 | case RAW_FILEINFO_MODE_INFORMATION:
|
---|
360 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 4));
|
---|
361 |
|
---|
362 | SIVAL(blob->data, 0, st->mode_information.out.mode);
|
---|
363 | return NT_STATUS_OK;
|
---|
364 |
|
---|
365 | case RAW_FILEINFO_ALIGNMENT_INFORMATION:
|
---|
366 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 4));
|
---|
367 |
|
---|
368 | SIVAL(blob->data, 0,
|
---|
369 | st->alignment_information.out.alignment_requirement);
|
---|
370 | return NT_STATUS_OK;
|
---|
371 |
|
---|
372 | case RAW_FILEINFO_ACCESS_INFORMATION:
|
---|
373 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 4));
|
---|
374 |
|
---|
375 | SIVAL(blob->data, 0, st->access_information.out.access_flags);
|
---|
376 | return NT_STATUS_OK;
|
---|
377 |
|
---|
378 | case RAW_FILEINFO_POSITION_INFORMATION:
|
---|
379 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 8));
|
---|
380 |
|
---|
381 | SBVAL(blob->data, 0, st->position_information.out.position);
|
---|
382 | return NT_STATUS_OK;
|
---|
383 |
|
---|
384 | case RAW_FILEINFO_COMPRESSION_INFORMATION:
|
---|
385 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 16));
|
---|
386 |
|
---|
387 | SBVAL(blob->data, 0, st->compression_info.out.compressed_size);
|
---|
388 | SSVAL(blob->data, 8, st->compression_info.out.format);
|
---|
389 | SCVAL(blob->data, 10, st->compression_info.out.unit_shift);
|
---|
390 | SCVAL(blob->data, 11, st->compression_info.out.chunk_shift);
|
---|
391 | SCVAL(blob->data, 12, st->compression_info.out.cluster_shift);
|
---|
392 | SSVAL(blob->data, 13, 0); /* 3 bytes padding */
|
---|
393 | SCVAL(blob->data, 15, 0);
|
---|
394 | return NT_STATUS_OK;
|
---|
395 |
|
---|
396 | case RAW_FILEINFO_INTERNAL_INFORMATION:
|
---|
397 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 8));
|
---|
398 |
|
---|
399 | SBVAL(blob->data, 0, st->internal_information.out.file_id);
|
---|
400 | return NT_STATUS_OK;
|
---|
401 |
|
---|
402 | case RAW_FILEINFO_ALL_INFORMATION:
|
---|
403 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 72));
|
---|
404 |
|
---|
405 | push_nttime(blob->data, 0, st->all_info.out.create_time);
|
---|
406 | push_nttime(blob->data, 8, st->all_info.out.access_time);
|
---|
407 | push_nttime(blob->data, 16, st->all_info.out.write_time);
|
---|
408 | push_nttime(blob->data, 24, st->all_info.out.change_time);
|
---|
409 | SIVAL(blob->data, 32, st->all_info.out.attrib);
|
---|
410 | SIVAL(blob->data, 36, 0); /* padding */
|
---|
411 | SBVAL(blob->data, 40, st->all_info.out.alloc_size);
|
---|
412 | SBVAL(blob->data, 48, st->all_info.out.size);
|
---|
413 | SIVAL(blob->data, 56, st->all_info.out.nlink);
|
---|
414 | SCVAL(blob->data, 60, st->all_info.out.delete_pending);
|
---|
415 | SCVAL(blob->data, 61, st->all_info.out.directory);
|
---|
416 | SSVAL(blob->data, 62, 0); /* padding */
|
---|
417 | SIVAL(blob->data, 64, st->all_info.out.ea_size);
|
---|
418 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
|
---|
419 | st->all_info.out.fname.s,
|
---|
420 | 68, default_str_flags,
|
---|
421 | STR_UNICODE));
|
---|
422 | return NT_STATUS_OK;
|
---|
423 |
|
---|
424 | case RAW_FILEINFO_NAME_INFORMATION:
|
---|
425 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 4));
|
---|
426 |
|
---|
427 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
|
---|
428 | st->name_info.out.fname.s,
|
---|
429 | 0, default_str_flags,
|
---|
430 | STR_UNICODE));
|
---|
431 | return NT_STATUS_OK;
|
---|
432 |
|
---|
433 | case RAW_FILEINFO_ALT_NAME_INFORMATION:
|
---|
434 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 4));
|
---|
435 |
|
---|
436 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
|
---|
437 | st->alt_name_info.out.fname.s,
|
---|
438 | 0, default_str_flags,
|
---|
439 | STR_UNICODE));
|
---|
440 | return NT_STATUS_OK;
|
---|
441 |
|
---|
442 | case RAW_FILEINFO_STREAM_INFORMATION:
|
---|
443 | for (i=0;i<st->stream_info.out.num_streams;i++) {
|
---|
444 | uint32_t data_size = blob->length;
|
---|
445 | uint8_t *data;
|
---|
446 |
|
---|
447 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, data_size + 24));
|
---|
448 | data = blob->data + data_size;
|
---|
449 | SBVAL(data, 8, st->stream_info.out.streams[i].size);
|
---|
450 | SBVAL(data, 16, st->stream_info.out.streams[i].alloc_size);
|
---|
451 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
|
---|
452 | st->stream_info.out.streams[i].stream_name.s,
|
---|
453 | data_size + 4, default_str_flags,
|
---|
454 | STR_UNICODE));
|
---|
455 | if (i == st->stream_info.out.num_streams - 1) {
|
---|
456 | SIVAL(blob->data, data_size, 0);
|
---|
457 | } else {
|
---|
458 | BLOB_CHECK(smbsrv_blob_fill_data(mem_ctx, blob, (blob->length+7)&~7));
|
---|
459 | SIVAL(blob->data, data_size,
|
---|
460 | blob->length - data_size);
|
---|
461 | }
|
---|
462 | }
|
---|
463 | return NT_STATUS_OK;
|
---|
464 |
|
---|
465 | case RAW_FILEINFO_SMB2_ALL_EAS:
|
---|
466 | /* if no eas are returned the backend should
|
---|
467 | * have returned NO_EAS_ON_FILE or NO_MORE_EAS
|
---|
468 | *
|
---|
469 | * so it's a programmer error if num_eas == 0
|
---|
470 | */
|
---|
471 | if (st->all_eas.out.num_eas == 0) {
|
---|
472 | smb_panic("0 eas for SMB2_ALL_EAS - programmer error in ntvfs backend");
|
---|
473 | }
|
---|
474 |
|
---|
475 | list_size = ea_list_size_chained(st->all_eas.out.num_eas,
|
---|
476 | st->all_eas.out.eas, 4);
|
---|
477 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, list_size));
|
---|
478 |
|
---|
479 | ea_put_list_chained(blob->data,
|
---|
480 | st->all_eas.out.num_eas,
|
---|
481 | st->all_eas.out.eas, 4);
|
---|
482 | return NT_STATUS_OK;
|
---|
483 |
|
---|
484 | case RAW_FILEINFO_SMB2_ALL_INFORMATION:
|
---|
485 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 0x64));
|
---|
486 |
|
---|
487 | push_nttime(blob->data, 0x00, st->all_info2.out.create_time);
|
---|
488 | push_nttime(blob->data, 0x08, st->all_info2.out.access_time);
|
---|
489 | push_nttime(blob->data, 0x10, st->all_info2.out.write_time);
|
---|
490 | push_nttime(blob->data, 0x18, st->all_info2.out.change_time);
|
---|
491 | SIVAL(blob->data, 0x20, st->all_info2.out.attrib);
|
---|
492 | SIVAL(blob->data, 0x24, st->all_info2.out.unknown1);
|
---|
493 | SBVAL(blob->data, 0x28, st->all_info2.out.alloc_size);
|
---|
494 | SBVAL(blob->data, 0x30, st->all_info2.out.size);
|
---|
495 | SIVAL(blob->data, 0x38, st->all_info2.out.nlink);
|
---|
496 | SCVAL(blob->data, 0x3C, st->all_info2.out.delete_pending);
|
---|
497 | SCVAL(blob->data, 0x3D, st->all_info2.out.directory);
|
---|
498 | SSVAL(blob->data, 0x3E, 0); /* padding */
|
---|
499 | SBVAL(blob->data, 0x40, st->all_info2.out.file_id);
|
---|
500 | SIVAL(blob->data, 0x48, st->all_info2.out.ea_size);
|
---|
501 | SIVAL(blob->data, 0x4C, st->all_info2.out.access_mask);
|
---|
502 | SBVAL(blob->data, 0x50, st->all_info2.out.position);
|
---|
503 | SIVAL(blob->data, 0x58, st->all_info2.out.mode);
|
---|
504 | SIVAL(blob->data, 0x5C, st->all_info2.out.alignment_requirement);
|
---|
505 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
|
---|
506 | st->all_info2.out.fname.s,
|
---|
507 | 0x60, default_str_flags,
|
---|
508 | STR_UNICODE));
|
---|
509 | return NT_STATUS_OK;
|
---|
510 |
|
---|
511 | default:
|
---|
512 | return NT_STATUS_INVALID_LEVEL;
|
---|
513 | }
|
---|
514 |
|
---|
515 | return NT_STATUS_INVALID_LEVEL;
|
---|
516 | }
|
---|
517 |
|
---|
518 | NTSTATUS smbsrv_pull_passthru_sfileinfo(TALLOC_CTX *mem_ctx,
|
---|
519 | enum smb_setfileinfo_level level,
|
---|
520 | union smb_setfileinfo *st,
|
---|
521 | const DATA_BLOB *blob,
|
---|
522 | int default_str_flags,
|
---|
523 | struct request_bufinfo *bufinfo)
|
---|
524 | {
|
---|
525 | uint32_t len, ofs;
|
---|
526 | DATA_BLOB str_blob;
|
---|
527 |
|
---|
528 | switch (level) {
|
---|
529 | case SMB_SFILEINFO_BASIC_INFORMATION:
|
---|
530 | BLOB_CHECK_MIN_SIZE(blob, 40);
|
---|
531 |
|
---|
532 | st->basic_info.in.create_time = pull_nttime(blob->data, 0);
|
---|
533 | st->basic_info.in.access_time = pull_nttime(blob->data, 8);
|
---|
534 | st->basic_info.in.write_time = pull_nttime(blob->data, 16);
|
---|
535 | st->basic_info.in.change_time = pull_nttime(blob->data, 24);
|
---|
536 | st->basic_info.in.attrib = IVAL(blob->data, 32);
|
---|
537 | st->basic_info.in.reserved = IVAL(blob->data, 36);
|
---|
538 |
|
---|
539 | return NT_STATUS_OK;
|
---|
540 |
|
---|
541 | case SMB_SFILEINFO_DISPOSITION_INFORMATION:
|
---|
542 | BLOB_CHECK_MIN_SIZE(blob, 1);
|
---|
543 |
|
---|
544 | st->disposition_info.in.delete_on_close = CVAL(blob->data, 0);
|
---|
545 |
|
---|
546 | return NT_STATUS_OK;
|
---|
547 |
|
---|
548 | case SMB_SFILEINFO_ALLOCATION_INFORMATION:
|
---|
549 | BLOB_CHECK_MIN_SIZE(blob, 8);
|
---|
550 |
|
---|
551 | st->allocation_info.in.alloc_size = BVAL(blob->data, 0);
|
---|
552 |
|
---|
553 | return NT_STATUS_OK;
|
---|
554 |
|
---|
555 | case RAW_SFILEINFO_END_OF_FILE_INFORMATION:
|
---|
556 | BLOB_CHECK_MIN_SIZE(blob, 8);
|
---|
557 |
|
---|
558 | st->end_of_file_info.in.size = BVAL(blob->data, 0);
|
---|
559 |
|
---|
560 | return NT_STATUS_OK;
|
---|
561 |
|
---|
562 | case RAW_SFILEINFO_RENAME_INFORMATION:
|
---|
563 | if (!bufinfo) {
|
---|
564 | return NT_STATUS_INTERNAL_ERROR;
|
---|
565 | }
|
---|
566 | BLOB_CHECK_MIN_SIZE(blob, 12);
|
---|
567 | st->rename_information.in.overwrite = CVAL(blob->data, 0);
|
---|
568 | st->rename_information.in.root_fid = IVAL(blob->data, 4);
|
---|
569 | len = IVAL(blob->data, 8);
|
---|
570 | ofs = 12;
|
---|
571 | str_blob = *blob;
|
---|
572 | str_blob.length = MIN(str_blob.length, ofs+len);
|
---|
573 | smbsrv_blob_pull_string(bufinfo, &str_blob, ofs,
|
---|
574 | &st->rename_information.in.new_name,
|
---|
575 | STR_UNICODE);
|
---|
576 | if (st->rename_information.in.new_name == NULL) {
|
---|
577 | return NT_STATUS_FOOBAR;
|
---|
578 | }
|
---|
579 |
|
---|
580 | return NT_STATUS_OK;
|
---|
581 |
|
---|
582 |
|
---|
583 | case RAW_SFILEINFO_LINK_INFORMATION:
|
---|
584 | if (!bufinfo) {
|
---|
585 | return NT_STATUS_INTERNAL_ERROR;
|
---|
586 | }
|
---|
587 | BLOB_CHECK_MIN_SIZE(blob, 20);
|
---|
588 | st->link_information.in.overwrite = CVAL(blob->data, 0);
|
---|
589 | st->link_information.in.root_fid = IVAL(blob->data, 8);
|
---|
590 | len = IVAL(blob->data, 16);
|
---|
591 | ofs = 20;
|
---|
592 | str_blob = *blob;
|
---|
593 | str_blob.length = MIN(str_blob.length, ofs+len);
|
---|
594 | smbsrv_blob_pull_string(bufinfo, &str_blob, ofs,
|
---|
595 | &st->link_information.in.new_name,
|
---|
596 | STR_UNICODE);
|
---|
597 | if (st->link_information.in.new_name == NULL) {
|
---|
598 | return NT_STATUS_FOOBAR;
|
---|
599 | }
|
---|
600 |
|
---|
601 | return NT_STATUS_OK;
|
---|
602 |
|
---|
603 | case RAW_SFILEINFO_RENAME_INFORMATION_SMB2:
|
---|
604 | /* SMB2 uses a different format for rename information */
|
---|
605 | if (!bufinfo) {
|
---|
606 | return NT_STATUS_INTERNAL_ERROR;
|
---|
607 | }
|
---|
608 | BLOB_CHECK_MIN_SIZE(blob, 20);
|
---|
609 | st->rename_information.in.overwrite = CVAL(blob->data, 0);
|
---|
610 | st->rename_information.in.root_fid = BVAL(blob->data, 8);
|
---|
611 | len = IVAL(blob->data,16);
|
---|
612 | ofs = 20;
|
---|
613 | str_blob = *blob;
|
---|
614 | str_blob.length = MIN(str_blob.length, ofs+len);
|
---|
615 | smbsrv_blob_pull_string(bufinfo, &str_blob, ofs,
|
---|
616 | &st->rename_information.in.new_name,
|
---|
617 | STR_UNICODE);
|
---|
618 | if (st->rename_information.in.new_name == NULL) {
|
---|
619 | return NT_STATUS_FOOBAR;
|
---|
620 | }
|
---|
621 |
|
---|
622 | return NT_STATUS_OK;
|
---|
623 |
|
---|
624 | case RAW_SFILEINFO_POSITION_INFORMATION:
|
---|
625 | BLOB_CHECK_MIN_SIZE(blob, 8);
|
---|
626 |
|
---|
627 | st->position_information.in.position = BVAL(blob->data, 0);
|
---|
628 |
|
---|
629 | return NT_STATUS_OK;
|
---|
630 |
|
---|
631 | case RAW_SFILEINFO_MODE_INFORMATION:
|
---|
632 | BLOB_CHECK_MIN_SIZE(blob, 4);
|
---|
633 |
|
---|
634 | st->mode_information.in.mode = IVAL(blob->data, 0);
|
---|
635 |
|
---|
636 | return NT_STATUS_OK;
|
---|
637 |
|
---|
638 | default:
|
---|
639 | return NT_STATUS_INVALID_LEVEL;
|
---|
640 | }
|
---|
641 |
|
---|
642 | return NT_STATUS_INVALID_LEVEL;
|
---|
643 | }
|
---|
644 |
|
---|
645 | /*
|
---|
646 | fill a single entry in a trans2 find reply
|
---|
647 | */
|
---|
648 | NTSTATUS smbsrv_push_passthru_search(TALLOC_CTX *mem_ctx,
|
---|
649 | DATA_BLOB *blob,
|
---|
650 | enum smb_search_data_level level,
|
---|
651 | const union smb_search_data *file,
|
---|
652 | int default_str_flags)
|
---|
653 | {
|
---|
654 | uint8_t *data;
|
---|
655 | uint_t ofs = blob->length;
|
---|
656 |
|
---|
657 | switch (level) {
|
---|
658 | case RAW_SEARCH_DATA_DIRECTORY_INFO:
|
---|
659 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, ofs + 64));
|
---|
660 | data = blob->data + ofs;
|
---|
661 | SIVAL(data, 4, file->directory_info.file_index);
|
---|
662 | push_nttime(data, 8, file->directory_info.create_time);
|
---|
663 | push_nttime(data, 16, file->directory_info.access_time);
|
---|
664 | push_nttime(data, 24, file->directory_info.write_time);
|
---|
665 | push_nttime(data, 32, file->directory_info.change_time);
|
---|
666 | SBVAL(data, 40, file->directory_info.size);
|
---|
667 | SBVAL(data, 48, file->directory_info.alloc_size);
|
---|
668 | SIVAL(data, 56, file->directory_info.attrib);
|
---|
669 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob, file->directory_info.name.s,
|
---|
670 | ofs + 60, default_str_flags,
|
---|
671 | STR_TERMINATE_ASCII));
|
---|
672 | BLOB_ALIGN(blob, 8);
|
---|
673 | data = blob->data + ofs;
|
---|
674 | SIVAL(data, 0, blob->length - ofs);
|
---|
675 | return NT_STATUS_OK;
|
---|
676 |
|
---|
677 | case RAW_SEARCH_DATA_FULL_DIRECTORY_INFO:
|
---|
678 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, ofs + 68));
|
---|
679 | data = blob->data + ofs;
|
---|
680 | SIVAL(data, 4, file->full_directory_info.file_index);
|
---|
681 | push_nttime(data, 8, file->full_directory_info.create_time);
|
---|
682 | push_nttime(data, 16, file->full_directory_info.access_time);
|
---|
683 | push_nttime(data, 24, file->full_directory_info.write_time);
|
---|
684 | push_nttime(data, 32, file->full_directory_info.change_time);
|
---|
685 | SBVAL(data, 40, file->full_directory_info.size);
|
---|
686 | SBVAL(data, 48, file->full_directory_info.alloc_size);
|
---|
687 | SIVAL(data, 56, file->full_directory_info.attrib);
|
---|
688 | SIVAL(data, 64, file->full_directory_info.ea_size);
|
---|
689 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob, file->full_directory_info.name.s,
|
---|
690 | ofs + 60, default_str_flags,
|
---|
691 | STR_TERMINATE_ASCII));
|
---|
692 | BLOB_ALIGN(blob, 8);
|
---|
693 | data = blob->data + ofs;
|
---|
694 | SIVAL(data, 0, blob->length - ofs);
|
---|
695 | return NT_STATUS_OK;
|
---|
696 |
|
---|
697 | case RAW_SEARCH_DATA_NAME_INFO:
|
---|
698 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, ofs + 12));
|
---|
699 | data = blob->data + ofs;
|
---|
700 | SIVAL(data, 4, file->name_info.file_index);
|
---|
701 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob, file->name_info.name.s,
|
---|
702 | ofs + 8, default_str_flags,
|
---|
703 | STR_TERMINATE_ASCII));
|
---|
704 | BLOB_ALIGN(blob, 8);
|
---|
705 | data = blob->data + ofs;
|
---|
706 | SIVAL(data, 0, blob->length - ofs);
|
---|
707 | return NT_STATUS_OK;
|
---|
708 |
|
---|
709 | case RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO:
|
---|
710 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, ofs + 94));
|
---|
711 | data = blob->data + ofs;
|
---|
712 | SIVAL(data, 4, file->both_directory_info.file_index);
|
---|
713 | push_nttime(data, 8, file->both_directory_info.create_time);
|
---|
714 | push_nttime(data, 16, file->both_directory_info.access_time);
|
---|
715 | push_nttime(data, 24, file->both_directory_info.write_time);
|
---|
716 | push_nttime(data, 32, file->both_directory_info.change_time);
|
---|
717 | SBVAL(data, 40, file->both_directory_info.size);
|
---|
718 | SBVAL(data, 48, file->both_directory_info.alloc_size);
|
---|
719 | SIVAL(data, 56, file->both_directory_info.attrib);
|
---|
720 | SIVAL(data, 64, file->both_directory_info.ea_size);
|
---|
721 | SCVAL(data, 69, 0); /* reserved */
|
---|
722 | memset(data+70,0,24);
|
---|
723 | smbsrv_blob_push_string(mem_ctx, blob,
|
---|
724 | 68 + ofs, 70 + ofs,
|
---|
725 | file->both_directory_info.short_name.s,
|
---|
726 | 24, default_str_flags,
|
---|
727 | STR_UNICODE | STR_LEN8BIT);
|
---|
728 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob, file->both_directory_info.name.s,
|
---|
729 | ofs + 60, default_str_flags,
|
---|
730 | STR_TERMINATE_ASCII));
|
---|
731 | BLOB_ALIGN(blob, 8);
|
---|
732 | data = blob->data + ofs;
|
---|
733 | SIVAL(data, 0, blob->length - ofs);
|
---|
734 | return NT_STATUS_OK;
|
---|
735 |
|
---|
736 | case RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO:
|
---|
737 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, ofs + 80));
|
---|
738 | data = blob->data + ofs;
|
---|
739 | SIVAL(data, 4, file->id_full_directory_info.file_index);
|
---|
740 | push_nttime(data, 8, file->id_full_directory_info.create_time);
|
---|
741 | push_nttime(data, 16, file->id_full_directory_info.access_time);
|
---|
742 | push_nttime(data, 24, file->id_full_directory_info.write_time);
|
---|
743 | push_nttime(data, 32, file->id_full_directory_info.change_time);
|
---|
744 | SBVAL(data, 40, file->id_full_directory_info.size);
|
---|
745 | SBVAL(data, 48, file->id_full_directory_info.alloc_size);
|
---|
746 | SIVAL(data, 56, file->id_full_directory_info.attrib);
|
---|
747 | SIVAL(data, 64, file->id_full_directory_info.ea_size);
|
---|
748 | SIVAL(data, 68, 0); /* padding */
|
---|
749 | SBVAL(data, 72, file->id_full_directory_info.file_id);
|
---|
750 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob, file->id_full_directory_info.name.s,
|
---|
751 | ofs + 60, default_str_flags,
|
---|
752 | STR_TERMINATE_ASCII));
|
---|
753 | BLOB_ALIGN(blob, 8);
|
---|
754 | data = blob->data + ofs;
|
---|
755 | SIVAL(data, 0, blob->length - ofs);
|
---|
756 | return NT_STATUS_OK;
|
---|
757 |
|
---|
758 | case RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO:
|
---|
759 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, ofs + 104));
|
---|
760 | data = blob->data + ofs;
|
---|
761 | SIVAL(data, 4, file->id_both_directory_info.file_index);
|
---|
762 | push_nttime(data, 8, file->id_both_directory_info.create_time);
|
---|
763 | push_nttime(data, 16, file->id_both_directory_info.access_time);
|
---|
764 | push_nttime(data, 24, file->id_both_directory_info.write_time);
|
---|
765 | push_nttime(data, 32, file->id_both_directory_info.change_time);
|
---|
766 | SBVAL(data, 40, file->id_both_directory_info.size);
|
---|
767 | SBVAL(data, 48, file->id_both_directory_info.alloc_size);
|
---|
768 | SIVAL(data, 56, file->id_both_directory_info.attrib);
|
---|
769 | SIVAL(data, 64, file->id_both_directory_info.ea_size);
|
---|
770 | SCVAL(data, 69, 0); /* reserved */
|
---|
771 | memset(data+70,0,26);
|
---|
772 | smbsrv_blob_push_string(mem_ctx, blob,
|
---|
773 | 68 + ofs, 70 + ofs,
|
---|
774 | file->id_both_directory_info.short_name.s,
|
---|
775 | 24, default_str_flags,
|
---|
776 | STR_UNICODE | STR_LEN8BIT);
|
---|
777 | SBVAL(data, 96, file->id_both_directory_info.file_id);
|
---|
778 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob, file->id_both_directory_info.name.s,
|
---|
779 | ofs + 60, default_str_flags,
|
---|
780 | STR_TERMINATE_ASCII));
|
---|
781 | BLOB_ALIGN(blob, 8);
|
---|
782 | data = blob->data + ofs;
|
---|
783 | SIVAL(data, 0, blob->length - ofs);
|
---|
784 | return NT_STATUS_OK;
|
---|
785 |
|
---|
786 | default:
|
---|
787 | return NT_STATUS_INVALID_LEVEL;
|
---|
788 | }
|
---|
789 |
|
---|
790 | return NT_STATUS_INVALID_LEVEL;
|
---|
791 | }
|
---|