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 | static ssize_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 | if (ret == -1) {
|
---|
146 | return -1;
|
---|
147 | }
|
---|
148 |
|
---|
149 | /* sometimes the string needs to be terminated, but the length
|
---|
150 | on the wire must not include the termination! */
|
---|
151 | pkt_len = ret;
|
---|
152 |
|
---|
153 | if ((flags & STR_LEN_NOTERM) && (flags & STR_TERMINATE)) {
|
---|
154 | if ((flags & STR_UNICODE) && ret >= 2) {
|
---|
155 | pkt_len = ret-2;
|
---|
156 | }
|
---|
157 | if ((flags & STR_ASCII) && ret >= 1) {
|
---|
158 | pkt_len = ret-1;
|
---|
159 | }
|
---|
160 | }
|
---|
161 |
|
---|
162 | if (flags & STR_LEN8BIT) {
|
---|
163 | SCVAL(blob->data, len_offset, pkt_len);
|
---|
164 | } else {
|
---|
165 | SIVAL(blob->data, len_offset, pkt_len);
|
---|
166 | }
|
---|
167 |
|
---|
168 | return ret + alignment;
|
---|
169 | }
|
---|
170 |
|
---|
171 | /*
|
---|
172 | append a string to the data section of a trans2 reply
|
---|
173 | len_offset points to the place in the packet where the length field
|
---|
174 | should go
|
---|
175 | */
|
---|
176 | NTSTATUS smbsrv_blob_append_string(TALLOC_CTX *mem_ctx,
|
---|
177 | DATA_BLOB *blob,
|
---|
178 | const char *str,
|
---|
179 | unsigned int len_offset,
|
---|
180 | int default_flags,
|
---|
181 | int flags)
|
---|
182 | {
|
---|
183 | size_t ret;
|
---|
184 | uint32_t offset;
|
---|
185 | const int max_bytes_per_char = 3;
|
---|
186 |
|
---|
187 | offset = blob->length;
|
---|
188 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, offset + (2+strlen_m(str))*max_bytes_per_char));
|
---|
189 | ret = smbsrv_blob_push_string(mem_ctx, blob, len_offset, offset, str, -1, default_flags, flags);
|
---|
190 | if (ret < 0) {
|
---|
191 | return NT_STATUS_FOOBAR;
|
---|
192 | }
|
---|
193 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, offset + ret));
|
---|
194 | return NT_STATUS_OK;
|
---|
195 | }
|
---|
196 |
|
---|
197 | NTSTATUS smbsrv_push_passthru_fsinfo(TALLOC_CTX *mem_ctx,
|
---|
198 | DATA_BLOB *blob,
|
---|
199 | enum smb_fsinfo_level level,
|
---|
200 | union smb_fsinfo *fsinfo,
|
---|
201 | int default_str_flags)
|
---|
202 | {
|
---|
203 | unsigned int i;
|
---|
204 | DATA_BLOB guid_blob;
|
---|
205 |
|
---|
206 | switch (level) {
|
---|
207 | case RAW_QFS_VOLUME_INFORMATION:
|
---|
208 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 18));
|
---|
209 |
|
---|
210 | push_nttime(blob->data, 0, fsinfo->volume_info.out.create_time);
|
---|
211 | SIVAL(blob->data, 8, fsinfo->volume_info.out.serial_number);
|
---|
212 | SSVAL(blob->data, 16, 0); /* padding */
|
---|
213 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
|
---|
214 | fsinfo->volume_info.out.volume_name.s,
|
---|
215 | 12, default_str_flags,
|
---|
216 | STR_UNICODE));
|
---|
217 |
|
---|
218 | return NT_STATUS_OK;
|
---|
219 |
|
---|
220 | case RAW_QFS_SIZE_INFORMATION:
|
---|
221 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 24));
|
---|
222 |
|
---|
223 | SBVAL(blob->data, 0, fsinfo->size_info.out.total_alloc_units);
|
---|
224 | SBVAL(blob->data, 8, fsinfo->size_info.out.avail_alloc_units);
|
---|
225 | SIVAL(blob->data, 16, fsinfo->size_info.out.sectors_per_unit);
|
---|
226 | SIVAL(blob->data, 20, fsinfo->size_info.out.bytes_per_sector);
|
---|
227 |
|
---|
228 | return NT_STATUS_OK;
|
---|
229 |
|
---|
230 | case RAW_QFS_DEVICE_INFORMATION:
|
---|
231 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 8));
|
---|
232 |
|
---|
233 | SIVAL(blob->data, 0, fsinfo->device_info.out.device_type);
|
---|
234 | SIVAL(blob->data, 4, fsinfo->device_info.out.characteristics);
|
---|
235 |
|
---|
236 | return NT_STATUS_OK;
|
---|
237 |
|
---|
238 | case RAW_QFS_ATTRIBUTE_INFORMATION:
|
---|
239 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 12));
|
---|
240 |
|
---|
241 | SIVAL(blob->data, 0, fsinfo->attribute_info.out.fs_attr);
|
---|
242 | SIVAL(blob->data, 4, fsinfo->attribute_info.out.max_file_component_length);
|
---|
243 | /* this must not be null terminated or win98 gets
|
---|
244 | confused! also note that w2k3 returns this as
|
---|
245 | unicode even when ascii is negotiated */
|
---|
246 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
|
---|
247 | fsinfo->attribute_info.out.fs_type.s,
|
---|
248 | 8, default_str_flags,
|
---|
249 | STR_UNICODE));
|
---|
250 | return NT_STATUS_OK;
|
---|
251 |
|
---|
252 |
|
---|
253 | case RAW_QFS_QUOTA_INFORMATION:
|
---|
254 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 48));
|
---|
255 |
|
---|
256 | SBVAL(blob->data, 0, fsinfo->quota_information.out.unknown[0]);
|
---|
257 | SBVAL(blob->data, 8, fsinfo->quota_information.out.unknown[1]);
|
---|
258 | SBVAL(blob->data, 16, fsinfo->quota_information.out.unknown[2]);
|
---|
259 | SBVAL(blob->data, 24, fsinfo->quota_information.out.quota_soft);
|
---|
260 | SBVAL(blob->data, 32, fsinfo->quota_information.out.quota_hard);
|
---|
261 | SBVAL(blob->data, 40, fsinfo->quota_information.out.quota_flags);
|
---|
262 |
|
---|
263 | return NT_STATUS_OK;
|
---|
264 |
|
---|
265 |
|
---|
266 | case RAW_QFS_FULL_SIZE_INFORMATION:
|
---|
267 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 32));
|
---|
268 |
|
---|
269 | SBVAL(blob->data, 0, fsinfo->full_size_information.out.total_alloc_units);
|
---|
270 | SBVAL(blob->data, 8, fsinfo->full_size_information.out.call_avail_alloc_units);
|
---|
271 | SBVAL(blob->data, 16, fsinfo->full_size_information.out.actual_avail_alloc_units);
|
---|
272 | SIVAL(blob->data, 24, fsinfo->full_size_information.out.sectors_per_unit);
|
---|
273 | SIVAL(blob->data, 28, fsinfo->full_size_information.out.bytes_per_sector);
|
---|
274 |
|
---|
275 | return NT_STATUS_OK;
|
---|
276 |
|
---|
277 | case RAW_QFS_OBJECTID_INFORMATION: {
|
---|
278 | NTSTATUS status;
|
---|
279 |
|
---|
280 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 64));
|
---|
281 |
|
---|
282 | status = GUID_to_ndr_blob(&fsinfo->objectid_information.out.guid, mem_ctx, &guid_blob);
|
---|
283 | if (!NT_STATUS_IS_OK(status)) {
|
---|
284 | BLOB_CHECK(status);
|
---|
285 | }
|
---|
286 |
|
---|
287 | memcpy(blob->data, guid_blob.data, guid_blob.length);
|
---|
288 |
|
---|
289 | for (i=0;i<6;i++) {
|
---|
290 | SBVAL(blob->data, 16 + 8*i, fsinfo->objectid_information.out.unknown[i]);
|
---|
291 | }
|
---|
292 |
|
---|
293 | return NT_STATUS_OK;
|
---|
294 | }
|
---|
295 | default:
|
---|
296 | return NT_STATUS_INVALID_LEVEL;
|
---|
297 | }
|
---|
298 | }
|
---|
299 |
|
---|
300 | NTSTATUS smbsrv_push_passthru_fileinfo(TALLOC_CTX *mem_ctx,
|
---|
301 | DATA_BLOB *blob,
|
---|
302 | enum smb_fileinfo_level level,
|
---|
303 | union smb_fileinfo *st,
|
---|
304 | int default_str_flags)
|
---|
305 | {
|
---|
306 | unsigned int i;
|
---|
307 | size_t list_size;
|
---|
308 |
|
---|
309 | switch (level) {
|
---|
310 | case RAW_FILEINFO_BASIC_INFORMATION:
|
---|
311 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 40));
|
---|
312 |
|
---|
313 | push_nttime(blob->data, 0, st->basic_info.out.create_time);
|
---|
314 | push_nttime(blob->data, 8, st->basic_info.out.access_time);
|
---|
315 | push_nttime(blob->data, 16, st->basic_info.out.write_time);
|
---|
316 | push_nttime(blob->data, 24, st->basic_info.out.change_time);
|
---|
317 | SIVAL(blob->data, 32, st->basic_info.out.attrib);
|
---|
318 | SIVAL(blob->data, 36, 0); /* padding */
|
---|
319 | return NT_STATUS_OK;
|
---|
320 |
|
---|
321 | case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:
|
---|
322 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 56));
|
---|
323 |
|
---|
324 | push_nttime(blob->data, 0, st->network_open_information.out.create_time);
|
---|
325 | push_nttime(blob->data, 8, st->network_open_information.out.access_time);
|
---|
326 | push_nttime(blob->data, 16, st->network_open_information.out.write_time);
|
---|
327 | push_nttime(blob->data, 24, st->network_open_information.out.change_time);
|
---|
328 | SBVAL(blob->data, 32, st->network_open_information.out.alloc_size);
|
---|
329 | SBVAL(blob->data, 40, st->network_open_information.out.size);
|
---|
330 | SIVAL(blob->data, 48, st->network_open_information.out.attrib);
|
---|
331 | SIVAL(blob->data, 52, 0); /* padding */
|
---|
332 | return NT_STATUS_OK;
|
---|
333 |
|
---|
334 | case RAW_FILEINFO_STANDARD_INFORMATION:
|
---|
335 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 24));
|
---|
336 |
|
---|
337 | SBVAL(blob->data, 0, st->standard_info.out.alloc_size);
|
---|
338 | SBVAL(blob->data, 8, st->standard_info.out.size);
|
---|
339 | SIVAL(blob->data, 16, st->standard_info.out.nlink);
|
---|
340 | SCVAL(blob->data, 20, st->standard_info.out.delete_pending);
|
---|
341 | SCVAL(blob->data, 21, st->standard_info.out.directory);
|
---|
342 | SSVAL(blob->data, 22, 0); /* padding */
|
---|
343 | return NT_STATUS_OK;
|
---|
344 |
|
---|
345 | case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
|
---|
346 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 8));
|
---|
347 |
|
---|
348 | SIVAL(blob->data, 0, st->attribute_tag_information.out.attrib);
|
---|
349 | SIVAL(blob->data, 4, st->attribute_tag_information.out.reparse_tag);
|
---|
350 | return NT_STATUS_OK;
|
---|
351 |
|
---|
352 | case RAW_FILEINFO_EA_INFORMATION:
|
---|
353 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 4));
|
---|
354 |
|
---|
355 | SIVAL(blob->data, 0, st->ea_info.out.ea_size);
|
---|
356 | return NT_STATUS_OK;
|
---|
357 |
|
---|
358 | case RAW_FILEINFO_MODE_INFORMATION:
|
---|
359 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 4));
|
---|
360 |
|
---|
361 | SIVAL(blob->data, 0, st->mode_information.out.mode);
|
---|
362 | return NT_STATUS_OK;
|
---|
363 |
|
---|
364 | case RAW_FILEINFO_ALIGNMENT_INFORMATION:
|
---|
365 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 4));
|
---|
366 |
|
---|
367 | SIVAL(blob->data, 0,
|
---|
368 | st->alignment_information.out.alignment_requirement);
|
---|
369 | return NT_STATUS_OK;
|
---|
370 |
|
---|
371 | case RAW_FILEINFO_ACCESS_INFORMATION:
|
---|
372 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 4));
|
---|
373 |
|
---|
374 | SIVAL(blob->data, 0, st->access_information.out.access_flags);
|
---|
375 | return NT_STATUS_OK;
|
---|
376 |
|
---|
377 | case RAW_FILEINFO_POSITION_INFORMATION:
|
---|
378 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 8));
|
---|
379 |
|
---|
380 | SBVAL(blob->data, 0, st->position_information.out.position);
|
---|
381 | return NT_STATUS_OK;
|
---|
382 |
|
---|
383 | case RAW_FILEINFO_COMPRESSION_INFORMATION:
|
---|
384 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 16));
|
---|
385 |
|
---|
386 | SBVAL(blob->data, 0, st->compression_info.out.compressed_size);
|
---|
387 | SSVAL(blob->data, 8, st->compression_info.out.format);
|
---|
388 | SCVAL(blob->data, 10, st->compression_info.out.unit_shift);
|
---|
389 | SCVAL(blob->data, 11, st->compression_info.out.chunk_shift);
|
---|
390 | SCVAL(blob->data, 12, st->compression_info.out.cluster_shift);
|
---|
391 | SSVAL(blob->data, 13, 0); /* 3 bytes padding */
|
---|
392 | SCVAL(blob->data, 15, 0);
|
---|
393 | return NT_STATUS_OK;
|
---|
394 |
|
---|
395 | case RAW_FILEINFO_INTERNAL_INFORMATION:
|
---|
396 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 8));
|
---|
397 |
|
---|
398 | SBVAL(blob->data, 0, st->internal_information.out.file_id);
|
---|
399 | return NT_STATUS_OK;
|
---|
400 |
|
---|
401 | case RAW_FILEINFO_ALL_INFORMATION:
|
---|
402 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 72));
|
---|
403 |
|
---|
404 | push_nttime(blob->data, 0, st->all_info.out.create_time);
|
---|
405 | push_nttime(blob->data, 8, st->all_info.out.access_time);
|
---|
406 | push_nttime(blob->data, 16, st->all_info.out.write_time);
|
---|
407 | push_nttime(blob->data, 24, st->all_info.out.change_time);
|
---|
408 | SIVAL(blob->data, 32, st->all_info.out.attrib);
|
---|
409 | SIVAL(blob->data, 36, 0); /* padding */
|
---|
410 | SBVAL(blob->data, 40, st->all_info.out.alloc_size);
|
---|
411 | SBVAL(blob->data, 48, st->all_info.out.size);
|
---|
412 | SIVAL(blob->data, 56, st->all_info.out.nlink);
|
---|
413 | SCVAL(blob->data, 60, st->all_info.out.delete_pending);
|
---|
414 | SCVAL(blob->data, 61, st->all_info.out.directory);
|
---|
415 | SSVAL(blob->data, 62, 0); /* padding */
|
---|
416 | SIVAL(blob->data, 64, st->all_info.out.ea_size);
|
---|
417 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
|
---|
418 | st->all_info.out.fname.s,
|
---|
419 | 68, default_str_flags,
|
---|
420 | STR_UNICODE));
|
---|
421 | return NT_STATUS_OK;
|
---|
422 |
|
---|
423 | case RAW_FILEINFO_NAME_INFORMATION:
|
---|
424 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 4));
|
---|
425 |
|
---|
426 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
|
---|
427 | st->name_info.out.fname.s,
|
---|
428 | 0, default_str_flags,
|
---|
429 | STR_UNICODE));
|
---|
430 | return NT_STATUS_OK;
|
---|
431 |
|
---|
432 | case RAW_FILEINFO_ALT_NAME_INFORMATION:
|
---|
433 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 4));
|
---|
434 |
|
---|
435 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
|
---|
436 | st->alt_name_info.out.fname.s,
|
---|
437 | 0, default_str_flags,
|
---|
438 | STR_UNICODE));
|
---|
439 | return NT_STATUS_OK;
|
---|
440 |
|
---|
441 | case RAW_FILEINFO_STREAM_INFORMATION:
|
---|
442 | for (i=0;i<st->stream_info.out.num_streams;i++) {
|
---|
443 | uint32_t data_size = blob->length;
|
---|
444 | uint8_t *data;
|
---|
445 |
|
---|
446 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, data_size + 24));
|
---|
447 | data = blob->data + data_size;
|
---|
448 | SBVAL(data, 8, st->stream_info.out.streams[i].size);
|
---|
449 | SBVAL(data, 16, st->stream_info.out.streams[i].alloc_size);
|
---|
450 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
|
---|
451 | st->stream_info.out.streams[i].stream_name.s,
|
---|
452 | data_size + 4, default_str_flags,
|
---|
453 | STR_UNICODE));
|
---|
454 | if (i == st->stream_info.out.num_streams - 1) {
|
---|
455 | SIVAL(blob->data, data_size, 0);
|
---|
456 | } else {
|
---|
457 | BLOB_CHECK(smbsrv_blob_fill_data(mem_ctx, blob, (blob->length+7)&~7));
|
---|
458 | SIVAL(blob->data, data_size,
|
---|
459 | blob->length - data_size);
|
---|
460 | }
|
---|
461 | }
|
---|
462 | return NT_STATUS_OK;
|
---|
463 |
|
---|
464 | case RAW_FILEINFO_SMB2_ALL_EAS:
|
---|
465 | /* if no eas are returned the backend should
|
---|
466 | * have returned NO_EAS_ON_FILE or NO_MORE_EAS
|
---|
467 | *
|
---|
468 | * so it's a programmer error if num_eas == 0
|
---|
469 | */
|
---|
470 | if (st->all_eas.out.num_eas == 0) {
|
---|
471 | smb_panic("0 eas for SMB2_ALL_EAS - programmer error in ntvfs backend");
|
---|
472 | }
|
---|
473 |
|
---|
474 | list_size = ea_list_size_chained(st->all_eas.out.num_eas,
|
---|
475 | st->all_eas.out.eas, 4);
|
---|
476 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, list_size));
|
---|
477 |
|
---|
478 | ea_put_list_chained(blob->data,
|
---|
479 | st->all_eas.out.num_eas,
|
---|
480 | st->all_eas.out.eas, 4);
|
---|
481 | return NT_STATUS_OK;
|
---|
482 |
|
---|
483 | case RAW_FILEINFO_SMB2_ALL_INFORMATION:
|
---|
484 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 0x64));
|
---|
485 |
|
---|
486 | push_nttime(blob->data, 0x00, st->all_info2.out.create_time);
|
---|
487 | push_nttime(blob->data, 0x08, st->all_info2.out.access_time);
|
---|
488 | push_nttime(blob->data, 0x10, st->all_info2.out.write_time);
|
---|
489 | push_nttime(blob->data, 0x18, st->all_info2.out.change_time);
|
---|
490 | SIVAL(blob->data, 0x20, st->all_info2.out.attrib);
|
---|
491 | SIVAL(blob->data, 0x24, st->all_info2.out.unknown1);
|
---|
492 | SBVAL(blob->data, 0x28, st->all_info2.out.alloc_size);
|
---|
493 | SBVAL(blob->data, 0x30, st->all_info2.out.size);
|
---|
494 | SIVAL(blob->data, 0x38, st->all_info2.out.nlink);
|
---|
495 | SCVAL(blob->data, 0x3C, st->all_info2.out.delete_pending);
|
---|
496 | SCVAL(blob->data, 0x3D, st->all_info2.out.directory);
|
---|
497 | SSVAL(blob->data, 0x3E, 0); /* padding */
|
---|
498 | SBVAL(blob->data, 0x40, st->all_info2.out.file_id);
|
---|
499 | SIVAL(blob->data, 0x48, st->all_info2.out.ea_size);
|
---|
500 | SIVAL(blob->data, 0x4C, st->all_info2.out.access_mask);
|
---|
501 | SBVAL(blob->data, 0x50, st->all_info2.out.position);
|
---|
502 | SIVAL(blob->data, 0x58, st->all_info2.out.mode);
|
---|
503 | SIVAL(blob->data, 0x5C, st->all_info2.out.alignment_requirement);
|
---|
504 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
|
---|
505 | st->all_info2.out.fname.s,
|
---|
506 | 0x60, default_str_flags,
|
---|
507 | STR_UNICODE));
|
---|
508 | return NT_STATUS_OK;
|
---|
509 |
|
---|
510 | default:
|
---|
511 | return NT_STATUS_INVALID_LEVEL;
|
---|
512 | }
|
---|
513 | }
|
---|
514 |
|
---|
515 | NTSTATUS smbsrv_pull_passthru_sfileinfo(TALLOC_CTX *mem_ctx,
|
---|
516 | enum smb_setfileinfo_level level,
|
---|
517 | union smb_setfileinfo *st,
|
---|
518 | const DATA_BLOB *blob,
|
---|
519 | int default_str_flags,
|
---|
520 | struct request_bufinfo *bufinfo)
|
---|
521 | {
|
---|
522 | uint32_t len, ofs;
|
---|
523 | DATA_BLOB str_blob;
|
---|
524 |
|
---|
525 | switch (level) {
|
---|
526 | case SMB_SFILEINFO_BASIC_INFORMATION:
|
---|
527 | BLOB_CHECK_MIN_SIZE(blob, 40);
|
---|
528 |
|
---|
529 | st->basic_info.in.create_time = pull_nttime(blob->data, 0);
|
---|
530 | st->basic_info.in.access_time = pull_nttime(blob->data, 8);
|
---|
531 | st->basic_info.in.write_time = pull_nttime(blob->data, 16);
|
---|
532 | st->basic_info.in.change_time = pull_nttime(blob->data, 24);
|
---|
533 | st->basic_info.in.attrib = IVAL(blob->data, 32);
|
---|
534 | st->basic_info.in.reserved = IVAL(blob->data, 36);
|
---|
535 |
|
---|
536 | return NT_STATUS_OK;
|
---|
537 |
|
---|
538 | case SMB_SFILEINFO_DISPOSITION_INFORMATION:
|
---|
539 | BLOB_CHECK_MIN_SIZE(blob, 1);
|
---|
540 |
|
---|
541 | st->disposition_info.in.delete_on_close = CVAL(blob->data, 0);
|
---|
542 |
|
---|
543 | return NT_STATUS_OK;
|
---|
544 |
|
---|
545 | case SMB_SFILEINFO_ALLOCATION_INFORMATION:
|
---|
546 | BLOB_CHECK_MIN_SIZE(blob, 8);
|
---|
547 |
|
---|
548 | st->allocation_info.in.alloc_size = BVAL(blob->data, 0);
|
---|
549 |
|
---|
550 | return NT_STATUS_OK;
|
---|
551 |
|
---|
552 | case RAW_SFILEINFO_END_OF_FILE_INFORMATION:
|
---|
553 | BLOB_CHECK_MIN_SIZE(blob, 8);
|
---|
554 |
|
---|
555 | st->end_of_file_info.in.size = BVAL(blob->data, 0);
|
---|
556 |
|
---|
557 | return NT_STATUS_OK;
|
---|
558 |
|
---|
559 | case RAW_SFILEINFO_RENAME_INFORMATION:
|
---|
560 | if (!bufinfo) {
|
---|
561 | return NT_STATUS_INTERNAL_ERROR;
|
---|
562 | }
|
---|
563 | BLOB_CHECK_MIN_SIZE(blob, 12);
|
---|
564 | st->rename_information.in.overwrite = CVAL(blob->data, 0);
|
---|
565 | st->rename_information.in.root_fid = IVAL(blob->data, 4);
|
---|
566 | len = IVAL(blob->data, 8);
|
---|
567 | ofs = 12;
|
---|
568 | str_blob = *blob;
|
---|
569 | str_blob.length = MIN(str_blob.length, ofs+len);
|
---|
570 | smbsrv_blob_pull_string(bufinfo, &str_blob, ofs,
|
---|
571 | &st->rename_information.in.new_name,
|
---|
572 | STR_UNICODE);
|
---|
573 | if (st->rename_information.in.new_name == NULL) {
|
---|
574 | return NT_STATUS_FOOBAR;
|
---|
575 | }
|
---|
576 |
|
---|
577 | return NT_STATUS_OK;
|
---|
578 |
|
---|
579 |
|
---|
580 | case RAW_SFILEINFO_LINK_INFORMATION:
|
---|
581 | if (!bufinfo) {
|
---|
582 | return NT_STATUS_INTERNAL_ERROR;
|
---|
583 | }
|
---|
584 | BLOB_CHECK_MIN_SIZE(blob, 20);
|
---|
585 | st->link_information.in.overwrite = CVAL(blob->data, 0);
|
---|
586 | st->link_information.in.root_fid = IVAL(blob->data, 8);
|
---|
587 | len = IVAL(blob->data, 16);
|
---|
588 | ofs = 20;
|
---|
589 | str_blob = *blob;
|
---|
590 | str_blob.length = MIN(str_blob.length, ofs+len);
|
---|
591 | smbsrv_blob_pull_string(bufinfo, &str_blob, ofs,
|
---|
592 | &st->link_information.in.new_name,
|
---|
593 | STR_UNICODE);
|
---|
594 | if (st->link_information.in.new_name == NULL) {
|
---|
595 | return NT_STATUS_FOOBAR;
|
---|
596 | }
|
---|
597 |
|
---|
598 | return NT_STATUS_OK;
|
---|
599 |
|
---|
600 | case RAW_SFILEINFO_RENAME_INFORMATION_SMB2:
|
---|
601 | /* SMB2 uses a different format for rename information */
|
---|
602 | if (!bufinfo) {
|
---|
603 | return NT_STATUS_INTERNAL_ERROR;
|
---|
604 | }
|
---|
605 | BLOB_CHECK_MIN_SIZE(blob, 20);
|
---|
606 | st->rename_information.in.overwrite = CVAL(blob->data, 0);
|
---|
607 | st->rename_information.in.root_fid = BVAL(blob->data, 8);
|
---|
608 | len = IVAL(blob->data,16);
|
---|
609 | ofs = 20;
|
---|
610 | str_blob = *blob;
|
---|
611 | str_blob.length = MIN(str_blob.length, ofs+len);
|
---|
612 | smbsrv_blob_pull_string(bufinfo, &str_blob, ofs,
|
---|
613 | &st->rename_information.in.new_name,
|
---|
614 | STR_UNICODE);
|
---|
615 | if (st->rename_information.in.new_name == NULL) {
|
---|
616 | return NT_STATUS_FOOBAR;
|
---|
617 | }
|
---|
618 |
|
---|
619 | return NT_STATUS_OK;
|
---|
620 |
|
---|
621 | case RAW_SFILEINFO_POSITION_INFORMATION:
|
---|
622 | BLOB_CHECK_MIN_SIZE(blob, 8);
|
---|
623 |
|
---|
624 | st->position_information.in.position = BVAL(blob->data, 0);
|
---|
625 |
|
---|
626 | return NT_STATUS_OK;
|
---|
627 |
|
---|
628 | case RAW_SFILEINFO_MODE_INFORMATION:
|
---|
629 | BLOB_CHECK_MIN_SIZE(blob, 4);
|
---|
630 |
|
---|
631 | st->mode_information.in.mode = IVAL(blob->data, 0);
|
---|
632 |
|
---|
633 | return NT_STATUS_OK;
|
---|
634 |
|
---|
635 | default:
|
---|
636 | return NT_STATUS_INVALID_LEVEL;
|
---|
637 | }
|
---|
638 | }
|
---|
639 |
|
---|
640 | /*
|
---|
641 | fill a single entry in a trans2 find reply
|
---|
642 | */
|
---|
643 | NTSTATUS smbsrv_push_passthru_search(TALLOC_CTX *mem_ctx,
|
---|
644 | DATA_BLOB *blob,
|
---|
645 | enum smb_search_data_level level,
|
---|
646 | const union smb_search_data *file,
|
---|
647 | int default_str_flags)
|
---|
648 | {
|
---|
649 | uint8_t *data;
|
---|
650 | unsigned int ofs = blob->length;
|
---|
651 |
|
---|
652 | switch (level) {
|
---|
653 | case RAW_SEARCH_DATA_DIRECTORY_INFO:
|
---|
654 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, ofs + 64));
|
---|
655 | data = blob->data + ofs;
|
---|
656 | SIVAL(data, 4, file->directory_info.file_index);
|
---|
657 | push_nttime(data, 8, file->directory_info.create_time);
|
---|
658 | push_nttime(data, 16, file->directory_info.access_time);
|
---|
659 | push_nttime(data, 24, file->directory_info.write_time);
|
---|
660 | push_nttime(data, 32, file->directory_info.change_time);
|
---|
661 | SBVAL(data, 40, file->directory_info.size);
|
---|
662 | SBVAL(data, 48, file->directory_info.alloc_size);
|
---|
663 | SIVAL(data, 56, file->directory_info.attrib);
|
---|
664 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob, file->directory_info.name.s,
|
---|
665 | ofs + 60, default_str_flags,
|
---|
666 | STR_TERMINATE_ASCII));
|
---|
667 | BLOB_ALIGN(blob, 8);
|
---|
668 | data = blob->data + ofs;
|
---|
669 | SIVAL(data, 0, blob->length - ofs);
|
---|
670 | return NT_STATUS_OK;
|
---|
671 |
|
---|
672 | case RAW_SEARCH_DATA_FULL_DIRECTORY_INFO:
|
---|
673 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, ofs + 68));
|
---|
674 | data = blob->data + ofs;
|
---|
675 | SIVAL(data, 4, file->full_directory_info.file_index);
|
---|
676 | push_nttime(data, 8, file->full_directory_info.create_time);
|
---|
677 | push_nttime(data, 16, file->full_directory_info.access_time);
|
---|
678 | push_nttime(data, 24, file->full_directory_info.write_time);
|
---|
679 | push_nttime(data, 32, file->full_directory_info.change_time);
|
---|
680 | SBVAL(data, 40, file->full_directory_info.size);
|
---|
681 | SBVAL(data, 48, file->full_directory_info.alloc_size);
|
---|
682 | SIVAL(data, 56, file->full_directory_info.attrib);
|
---|
683 | SIVAL(data, 64, file->full_directory_info.ea_size);
|
---|
684 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob, file->full_directory_info.name.s,
|
---|
685 | ofs + 60, default_str_flags,
|
---|
686 | STR_TERMINATE_ASCII));
|
---|
687 | BLOB_ALIGN(blob, 8);
|
---|
688 | data = blob->data + ofs;
|
---|
689 | SIVAL(data, 0, blob->length - ofs);
|
---|
690 | return NT_STATUS_OK;
|
---|
691 |
|
---|
692 | case RAW_SEARCH_DATA_NAME_INFO:
|
---|
693 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, ofs + 12));
|
---|
694 | data = blob->data + ofs;
|
---|
695 | SIVAL(data, 4, file->name_info.file_index);
|
---|
696 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob, file->name_info.name.s,
|
---|
697 | ofs + 8, default_str_flags,
|
---|
698 | STR_TERMINATE_ASCII));
|
---|
699 | BLOB_ALIGN(blob, 8);
|
---|
700 | data = blob->data + ofs;
|
---|
701 | SIVAL(data, 0, blob->length - ofs);
|
---|
702 | return NT_STATUS_OK;
|
---|
703 |
|
---|
704 | case RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO:
|
---|
705 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, ofs + 94));
|
---|
706 | data = blob->data + ofs;
|
---|
707 | SIVAL(data, 4, file->both_directory_info.file_index);
|
---|
708 | push_nttime(data, 8, file->both_directory_info.create_time);
|
---|
709 | push_nttime(data, 16, file->both_directory_info.access_time);
|
---|
710 | push_nttime(data, 24, file->both_directory_info.write_time);
|
---|
711 | push_nttime(data, 32, file->both_directory_info.change_time);
|
---|
712 | SBVAL(data, 40, file->both_directory_info.size);
|
---|
713 | SBVAL(data, 48, file->both_directory_info.alloc_size);
|
---|
714 | SIVAL(data, 56, file->both_directory_info.attrib);
|
---|
715 | SIVAL(data, 64, file->both_directory_info.ea_size);
|
---|
716 | SCVAL(data, 69, 0); /* reserved */
|
---|
717 | memset(data+70,0,24);
|
---|
718 | smbsrv_blob_push_string(mem_ctx, blob,
|
---|
719 | 68 + ofs, 70 + ofs,
|
---|
720 | file->both_directory_info.short_name.s,
|
---|
721 | 24, default_str_flags,
|
---|
722 | STR_UNICODE | STR_LEN8BIT);
|
---|
723 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob, file->both_directory_info.name.s,
|
---|
724 | ofs + 60, default_str_flags,
|
---|
725 | STR_TERMINATE_ASCII));
|
---|
726 | BLOB_ALIGN(blob, 8);
|
---|
727 | data = blob->data + ofs;
|
---|
728 | SIVAL(data, 0, blob->length - ofs);
|
---|
729 | return NT_STATUS_OK;
|
---|
730 |
|
---|
731 | case RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO:
|
---|
732 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, ofs + 80));
|
---|
733 | data = blob->data + ofs;
|
---|
734 | SIVAL(data, 4, file->id_full_directory_info.file_index);
|
---|
735 | push_nttime(data, 8, file->id_full_directory_info.create_time);
|
---|
736 | push_nttime(data, 16, file->id_full_directory_info.access_time);
|
---|
737 | push_nttime(data, 24, file->id_full_directory_info.write_time);
|
---|
738 | push_nttime(data, 32, file->id_full_directory_info.change_time);
|
---|
739 | SBVAL(data, 40, file->id_full_directory_info.size);
|
---|
740 | SBVAL(data, 48, file->id_full_directory_info.alloc_size);
|
---|
741 | SIVAL(data, 56, file->id_full_directory_info.attrib);
|
---|
742 | SIVAL(data, 64, file->id_full_directory_info.ea_size);
|
---|
743 | SIVAL(data, 68, 0); /* padding */
|
---|
744 | SBVAL(data, 72, file->id_full_directory_info.file_id);
|
---|
745 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob, file->id_full_directory_info.name.s,
|
---|
746 | ofs + 60, default_str_flags,
|
---|
747 | STR_TERMINATE_ASCII));
|
---|
748 | BLOB_ALIGN(blob, 8);
|
---|
749 | data = blob->data + ofs;
|
---|
750 | SIVAL(data, 0, blob->length - ofs);
|
---|
751 | return NT_STATUS_OK;
|
---|
752 |
|
---|
753 | case RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO:
|
---|
754 | BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, ofs + 104));
|
---|
755 | data = blob->data + ofs;
|
---|
756 | SIVAL(data, 4, file->id_both_directory_info.file_index);
|
---|
757 | push_nttime(data, 8, file->id_both_directory_info.create_time);
|
---|
758 | push_nttime(data, 16, file->id_both_directory_info.access_time);
|
---|
759 | push_nttime(data, 24, file->id_both_directory_info.write_time);
|
---|
760 | push_nttime(data, 32, file->id_both_directory_info.change_time);
|
---|
761 | SBVAL(data, 40, file->id_both_directory_info.size);
|
---|
762 | SBVAL(data, 48, file->id_both_directory_info.alloc_size);
|
---|
763 | SIVAL(data, 56, file->id_both_directory_info.attrib);
|
---|
764 | SIVAL(data, 64, file->id_both_directory_info.ea_size);
|
---|
765 | SCVAL(data, 69, 0); /* reserved */
|
---|
766 | memset(data+70,0,26);
|
---|
767 | smbsrv_blob_push_string(mem_ctx, blob,
|
---|
768 | 68 + ofs, 70 + ofs,
|
---|
769 | file->id_both_directory_info.short_name.s,
|
---|
770 | 24, default_str_flags,
|
---|
771 | STR_UNICODE | STR_LEN8BIT);
|
---|
772 | SBVAL(data, 96, file->id_both_directory_info.file_id);
|
---|
773 | BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob, file->id_both_directory_info.name.s,
|
---|
774 | ofs + 60, default_str_flags,
|
---|
775 | STR_TERMINATE_ASCII));
|
---|
776 | BLOB_ALIGN(blob, 8);
|
---|
777 | data = blob->data + ofs;
|
---|
778 | SIVAL(data, 0, blob->length - ofs);
|
---|
779 | return NT_STATUS_OK;
|
---|
780 |
|
---|
781 | default:
|
---|
782 | return NT_STATUS_INVALID_LEVEL;
|
---|
783 | }
|
---|
784 | }
|
---|