2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 2003
5 Copyright (C) Stefan Metzmacher 2006
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 2 of the License, or
10 (at your option) any later version.
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.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "dlinklist.h"
24 #include "smb_server/smb_server.h"
25 #include "librpc/gen_ndr/ndr_misc.h"
26 #include "ntvfs/ntvfs.h"
27 #include "libcli/raw/libcliraw.h"
29 #define BLOB_CHECK(cmd) do { \
32 NT_STATUS_NOT_OK_RETURN(_status); \
35 /* grow the data size of a trans2 reply */
36 NTSTATUS
smbsrv_blob_grow_data(TALLOC_CTX
*mem_ctx
,
40 if (new_size
> blob
->length
) {
42 p
= talloc_realloc(mem_ctx
, blob
->data
, uint8_t, new_size
);
43 NT_STATUS_HAVE_NO_MEMORY(p
);
46 blob
->length
= new_size
;
50 /* grow the data, zero filling any new bytes */
51 NTSTATUS
smbsrv_blob_fill_data(TALLOC_CTX
*mem_ctx
,
55 uint32_t old_size
= blob
->length
;
56 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, new_size
));
57 if (new_size
> old_size
) {
58 memset(blob
->data
+ old_size
, 0, new_size
- old_size
);
64 pull a string from a blob in a trans2 request
66 size_t smbsrv_blob_pull_string(struct smbsrv_request
*req
,
67 const DATA_BLOB
*blob
,
73 /* we use STR_NO_RANGE_CHECK because the params are allocated
74 separately in a DATA_BLOB, so we need to do our own range
76 if (offset
>= blob
->length
) {
80 return req_pull_string(req
, str
,
82 blob
->length
- offset
,
83 STR_NO_RANGE_CHECK
| flags
);
87 push a string into the data section of a trans2 request
88 return the number of bytes consumed in the output
90 size_t smbsrv_blob_push_string(TALLOC_CTX
*mem_ctx
,
99 int alignment
= 0, ret
= 0, pkt_len
;
101 /* we use STR_NO_RANGE_CHECK because the params are allocated
102 separately in a DATA_BLOB, so we need to do our own range
104 if (!str
|| offset
>= blob
->length
) {
105 if (flags
& STR_LEN8BIT
) {
106 SCVAL(blob
->data
, len_offset
, 0);
108 SIVAL(blob
->data
, len_offset
, 0);
113 flags
|= STR_NO_RANGE_CHECK
;
115 if (dest_len
== -1 || (dest_len
> blob
->length
- offset
)) {
116 dest_len
= blob
->length
- offset
;
119 if (!(flags
& (STR_ASCII
|STR_UNICODE
))) {
120 flags
|= default_flags
;
123 if ((offset
&1) && (flags
& STR_UNICODE
) && !(flags
& STR_NOALIGN
)) {
126 SCVAL(blob
->data
+ offset
, 0, 0);
127 ret
= push_string(blob
->data
+ offset
+ 1, str
, dest_len
-1, flags
);
130 ret
= push_string(blob
->data
+ offset
, str
, dest_len
, flags
);
133 /* sometimes the string needs to be terminated, but the length
134 on the wire must not include the termination! */
137 if ((flags
& STR_LEN_NOTERM
) && (flags
& STR_TERMINATE
)) {
138 if ((flags
& STR_UNICODE
) && ret
>= 2) {
141 if ((flags
& STR_ASCII
) && ret
>= 1) {
146 if (flags
& STR_LEN8BIT
) {
147 SCVAL(blob
->data
, len_offset
, pkt_len
);
149 SIVAL(blob
->data
, len_offset
, pkt_len
);
152 return ret
+ alignment
;
156 append a string to the data section of a trans2 reply
157 len_offset points to the place in the packet where the length field
160 NTSTATUS
smbsrv_blob_append_string(TALLOC_CTX
*mem_ctx
,
169 const int max_bytes_per_char
= 3;
171 offset
= blob
->length
;
172 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, offset
+ (2+strlen_m(str
))*max_bytes_per_char
));
173 ret
= smbsrv_blob_push_string(mem_ctx
, blob
, len_offset
, offset
, str
, -1, default_flags
, flags
);
175 return NT_STATUS_FOOBAR
;
177 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, offset
+ ret
));
181 NTSTATUS
smbsrv_push_passthru_fsinfo(TALLOC_CTX
*mem_ctx
,
183 enum smb_fsinfo_level level
,
184 union smb_fsinfo
*fsinfo
,
185 int default_str_flags
)
191 case RAW_QFS_VOLUME_INFORMATION
:
192 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, 18));
194 push_nttime(blob
->data
, 0, fsinfo
->volume_info
.out
.create_time
);
195 SIVAL(blob
->data
, 8, fsinfo
->volume_info
.out
.serial_number
);
196 SSVAL(blob
->data
, 16, 0); /* padding */
197 BLOB_CHECK(smbsrv_blob_append_string(mem_ctx
, blob
,
198 fsinfo
->volume_info
.out
.volume_name
.s
,
199 12, default_str_flags
,
204 case RAW_QFS_SIZE_INFORMATION
:
205 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, 24));
207 SBVAL(blob
->data
, 0, fsinfo
->size_info
.out
.total_alloc_units
);
208 SBVAL(blob
->data
, 8, fsinfo
->size_info
.out
.avail_alloc_units
);
209 SIVAL(blob
->data
, 16, fsinfo
->size_info
.out
.sectors_per_unit
);
210 SIVAL(blob
->data
, 20, fsinfo
->size_info
.out
.bytes_per_sector
);
214 case RAW_QFS_DEVICE_INFORMATION
:
215 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, 8));
217 SIVAL(blob
->data
, 0, fsinfo
->device_info
.out
.device_type
);
218 SIVAL(blob
->data
, 4, fsinfo
->device_info
.out
.characteristics
);
222 case RAW_QFS_ATTRIBUTE_INFORMATION
:
223 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, 12));
225 SIVAL(blob
->data
, 0, fsinfo
->attribute_info
.out
.fs_attr
);
226 SIVAL(blob
->data
, 4, fsinfo
->attribute_info
.out
.max_file_component_length
);
227 /* this must not be null terminated or win98 gets
228 confused! also note that w2k3 returns this as
229 unicode even when ascii is negotiated */
230 BLOB_CHECK(smbsrv_blob_append_string(mem_ctx
, blob
,
231 fsinfo
->attribute_info
.out
.fs_type
.s
,
232 8, default_str_flags
,
237 case RAW_QFS_QUOTA_INFORMATION
:
238 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, 48));
240 SBVAL(blob
->data
, 0, fsinfo
->quota_information
.out
.unknown
[0]);
241 SBVAL(blob
->data
, 8, fsinfo
->quota_information
.out
.unknown
[1]);
242 SBVAL(blob
->data
, 16, fsinfo
->quota_information
.out
.unknown
[2]);
243 SBVAL(blob
->data
, 24, fsinfo
->quota_information
.out
.quota_soft
);
244 SBVAL(blob
->data
, 32, fsinfo
->quota_information
.out
.quota_hard
);
245 SBVAL(blob
->data
, 40, fsinfo
->quota_information
.out
.quota_flags
);
250 case RAW_QFS_FULL_SIZE_INFORMATION
:
251 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, 32));
253 SBVAL(blob
->data
, 0, fsinfo
->full_size_information
.out
.total_alloc_units
);
254 SBVAL(blob
->data
, 8, fsinfo
->full_size_information
.out
.call_avail_alloc_units
);
255 SBVAL(blob
->data
, 16, fsinfo
->full_size_information
.out
.actual_avail_alloc_units
);
256 SIVAL(blob
->data
, 24, fsinfo
->full_size_information
.out
.sectors_per_unit
);
257 SIVAL(blob
->data
, 28, fsinfo
->full_size_information
.out
.bytes_per_sector
);
261 case RAW_QFS_OBJECTID_INFORMATION
:
262 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, 64));
264 BLOB_CHECK(ndr_push_struct_blob(&guid_blob
, mem_ctx
,
265 &fsinfo
->objectid_information
.out
.guid
,
266 (ndr_push_flags_fn_t
)ndr_push_GUID
));
267 memcpy(blob
->data
, guid_blob
.data
, guid_blob
.length
);
270 SBVAL(blob
->data
, 16 + 8*i
, fsinfo
->objectid_information
.out
.unknown
[i
]);
276 return NT_STATUS_INVALID_LEVEL
;
279 return NT_STATUS_INVALID_LEVEL
;
282 NTSTATUS
smbsrv_push_passthru_fileinfo(TALLOC_CTX
*mem_ctx
,
284 enum smb_fileinfo_level level
,
285 union smb_fileinfo
*st
,
286 int default_str_flags
)
292 case RAW_FILEINFO_BASIC_INFORMATION
:
293 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, 40));
295 push_nttime(blob
->data
, 0, st
->basic_info
.out
.create_time
);
296 push_nttime(blob
->data
, 8, st
->basic_info
.out
.access_time
);
297 push_nttime(blob
->data
, 16, st
->basic_info
.out
.write_time
);
298 push_nttime(blob
->data
, 24, st
->basic_info
.out
.change_time
);
299 SIVAL(blob
->data
, 32, st
->basic_info
.out
.attrib
);
300 SIVAL(blob
->data
, 36, 0); /* padding */
303 case RAW_FILEINFO_NETWORK_OPEN_INFORMATION
:
304 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, 56));
306 push_nttime(blob
->data
, 0, st
->network_open_information
.out
.create_time
);
307 push_nttime(blob
->data
, 8, st
->network_open_information
.out
.access_time
);
308 push_nttime(blob
->data
, 16, st
->network_open_information
.out
.write_time
);
309 push_nttime(blob
->data
, 24, st
->network_open_information
.out
.change_time
);
310 SBVAL(blob
->data
, 32, st
->network_open_information
.out
.alloc_size
);
311 SBVAL(blob
->data
, 40, st
->network_open_information
.out
.size
);
312 SIVAL(blob
->data
, 48, st
->network_open_information
.out
.attrib
);
313 SIVAL(blob
->data
, 52, 0); /* padding */
316 case RAW_FILEINFO_STANDARD_INFORMATION
:
317 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, 24));
319 SBVAL(blob
->data
, 0, st
->standard_info
.out
.alloc_size
);
320 SBVAL(blob
->data
, 8, st
->standard_info
.out
.size
);
321 SIVAL(blob
->data
, 16, st
->standard_info
.out
.nlink
);
322 SCVAL(blob
->data
, 20, st
->standard_info
.out
.delete_pending
);
323 SCVAL(blob
->data
, 21, st
->standard_info
.out
.directory
);
324 SSVAL(blob
->data
, 22, 0); /* padding */
327 case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION
:
328 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, 8));
330 SIVAL(blob
->data
, 0, st
->attribute_tag_information
.out
.attrib
);
331 SIVAL(blob
->data
, 4, st
->attribute_tag_information
.out
.reparse_tag
);
334 case RAW_FILEINFO_EA_INFORMATION
:
335 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, 4));
337 SIVAL(blob
->data
, 0, st
->ea_info
.out
.ea_size
);
340 case RAW_FILEINFO_MODE_INFORMATION
:
341 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, 4));
343 SIVAL(blob
->data
, 0, st
->mode_information
.out
.mode
);
346 case RAW_FILEINFO_ALIGNMENT_INFORMATION
:
347 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, 4));
350 st
->alignment_information
.out
.alignment_requirement
);
353 case RAW_FILEINFO_ACCESS_INFORMATION
:
354 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, 4));
356 SIVAL(blob
->data
, 0, st
->access_information
.out
.access_flags
);
359 case RAW_FILEINFO_POSITION_INFORMATION
:
360 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, 8));
362 SBVAL(blob
->data
, 0, st
->position_information
.out
.position
);
365 case RAW_FILEINFO_COMPRESSION_INFORMATION
:
366 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, 16));
368 SBVAL(blob
->data
, 0, st
->compression_info
.out
.compressed_size
);
369 SSVAL(blob
->data
, 8, st
->compression_info
.out
.format
);
370 SCVAL(blob
->data
, 10, st
->compression_info
.out
.unit_shift
);
371 SCVAL(blob
->data
, 11, st
->compression_info
.out
.chunk_shift
);
372 SCVAL(blob
->data
, 12, st
->compression_info
.out
.cluster_shift
);
373 SSVAL(blob
->data
, 13, 0); /* 3 bytes padding */
374 SCVAL(blob
->data
, 15, 0);
377 case RAW_FILEINFO_INTERNAL_INFORMATION
:
378 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, 8));
380 SBVAL(blob
->data
, 0, st
->internal_information
.out
.file_id
);
383 case RAW_FILEINFO_ALL_INFORMATION
:
384 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, 72));
386 push_nttime(blob
->data
, 0, st
->all_info
.out
.create_time
);
387 push_nttime(blob
->data
, 8, st
->all_info
.out
.access_time
);
388 push_nttime(blob
->data
, 16, st
->all_info
.out
.write_time
);
389 push_nttime(blob
->data
, 24, st
->all_info
.out
.change_time
);
390 SIVAL(blob
->data
, 32, st
->all_info
.out
.attrib
);
391 SIVAL(blob
->data
, 36, 0); /* padding */
392 SBVAL(blob
->data
, 40, st
->all_info
.out
.alloc_size
);
393 SBVAL(blob
->data
, 48, st
->all_info
.out
.size
);
394 SIVAL(blob
->data
, 56, st
->all_info
.out
.nlink
);
395 SCVAL(blob
->data
, 60, st
->all_info
.out
.delete_pending
);
396 SCVAL(blob
->data
, 61, st
->all_info
.out
.directory
);
397 SSVAL(blob
->data
, 62, 0); /* padding */
398 SIVAL(blob
->data
, 64, st
->all_info
.out
.ea_size
);
399 BLOB_CHECK(smbsrv_blob_append_string(mem_ctx
, blob
,
400 st
->all_info
.out
.fname
.s
,
401 68, default_str_flags
,
405 case RAW_FILEINFO_NAME_INFORMATION
:
406 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, 4));
408 BLOB_CHECK(smbsrv_blob_append_string(mem_ctx
, blob
,
409 st
->name_info
.out
.fname
.s
,
410 0, default_str_flags
,
414 case RAW_FILEINFO_ALT_NAME_INFORMATION
:
415 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, 4));
417 BLOB_CHECK(smbsrv_blob_append_string(mem_ctx
, blob
,
418 st
->alt_name_info
.out
.fname
.s
,
419 0, default_str_flags
,
423 case RAW_FILEINFO_STREAM_INFORMATION
:
424 for (i
=0;i
<st
->stream_info
.out
.num_streams
;i
++) {
425 uint32_t data_size
= blob
->length
;
428 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, data_size
+ 24));
429 data
= blob
->data
+ data_size
;
430 SBVAL(data
, 8, st
->stream_info
.out
.streams
[i
].size
);
431 SBVAL(data
, 16, st
->stream_info
.out
.streams
[i
].alloc_size
);
432 BLOB_CHECK(smbsrv_blob_append_string(mem_ctx
, blob
,
433 st
->stream_info
.out
.streams
[i
].stream_name
.s
,
434 data_size
+ 4, default_str_flags
,
436 if (i
== st
->stream_info
.out
.num_streams
- 1) {
437 SIVAL(blob
->data
, data_size
, 0);
439 BLOB_CHECK(smbsrv_blob_fill_data(mem_ctx
, blob
, (blob
->length
+7)&~7));
440 SIVAL(blob
->data
, data_size
,
441 blob
->length
- data_size
);
446 case RAW_FILEINFO_SMB2_ALL_EAS
:
447 list_size
= ea_list_size_chained(st
->all_eas
.out
.num_eas
,
448 st
->all_eas
.out
.eas
);
449 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, list_size
));
451 ea_put_list_chained(blob
->data
,
452 st
->all_eas
.out
.num_eas
,
453 st
->all_eas
.out
.eas
);
456 case RAW_FILEINFO_SMB2_ALL_INFORMATION
:
457 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx
, blob
, 0x64));
459 push_nttime(blob
->data
, 0x00, st
->all_info2
.out
.create_time
);
460 push_nttime(blob
->data
, 0x08, st
->all_info2
.out
.access_time
);
461 push_nttime(blob
->data
, 0x10, st
->all_info2
.out
.write_time
);
462 push_nttime(blob
->data
, 0x18, st
->all_info2
.out
.change_time
);
463 SIVAL(blob
->data
, 0x20, st
->all_info2
.out
.attrib
);
464 SIVAL(blob
->data
, 0x24, st
->all_info2
.out
.unknown1
);
465 SBVAL(blob
->data
, 0x28, st
->all_info2
.out
.alloc_size
);
466 SBVAL(blob
->data
, 0x30, st
->all_info2
.out
.size
);
467 SIVAL(blob
->data
, 0x38, st
->all_info2
.out
.nlink
);
468 SCVAL(blob
->data
, 0x3C, st
->all_info2
.out
.delete_pending
);
469 SCVAL(blob
->data
, 0x3D, st
->all_info2
.out
.directory
);
470 SBVAL(blob
->data
, 0x40, st
->all_info2
.out
.file_id
);
471 SIVAL(blob
->data
, 0x48, st
->all_info2
.out
.ea_size
);
472 SIVAL(blob
->data
, 0x4C, st
->all_info2
.out
.access_mask
);
473 SBVAL(blob
->data
, 0x50, st
->all_info2
.out
.position
);
474 SBVAL(blob
->data
, 0x58, st
->all_info2
.out
.mode
);
475 BLOB_CHECK(smbsrv_blob_append_string(mem_ctx
, blob
,
476 st
->all_info2
.out
.fname
.s
,
477 0x60, default_str_flags
,
482 return NT_STATUS_INVALID_LEVEL
;
485 return NT_STATUS_INVALID_LEVEL
;