Coverage Report

Created: 2025-07-23 07:04

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