Ensure convert_string_XXX is always called with a valid converted_size pointer.
[samba.git] / source4 / libcli / raw / rawfileinfo.c
1 /* 
2    Unix SMB/CIFS implementation.
3    client trans2 operations
4    Copyright (C) James Myers 2003
5    Copyright (C) Andrew Tridgell 2003
6    Copyright (C) James Peach 2007
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "libcli/raw/raw_proto.h"
25 #include "librpc/gen_ndr/ndr_security.h"
26
27 /* local macros to make the code more readable */
28 #define FINFO_CHECK_MIN_SIZE(size) if (blob->length < (size)) { \
29       DEBUG(1,("Unexpected FILEINFO reply size %d for level %u - expected min of %d\n", \
30                (int)blob->length, parms->generic.level, (size))); \
31       return NT_STATUS_INFO_LENGTH_MISMATCH; \
32 }
33 #define FINFO_CHECK_SIZE(size) if (blob->length != (size)) { \
34       DEBUG(1,("Unexpected FILEINFO reply size %d for level %u - expected %d\n", \
35                (int)blob->length, parms->generic.level, (size))); \
36       return NT_STATUS_INFO_LENGTH_MISMATCH; \
37 }
38
39 /*
40   parse a stream information structure
41 */
42 NTSTATUS smbcli_parse_stream_info(DATA_BLOB blob, TALLOC_CTX *mem_ctx,
43                                   struct stream_information *io)
44 {
45         uint32_t ofs = 0;
46         io->num_streams = 0;
47         io->streams = NULL;
48
49         while (blob.length - ofs >= 24) {
50                 unsigned int n = io->num_streams;
51                 uint32_t nlen, len;
52                 bool ret;
53                 void *vstr;
54                 size_t converted_size = 0;
55
56                 io->streams = 
57                         talloc_realloc(mem_ctx, io->streams, struct stream_struct, n+1);
58                 if (!io->streams) {
59                         return NT_STATUS_NO_MEMORY;
60                 }
61                 nlen                      = IVAL(blob.data, ofs + 0x04);
62                 io->streams[n].size       = BVAL(blob.data, ofs + 0x08);
63                 io->streams[n].alloc_size = BVAL(blob.data, ofs + 0x10);
64                 if (nlen > blob.length - (ofs + 24)) {
65                         return NT_STATUS_INFO_LENGTH_MISMATCH;
66                 }
67                 ret = convert_string_talloc(io->streams, 
68                                              CH_UTF16, CH_UNIX,
69                                              blob.data+ofs+24, nlen, &vstr, &converted_size);
70                 if (!ret) {
71                         return NT_STATUS_ILLEGAL_CHARACTER;
72                 }
73                 io->streams[n].stream_name.s = (const char *)vstr;
74                 io->streams[n].stream_name.private_length = nlen;
75                 io->num_streams++;
76                 len = IVAL(blob.data, ofs);
77                 if (len > blob.length - ofs) {
78                         return NT_STATUS_INFO_LENGTH_MISMATCH;
79                 }
80                 if (len == 0) break;
81                 ofs += len;
82         }
83
84         return NT_STATUS_OK;
85 }
86
87 /*
88   parse the fsinfo 'passthru' level replies
89 */
90 NTSTATUS smb_raw_fileinfo_passthru_parse(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, 
91                                          enum smb_fileinfo_level level,
92                                          union smb_fileinfo *parms)
93 {       
94         switch (level) {
95         case RAW_FILEINFO_BASIC_INFORMATION:
96                 /* some servers return 40 bytes and some 36. w2k3 return 40, so thats
97                    what we should do, but we need to accept 36 */
98                 if (blob->length != 36) {
99                         FINFO_CHECK_SIZE(40);
100                 }
101                 parms->basic_info.out.create_time = smbcli_pull_nttime(blob->data, 0);
102                 parms->basic_info.out.access_time = smbcli_pull_nttime(blob->data, 8);
103                 parms->basic_info.out.write_time  = smbcli_pull_nttime(blob->data, 16);
104                 parms->basic_info.out.change_time = smbcli_pull_nttime(blob->data, 24);
105                 parms->basic_info.out.attrib      = IVAL(blob->data, 32);
106                 return NT_STATUS_OK;
107
108         case RAW_FILEINFO_STANDARD_INFORMATION:
109                 FINFO_CHECK_SIZE(24);
110                 parms->standard_info.out.alloc_size =     BVAL(blob->data, 0);
111                 parms->standard_info.out.size =           BVAL(blob->data, 8);
112                 parms->standard_info.out.nlink =          IVAL(blob->data, 16);
113                 parms->standard_info.out.delete_pending = CVAL(blob->data, 20);
114                 parms->standard_info.out.directory =      CVAL(blob->data, 21);
115                 return NT_STATUS_OK;
116
117         case RAW_FILEINFO_EA_INFORMATION:
118                 FINFO_CHECK_SIZE(4);
119                 parms->ea_info.out.ea_size = IVAL(blob->data, 0);
120                 return NT_STATUS_OK;
121
122         case RAW_FILEINFO_NAME_INFORMATION:
123                 FINFO_CHECK_MIN_SIZE(4);
124                 smbcli_blob_pull_string(NULL, mem_ctx, blob, 
125                                         &parms->name_info.out.fname, 0, 4, STR_UNICODE);
126                 return NT_STATUS_OK;
127
128         case RAW_FILEINFO_ALL_INFORMATION:
129                 FINFO_CHECK_MIN_SIZE(72);
130                 parms->all_info.out.create_time =           smbcli_pull_nttime(blob->data, 0);
131                 parms->all_info.out.access_time =           smbcli_pull_nttime(blob->data, 8);
132                 parms->all_info.out.write_time =            smbcli_pull_nttime(blob->data, 16);
133                 parms->all_info.out.change_time =           smbcli_pull_nttime(blob->data, 24);
134                 parms->all_info.out.attrib =                IVAL(blob->data, 32);
135                 parms->all_info.out.alloc_size =            BVAL(blob->data, 40);
136                 parms->all_info.out.size =                  BVAL(blob->data, 48);
137                 parms->all_info.out.nlink =                 IVAL(blob->data, 56);
138                 parms->all_info.out.delete_pending =        CVAL(blob->data, 60);
139                 parms->all_info.out.directory =             CVAL(blob->data, 61);
140 #if 1
141                 parms->all_info.out.ea_size =               IVAL(blob->data, 64);
142                 smbcli_blob_pull_string(NULL, mem_ctx, blob,
143                                         &parms->all_info.out.fname, 68, 72, STR_UNICODE);
144 #else
145                 /* this is what the CIFS spec says - and its totally
146                    wrong, but its useful having it here so we can
147                    quickly adapt to broken servers when running
148                    tests */
149                 parms->all_info.out.ea_size =               IVAL(blob->data, 72);
150                 /* access flags 4 bytes at 76
151                    current_position 8 bytes at 80
152                    mode 4 bytes at 88
153                    alignment 4 bytes at 92
154                 */
155                 smbcli_blob_pull_string(NULL, mem_ctx, blob,
156                                         &parms->all_info.out.fname, 96, 100, STR_UNICODE);
157 #endif
158                 return NT_STATUS_OK;
159
160         case RAW_FILEINFO_ALT_NAME_INFORMATION:
161                 FINFO_CHECK_MIN_SIZE(4);
162                 smbcli_blob_pull_string(NULL, mem_ctx, blob, 
163                                         &parms->alt_name_info.out.fname, 0, 4, STR_UNICODE);
164                 return NT_STATUS_OK;
165
166         case RAW_FILEINFO_STREAM_INFORMATION:
167                 return smbcli_parse_stream_info(*blob, mem_ctx, &parms->stream_info.out);
168
169         case RAW_FILEINFO_INTERNAL_INFORMATION:
170                 FINFO_CHECK_SIZE(8);
171                 parms->internal_information.out.file_id = BVAL(blob->data, 0);
172                 return NT_STATUS_OK;
173
174         case RAW_FILEINFO_ACCESS_INFORMATION:
175                 FINFO_CHECK_SIZE(4);
176                 parms->access_information.out.access_flags = IVAL(blob->data, 0);
177                 return NT_STATUS_OK;
178
179         case RAW_FILEINFO_POSITION_INFORMATION:
180                 FINFO_CHECK_SIZE(8);
181                 parms->position_information.out.position = BVAL(blob->data, 0);
182                 return NT_STATUS_OK;
183
184         case RAW_FILEINFO_MODE_INFORMATION:
185                 FINFO_CHECK_SIZE(4);
186                 parms->mode_information.out.mode = IVAL(blob->data, 0);
187                 return NT_STATUS_OK;
188
189         case RAW_FILEINFO_ALIGNMENT_INFORMATION:
190                 FINFO_CHECK_SIZE(4);
191                 parms->alignment_information.out.alignment_requirement 
192                         = IVAL(blob->data, 0);
193                 return NT_STATUS_OK;
194
195         case RAW_FILEINFO_COMPRESSION_INFORMATION:
196                 FINFO_CHECK_SIZE(16);
197                 parms->compression_info.out.compressed_size = BVAL(blob->data,  0);
198                 parms->compression_info.out.format          = SVAL(blob->data,  8);
199                 parms->compression_info.out.unit_shift      = CVAL(blob->data, 10);
200                 parms->compression_info.out.chunk_shift     = CVAL(blob->data, 11);
201                 parms->compression_info.out.cluster_shift   = CVAL(blob->data, 12);
202                 /* 3 bytes of padding */
203                 return NT_STATUS_OK;
204
205         case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:             
206                 FINFO_CHECK_SIZE(56);
207                 parms->network_open_information.out.create_time = smbcli_pull_nttime(blob->data,  0);
208                 parms->network_open_information.out.access_time = smbcli_pull_nttime(blob->data,  8);
209                 parms->network_open_information.out.write_time =  smbcli_pull_nttime(blob->data, 16);
210                 parms->network_open_information.out.change_time = smbcli_pull_nttime(blob->data, 24);
211                 parms->network_open_information.out.alloc_size =             BVAL(blob->data, 32);
212                 parms->network_open_information.out.size =                   BVAL(blob->data, 40);
213                 parms->network_open_information.out.attrib =                 IVAL(blob->data, 48);
214                 return NT_STATUS_OK;
215
216         case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
217                 FINFO_CHECK_SIZE(8);
218                 parms->attribute_tag_information.out.attrib =      IVAL(blob->data, 0);
219                 parms->attribute_tag_information.out.reparse_tag = IVAL(blob->data, 4);
220                 return NT_STATUS_OK;
221
222         case RAW_FILEINFO_SMB2_ALL_EAS:
223                 FINFO_CHECK_MIN_SIZE(4);
224                 return ea_pull_list_chained(blob, mem_ctx, 
225                                             &parms->all_eas.out.num_eas,
226                                             &parms->all_eas.out.eas);
227
228         case RAW_FILEINFO_SMB2_ALL_INFORMATION:
229                 FINFO_CHECK_MIN_SIZE(0x64);
230                 parms->all_info2.out.create_time    = smbcli_pull_nttime(blob->data, 0x00);
231                 parms->all_info2.out.access_time    = smbcli_pull_nttime(blob->data, 0x08);
232                 parms->all_info2.out.write_time     = smbcli_pull_nttime(blob->data, 0x10);
233                 parms->all_info2.out.change_time    = smbcli_pull_nttime(blob->data, 0x18);
234                 parms->all_info2.out.attrib         = IVAL(blob->data, 0x20);
235                 parms->all_info2.out.unknown1       = IVAL(blob->data, 0x24);
236                 parms->all_info2.out.alloc_size     = BVAL(blob->data, 0x28);
237                 parms->all_info2.out.size           = BVAL(blob->data, 0x30);
238                 parms->all_info2.out.nlink          = IVAL(blob->data, 0x38);
239                 parms->all_info2.out.delete_pending = CVAL(blob->data, 0x3C);
240                 parms->all_info2.out.directory      = CVAL(blob->data, 0x3D);
241                 /* 0x3E-0x3F padding */
242                 parms->all_info2.out.file_id        = BVAL(blob->data, 0x40);
243                 parms->all_info2.out.ea_size        = IVAL(blob->data, 0x48);
244                 parms->all_info2.out.access_mask    = IVAL(blob->data, 0x4C);
245                 parms->all_info2.out.position       = BVAL(blob->data, 0x50);
246                 parms->all_info2.out.mode           = IVAL(blob->data, 0x58);
247                 parms->all_info2.out.alignment_requirement = IVAL(blob->data, 0x5C);
248                 smbcli_blob_pull_string(NULL, mem_ctx, blob,
249                                         &parms->all_info2.out.fname, 0x60, 0x64, STR_UNICODE);
250                 return NT_STATUS_OK;
251
252         case RAW_FILEINFO_SEC_DESC: {
253                 enum ndr_err_code ndr_err;
254
255                 parms->query_secdesc.out.sd = talloc(mem_ctx, struct security_descriptor);
256                 NT_STATUS_HAVE_NO_MEMORY(parms->query_secdesc.out.sd);
257
258                 ndr_err = ndr_pull_struct_blob(blob, mem_ctx,
259                         parms->query_secdesc.out.sd,
260                         (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
261                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
262                         return ndr_map_error2ntstatus(ndr_err);
263                 }
264
265                 return NT_STATUS_OK;
266         }
267
268         default:
269                 break;
270         }
271
272         return NT_STATUS_INVALID_LEVEL;
273 }
274
275
276 /****************************************************************************
277  Handle qfileinfo/qpathinfo trans2 backend.
278 ****************************************************************************/
279 static NTSTATUS smb_raw_info_backend(struct smbcli_session *session,
280                                      TALLOC_CTX *mem_ctx,
281                                      union smb_fileinfo *parms, 
282                                      DATA_BLOB *blob)
283 {       
284         switch (parms->generic.level) {
285         case RAW_FILEINFO_GENERIC:
286         case RAW_FILEINFO_GETATTR:
287         case RAW_FILEINFO_GETATTRE:
288         case RAW_FILEINFO_SEC_DESC:
289                 /* not handled here */
290                 return NT_STATUS_INVALID_LEVEL;
291
292         case RAW_FILEINFO_STANDARD:
293                 FINFO_CHECK_SIZE(22);
294                 parms->standard.out.create_time = raw_pull_dos_date2(session->transport,
295                                                                      blob->data +  0);
296                 parms->standard.out.access_time = raw_pull_dos_date2(session->transport,
297                                                                      blob->data +  4);
298                 parms->standard.out.write_time =  raw_pull_dos_date2(session->transport,
299                                                                      blob->data +  8);
300                 parms->standard.out.size =        IVAL(blob->data,             12);
301                 parms->standard.out.alloc_size =  IVAL(blob->data,             16);
302                 parms->standard.out.attrib =      SVAL(blob->data,             20);
303                 return NT_STATUS_OK;
304
305         case RAW_FILEINFO_EA_SIZE:
306                 FINFO_CHECK_SIZE(26);
307                 parms->ea_size.out.create_time = raw_pull_dos_date2(session->transport,
308                                                                     blob->data +  0);
309                 parms->ea_size.out.access_time = raw_pull_dos_date2(session->transport,
310                                                                     blob->data +  4);
311                 parms->ea_size.out.write_time =  raw_pull_dos_date2(session->transport,
312                                                                     blob->data +  8);
313                 parms->ea_size.out.size =        IVAL(blob->data,             12);
314                 parms->ea_size.out.alloc_size =  IVAL(blob->data,             16);
315                 parms->ea_size.out.attrib =      SVAL(blob->data,             20);
316                 parms->ea_size.out.ea_size =     IVAL(blob->data,             22);
317                 return NT_STATUS_OK;
318
319         case RAW_FILEINFO_EA_LIST:
320                 FINFO_CHECK_MIN_SIZE(4);
321                 return ea_pull_list(blob, mem_ctx, 
322                                     &parms->ea_list.out.num_eas,
323                                     &parms->ea_list.out.eas);
324
325         case RAW_FILEINFO_ALL_EAS:
326                 FINFO_CHECK_MIN_SIZE(4);
327                 return ea_pull_list(blob, mem_ctx, 
328                                     &parms->all_eas.out.num_eas,
329                                     &parms->all_eas.out.eas);
330
331         case RAW_FILEINFO_IS_NAME_VALID:
332                 /* no data! */
333                 FINFO_CHECK_SIZE(0);
334                 return NT_STATUS_OK;
335
336         case RAW_FILEINFO_BASIC_INFO:
337         case RAW_FILEINFO_BASIC_INFORMATION:
338                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
339                                                        RAW_FILEINFO_BASIC_INFORMATION, parms);
340
341         case RAW_FILEINFO_STANDARD_INFO:
342         case RAW_FILEINFO_STANDARD_INFORMATION:
343                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
344                                                        RAW_FILEINFO_STANDARD_INFORMATION, parms);
345
346         case RAW_FILEINFO_EA_INFO:
347         case RAW_FILEINFO_EA_INFORMATION:
348                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
349                                                        RAW_FILEINFO_EA_INFORMATION, parms);
350
351         case RAW_FILEINFO_NAME_INFO:
352         case RAW_FILEINFO_NAME_INFORMATION:
353                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
354                                                        RAW_FILEINFO_NAME_INFORMATION, parms);
355
356         case RAW_FILEINFO_ALL_INFO:
357         case RAW_FILEINFO_ALL_INFORMATION:
358                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
359                                                        RAW_FILEINFO_ALL_INFORMATION, parms);
360
361         case RAW_FILEINFO_ALT_NAME_INFO:
362         case RAW_FILEINFO_ALT_NAME_INFORMATION:
363                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
364                                                        RAW_FILEINFO_ALT_NAME_INFORMATION, parms);
365
366         case RAW_FILEINFO_STREAM_INFO:
367         case RAW_FILEINFO_STREAM_INFORMATION:
368                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
369                                                        RAW_FILEINFO_STREAM_INFORMATION, parms);
370
371         case RAW_FILEINFO_INTERNAL_INFORMATION:
372                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
373                                                        RAW_FILEINFO_INTERNAL_INFORMATION, parms);
374
375         case RAW_FILEINFO_ACCESS_INFORMATION:
376                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
377                                                        RAW_FILEINFO_ACCESS_INFORMATION, parms);
378
379         case RAW_FILEINFO_POSITION_INFORMATION:
380                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
381                                                        RAW_FILEINFO_POSITION_INFORMATION, parms);
382
383         case RAW_FILEINFO_MODE_INFORMATION:
384                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
385                                                        RAW_FILEINFO_MODE_INFORMATION, parms);
386
387         case RAW_FILEINFO_ALIGNMENT_INFORMATION:
388                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
389                                                        RAW_FILEINFO_ALIGNMENT_INFORMATION, parms);
390
391         case RAW_FILEINFO_COMPRESSION_INFO:
392         case RAW_FILEINFO_COMPRESSION_INFORMATION:
393                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
394                                                        RAW_FILEINFO_COMPRESSION_INFORMATION, parms);
395
396         case RAW_FILEINFO_UNIX_BASIC:
397                 FINFO_CHECK_SIZE(100);
398                 parms->unix_basic_info.out.end_of_file        =            BVAL(blob->data,  0);
399                 parms->unix_basic_info.out.num_bytes          =            BVAL(blob->data,  8);
400                 parms->unix_basic_info.out.status_change_time = smbcli_pull_nttime(blob->data, 16);
401                 parms->unix_basic_info.out.access_time        = smbcli_pull_nttime(blob->data, 24);
402                 parms->unix_basic_info.out.change_time        = smbcli_pull_nttime(blob->data, 32);
403                 parms->unix_basic_info.out.uid                =            BVAL(blob->data, 40);
404                 parms->unix_basic_info.out.gid                =            BVAL(blob->data, 48);
405                 parms->unix_basic_info.out.file_type          =            IVAL(blob->data, 52);
406                 parms->unix_basic_info.out.dev_major          =            BVAL(blob->data, 60);
407                 parms->unix_basic_info.out.dev_minor          =            BVAL(blob->data, 68);
408                 parms->unix_basic_info.out.unique_id          =            BVAL(blob->data, 76);
409                 parms->unix_basic_info.out.permissions        =            BVAL(blob->data, 84);
410                 parms->unix_basic_info.out.nlink              =            BVAL(blob->data, 92);
411                 return NT_STATUS_OK;
412
413         case RAW_FILEINFO_UNIX_INFO2:
414                 FINFO_CHECK_SIZE(116);
415                 parms->unix_info2.out.end_of_file       = BVAL(blob->data,  0);
416                 parms->unix_info2.out.num_bytes         = BVAL(blob->data,  8);
417                 parms->unix_info2.out.status_change_time = smbcli_pull_nttime(blob->data, 16);
418                 parms->unix_info2.out.access_time       = smbcli_pull_nttime(blob->data, 24);
419                 parms->unix_info2.out.change_time       = smbcli_pull_nttime(blob->data, 32);
420                 parms->unix_info2.out.uid               = BVAL(blob->data, 40);
421                 parms->unix_info2.out.gid               = BVAL(blob->data, 48);
422                 parms->unix_info2.out.file_type         = IVAL(blob->data, 52);
423                 parms->unix_info2.out.dev_major         = BVAL(blob->data, 60);
424                 parms->unix_info2.out.dev_minor         = BVAL(blob->data, 68);
425                 parms->unix_info2.out.unique_id         = BVAL(blob->data, 76);
426                 parms->unix_info2.out.permissions       = BVAL(blob->data, 84);
427                 parms->unix_info2.out.nlink             = BVAL(blob->data, 92);
428                 parms->unix_info2.out.create_time       = smbcli_pull_nttime(blob->data, 100);
429                 parms->unix_info2.out.file_flags        = IVAL(blob->data, 108);
430                 parms->unix_info2.out.flags_mask        = IVAL(blob->data, 112);
431                 return NT_STATUS_OK;
432
433         case RAW_FILEINFO_UNIX_LINK:
434                 smbcli_blob_pull_string(session, mem_ctx, blob, 
435                                      &parms->unix_link_info.out.link_dest, 0, 4, STR_UNICODE);
436                 return NT_STATUS_OK;
437                 
438         case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:             
439                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
440                                                        RAW_FILEINFO_NETWORK_OPEN_INFORMATION, parms);
441
442         case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
443                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
444                                                        RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION, parms);
445
446         case RAW_FILEINFO_SMB2_ALL_INFORMATION:
447                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
448                                                        RAW_FILEINFO_SMB2_ALL_INFORMATION, parms);
449
450         case RAW_FILEINFO_SMB2_ALL_EAS:
451                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
452                                                        RAW_FILEINFO_SMB2_ALL_EAS, parms);
453
454         }
455
456         return NT_STATUS_INVALID_LEVEL;
457 }
458
459
460 /****************************************************************************
461  Very raw query file info - returns param/data blobs - (async send)
462 ****************************************************************************/
463 static struct smbcli_request *smb_raw_fileinfo_blob_send(struct smbcli_tree *tree,
464                                                          uint16_t fnum, 
465                                                          uint16_t info_level,
466                                                          DATA_BLOB data)
467 {
468         struct smb_trans2 tp;
469         uint16_t setup = TRANSACT2_QFILEINFO;
470         struct smbcli_request *req;
471         TALLOC_CTX *mem_ctx = talloc_init("raw_fileinfo");
472         
473         tp.in.max_setup = 0;
474         tp.in.flags = 0; 
475         tp.in.timeout = 0;
476         tp.in.setup_count = 1;
477         tp.in.data = data;
478         tp.in.max_param = 2;
479         tp.in.max_data = 0xFFFF;
480         tp.in.setup = &setup;
481         
482         tp.in.params = data_blob_talloc(mem_ctx, NULL, 4);
483         if (!tp.in.params.data) {
484                 talloc_free(mem_ctx);
485                 return NULL;
486         }
487
488         SSVAL(tp.in.params.data, 0, fnum);
489         SSVAL(tp.in.params.data, 2, info_level);
490
491         req = smb_raw_trans2_send(tree, &tp);
492
493         talloc_free(mem_ctx);
494
495         return req;
496 }
497
498
499 /****************************************************************************
500  Very raw query file info - returns param/data blobs - (async recv)
501 ****************************************************************************/
502 static NTSTATUS smb_raw_fileinfo_blob_recv(struct smbcli_request *req,
503                                            TALLOC_CTX *mem_ctx,
504                                            DATA_BLOB *blob)
505 {
506         struct smb_trans2 tp;
507         NTSTATUS status = smb_raw_trans2_recv(req, mem_ctx, &tp);
508         if (NT_STATUS_IS_OK(status)) {
509                 *blob = tp.out.data;
510         }
511         return status;
512 }
513
514 /****************************************************************************
515  Very raw query path info - returns param/data blobs (async send)
516 ****************************************************************************/
517 static struct smbcli_request *smb_raw_pathinfo_blob_send(struct smbcli_tree *tree,
518                                                          const char *fname,
519                                                          uint16_t info_level,
520                                                          DATA_BLOB data)
521 {
522         struct smb_trans2 tp;
523         uint16_t setup = TRANSACT2_QPATHINFO;
524         struct smbcli_request *req;
525         TALLOC_CTX *mem_ctx = talloc_init("raw_pathinfo");
526
527         tp.in.max_setup = 0;
528         tp.in.flags = 0; 
529         tp.in.timeout = 0;
530         tp.in.setup_count = 1;
531         tp.in.data = data;
532         tp.in.max_param = 2;
533         tp.in.max_data = 0xFFFF;
534         tp.in.setup = &setup;
535         
536         tp.in.params = data_blob_talloc(mem_ctx, NULL, 6);
537         if (!tp.in.params.data) {
538                 talloc_free(mem_ctx);
539                 return NULL;
540         }
541
542         SSVAL(tp.in.params.data, 0, info_level);
543         SIVAL(tp.in.params.data, 2, 0);
544         smbcli_blob_append_string(tree->session, mem_ctx, &tp.in.params,
545                                fname, STR_TERMINATE);
546         
547         req = smb_raw_trans2_send(tree, &tp);
548
549         talloc_free(mem_ctx);
550
551         return req;
552 }
553
554 /****************************************************************************
555  send a SMBgetatr (async send)
556 ****************************************************************************/
557 static struct smbcli_request *smb_raw_getattr_send(struct smbcli_tree *tree,
558                                                 union smb_fileinfo *parms)
559 {
560         struct smbcli_request *req;
561         
562         req = smbcli_request_setup(tree, SMBgetatr, 0, 0);
563         if (!req) return NULL;
564
565         smbcli_req_append_ascii4(req, parms->getattr.in.file.path, STR_TERMINATE);
566         
567         if (!smbcli_request_send(req)) {
568                 smbcli_request_destroy(req);
569                 return NULL;
570         }
571
572         return req;
573 }
574
575 /****************************************************************************
576  send a SMBgetatr (async recv)
577 ****************************************************************************/
578 static NTSTATUS smb_raw_getattr_recv(struct smbcli_request *req,
579                                      union smb_fileinfo *parms)
580 {
581         if (!smbcli_request_receive(req) ||
582             smbcli_request_is_error(req)) {
583                 return smbcli_request_destroy(req);
584         }
585
586         SMBCLI_CHECK_WCT(req, 10);
587         parms->getattr.out.attrib =     SVAL(req->in.vwv, VWV(0));
588         parms->getattr.out.write_time = raw_pull_dos_date3(req->transport,
589                                                            req->in.vwv + VWV(1));
590         parms->getattr.out.size =       IVAL(req->in.vwv, VWV(3));
591
592 failed:
593         return smbcli_request_destroy(req);
594 }
595
596
597 /****************************************************************************
598  Handle SMBgetattrE (async send)
599 ****************************************************************************/
600 static struct smbcli_request *smb_raw_getattrE_send(struct smbcli_tree *tree,
601                                                  union smb_fileinfo *parms)
602 {
603         struct smbcli_request *req;
604         
605         req = smbcli_request_setup(tree, SMBgetattrE, 1, 0);
606         if (!req) return NULL;
607         
608         SSVAL(req->out.vwv, VWV(0), parms->getattre.in.file.fnum);
609         if (!smbcli_request_send(req)) {
610                 smbcli_request_destroy(req);
611                 return NULL;
612         }
613
614         return req;
615 }
616
617 /****************************************************************************
618  Handle SMBgetattrE (async send)
619 ****************************************************************************/
620 static NTSTATUS smb_raw_getattrE_recv(struct smbcli_request *req,
621                                       union smb_fileinfo *parms)
622 {
623         if (!smbcli_request_receive(req) ||
624             smbcli_request_is_error(req)) {
625                 return smbcli_request_destroy(req);
626         }
627         
628         SMBCLI_CHECK_WCT(req, 11);
629         parms->getattre.out.create_time =   raw_pull_dos_date2(req->transport,
630                                                                req->in.vwv + VWV(0));
631         parms->getattre.out.access_time =   raw_pull_dos_date2(req->transport,
632                                                                req->in.vwv + VWV(2));
633         parms->getattre.out.write_time  =   raw_pull_dos_date2(req->transport,
634                                                                req->in.vwv + VWV(4));
635         parms->getattre.out.size =          IVAL(req->in.vwv,             VWV(6));
636         parms->getattre.out.alloc_size =    IVAL(req->in.vwv,             VWV(8));
637         parms->getattre.out.attrib =        SVAL(req->in.vwv,             VWV(10));
638
639 failed:
640         return smbcli_request_destroy(req);
641 }
642
643
644 /****************************************************************************
645  Query file info (async send)
646 ****************************************************************************/
647 struct smbcli_request *smb_raw_fileinfo_send(struct smbcli_tree *tree,
648                                              union smb_fileinfo *parms)
649 {
650         DATA_BLOB data;
651         struct smbcli_request *req;
652
653         /* pass off the non-trans2 level to specialised functions */
654         if (parms->generic.level == RAW_FILEINFO_GETATTRE) {
655                 return smb_raw_getattrE_send(tree, parms);
656         }
657         if (parms->generic.level == RAW_FILEINFO_SEC_DESC) {
658                 return smb_raw_query_secdesc_send(tree, parms);
659         }
660         if (parms->generic.level >= RAW_FILEINFO_GENERIC) {
661                 return NULL;
662         }
663
664         data = data_blob(NULL, 0);
665
666         if (parms->generic.level == RAW_FILEINFO_EA_LIST) {
667                 if (!ea_push_name_list(tree, 
668                                        &data,
669                                        parms->ea_list.in.num_names,
670                                        parms->ea_list.in.ea_names)) {
671                         return NULL;
672                 }
673         }
674
675         req = smb_raw_fileinfo_blob_send(tree, 
676                                          parms->generic.in.file.fnum,
677                                          parms->generic.level, data);
678
679         data_blob_free(&data);
680
681         return req;
682 }
683
684 /****************************************************************************
685  Query file info (async recv)
686 ****************************************************************************/
687 NTSTATUS smb_raw_fileinfo_recv(struct smbcli_request *req,
688                                TALLOC_CTX *mem_ctx,
689                                union smb_fileinfo *parms)
690 {
691         DATA_BLOB blob;
692         NTSTATUS status;
693         struct smbcli_session *session = req?req->session:NULL;
694
695         if (parms->generic.level == RAW_FILEINFO_GETATTRE) {
696                 return smb_raw_getattrE_recv(req, parms);
697         }
698         if (parms->generic.level == RAW_FILEINFO_SEC_DESC) {
699                 return smb_raw_query_secdesc_recv(req, mem_ctx, parms);
700         }
701         if (parms->generic.level == RAW_FILEINFO_GETATTR) {
702                 return smb_raw_getattr_recv(req, parms);
703         }
704
705         status = smb_raw_fileinfo_blob_recv(req, mem_ctx, &blob);
706         if (!NT_STATUS_IS_OK(status)) {
707                 return status;
708         }
709
710         return smb_raw_info_backend(session, mem_ctx, parms, &blob);
711 }
712
713 /****************************************************************************
714  Query file info (sync interface)
715 ****************************************************************************/
716 _PUBLIC_ NTSTATUS smb_raw_fileinfo(struct smbcli_tree *tree,
717                           TALLOC_CTX *mem_ctx,
718                           union smb_fileinfo *parms)
719 {
720         struct smbcli_request *req = smb_raw_fileinfo_send(tree, parms);
721         return smb_raw_fileinfo_recv(req, mem_ctx, parms);
722 }
723
724 /****************************************************************************
725  Query path info (async send)
726 ****************************************************************************/
727 _PUBLIC_ struct smbcli_request *smb_raw_pathinfo_send(struct smbcli_tree *tree,
728                                              union smb_fileinfo *parms)
729 {
730         DATA_BLOB data;
731         struct smbcli_request *req;
732
733         if (parms->generic.level == RAW_FILEINFO_GETATTR) {
734                 return smb_raw_getattr_send(tree, parms);
735         }
736         if (parms->generic.level >= RAW_FILEINFO_GENERIC) {
737                 return NULL;
738         }
739         
740         data = data_blob(NULL, 0);
741
742         if (parms->generic.level == RAW_FILEINFO_EA_LIST) {
743                 if (!ea_push_name_list(tree, 
744                                        &data,
745                                        parms->ea_list.in.num_names,
746                                        parms->ea_list.in.ea_names)) {
747                         return NULL;
748                 }
749         }
750
751         req = smb_raw_pathinfo_blob_send(tree, parms->generic.in.file.path,
752                                          parms->generic.level, data);
753         data_blob_free(&data);
754
755         return req;
756 }
757
758 /****************************************************************************
759  Query path info (async recv)
760 ****************************************************************************/
761 _PUBLIC_ NTSTATUS smb_raw_pathinfo_recv(struct smbcli_request *req,
762                                TALLOC_CTX *mem_ctx,
763                                union smb_fileinfo *parms)
764 {
765         /* recv is idential to fileinfo */
766         return smb_raw_fileinfo_recv(req, mem_ctx, parms);
767 }
768
769 /****************************************************************************
770  Query path info (sync interface)
771 ****************************************************************************/
772 _PUBLIC_ NTSTATUS smb_raw_pathinfo(struct smbcli_tree *tree,
773                           TALLOC_CTX *mem_ctx,
774                           union smb_fileinfo *parms)
775 {
776         struct smbcli_request *req = smb_raw_pathinfo_send(tree, parms);
777         return smb_raw_pathinfo_recv(req, mem_ctx, parms);
778 }