Coverage Report

Created: 2026-01-16 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source3/smbd/smb2_trans2.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
   SMB transaction2 handling
4
   Copyright (C) Jeremy Allison     1994-2007
5
   Copyright (C) Stefan (metze) Metzmacher  2003
6
   Copyright (C) Volker Lendecke    2005-2007
7
   Copyright (C) Steve French     2005
8
   Copyright (C) James Peach      2006-2007
9
10
   Extensively modified by Andrew Tridgell, 1995
11
12
   This program is free software; you can redistribute it and/or modify
13
   it under the terms of the GNU General Public License as published by
14
   the Free Software Foundation; either version 3 of the License, or
15
   (at your option) any later version.
16
17
   This program is distributed in the hope that it will be useful,
18
   but WITHOUT ANY WARRANTY; without even the implied warranty of
19
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
   GNU General Public License for more details.
21
22
   You should have received a copy of the GNU General Public License
23
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
24
*/
25
26
#include "includes.h"
27
#include "ntioctl.h"
28
#include "system/filesys.h"
29
#include "lib/util/time_basic.h"
30
#include "version.h"
31
#include "smbd/smbd.h"
32
#include "smbd/globals.h"
33
#include "../libcli/auth/libcli_auth.h"
34
#include "../librpc/gen_ndr/xattr.h"
35
#include "../librpc/gen_ndr/ndr_security.h"
36
#include "../librpc/gen_ndr/ndr_smb3posix.h"
37
#include "libcli/security/security.h"
38
#include "trans2.h"
39
#include "auth.h"
40
#include "smbprofile.h"
41
#include "rpc_server/srv_pipe_hnd.h"
42
#include "printing.h"
43
#include "lib/util_ea.h"
44
#include "lib/readdir_attr.h"
45
#include "messages.h"
46
#include "libcli/smb/smb2_posix.h"
47
#include "lib/util/string_wrappers.h"
48
#include "source3/lib/substitute.h"
49
#include "source3/lib/adouble.h"
50
#include "source3/smbd/dir.h"
51
#include "source3/modules/util_reparse.h"
52
53
0
#define DIR_ENTRY_SAFETY_MARGIN 4096
54
55
static uint32_t generate_volume_serial_number(
56
        const struct loadparm_substitution *lp_sub,
57
        int snum);
58
59
/****************************************************************************
60
 Check if an open file handle is a symlink.
61
****************************************************************************/
62
63
bool refuse_symlink_fsp(const files_struct *fsp)
64
0
{
65
66
0
  if (!VALID_STAT(fsp->fsp_name->st)) {
67
0
    return true;
68
0
  }
69
0
  if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
70
0
    return true;
71
0
  }
72
0
  if (fsp_get_pathref_fd(fsp) == -1) {
73
0
    return true;
74
0
  }
75
0
  return false;
76
0
}
77
78
/**
79
 * Check that one or more of the rights in access mask are
80
 * allowed. Iow, access_requested can contain more then one right and
81
 * it is sufficient having only one of those granted to pass.
82
 **/
83
NTSTATUS check_any_access_fsp(struct files_struct *fsp,
84
            uint32_t access_requested)
85
0
{
86
0
  const uint32_t ro_access = SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
87
0
  uint32_t ro_access_granted = 0;
88
0
  uint32_t access_granted = 0;
89
0
  NTSTATUS status;
90
91
0
  if (fsp->fsp_flags.is_fsa) {
92
0
    access_granted = fsp->access_mask;
93
0
  } else {
94
0
    uint32_t mask = 1;
95
96
0
    while (mask != 0) {
97
0
      if (!(mask & access_requested)) {
98
0
        mask <<= 1;
99
0
        continue;
100
0
      }
101
102
0
      status = smbd_check_access_rights_fsp(
103
0
              fsp->conn->cwd_fsp,
104
0
              fsp,
105
0
              false,
106
0
              mask);
107
0
      if (NT_STATUS_IS_OK(status)) {
108
0
        access_granted |= mask;
109
0
        if (fsp->fsp_name->twrp == 0) {
110
          /*
111
           * We can only optimize
112
           * the non-snapshot case
113
           */
114
0
          break;
115
0
        }
116
0
      }
117
0
      mask <<= 1;
118
0
    }
119
0
  }
120
0
  if ((access_granted & access_requested) == 0) {
121
0
    return NT_STATUS_ACCESS_DENIED;
122
0
  }
123
124
0
  if (fsp->fsp_name->twrp == 0) {
125
0
    return NT_STATUS_OK;
126
0
  }
127
128
0
  ro_access_granted = access_granted & ro_access;
129
0
  if ((ro_access_granted & access_requested) == 0) {
130
0
    return NT_STATUS_MEDIA_WRITE_PROTECTED;
131
0
  }
132
133
0
  return NT_STATUS_OK;
134
0
}
135
136
/********************************************************************
137
 Roundup a value to the nearest allocation roundup size boundary.
138
 Only do this for Windows clients.
139
********************************************************************/
140
141
uint64_t smb_roundup(connection_struct *conn, uint64_t val)
142
0
{
143
0
  uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
144
145
  /* Only roundup for Windows clients. */
146
0
  enum remote_arch_types ra_type = get_remote_arch();
147
0
  if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
148
0
    val = SMB_ROUNDUP(val,rval);
149
0
  }
150
0
  return val;
151
0
}
152
153
/****************************************************************************
154
 Utility functions for dealing with extended attributes.
155
****************************************************************************/
156
157
/****************************************************************************
158
 Refuse to allow clients to overwrite our private xattrs.
159
****************************************************************************/
160
161
bool samba_private_attr_name(const char *unix_ea_name)
162
0
{
163
0
  bool prohibited = false;
164
165
0
  prohibited |= strequal(unix_ea_name, SAMBA_POSIX_INHERITANCE_EA_NAME);
166
0
  prohibited |= strequal(unix_ea_name, SAMBA_XATTR_DOS_ATTRIB);
167
0
  prohibited |= strequal(unix_ea_name, SAMBA_XATTR_MARKER);
168
0
  prohibited |= strequal(unix_ea_name, SAMBA_XATTR_REPARSE_ATTRIB);
169
0
  prohibited |= strequal(unix_ea_name, XATTR_NTACL_NAME);
170
0
  prohibited |= strequal(unix_ea_name, AFPINFO_EA_NETATALK);
171
0
  prohibited |= strnequal(unix_ea_name,
172
0
        SAMBA_XATTR_DOSSTREAM_PREFIX,
173
0
        strlen(SAMBA_XATTR_DOSSTREAM_PREFIX));
174
175
0
  return prohibited;
176
0
}
177
178
/****************************************************************************
179
 Get one EA value. Fill in a struct ea_struct.
180
****************************************************************************/
181
182
int get_ea_value_fsp(TALLOC_CTX *mem_ctx,
183
         files_struct *fsp,
184
         const char *ea_name,
185
         struct ea_struct *pea)
186
0
{
187
  /* Get the value of this xattr. Max size is 64k. */
188
0
  size_t attr_size = 256;
189
0
  char *val = NULL;
190
0
  ssize_t sizeret;
191
0
  size_t max_xattr_size = 0;
192
0
  bool refuse;
193
194
0
  if (fsp == NULL) {
195
0
    return EINVAL;
196
0
  }
197
0
  refuse = refuse_symlink_fsp(fsp);
198
0
  if (refuse) {
199
0
    return EACCES;
200
0
  }
201
202
0
  max_xattr_size = lp_smbd_max_xattr_size(SNUM(fsp->conn));
203
204
0
 again:
205
206
0
  val = talloc_realloc(mem_ctx, val, char, attr_size);
207
0
  if (!val) {
208
0
    return ENOMEM;
209
0
  }
210
211
0
  sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
212
0
  if (sizeret == -1 && errno == ERANGE && attr_size < max_xattr_size) {
213
0
    attr_size = max_xattr_size;
214
0
    goto again;
215
0
  }
216
217
0
  if (sizeret == -1) {
218
0
    return errno;
219
0
  }
220
221
0
  DBG_DEBUG("EA %s is of length %zd\n", ea_name, sizeret);
222
0
  dump_data(10, (uint8_t *)val, sizeret);
223
224
0
  pea->flags = 0;
225
0
  if (strnequal(ea_name, "user.", 5)) {
226
0
    pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
227
0
  } else {
228
0
    pea->name = talloc_strdup(mem_ctx, ea_name);
229
0
  }
230
0
  if (pea->name == NULL) {
231
0
    TALLOC_FREE(val);
232
0
    return ENOMEM;
233
0
  }
234
0
  pea->value.data = (unsigned char *)val;
235
0
  pea->value.length = (size_t)sizeret;
236
0
  return 0;
237
0
}
238
239
NTSTATUS get_ea_names_from_fsp(TALLOC_CTX *mem_ctx,
240
        files_struct *fsp,
241
        char ***pnames,
242
        size_t *pnum_names)
243
0
{
244
0
  char smallbuf[1024];
245
  /* Get a list of all xattrs. Max namesize is 64k. */
246
0
  size_t ea_namelist_size = 1024;
247
0
  char *ea_namelist = smallbuf;
248
0
  char *to_free = NULL;
249
250
0
  char *p;
251
0
  char **names;
252
0
  size_t num_names;
253
0
  ssize_t sizeret = -1;
254
0
  NTSTATUS status;
255
256
0
  if (pnames) {
257
0
    *pnames = NULL;
258
0
  }
259
0
  *pnum_names = 0;
260
261
0
  if ((fsp == NULL) || refuse_symlink_fsp(fsp)) {
262
    /*
263
     * Callers may pass fsp == NULL when passing smb_fname->fsp of a
264
     * symlink. This is ok, handle it here, by just return no EA's
265
     * on a symlink.
266
     */
267
0
    return NT_STATUS_OK;
268
0
  }
269
270
0
  sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
271
0
             ea_namelist_size);
272
273
0
  if ((sizeret == -1) && (errno == ERANGE)) {
274
0
    ea_namelist_size = 65536;
275
0
    ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
276
0
    if (ea_namelist == NULL) {
277
0
      return NT_STATUS_NO_MEMORY;
278
0
    }
279
0
    to_free = ea_namelist;
280
281
0
    sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
282
0
               ea_namelist_size);
283
0
  }
284
285
0
  if (sizeret == -1) {
286
0
    status = map_nt_error_from_unix(errno);
287
0
    TALLOC_FREE(to_free);
288
0
    return status;
289
0
  }
290
291
0
  DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
292
293
0
  if (sizeret == 0) {
294
0
    TALLOC_FREE(to_free);
295
0
    return NT_STATUS_OK;
296
0
  }
297
298
  /*
299
   * Ensure the result is 0-terminated
300
   */
301
302
0
  if (ea_namelist[sizeret-1] != '\0') {
303
0
    TALLOC_FREE(to_free);
304
0
    return NT_STATUS_INTERNAL_ERROR;
305
0
  }
306
307
  /*
308
   * count the names
309
   */
310
0
  num_names = 0;
311
312
0
  for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
313
0
    num_names += 1;
314
0
  }
315
316
0
  *pnum_names = num_names;
317
318
0
  if (pnames == NULL) {
319
0
    TALLOC_FREE(to_free);
320
0
    return NT_STATUS_OK;
321
0
  }
322
323
0
  names = talloc_array(mem_ctx, char *, num_names);
324
0
  if (names == NULL) {
325
0
    DEBUG(0, ("talloc failed\n"));
326
0
    TALLOC_FREE(to_free);
327
0
    return NT_STATUS_NO_MEMORY;
328
0
  }
329
330
0
  if (ea_namelist == smallbuf) {
331
0
    ea_namelist = talloc_memdup(names, smallbuf, sizeret);
332
0
    if (ea_namelist == NULL) {
333
0
      TALLOC_FREE(names);
334
0
      return NT_STATUS_NO_MEMORY;
335
0
    }
336
0
  } else {
337
0
    talloc_steal(names, ea_namelist);
338
339
0
    ea_namelist = talloc_realloc(names, ea_namelist, char,
340
0
               sizeret);
341
0
    if (ea_namelist == NULL) {
342
0
      TALLOC_FREE(names);
343
0
      return NT_STATUS_NO_MEMORY;
344
0
    }
345
0
  }
346
347
0
  num_names = 0;
348
349
0
  for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
350
0
    names[num_names++] = p;
351
0
  }
352
353
0
  *pnames = names;
354
355
0
  return NT_STATUS_OK;
356
0
}
357
358
/****************************************************************************
359
 Return a linked list of the total EA's. Plus the total size
360
****************************************************************************/
361
362
static NTSTATUS get_ea_list_from_fsp(TALLOC_CTX *mem_ctx,
363
        files_struct *fsp,
364
        size_t *pea_total_len,
365
        struct ea_list **ea_list)
366
0
{
367
  /* Get a list of all xattrs. Max namesize is 64k. */
368
0
  size_t i, num_names;
369
0
  char **names;
370
0
  struct ea_list *ea_list_head = NULL;
371
0
  bool posix_pathnames = false;
372
0
  NTSTATUS status;
373
374
0
  *pea_total_len = 0;
375
0
  *ea_list = NULL;
376
377
  /* symlink */
378
0
  if (fsp == NULL) {
379
0
    return NT_STATUS_OK;
380
0
  }
381
382
0
  if (!lp_ea_support(SNUM(fsp->conn))) {
383
0
    return NT_STATUS_OK;
384
0
  }
385
386
0
  if (fsp_is_alternate_stream(fsp)) {
387
0
    return NT_STATUS_INVALID_PARAMETER;
388
0
  }
389
390
0
  posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
391
392
0
  status = get_ea_names_from_fsp(talloc_tos(),
393
0
        fsp,
394
0
        &names,
395
0
        &num_names);
396
397
0
  if (!NT_STATUS_IS_OK(status)) {
398
0
    return status;
399
0
  }
400
401
0
  if (num_names == 0) {
402
0
    return NT_STATUS_OK;
403
0
  }
404
405
0
  for (i=0; i<num_names; i++) {
406
0
    struct ea_list *listp;
407
0
    fstring dos_ea_name;
408
0
    int ret;
409
410
    /*
411
     * POSIX EA names are divided into several namespaces by
412
     * means of string prefixes. Usually, the system controls
413
     * semantics for each namespace, but the 'user' namespace is
414
     * available for arbitrary use, which comes closest to
415
     * Windows EA semantics. Hence, we map POSIX EAs from the
416
     * 'user' namespace to Windows EAs, and just ignore all the
417
     * other namespaces. Also, a few specific names in the 'user'
418
     * namespace are used by Samba internally. Filter them out as
419
     * well, and only present the EAs that are available for
420
     * arbitrary use.
421
     */
422
0
    if (!strnequal(names[i], "user.", 5)
423
0
        || samba_private_attr_name(names[i]))
424
0
      continue;
425
426
    /*
427
     * Filter out any underlying POSIX EA names
428
     * that a Windows client can't handle.
429
     */
430
0
    if (!posix_pathnames &&
431
0
        is_invalid_windows_ea_name(names[i])) {
432
0
      continue;
433
0
    }
434
435
0
    listp = talloc(mem_ctx, struct ea_list);
436
0
    if (listp == NULL) {
437
0
      return NT_STATUS_NO_MEMORY;
438
0
    }
439
440
0
    ret = get_ea_value_fsp(listp, fsp, names[i], &listp->ea);
441
442
0
    if (ret != 0) {
443
0
      TALLOC_FREE(listp);
444
0
      return map_nt_error_from_unix(ret);
445
0
    }
446
447
0
    if (listp->ea.value.length == 0) {
448
      /*
449
       * We can never return a zero length EA.
450
       * Windows reports the EA's as corrupted.
451
       */
452
0
      TALLOC_FREE(listp);
453
0
      continue;
454
0
    }
455
0
    if (listp->ea.value.length > 65536) {
456
      /*
457
       * SMB clients may report error with file
458
       * if large EA is presented to them.
459
       */
460
0
      DBG_ERR("EA [%s] on file [%s] exceeds "
461
0
        "maximum permitted EA size of 64KiB: %zu\n.",
462
0
        listp->ea.name, fsp_str_dbg(fsp),
463
0
        listp->ea.value.length);
464
0
      TALLOC_FREE(listp);
465
0
      continue;
466
0
    }
467
468
0
    push_ascii_fstring(dos_ea_name, listp->ea.name);
469
470
0
    *pea_total_len +=
471
0
      4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
472
473
0
    DBG_DEBUG("total_len = %zu, %s, val len = %zu\n",
474
0
        *pea_total_len,
475
0
        dos_ea_name,
476
0
        listp->ea.value.length);
477
478
0
    DLIST_ADD_END(ea_list_head, listp);
479
480
0
  }
481
482
  /* Add on 4 for total length. */
483
0
  if (*pea_total_len) {
484
0
    *pea_total_len += 4;
485
0
  }
486
487
0
  DBG_DEBUG("total_len = %zu\n", *pea_total_len);
488
489
0
  *ea_list = ea_list_head;
490
0
  return NT_STATUS_OK;
491
0
}
492
493
/****************************************************************************
494
 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
495
 that was filled.
496
****************************************************************************/
497
498
static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
499
  connection_struct *conn, struct ea_list *ea_list)
500
0
{
501
0
  unsigned int ret_data_size = 4;
502
0
  char *p = pdata;
503
504
0
  SMB_ASSERT(total_data_size >= 4);
505
506
0
  if (!lp_ea_support(SNUM(conn))) {
507
0
    SIVAL(pdata,4,0);
508
0
    return 4;
509
0
  }
510
511
0
  for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
512
0
    size_t dos_namelen;
513
0
    fstring dos_ea_name;
514
0
    push_ascii_fstring(dos_ea_name, ea_list->ea.name);
515
0
    dos_namelen = strlen(dos_ea_name);
516
0
    if (dos_namelen > 255 || dos_namelen == 0) {
517
0
      break;
518
0
    }
519
0
    if (ea_list->ea.value.length > 65535) {
520
0
      break;
521
0
    }
522
0
    if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
523
0
      break;
524
0
    }
525
526
    /* We know we have room. */
527
0
    SCVAL(p,0,ea_list->ea.flags);
528
0
    SCVAL(p,1,dos_namelen);
529
0
    SSVAL(p,2,ea_list->ea.value.length);
530
0
    strlcpy(p+4, dos_ea_name, dos_namelen+1);
531
0
    if (ea_list->ea.value.length > 0) {
532
0
      memcpy(p + 4 + dos_namelen + 1,
533
0
             ea_list->ea.value.data,
534
0
             ea_list->ea.value.length);
535
0
    }
536
537
0
    total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
538
0
    p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
539
0
  }
540
541
0
  ret_data_size = PTR_DIFF(p, pdata);
542
0
  DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
543
0
  SIVAL(pdata,0,ret_data_size);
544
0
  return ret_data_size;
545
0
}
546
547
static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
548
               char *pdata,
549
               unsigned int total_data_size,
550
               unsigned int *ret_data_size,
551
               connection_struct *conn,
552
               struct ea_list *ea_list)
553
0
{
554
0
  uint8_t *p = (uint8_t *)pdata;
555
0
  uint8_t *last_start = NULL;
556
0
  bool do_store_data = (pdata != NULL);
557
558
0
  *ret_data_size = 0;
559
560
0
  if (!lp_ea_support(SNUM(conn))) {
561
0
    return NT_STATUS_NO_EAS_ON_FILE;
562
0
  }
563
564
0
  for (; ea_list; ea_list = ea_list->next) {
565
0
    size_t dos_namelen;
566
0
    fstring dos_ea_name;
567
0
    size_t this_size;
568
0
    size_t pad = 0;
569
570
0
    if (last_start != NULL && do_store_data) {
571
0
      SIVAL(last_start, 0, PTR_DIFF(p, last_start));
572
0
    }
573
0
    last_start = p;
574
575
0
    push_ascii_fstring(dos_ea_name, ea_list->ea.name);
576
0
    dos_namelen = strlen(dos_ea_name);
577
0
    if (dos_namelen > 255 || dos_namelen == 0) {
578
0
      return NT_STATUS_INTERNAL_ERROR;
579
0
    }
580
0
    if (ea_list->ea.value.length > 65535) {
581
0
      return NT_STATUS_INTERNAL_ERROR;
582
0
    }
583
584
0
    this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
585
586
0
    if (ea_list->next) {
587
0
      pad = (4 - (this_size % 4)) % 4;
588
0
      this_size += pad;
589
0
    }
590
591
0
    if (do_store_data) {
592
0
      if (this_size > total_data_size) {
593
0
        return NT_STATUS_INFO_LENGTH_MISMATCH;
594
0
      }
595
596
      /* We know we have room. */
597
0
      SIVAL(p, 0x00, 0); /* next offset */
598
0
      SCVAL(p, 0x04, ea_list->ea.flags);
599
0
      SCVAL(p, 0x05, dos_namelen);
600
0
      SSVAL(p, 0x06, ea_list->ea.value.length);
601
0
      strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
602
0
      memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
603
0
      if (pad) {
604
0
        memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
605
0
          '\0',
606
0
          pad);
607
0
      }
608
0
      total_data_size -= this_size;
609
0
    }
610
611
0
    p += this_size;
612
0
  }
613
614
0
  *ret_data_size = PTR_DIFF(p, pdata);
615
0
  DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
616
0
  return NT_STATUS_OK;
617
0
}
618
619
unsigned int estimate_ea_size(files_struct *fsp)
620
0
{
621
0
  size_t total_ea_len = 0;
622
0
  TALLOC_CTX *mem_ctx;
623
0
  struct ea_list *ea_list = NULL;
624
0
  NTSTATUS status;
625
626
  /* symlink */
627
0
  if (fsp == NULL) {
628
0
    return 0;
629
0
  }
630
631
0
  if (!lp_ea_support(SNUM(fsp->conn))) {
632
0
    return 0;
633
0
  }
634
635
0
  mem_ctx = talloc_stackframe();
636
637
  /* If this is a stream fsp, then we need to instead find the
638
   * estimated ea len from the main file, not the stream
639
   * (streams cannot have EAs), but the estimate isn't just 0 in
640
   * this case! */
641
0
  fsp = metadata_fsp(fsp);
642
0
  (void)get_ea_list_from_fsp(mem_ctx,
643
0
           fsp,
644
0
           &total_ea_len,
645
0
           &ea_list);
646
647
0
  if(conn_using_smb2(fsp->conn->sconn)) {
648
0
    unsigned int ret_data_size;
649
    /*
650
     * We're going to be using fill_ea_chained_buffer() to
651
     * marshall EA's - this size is significantly larger
652
     * than the SMB1 buffer. Re-calculate the size without
653
     * marshalling.
654
     */
655
0
    status = fill_ea_chained_buffer(mem_ctx,
656
0
            NULL,
657
0
            0,
658
0
            &ret_data_size,
659
0
            fsp->conn,
660
0
            ea_list);
661
0
    if (!NT_STATUS_IS_OK(status)) {
662
0
      ret_data_size = 0;
663
0
    }
664
0
    total_ea_len = ret_data_size;
665
0
  }
666
0
  TALLOC_FREE(mem_ctx);
667
0
  return total_ea_len;
668
0
}
669
670
/****************************************************************************
671
 Ensure the EA name is case insensitive by matching any existing EA name.
672
****************************************************************************/
673
674
static void canonicalize_ea_name(files_struct *fsp,
675
      fstring unix_ea_name)
676
0
{
677
0
  size_t total_ea_len;
678
0
  TALLOC_CTX *mem_ctx = talloc_tos();
679
0
  struct ea_list *ea_list;
680
0
  NTSTATUS status = get_ea_list_from_fsp(mem_ctx,
681
0
                 fsp,
682
0
                 &total_ea_len,
683
0
                 &ea_list);
684
0
  if (!NT_STATUS_IS_OK(status)) {
685
0
    return;
686
0
  }
687
688
0
  for (; ea_list; ea_list = ea_list->next) {
689
0
    if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
690
0
      DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
691
0
        &unix_ea_name[5], ea_list->ea.name));
692
0
      strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
693
0
      break;
694
0
    }
695
0
  }
696
0
}
697
698
/****************************************************************************
699
 Set or delete an extended attribute.
700
****************************************************************************/
701
702
NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
703
    struct ea_list *ea_list)
704
0
{
705
0
  NTSTATUS status;
706
0
  bool posix_pathnames = false;
707
0
  bool refuse;
708
709
0
  if (!lp_ea_support(SNUM(conn))) {
710
0
    return NT_STATUS_EAS_NOT_SUPPORTED;
711
0
  }
712
713
0
  if (fsp == NULL) {
714
0
    return NT_STATUS_INVALID_HANDLE;
715
0
  }
716
717
0
  posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
718
719
0
  refuse = refuse_symlink_fsp(fsp);
720
0
  if (refuse) {
721
0
    return NT_STATUS_ACCESS_DENIED;
722
0
  }
723
724
0
  status = check_any_access_fsp(fsp, FILE_WRITE_EA);
725
0
  if (!NT_STATUS_IS_OK(status)) {
726
0
    return status;
727
0
  }
728
729
  /* Setting EAs on streams isn't supported. */
730
0
  if (fsp_is_alternate_stream(fsp)) {
731
0
    return NT_STATUS_INVALID_PARAMETER;
732
0
  }
733
734
  /*
735
   * Filter out invalid Windows EA names - before
736
   * we set *any* of them.
737
   */
738
739
0
  if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
740
0
    return STATUS_INVALID_EA_NAME;
741
0
  }
742
743
0
  for (;ea_list; ea_list = ea_list->next) {
744
0
    int ret;
745
0
    fstring unix_ea_name;
746
747
    /*
748
     * Complementing the forward mapping from POSIX EAs to
749
     * Windows EAs in get_ea_list_from_fsp(), here we map in the
750
     * opposite direction from Windows EAs to the 'user' namespace
751
     * of POSIX EAs. Hence, all POSIX EA names the we set here must
752
     * start with a 'user.' prefix.
753
     */
754
0
    fstrcpy(unix_ea_name, "user.");
755
0
    fstrcat(unix_ea_name, ea_list->ea.name);
756
757
0
    canonicalize_ea_name(fsp, unix_ea_name);
758
759
0
    DBG_DEBUG("ea_name %s ealen = %zu\n",
760
0
        unix_ea_name,
761
0
        ea_list->ea.value.length);
762
763
0
    if (samba_private_attr_name(unix_ea_name)) {
764
0
      DBG_DEBUG("ea name %s is a private Samba name.\n",
765
0
          unix_ea_name);
766
0
      return NT_STATUS_ACCESS_DENIED;
767
0
    }
768
769
0
    if (ea_list->ea.value.length == 0) {
770
      /* Remove the attribute. */
771
0
      DBG_DEBUG("deleting ea name %s on "
772
0
          "file %s by file descriptor.\n",
773
0
          unix_ea_name, fsp_str_dbg(fsp));
774
0
      ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
775
0
#ifdef ENOATTR
776
      /* Removing a non existent attribute always succeeds. */
777
0
      if (ret == -1 && errno == ENOATTR) {
778
0
        DBG_DEBUG("deleting ea name %s didn't exist - "
779
0
            "succeeding by default.\n",
780
0
            unix_ea_name);
781
0
        ret = 0;
782
0
      }
783
0
#endif
784
0
    } else {
785
0
      DBG_DEBUG("setting ea name %s on file "
786
0
          "%s by file descriptor.\n",
787
0
          unix_ea_name,
788
0
          fsp_str_dbg(fsp));
789
0
      ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
790
0
            ea_list->ea.value.data, ea_list->ea.value.length, 0);
791
0
    }
792
793
0
    if (ret == -1) {
794
0
#ifdef ENOTSUP
795
0
      if (errno == ENOTSUP) {
796
0
        return NT_STATUS_EAS_NOT_SUPPORTED;
797
0
      }
798
0
#endif
799
0
      return map_nt_error_from_unix(errno);
800
0
    }
801
802
0
  }
803
0
  return NT_STATUS_OK;
804
0
}
805
806
/****************************************************************************
807
 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
808
****************************************************************************/
809
810
struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
811
0
{
812
0
  struct ea_list *ea_list_head = NULL;
813
0
  size_t offset = 0;
814
0
  size_t bytes_used = 0;
815
816
0
  while (offset < data_size) {
817
0
    struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
818
819
0
    if (!eal) {
820
0
      return NULL;
821
0
    }
822
823
0
    DLIST_ADD_END(ea_list_head, eal);
824
0
    offset += bytes_used;
825
0
  }
826
827
0
  return ea_list_head;
828
0
}
829
830
/****************************************************************************
831
 Count the total EA size needed.
832
****************************************************************************/
833
834
static size_t ea_list_size(struct ea_list *ealist)
835
0
{
836
0
  fstring dos_ea_name;
837
0
  struct ea_list *listp;
838
0
  size_t ret = 0;
839
840
0
  for (listp = ealist; listp; listp = listp->next) {
841
0
    push_ascii_fstring(dos_ea_name, listp->ea.name);
842
0
    ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
843
0
  }
844
  /* Add on 4 for total length. */
845
0
  if (ret) {
846
0
    ret += 4;
847
0
  }
848
849
0
  return ret;
850
0
}
851
852
/****************************************************************************
853
 Return a union of EA's from a file list and a list of names.
854
 The TALLOC context for the two lists *MUST* be identical as we steal
855
 memory from one list to add to another. JRA.
856
****************************************************************************/
857
858
static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
859
0
{
860
0
  struct ea_list *nlistp, *flistp;
861
862
0
  for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
863
0
    for (flistp = file_list; flistp; flistp = flistp->next) {
864
0
      if (strequal(nlistp->ea.name, flistp->ea.name)) {
865
0
        break;
866
0
      }
867
0
    }
868
869
0
    if (flistp) {
870
      /* Copy the data from this entry. */
871
0
      nlistp->ea.flags = flistp->ea.flags;
872
0
      nlistp->ea.value = flistp->ea.value;
873
0
    } else {
874
      /* Null entry. */
875
0
      nlistp->ea.flags = 0;
876
0
      ZERO_STRUCT(nlistp->ea.value);
877
0
    }
878
0
  }
879
880
0
  *total_ea_len = ea_list_size(name_list);
881
0
  return name_list;
882
0
}
883
884
/****************************************************************************
885
 Map wire perms onto standard UNIX permissions. Obey share restrictions.
886
****************************************************************************/
887
888
NTSTATUS unix_perms_from_wire(connection_struct *conn,
889
            const SMB_STRUCT_STAT *psbuf,
890
            uint32_t perms,
891
            mode_t *ret_perms)
892
0
{
893
0
  mode_t ret = 0;
894
895
0
  if (perms == SMB_MODE_NO_CHANGE) {
896
0
    if (!VALID_STAT(*psbuf)) {
897
0
      return NT_STATUS_INVALID_PARAMETER;
898
0
    }
899
0
    *ret_perms = psbuf->st_ex_mode;
900
0
    return NT_STATUS_OK;
901
0
  }
902
903
0
  ret = wire_perms_to_unix(perms);
904
905
0
  *ret_perms = ret;
906
0
  return NT_STATUS_OK;
907
0
}
908
909
/****************************************************************************
910
 Get a level dependent lanman2 dir entry.
911
****************************************************************************/
912
913
struct smbd_dirptr_lanman2_state {
914
  connection_struct *conn;
915
  uint32_t info_level;
916
  bool check_mangled_names;
917
  bool case_sensitive;
918
  bool posix_paths;
919
};
920
921
static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
922
           void *private_data,
923
           const char *dname,
924
           const char *mask,
925
           char **_fname)
926
0
{
927
0
  struct smbd_dirptr_lanman2_state *state =
928
0
    (struct smbd_dirptr_lanman2_state *)private_data;
929
0
  bool ok;
930
0
  char mangled_name[13]; /* mangled 8.3 name. */
931
0
  bool got_match;
932
0
  const char *fname;
933
934
  /* Mangle fname if it's an illegal name. */
935
0
  if (!state->posix_paths &&
936
0
      mangle_must_mangle(dname, state->conn->params))
937
0
  {
938
    /*
939
     * Slow path - ensure we can push the original name as UCS2. If
940
     * not, then just don't return this name.
941
     */
942
0
    NTSTATUS status;
943
0
    size_t ret_len = 0;
944
0
    size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
945
0
    uint8_t *tmp = talloc_array(talloc_tos(),
946
0
          uint8_t,
947
0
          len);
948
949
0
    status = srvstr_push(NULL,
950
0
      FLAGS2_UNICODE_STRINGS,
951
0
      tmp,
952
0
      dname,
953
0
      len,
954
0
      STR_TERMINATE,
955
0
      &ret_len);
956
957
0
    TALLOC_FREE(tmp);
958
959
0
    if (!NT_STATUS_IS_OK(status)) {
960
0
      return false;
961
0
    }
962
963
0
    ok = name_to_8_3(dname, mangled_name,
964
0
         true, state->conn->params);
965
0
    if (!ok) {
966
0
      return false;
967
0
    }
968
0
    fname = mangled_name;
969
0
  } else {
970
0
    fname = dname;
971
0
  }
972
973
0
  got_match = mask_match(fname, mask,
974
0
             state->case_sensitive);
975
976
0
  if(!got_match && state->check_mangled_names &&
977
0
     !mangle_is_8_3(fname, false, state->conn->params)) {
978
    /*
979
     * It turns out that NT matches wildcards against
980
     * both long *and* short names. This may explain some
981
     * of the wildcard weirdness from old DOS clients
982
     * that some people have been seeing.... JRA.
983
     */
984
    /* Force the mangling into 8.3. */
985
0
    ok = name_to_8_3(fname, mangled_name,
986
0
         false, state->conn->params);
987
0
    if (!ok) {
988
0
      return false;
989
0
    }
990
991
0
    got_match = mask_match(mangled_name, mask,
992
0
               state->case_sensitive);
993
0
  }
994
995
0
  if (!got_match) {
996
0
    return false;
997
0
  }
998
999
0
  *_fname = talloc_strdup(ctx, fname);
1000
0
  if (*_fname == NULL) {
1001
0
    return false;
1002
0
  }
1003
1004
0
  return true;
1005
0
}
1006
1007
static uint32_t get_dirent_ea_size(uint32_t mode, files_struct *fsp)
1008
0
{
1009
0
  uint32_t ea_size = IO_REPARSE_TAG_DFS;
1010
1011
0
  if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1012
0
    (void)fsctl_get_reparse_tag(fsp, &ea_size);
1013
0
  } else {
1014
0
    ea_size = estimate_ea_size(fsp);
1015
0
  }
1016
1017
0
  return ea_size;
1018
0
}
1019
1020
static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1021
            connection_struct *conn,
1022
            uint16_t flags2,
1023
            uint32_t info_level,
1024
            struct ea_list *name_list,
1025
            bool check_mangled_names,
1026
            bool requires_resume_key,
1027
            uint32_t mode,
1028
            const char *fname,
1029
            const struct smb_filename *smb_fname,
1030
            int space_remaining,
1031
            uint8_t align,
1032
            bool do_pad,
1033
            char *base_data,
1034
            char **ppdata,
1035
            char *end_data,
1036
            uint64_t *last_entry_off)
1037
0
{
1038
0
  char *p, *q, *pdata = *ppdata;
1039
0
  uint32_t reskey=0;
1040
0
  uint64_t file_size = 0;
1041
0
  uint64_t allocation_size = 0;
1042
0
  uint64_t file_id = 0;
1043
0
  size_t len = 0;
1044
0
  struct timespec mdate_ts = {0};
1045
0
  struct timespec adate_ts = {0};
1046
0
  struct timespec cdate_ts = {0};
1047
0
  struct timespec create_date_ts = {0};
1048
0
  char *nameptr;
1049
0
  char *last_entry_ptr;
1050
0
  bool was_8_3;
1051
0
  int off;
1052
0
  int pad = 0;
1053
0
  NTSTATUS status;
1054
0
  struct readdir_attr_data *readdir_attr_data = NULL;
1055
0
  uint32_t ea_size;
1056
1057
0
  if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1058
0
    file_size = get_file_size_stat(&smb_fname->st);
1059
0
  }
1060
0
  allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1061
1062
  /*
1063
   * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1064
   * a DFS symlink.
1065
   */
1066
0
  if (smb_fname->fsp != NULL &&
1067
0
      !(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1068
0
    status = SMB_VFS_FREADDIR_ATTR(smb_fname->fsp,
1069
0
                 ctx,
1070
0
                 &readdir_attr_data);
1071
0
    if (!NT_STATUS_IS_OK(status)) {
1072
0
      if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED,
1073
0
               status)) {
1074
0
        return status;
1075
0
      }
1076
0
    }
1077
0
  }
1078
1079
0
  file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1080
1081
0
  mdate_ts = smb_fname->st.st_ex_mtime;
1082
0
  adate_ts = smb_fname->st.st_ex_atime;
1083
0
  create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1084
0
  cdate_ts = smb_fname->st.st_ex_ctime;
1085
1086
0
  if (lp_dos_filetime_resolution(SNUM(conn))) {
1087
0
    dos_filetime_timespec(&create_date_ts);
1088
0
    dos_filetime_timespec(&mdate_ts);
1089
0
    dos_filetime_timespec(&adate_ts);
1090
0
    dos_filetime_timespec(&cdate_ts);
1091
0
  }
1092
1093
  /* align the record */
1094
0
  SMB_ASSERT(align >= 1);
1095
1096
0
  off = (int)PTR_DIFF(pdata, base_data);
1097
0
  pad = (off + (align-1)) & ~(align-1);
1098
0
  pad -= off;
1099
1100
0
  if (pad && pad > space_remaining) {
1101
0
    DEBUG(9,("smbd_marshall_dir_entry: out of space "
1102
0
      "for padding (wanted %u, had %d)\n",
1103
0
      (unsigned int)pad,
1104
0
      space_remaining ));
1105
0
    return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1106
0
  }
1107
1108
0
  off += pad;
1109
  /* initialize padding to 0 */
1110
0
  if (pad) {
1111
0
    memset(pdata, 0, pad);
1112
0
  }
1113
0
  space_remaining -= pad;
1114
1115
0
  DBG_DEBUG("space_remaining = %d\n", space_remaining);
1116
1117
0
  pdata += pad;
1118
0
  p = pdata;
1119
0
  last_entry_ptr = p;
1120
1121
0
  pad = 0;
1122
0
  off = 0;
1123
1124
0
  switch (info_level) {
1125
0
  case SMB_FIND_INFO_STANDARD:
1126
0
    DBG_DEBUG("SMB_FIND_INFO_STANDARD\n");
1127
0
    if(requires_resume_key) {
1128
0
      SIVAL(p,0,reskey);
1129
0
      p += 4;
1130
0
    }
1131
0
    srv_put_dos_date2_ts(p, 0, create_date_ts);
1132
0
    srv_put_dos_date2_ts(p, 4, adate_ts);
1133
0
    srv_put_dos_date2_ts(p, 8, mdate_ts);
1134
0
    SIVAL(p,12,(uint32_t)file_size);
1135
0
    SIVAL(p,16,(uint32_t)allocation_size);
1136
0
    SSVAL(p,20,mode);
1137
0
    p += 23;
1138
0
    nameptr = p;
1139
0
    if (flags2 & FLAGS2_UNICODE_STRINGS) {
1140
0
      p += ucs2_align(base_data, p, 0);
1141
0
    }
1142
0
    status = srvstr_push(base_data, flags2, p,
1143
0
          fname, PTR_DIFF(end_data, p),
1144
0
          STR_TERMINATE, &len);
1145
0
    if (!NT_STATUS_IS_OK(status)) {
1146
0
      return status;
1147
0
    }
1148
0
    if (flags2 & FLAGS2_UNICODE_STRINGS) {
1149
0
      if (len > 2) {
1150
0
        SCVAL(nameptr, -1, len - 2);
1151
0
      } else {
1152
0
        SCVAL(nameptr, -1, 0);
1153
0
      }
1154
0
    } else {
1155
0
      if (len > 1) {
1156
0
        SCVAL(nameptr, -1, len - 1);
1157
0
      } else {
1158
0
        SCVAL(nameptr, -1, 0);
1159
0
      }
1160
0
    }
1161
0
    p += len;
1162
0
    break;
1163
1164
0
  case SMB_FIND_EA_SIZE:
1165
0
    DBG_DEBUG("SMB_FIND_EA_SIZE\n");
1166
0
    if (requires_resume_key) {
1167
0
      SIVAL(p,0,reskey);
1168
0
      p += 4;
1169
0
    }
1170
0
    srv_put_dos_date2_ts(p, 0, create_date_ts);
1171
0
    srv_put_dos_date2_ts(p, 4, adate_ts);
1172
0
    srv_put_dos_date2_ts(p, 8, mdate_ts);
1173
0
    SIVAL(p,12,(uint32_t)file_size);
1174
0
    SIVAL(p,16,(uint32_t)allocation_size);
1175
0
    SSVAL(p,20,mode);
1176
0
    {
1177
0
      ea_size = estimate_ea_size(smb_fname->fsp);
1178
0
      SIVAL(p,22,ea_size); /* Extended attributes */
1179
0
    }
1180
0
    p += 27;
1181
0
    nameptr = p - 1;
1182
0
    status = srvstr_push(base_data, flags2,
1183
0
          p, fname, PTR_DIFF(end_data, p),
1184
0
          STR_TERMINATE | STR_NOALIGN, &len);
1185
0
    if (!NT_STATUS_IS_OK(status)) {
1186
0
      return status;
1187
0
    }
1188
0
    if (flags2 & FLAGS2_UNICODE_STRINGS) {
1189
0
      if (len > 2) {
1190
0
        len -= 2;
1191
0
      } else {
1192
0
        len = 0;
1193
0
      }
1194
0
    } else {
1195
0
      if (len > 1) {
1196
0
        len -= 1;
1197
0
      } else {
1198
0
        len = 0;
1199
0
      }
1200
0
    }
1201
0
    SCVAL(nameptr,0,len);
1202
0
    p += len;
1203
0
    SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1204
0
    break;
1205
1206
0
  case SMB_FIND_EA_LIST:
1207
0
  {
1208
0
    struct ea_list *file_list = NULL;
1209
0
    size_t ea_len = 0;
1210
1211
0
    DBG_DEBUG("SMB_FIND_EA_LIST\n");
1212
0
    if (!name_list) {
1213
0
      return NT_STATUS_INVALID_PARAMETER;
1214
0
    }
1215
0
    if (requires_resume_key) {
1216
0
      SIVAL(p,0,reskey);
1217
0
      p += 4;
1218
0
    }
1219
0
    srv_put_dos_date2_ts(p, 0, create_date_ts);
1220
0
    srv_put_dos_date2_ts(p, 4, adate_ts);
1221
0
    srv_put_dos_date2_ts(p, 8, mdate_ts);
1222
0
    SIVAL(p,12,(uint32_t)file_size);
1223
0
    SIVAL(p,16,(uint32_t)allocation_size);
1224
0
    SSVAL(p,20,mode);
1225
0
    p += 22; /* p now points to the EA area. */
1226
1227
0
    status = get_ea_list_from_fsp(ctx,
1228
0
                 smb_fname->fsp,
1229
0
                 &ea_len, &file_list);
1230
0
    if (!NT_STATUS_IS_OK(status)) {
1231
0
      file_list = NULL;
1232
0
    }
1233
0
    name_list = ea_list_union(name_list, file_list, &ea_len);
1234
1235
    /* We need to determine if this entry will fit in the space available. */
1236
    /* Max string size is 255 bytes. */
1237
0
    if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1238
0
      DEBUG(9,("smbd_marshall_dir_entry: out of space "
1239
0
        "(wanted %u, had %d)\n",
1240
0
        (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1241
0
        space_remaining ));
1242
0
      return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1243
0
    }
1244
1245
    /* Push the ea_data followed by the name. */
1246
0
    p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1247
0
    nameptr = p;
1248
0
    status = srvstr_push(base_data, flags2,
1249
0
          p + 1, fname, PTR_DIFF(end_data, p+1),
1250
0
          STR_TERMINATE | STR_NOALIGN, &len);
1251
0
    if (!NT_STATUS_IS_OK(status)) {
1252
0
      return status;
1253
0
    }
1254
0
    if (flags2 & FLAGS2_UNICODE_STRINGS) {
1255
0
      if (len > 2) {
1256
0
        len -= 2;
1257
0
      } else {
1258
0
        len = 0;
1259
0
      }
1260
0
    } else {
1261
0
      if (len > 1) {
1262
0
        len -= 1;
1263
0
      } else {
1264
0
        len = 0;
1265
0
      }
1266
0
    }
1267
0
    SCVAL(nameptr,0,len);
1268
0
    p += len + 1;
1269
0
    SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1270
0
    break;
1271
0
  }
1272
1273
0
  case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1274
0
    DBG_DEBUG("SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n");
1275
0
    was_8_3 = mangle_is_8_3(fname, True, conn->params);
1276
0
    p += 4;
1277
0
    SIVAL(p,0,reskey); p += 4;
1278
0
    put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1279
0
    put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1280
0
    put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1281
0
    put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1282
0
    SOFF_T(p,0,file_size); p += 8;
1283
0
    SOFF_T(p,0,allocation_size); p += 8;
1284
0
    SIVAL(p,0,mode); p += 4;
1285
0
    q = p; p += 4; /* q is placeholder for name length. */
1286
0
    ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1287
0
    SIVAL(p, 0, ea_size);
1288
0
    p += 4;
1289
    /* Clear the short name buffer. This is
1290
     * IMPORTANT as not doing so will trigger
1291
     * a Win2k client bug. JRA.
1292
     */
1293
0
    if (!was_8_3 && check_mangled_names) {
1294
0
      char mangled_name[13]; /* mangled 8.3 name. */
1295
0
      if (!name_to_8_3(fname,mangled_name,True,
1296
0
             conn->params)) {
1297
        /* Error - mangle failed ! */
1298
0
        memset(mangled_name,'\0',12);
1299
0
      }
1300
0
      mangled_name[12] = 0;
1301
0
      status = srvstr_push(base_data, flags2,
1302
0
            p+2, mangled_name, 24,
1303
0
            STR_UPPER|STR_UNICODE, &len);
1304
0
      if (!NT_STATUS_IS_OK(status)) {
1305
0
        return status;
1306
0
      }
1307
0
      if (len < 24) {
1308
0
        memset(p + 2 + len,'\0',24 - len);
1309
0
      }
1310
0
      SSVAL(p, 0, len);
1311
0
    } else {
1312
0
      memset(p,'\0',26);
1313
0
    }
1314
0
    p += 2 + 24;
1315
0
    status = srvstr_push(base_data, flags2, p,
1316
0
          fname, PTR_DIFF(end_data, p),
1317
0
          STR_TERMINATE_ASCII, &len);
1318
0
    if (!NT_STATUS_IS_OK(status)) {
1319
0
      return status;
1320
0
    }
1321
0
    SIVAL(q,0,len);
1322
0
    p += len;
1323
1324
0
    len = PTR_DIFF(p, pdata);
1325
0
    pad = (len + (align-1)) & ~(align-1);
1326
    /*
1327
     * offset to the next entry, the caller
1328
     * will overwrite it for the last entry
1329
     * that's why we always include the padding
1330
     */
1331
0
    SIVAL(pdata,0,pad);
1332
    /*
1333
     * set padding to zero
1334
     */
1335
0
    if (do_pad) {
1336
0
      memset(p, 0, pad - len);
1337
0
      p = pdata + pad;
1338
0
    } else {
1339
0
      p = pdata + len;
1340
0
    }
1341
0
    break;
1342
1343
0
  case SMB_FIND_FILE_DIRECTORY_INFO:
1344
0
    DBG_DEBUG("SMB_FIND_FILE_DIRECTORY_INFO\n");
1345
0
    p += 4;
1346
0
    SIVAL(p,0,reskey); p += 4;
1347
0
    put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1348
0
    put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1349
0
    put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1350
0
    put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1351
0
    SOFF_T(p,0,file_size); p += 8;
1352
0
    SOFF_T(p,0,allocation_size); p += 8;
1353
0
    SIVAL(p,0,mode); p += 4;
1354
0
    status = srvstr_push(base_data, flags2,
1355
0
          p + 4, fname, PTR_DIFF(end_data, p+4),
1356
0
          STR_TERMINATE_ASCII, &len);
1357
0
    if (!NT_STATUS_IS_OK(status)) {
1358
0
      return status;
1359
0
    }
1360
0
    SIVAL(p,0,len);
1361
0
    p += 4 + len;
1362
1363
0
    len = PTR_DIFF(p, pdata);
1364
0
    pad = (len + (align-1)) & ~(align-1);
1365
    /*
1366
     * offset to the next entry, the caller
1367
     * will overwrite it for the last entry
1368
     * that's why we always include the padding
1369
     */
1370
0
    SIVAL(pdata,0,pad);
1371
    /*
1372
     * set padding to zero
1373
     */
1374
0
    if (do_pad) {
1375
0
      memset(p, 0, pad - len);
1376
0
      p = pdata + pad;
1377
0
    } else {
1378
0
      p = pdata + len;
1379
0
    }
1380
0
    break;
1381
1382
0
  case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1383
0
    DBG_DEBUG("SMB_FIND_FILE_FULL_DIRECTORY_INFO\n");
1384
0
    p += 4;
1385
0
    SIVAL(p,0,reskey); p += 4;
1386
0
    put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1387
0
    put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1388
0
    put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1389
0
    put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1390
0
    SOFF_T(p,0,file_size); p += 8;
1391
0
    SOFF_T(p,0,allocation_size); p += 8;
1392
0
    SIVAL(p,0,mode); p += 4;
1393
0
    q = p; p += 4; /* q is placeholder for name length. */
1394
0
    ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1395
0
    SIVAL(p, 0, ea_size);
1396
0
    p +=4;
1397
0
    status = srvstr_push(base_data, flags2, p,
1398
0
          fname, PTR_DIFF(end_data, p),
1399
0
          STR_TERMINATE_ASCII, &len);
1400
0
    if (!NT_STATUS_IS_OK(status)) {
1401
0
      return status;
1402
0
    }
1403
0
    SIVAL(q, 0, len);
1404
0
    p += len;
1405
1406
0
    len = PTR_DIFF(p, pdata);
1407
0
    pad = (len + (align-1)) & ~(align-1);
1408
    /*
1409
     * offset to the next entry, the caller
1410
     * will overwrite it for the last entry
1411
     * that's why we always include the padding
1412
     */
1413
0
    SIVAL(pdata,0,pad);
1414
    /*
1415
     * set padding to zero
1416
     */
1417
0
    if (do_pad) {
1418
0
      memset(p, 0, pad - len);
1419
0
      p = pdata + pad;
1420
0
    } else {
1421
0
      p = pdata + len;
1422
0
    }
1423
0
    break;
1424
1425
0
  case SMB_FIND_FILE_NAMES_INFO:
1426
0
    DBG_DEBUG("SMB_FIND_FILE_NAMES_INFO\n");
1427
0
    p += 4;
1428
0
    SIVAL(p,0,reskey); p += 4;
1429
0
    p += 4;
1430
    /* this must *not* be null terminated or w2k gets in a loop trying to set an
1431
       acl on a dir (tridge) */
1432
0
    status = srvstr_push(base_data, flags2, p,
1433
0
          fname, PTR_DIFF(end_data, p),
1434
0
          STR_TERMINATE_ASCII, &len);
1435
0
    if (!NT_STATUS_IS_OK(status)) {
1436
0
      return status;
1437
0
    }
1438
0
    SIVAL(p, -4, len);
1439
0
    p += len;
1440
1441
0
    len = PTR_DIFF(p, pdata);
1442
0
    pad = (len + (align-1)) & ~(align-1);
1443
    /*
1444
     * offset to the next entry, the caller
1445
     * will overwrite it for the last entry
1446
     * that's why we always include the padding
1447
     */
1448
0
    SIVAL(pdata,0,pad);
1449
    /*
1450
     * set padding to zero
1451
     */
1452
0
    if (do_pad) {
1453
0
      memset(p, 0, pad - len);
1454
0
      p = pdata + pad;
1455
0
    } else {
1456
0
      p = pdata + len;
1457
0
    }
1458
0
    break;
1459
1460
0
  case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1461
0
    DBG_DEBUG("SMB_FIND_ID_FULL_DIRECTORY_INFO\n");
1462
0
    p += 4;
1463
0
    SIVAL(p,0,reskey); p += 4;
1464
0
    put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1465
0
    put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1466
0
    put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1467
0
    put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1468
0
    SOFF_T(p,0,file_size); p += 8;
1469
0
    SOFF_T(p,0,allocation_size); p += 8;
1470
0
    SIVAL(p,0,mode); p += 4;
1471
0
    q = p; p += 4; /* q is placeholder for name length. */
1472
0
    ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1473
0
    SIVAL(p, 0, ea_size);
1474
0
    p += 4;
1475
0
    SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1476
0
    SBVAL(p,0,file_id); p += 8;
1477
0
    status = srvstr_push(base_data, flags2, p,
1478
0
          fname, PTR_DIFF(end_data, p),
1479
0
          STR_TERMINATE_ASCII, &len);
1480
0
    if (!NT_STATUS_IS_OK(status)) {
1481
0
      return status;
1482
0
    }
1483
0
    SIVAL(q, 0, len);
1484
0
    p += len;
1485
1486
0
    len = PTR_DIFF(p, pdata);
1487
0
    pad = (len + (align-1)) & ~(align-1);
1488
    /*
1489
     * offset to the next entry, the caller
1490
     * will overwrite it for the last entry
1491
     * that's why we always include the padding
1492
     */
1493
0
    SIVAL(pdata,0,pad);
1494
    /*
1495
     * set padding to zero
1496
     */
1497
0
    if (do_pad) {
1498
0
      memset(p, 0, pad - len);
1499
0
      p = pdata + pad;
1500
0
    } else {
1501
0
      p = pdata + len;
1502
0
    }
1503
0
    break;
1504
1505
0
  case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1506
0
    DBG_DEBUG("SMB_FIND_ID_BOTH_DIRECTORY_INFO\n");
1507
0
    was_8_3 = mangle_is_8_3(fname, True, conn->params);
1508
0
    p += 4;
1509
0
    SIVAL(p,0,reskey); p += 4;
1510
0
    put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1511
0
    put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1512
0
    put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1513
0
    put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1514
0
    SOFF_T(p,0,file_size); p += 8;
1515
0
    SOFF_T(p,0,allocation_size); p += 8;
1516
0
    SIVAL(p,0,mode); p += 4;
1517
0
    q = p; p += 4; /* q is placeholder for name length */
1518
0
    if (readdir_attr_data &&
1519
0
        readdir_attr_data->type == RDATTR_AAPL) {
1520
      /*
1521
       * OS X specific SMB2 extension negotiated via
1522
       * AAPL create context: return max_access in
1523
       * ea_size field.
1524
       */
1525
0
      ea_size = readdir_attr_data->attr_data.aapl.max_access;
1526
0
    } else {
1527
0
      ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1528
0
    }
1529
0
    SIVAL(p,0,ea_size); /* Extended attributes */
1530
0
    p += 4;
1531
1532
0
    if (readdir_attr_data &&
1533
0
        readdir_attr_data->type == RDATTR_AAPL) {
1534
      /*
1535
       * OS X specific SMB2 extension negotiated via
1536
       * AAPL create context: return resource fork
1537
       * length and compressed FinderInfo in
1538
       * shortname field.
1539
       *
1540
       * According to documentation short_name_len
1541
       * should be 0, but on the wire behaviour
1542
       * shows its set to 24 by clients.
1543
       */
1544
0
      SSVAL(p, 0, 24);
1545
1546
      /* Resourefork length */
1547
0
      SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
1548
1549
      /* Compressed FinderInfo */
1550
0
      memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
1551
0
    } else if (!was_8_3 && check_mangled_names) {
1552
0
      char mangled_name[13]; /* mangled 8.3 name. */
1553
0
      if (!name_to_8_3(fname,mangled_name,True,
1554
0
          conn->params)) {
1555
        /* Error - mangle failed ! */
1556
0
        memset(mangled_name,'\0',12);
1557
0
      }
1558
0
      mangled_name[12] = 0;
1559
0
      status = srvstr_push(base_data, flags2,
1560
0
            p+2, mangled_name, 24,
1561
0
            STR_UPPER|STR_UNICODE, &len);
1562
0
      if (!NT_STATUS_IS_OK(status)) {
1563
0
        return status;
1564
0
      }
1565
0
      SSVAL(p, 0, len);
1566
0
      if (len < 24) {
1567
0
        memset(p + 2 + len,'\0',24 - len);
1568
0
      }
1569
0
      SSVAL(p, 0, len);
1570
0
    } else {
1571
      /* Clear the short name buffer. This is
1572
       * IMPORTANT as not doing so will trigger
1573
       * a Win2k client bug. JRA.
1574
       */
1575
0
      memset(p,'\0',26);
1576
0
    }
1577
0
    p += 26;
1578
1579
    /* Reserved ? */
1580
0
    if (readdir_attr_data &&
1581
0
        readdir_attr_data->type == RDATTR_AAPL) {
1582
      /*
1583
       * OS X specific SMB2 extension negotiated via
1584
       * AAPL create context: return UNIX mode in
1585
       * reserved field.
1586
       */
1587
0
      uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
1588
0
      SSVAL(p, 0, aapl_mode);
1589
0
    } else {
1590
0
      SSVAL(p, 0, 0);
1591
0
    }
1592
0
    p += 2;
1593
1594
0
    SBVAL(p,0,file_id); p += 8;
1595
0
    status = srvstr_push(base_data, flags2, p,
1596
0
          fname, PTR_DIFF(end_data, p),
1597
0
          STR_TERMINATE_ASCII, &len);
1598
0
    if (!NT_STATUS_IS_OK(status)) {
1599
0
      return status;
1600
0
    }
1601
0
    SIVAL(q,0,len);
1602
0
    p += len;
1603
1604
0
    len = PTR_DIFF(p, pdata);
1605
0
    pad = (len + (align-1)) & ~(align-1);
1606
    /*
1607
     * offset to the next entry, the caller
1608
     * will overwrite it for the last entry
1609
     * that's why we always include the padding
1610
     */
1611
0
    SIVAL(pdata,0,pad);
1612
    /*
1613
     * set padding to zero
1614
     */
1615
0
    if (do_pad) {
1616
0
      memset(p, 0, pad - len);
1617
0
      p = pdata + pad;
1618
0
    } else {
1619
0
      p = pdata + len;
1620
0
    }
1621
0
    break;
1622
1623
  /* CIFS UNIX Extension. */
1624
1625
0
  case SMB_FIND_FILE_UNIX:
1626
0
  case SMB_FIND_FILE_UNIX_INFO2:
1627
0
    p+= 4;
1628
0
    SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
1629
1630
    /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1631
1632
0
    if (info_level == SMB_FIND_FILE_UNIX) {
1633
0
      DBG_DEBUG("SMB_FIND_FILE_UNIX\n");
1634
0
      p = store_file_unix_basic(conn, p,
1635
0
            NULL, &smb_fname->st);
1636
0
      status = srvstr_push(base_data, flags2, p,
1637
0
            fname, PTR_DIFF(end_data, p),
1638
0
            STR_TERMINATE, &len);
1639
0
      if (!NT_STATUS_IS_OK(status)) {
1640
0
        return status;
1641
0
      }
1642
0
    } else {
1643
0
      DBG_DEBUG("SMB_FIND_FILE_UNIX_INFO2\n");
1644
0
      p = store_file_unix_basic_info2(conn, p,
1645
0
            NULL, &smb_fname->st);
1646
0
      nameptr = p;
1647
0
      p += 4;
1648
0
      status = srvstr_push(base_data, flags2, p, fname,
1649
0
            PTR_DIFF(end_data, p), 0, &len);
1650
0
      if (!NT_STATUS_IS_OK(status)) {
1651
0
        return status;
1652
0
      }
1653
0
      SIVAL(nameptr, 0, len);
1654
0
    }
1655
1656
0
    p += len;
1657
1658
0
    len = PTR_DIFF(p, pdata);
1659
0
    pad = (len + (align-1)) & ~(align-1);
1660
    /*
1661
     * offset to the next entry, the caller
1662
     * will overwrite it for the last entry
1663
     * that's why we always include the padding
1664
     */
1665
0
    SIVAL(pdata,0,pad);
1666
    /*
1667
     * set padding to zero
1668
     */
1669
0
    if (do_pad) {
1670
0
      memset(p, 0, pad - len);
1671
0
      p = pdata + pad;
1672
0
    } else {
1673
0
      p = pdata + len;
1674
0
    }
1675
    /* End of SMB_QUERY_FILE_UNIX_BASIC */
1676
1677
0
    break;
1678
1679
  /* SMB2 UNIX Extension. */
1680
1681
0
  case FSCC_FILE_POSIX_INFORMATION:
1682
0
    {
1683
0
      struct smb3_file_posix_information info = {};
1684
0
      uint8_t buf[sizeof(info)];
1685
0
      struct ndr_push ndr = {
1686
0
        .data = buf,
1687
0
        .alloc_size = sizeof(buf),
1688
0
        .fixed_buf_size = true,
1689
0
      };
1690
0
      enum ndr_err_code ndr_err;
1691
1692
0
      DBG_DEBUG("FSCC_FILE_POSIX_INFORMATION\n");
1693
1694
0
      p+= 4;
1695
0
      SIVAL(p,0,reskey); p+= 4;
1696
1697
0
      if (!conn_using_smb2(conn->sconn)) {
1698
0
        return NT_STATUS_INVALID_LEVEL;
1699
0
      }
1700
1701
0
      status = smb3_file_posix_information_init(
1702
0
        conn, smb_fname, mode, &info);
1703
0
      if (!NT_STATUS_IS_OK(status)) {
1704
0
        return status;
1705
0
      }
1706
1707
0
      ndr_err = ndr_push_smb3_file_posix_information(
1708
0
        &ndr, NDR_SCALARS|NDR_BUFFERS, &info);
1709
0
      if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1710
0
        return NT_STATUS_INSUFFICIENT_RESOURCES;
1711
0
      }
1712
1713
0
      memcpy(p, buf, ndr.offset);
1714
0
      p += ndr.offset;
1715
1716
0
      nameptr = p;
1717
0
      p += 4;
1718
0
      status = srvstr_push(base_data, flags2, p, fname,
1719
0
          PTR_DIFF(end_data, p), 0, &len);
1720
0
      if (!NT_STATUS_IS_OK(status)) {
1721
0
        return status;
1722
0
      }
1723
0
      SIVAL(nameptr, 0, len);
1724
1725
0
      p += len;
1726
1727
0
      len = PTR_DIFF(p, pdata);
1728
0
      pad = (len + (align-1)) & ~(align-1);
1729
      /*
1730
       * offset to the next entry, the caller
1731
       * will overwrite it for the last entry
1732
       * that's why we always include the padding
1733
       */
1734
0
      SIVAL(pdata,0,pad);
1735
0
      break;
1736
0
    }
1737
1738
0
  default:
1739
0
    return NT_STATUS_INVALID_LEVEL;
1740
0
  }
1741
1742
0
  if (PTR_DIFF(p,pdata) > space_remaining) {
1743
0
    DEBUG(9,("smbd_marshall_dir_entry: out of space "
1744
0
      "(wanted %u, had %d)\n",
1745
0
      (unsigned int)PTR_DIFF(p,pdata),
1746
0
      space_remaining ));
1747
0
    return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1748
0
  }
1749
1750
  /* Setup the last entry pointer, as an offset from base_data */
1751
0
  *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1752
  /* Advance the data pointer to the next slot */
1753
0
  *ppdata = p;
1754
1755
0
  return NT_STATUS_OK;
1756
0
}
1757
1758
NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
1759
             struct files_struct *dirfsp,
1760
             uint16_t flags2,
1761
             const char *path_mask,
1762
             uint32_t dirtype,
1763
             int info_level,
1764
             int requires_resume_key,
1765
             bool dont_descend,
1766
             bool get_dosmode,
1767
             uint8_t align,
1768
             bool do_pad,
1769
             char **ppdata,
1770
             char *base_data,
1771
             char *end_data,
1772
             int space_remaining,
1773
             struct smb_filename **_smb_fname,
1774
             int *_last_entry_off,
1775
             struct ea_list *name_list,
1776
             struct file_id *file_id)
1777
0
{
1778
0
  struct connection_struct *conn = dirfsp->conn;
1779
0
  struct dptr_struct *dirptr = dirfsp->dptr;
1780
0
  const char *p;
1781
0
  const char *mask = NULL;
1782
0
  uint32_t mode = 0;
1783
0
  char *fname = NULL;
1784
0
  struct smb_filename *smb_fname = NULL;
1785
0
  struct smbd_dirptr_lanman2_state state = {
1786
0
    .conn = conn,
1787
0
    .info_level = info_level,
1788
0
  };
1789
0
  bool ok;
1790
0
  uint64_t last_entry_off = 0;
1791
0
  NTSTATUS status;
1792
0
  enum mangled_names_options mangled_names;
1793
0
  bool marshall_with_83_names;
1794
1795
0
  mangled_names = lp_mangled_names(conn->params);
1796
1797
0
  if (mangled_names != MANGLED_NAMES_NO) {
1798
0
    state.check_mangled_names = true;
1799
0
  }
1800
0
  state.case_sensitive = dptr_case_sensitive(dirptr);
1801
0
  if (dirfsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH) {
1802
0
    state.posix_paths = true;
1803
0
  }
1804
1805
0
  p = strrchr_m(path_mask,'/');
1806
0
  if(p != NULL) {
1807
0
    if(p[1] == '\0') {
1808
0
      mask = "*.*";
1809
0
    } else {
1810
0
      mask = p+1;
1811
0
    }
1812
0
  } else {
1813
0
    mask = path_mask;
1814
0
  }
1815
1816
0
  ok = smbd_dirptr_get_entry(ctx,
1817
0
           dirptr,
1818
0
           mask,
1819
0
           dirtype,
1820
0
           dont_descend,
1821
0
           get_dosmode,
1822
0
           smbd_dirptr_lanman2_match_fn,
1823
0
           &state,
1824
0
           &fname,
1825
0
           &smb_fname,
1826
0
           &mode);
1827
0
  if (!ok) {
1828
0
    return NT_STATUS_END_OF_FILE;
1829
0
  }
1830
1831
0
  marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
1832
1833
0
  status = smbd_marshall_dir_entry(ctx,
1834
0
             conn,
1835
0
             flags2,
1836
0
             info_level,
1837
0
             name_list,
1838
0
             marshall_with_83_names,
1839
0
             requires_resume_key,
1840
0
             mode,
1841
0
             fname,
1842
0
             smb_fname,
1843
0
             space_remaining,
1844
0
             align,
1845
0
             do_pad,
1846
0
             base_data,
1847
0
             ppdata,
1848
0
             end_data,
1849
0
             &last_entry_off);
1850
0
  if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
1851
0
    DEBUG(1,("Conversion error: illegal character: %s\n",
1852
0
       smb_fname_str_dbg(smb_fname)));
1853
0
  }
1854
1855
0
  if (file_id != NULL) {
1856
0
    *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1857
0
  }
1858
1859
0
  if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1860
0
    smbd_dirptr_push_overflow(dirptr, &fname, &smb_fname, mode);
1861
0
  }
1862
1863
0
  if (!NT_STATUS_IS_OK(status)) {
1864
0
    TALLOC_FREE(smb_fname);
1865
0
    TALLOC_FREE(fname);
1866
0
    return status;
1867
0
  }
1868
1869
0
  smbd_dirptr_set_last_name_sent(dirptr, &smb_fname->base_name);
1870
1871
0
  if (_smb_fname != NULL) {
1872
    /*
1873
     * smb_fname is already talloc'ed off ctx.
1874
     * We just need to make sure we don't return
1875
     * any stream_name, and replace base_name
1876
     * with fname in case base_name got mangled.
1877
     * This allows us to preserve any smb_fname->fsp
1878
     * for asynchronous handle lookups.
1879
     */
1880
0
    TALLOC_FREE(smb_fname->stream_name);
1881
1882
    /*
1883
     * smbd_dirptr_set_last_name_sent() above consumed
1884
     * base_name
1885
     */
1886
0
    smb_fname->base_name = talloc_strdup(smb_fname, fname);
1887
1888
0
    if (smb_fname->base_name == NULL) {
1889
0
      TALLOC_FREE(smb_fname);
1890
0
      TALLOC_FREE(fname);
1891
0
      return NT_STATUS_NO_MEMORY;
1892
0
    }
1893
0
    *_smb_fname = smb_fname;
1894
0
  } else {
1895
0
    TALLOC_FREE(smb_fname);
1896
0
  }
1897
0
  TALLOC_FREE(fname);
1898
1899
0
  *_last_entry_off = last_entry_off;
1900
0
  return NT_STATUS_OK;
1901
0
}
1902
1903
unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
1904
0
{
1905
0
  const struct loadparm_substitution *lp_sub =
1906
0
    loadparm_s3_global_substitution();
1907
1908
0
  E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
1909
0
  return objid;
1910
0
}
1911
1912
static void samba_extended_info_version(struct smb_extended_info *extended_info)
1913
0
{
1914
0
  SMB_ASSERT(extended_info != NULL);
1915
1916
0
  extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
1917
0
  extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
1918
0
               | ((SAMBA_VERSION_MINOR & 0xff) << 16)
1919
0
               | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
1920
#ifdef SAMBA_VERSION_REVISION
1921
  extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
1922
#endif
1923
0
  extended_info->samba_subversion = 0;
1924
#ifdef SAMBA_VERSION_RC_RELEASE
1925
  extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
1926
#else
1927
0
#ifdef SAMBA_VERSION_PRE_RELEASE
1928
0
  extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
1929
0
#endif
1930
0
#endif
1931
#ifdef SAMBA_VERSION_VENDOR_PATCH
1932
  extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
1933
#endif
1934
0
  extended_info->samba_gitcommitdate = 0;
1935
#ifdef SAMBA_VERSION_COMMIT_TIME
1936
  unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
1937
#endif
1938
1939
0
  memset(extended_info->samba_version_string, 0,
1940
0
         sizeof(extended_info->samba_version_string));
1941
1942
0
  snprintf (extended_info->samba_version_string,
1943
0
      sizeof(extended_info->samba_version_string),
1944
0
      "%s", samba_version_string());
1945
0
}
1946
1947
static bool fsinfo_unix_valid_level(connection_struct *conn,
1948
            struct files_struct *fsp,
1949
            uint16_t info_level)
1950
0
{
1951
0
  if (conn_using_smb2(conn->sconn) &&
1952
0
      fsp->fsp_flags.posix_open &&
1953
0
      info_level == FSCC_FS_POSIX_INFORMATION)
1954
0
  {
1955
0
    return true;
1956
0
  }
1957
#if defined(SMB1SERVER)
1958
  if (lp_smb1_unix_extensions() &&
1959
      info_level == SMB_QUERY_POSIX_FS_INFO) {
1960
    return true;
1961
  }
1962
#endif
1963
0
  return false;
1964
0
}
1965
1966
/*
1967
 * fsp is only valid for SMB2.
1968
 */
1969
NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
1970
       connection_struct *conn,
1971
       TALLOC_CTX *mem_ctx,
1972
       uint16_t info_level,
1973
       uint16_t flags2,
1974
       unsigned int max_data_bytes,
1975
       size_t *fixed_portion,
1976
       struct files_struct *fsp,
1977
       struct smb_filename *fname,
1978
       char **ppdata,
1979
       int *ret_data_len)
1980
0
{
1981
0
  const struct loadparm_substitution *lp_sub =
1982
0
    loadparm_s3_global_substitution();
1983
0
  char *pdata, *end_data;
1984
0
  int data_len = 0;
1985
0
  size_t len = 0;
1986
0
  const char *vname = volume_label(talloc_tos(), SNUM(conn));
1987
0
  int snum = SNUM(conn);
1988
0
  const char *fstype = lp_fstype(SNUM(conn));
1989
0
  const char *filename = NULL;
1990
0
  uint64_t bytes_per_sector = 512;
1991
0
  struct smb_filename smb_fname;
1992
0
  SMB_STRUCT_STAT st;
1993
0
  NTSTATUS status = NT_STATUS_OK;
1994
0
  uint64_t df_ret;
1995
0
  uint32_t serial;
1996
1997
0
  if (fname == NULL || fname->base_name == NULL) {
1998
0
    filename = ".";
1999
0
  } else {
2000
0
    filename = fname->base_name;
2001
0
  }
2002
2003
0
  if (IS_IPC(conn)) {
2004
0
    if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2005
0
      DBG_ERR("not an allowed info level (0x%x) on IPC$.\n",
2006
0
        (unsigned int)info_level);
2007
0
      return NT_STATUS_ACCESS_DENIED;
2008
0
    }
2009
0
  }
2010
2011
0
  DBG_NOTICE("level = %d\n", info_level);
2012
2013
0
  smb_fname = (struct smb_filename) {
2014
0
    .base_name = discard_const_p(char, filename),
2015
0
    .flags = fname ? fname->flags : 0,
2016
0
    .twrp = fname ? fname->twrp : 0,
2017
0
  };
2018
2019
0
  if(info_level != SMB_FS_QUOTA_INFORMATION
2020
0
     && SMB_VFS_STAT(conn, &smb_fname) != 0) {
2021
0
    DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2022
0
    return map_nt_error_from_unix(errno);
2023
0
  }
2024
2025
0
  st = smb_fname.st;
2026
2027
0
  if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2028
0
    return NT_STATUS_INVALID_PARAMETER;
2029
0
  }
2030
2031
0
  *ppdata = (char *)SMB_REALLOC(
2032
0
    *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2033
0
  if (*ppdata == NULL) {
2034
0
    return NT_STATUS_NO_MEMORY;
2035
0
  }
2036
2037
0
  pdata = *ppdata;
2038
0
  memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2039
0
  end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2040
2041
0
  *fixed_portion = 0;
2042
2043
0
  switch (info_level) {
2044
0
    case SMB_INFO_ALLOCATION:
2045
0
    {
2046
0
      uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2047
0
      data_len = 18;
2048
0
      df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2049
0
            &dfree, &dsize);
2050
0
      if (df_ret == (uint64_t)-1) {
2051
0
        return map_nt_error_from_unix(errno);
2052
0
      }
2053
2054
0
      block_size = lp_block_size(snum);
2055
0
      if (bsize < block_size) {
2056
0
        uint64_t factor = block_size/bsize;
2057
0
        bsize = block_size;
2058
0
        dsize /= factor;
2059
0
        dfree /= factor;
2060
0
      }
2061
0
      if (bsize > block_size) {
2062
0
        uint64_t factor = bsize/block_size;
2063
0
        bsize = block_size;
2064
0
        dsize *= factor;
2065
0
        dfree *= factor;
2066
0
      }
2067
0
      sectors_per_unit = bsize/bytes_per_sector;
2068
2069
0
      DBG_INFO("SMB_INFO_ALLOCATION id=%x, bsize=%" PRIu64
2070
0
         ", cSectorUnit=%" PRIu64
2071
0
         ", cBytesSector=%" PRIu64
2072
0
         ", cUnitTotal=%" PRIu64
2073
0
         ", cUnitAvail=%" PRIu64 "\n",
2074
0
         (unsigned int)st.st_ex_dev,
2075
0
         bsize,
2076
0
         sectors_per_unit,
2077
0
         bytes_per_sector,
2078
0
         dsize,
2079
0
         dfree);
2080
2081
      /*
2082
       * For large drives, return max values and not modulo.
2083
       */
2084
0
      dsize = MIN(dsize, UINT32_MAX);
2085
0
      dfree = MIN(dfree, UINT32_MAX);
2086
2087
0
      SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2088
0
      SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2089
0
      SIVAL(pdata,l1_cUnit,dsize);
2090
0
      SIVAL(pdata,l1_cUnitAvail,dfree);
2091
0
      SSVAL(pdata,l1_cbSector,bytes_per_sector);
2092
0
      break;
2093
0
    }
2094
2095
0
    case SMB_INFO_VOLUME:
2096
      /* Return volume name */
2097
      /*
2098
       * Add volume serial number - hash of a combination of
2099
       * the called hostname and the service name.
2100
       */
2101
0
      serial = generate_volume_serial_number(lp_sub, snum);
2102
0
      SIVAL(pdata,0,serial);
2103
      /*
2104
       * Win2k3 and previous mess this up by sending a name length
2105
       * one byte short. I believe only older clients (OS/2 Win9x) use
2106
       * this call so try fixing this by adding a terminating null to
2107
       * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2108
       */
2109
0
      status = srvstr_push(
2110
0
        pdata, flags2,
2111
0
        pdata+l2_vol_szVolLabel, vname,
2112
0
        PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2113
0
        STR_NOALIGN|STR_TERMINATE, &len);
2114
0
      if (!NT_STATUS_IS_OK(status)) {
2115
0
        return status;
2116
0
      }
2117
0
      SCVAL(pdata,l2_vol_cch,len);
2118
0
      data_len = l2_vol_szVolLabel + len;
2119
2120
0
      DBG_INFO("time = %jx, namelen = %zu, "
2121
0
         "name = %s serial = 0x%04" PRIx32 "\n",
2122
0
         (intmax_t)convert_timespec_to_time_t(
2123
0
           st.st_ex_ctime),
2124
0
         len,
2125
0
         vname,
2126
0
         serial);
2127
0
      break;
2128
2129
0
    case SMB_QUERY_FS_ATTRIBUTE_INFO:
2130
0
    case SMB_FS_ATTRIBUTE_INFORMATION:
2131
2132
0
      SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2133
0
        FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2134
0
        conn->fs_capabilities); /* FS ATTRIBUTES */
2135
2136
0
      SIVAL(pdata,4,255); /* Max filename component length */
2137
      /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2138
        and will think we can't do long filenames */
2139
0
      status = srvstr_push(pdata, flags2, pdata+12, fstype,
2140
0
            PTR_DIFF(end_data, pdata+12),
2141
0
            STR_UNICODE, &len);
2142
0
      if (!NT_STATUS_IS_OK(status)) {
2143
0
        return status;
2144
0
      }
2145
0
      SIVAL(pdata,8,len);
2146
0
      data_len = 12 + len;
2147
0
      if (max_data_bytes >= 16 && data_len > max_data_bytes) {
2148
        /* the client only requested a portion of the
2149
           file system name */
2150
0
        data_len = max_data_bytes;
2151
0
        status = STATUS_BUFFER_OVERFLOW;
2152
0
      }
2153
0
      *fixed_portion = 16;
2154
0
      break;
2155
2156
0
    case SMB_QUERY_FS_LABEL_INFO:
2157
0
    case SMB_FS_LABEL_INFORMATION:
2158
0
      status = srvstr_push(pdata, flags2, pdata+4, vname,
2159
0
            PTR_DIFF(end_data, pdata+4), 0, &len);
2160
0
      if (!NT_STATUS_IS_OK(status)) {
2161
0
        return status;
2162
0
      }
2163
0
      data_len = 4 + len;
2164
0
      SIVAL(pdata,0,len);
2165
0
      break;
2166
2167
0
    case SMB_QUERY_FS_VOLUME_INFO:
2168
0
    case SMB_FS_VOLUME_INFORMATION:
2169
0
      put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,
2170
0
                pdata, &st.st_ex_btime);
2171
      /*
2172
       * Add volume serial number - hash of a combination of
2173
       * the called hostname and the service name.
2174
       */
2175
0
      serial = generate_volume_serial_number(lp_sub, snum);
2176
0
      SIVAL(pdata,8,serial);
2177
2178
      /* Max label len is 32 characters. */
2179
0
      status = srvstr_push(pdata, flags2, pdata+18, vname,
2180
0
            PTR_DIFF(end_data, pdata+18),
2181
0
            STR_UNICODE, &len);
2182
0
      if (!NT_STATUS_IS_OK(status)) {
2183
0
        return status;
2184
0
      }
2185
0
      SIVAL(pdata,12,len);
2186
0
      data_len = 18+len;
2187
2188
0
      DBG_INFO("SMB_QUERY_FS_VOLUME_INFO namelen = %zu, "
2189
0
         "vol=%s serv=%s "
2190
0
         "serial=0x%04" PRIx32 "\n",
2191
0
         strlen(vname),
2192
0
         vname,
2193
0
         lp_servicename(talloc_tos(), lp_sub, snum),
2194
0
         serial);
2195
0
      if (max_data_bytes >= 24 && data_len > max_data_bytes) {
2196
        /* the client only requested a portion of the
2197
           volume label */
2198
0
        data_len = max_data_bytes;
2199
0
        status = STATUS_BUFFER_OVERFLOW;
2200
0
      }
2201
0
      *fixed_portion = 24;
2202
0
      break;
2203
2204
0
    case SMB_QUERY_FS_SIZE_INFO:
2205
0
    case SMB_FS_SIZE_INFORMATION:
2206
0
    {
2207
0
      uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2208
0
      data_len = 24;
2209
0
      df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2210
0
            &dfree, &dsize);
2211
0
      if (df_ret == (uint64_t)-1) {
2212
0
        return map_nt_error_from_unix(errno);
2213
0
      }
2214
0
      block_size = lp_block_size(snum);
2215
0
      if (bsize < block_size) {
2216
0
        uint64_t factor = block_size/bsize;
2217
0
        bsize = block_size;
2218
0
        dsize /= factor;
2219
0
        dfree /= factor;
2220
0
      }
2221
0
      if (bsize > block_size) {
2222
0
        uint64_t factor = bsize/block_size;
2223
0
        bsize = block_size;
2224
0
        dsize *= factor;
2225
0
        dfree *= factor;
2226
0
      }
2227
0
      sectors_per_unit = bsize/bytes_per_sector;
2228
2229
0
      DBG_INFO("SMB_QUERY_FS_SIZE_INFO bsize=%" PRIu64
2230
0
         ", cSectorUnit=%" PRIu64
2231
0
         ", cBytesSector=%" PRIu64
2232
0
         ", cUnitTotal=%" PRIu64
2233
0
         ", cUnitAvail=%" PRIu64 "\n",
2234
0
         bsize,
2235
0
         sectors_per_unit,
2236
0
         bytes_per_sector,
2237
0
         dsize,
2238
0
         dfree);
2239
0
      SBIG_UINT(pdata,0,dsize);
2240
0
      SBIG_UINT(pdata,8,dfree);
2241
0
      SIVAL(pdata,16,sectors_per_unit);
2242
0
      SIVAL(pdata,20,bytes_per_sector);
2243
0
      *fixed_portion = 24;
2244
0
      break;
2245
0
    }
2246
2247
0
    case SMB_FS_FULL_SIZE_INFORMATION:
2248
0
    {
2249
0
      uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2250
0
      data_len = 32;
2251
0
      df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2252
0
            &dfree, &dsize);
2253
0
      if (df_ret == (uint64_t)-1) {
2254
0
        return map_nt_error_from_unix(errno);
2255
0
      }
2256
0
      block_size = lp_block_size(snum);
2257
0
      if (bsize < block_size) {
2258
0
        uint64_t factor = block_size/bsize;
2259
0
        bsize = block_size;
2260
0
        dsize /= factor;
2261
0
        dfree /= factor;
2262
0
      }
2263
0
      if (bsize > block_size) {
2264
0
        uint64_t factor = bsize/block_size;
2265
0
        bsize = block_size;
2266
0
        dsize *= factor;
2267
0
        dfree *= factor;
2268
0
      }
2269
0
      sectors_per_unit = bsize/bytes_per_sector;
2270
2271
0
      DBG_INFO("SMB_QUERY_FS_FULL_SIZE_INFO bsize=%" PRIu64
2272
0
         ", cSectorUnit=%" PRIu64
2273
0
         ", cBytesSector=%" PRIu64
2274
0
         ", cUnitTotal=%" PRIu64
2275
0
         ", cUnitAvail=%" PRIu64 "\n",
2276
0
         bsize,
2277
0
         sectors_per_unit,
2278
0
         bytes_per_sector,
2279
0
         dsize,
2280
0
         dfree);
2281
0
      SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2282
0
      SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2283
0
      SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2284
0
      SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2285
0
      SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2286
0
      *fixed_portion = 32;
2287
0
      break;
2288
0
    }
2289
2290
0
    case SMB_QUERY_FS_DEVICE_INFO:
2291
0
    case SMB_FS_DEVICE_INFORMATION:
2292
0
    {
2293
0
      uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
2294
2295
0
      if (!CAN_WRITE(conn)) {
2296
0
        characteristics |= FILE_READ_ONLY_DEVICE;
2297
0
      }
2298
0
      data_len = 8;
2299
0
      SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
2300
0
      SIVAL(pdata,4,characteristics);
2301
0
      *fixed_portion = 8;
2302
0
      break;
2303
0
    }
2304
2305
0
#ifdef HAVE_SYS_QUOTAS
2306
0
    case SMB_FS_QUOTA_INFORMATION:
2307
    /*
2308
     * what we have to send --metze:
2309
     *
2310
     * Unknown1:    24 NULL bytes
2311
     * Soft Quota Threshold: 8 bytes seems like uint64_t or so
2312
     * Hard Quota Limit:  8 bytes seems like uint64_t or so
2313
     * Quota Flags:   2 byte :
2314
     * Unknown3:    6 NULL bytes
2315
     *
2316
     * 48 bytes total
2317
     *
2318
     * details for Quota Flags:
2319
     *
2320
     * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2321
     * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
2322
     * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2323
     * 0x0001 Enable Quotas: enable quota for this fs
2324
     *
2325
     */
2326
0
    {
2327
      /* we need to fake up a fsp here,
2328
       * because its not send in this call
2329
       */
2330
0
      files_struct tmpfsp = {
2331
0
        .conn = conn,
2332
0
        .fnum = FNUM_FIELD_INVALID,
2333
0
      };
2334
0
      SMB_NTQUOTA_STRUCT quotas = {};
2335
2336
      /* access check */
2337
0
      if (get_current_uid(conn) != 0) {
2338
0
        DEBUG(0,("get_user_quota: access_denied "
2339
0
           "service [%s] user [%s]\n",
2340
0
           lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2341
0
           conn->session_info->unix_info->unix_name));
2342
0
        return NT_STATUS_ACCESS_DENIED;
2343
0
      }
2344
2345
0
      status = vfs_get_ntquota(&tmpfsp, SMB_USER_FS_QUOTA_TYPE,
2346
0
             NULL, &quotas);
2347
0
      if (!NT_STATUS_IS_OK(status)) {
2348
0
        DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2349
0
        return status;
2350
0
      }
2351
2352
0
      data_len = 48;
2353
2354
0
      DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2355
0
          lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2356
2357
      /* Unknown1 24 NULL bytes*/
2358
0
      SBIG_UINT(pdata,0,(uint64_t)0);
2359
0
      SBIG_UINT(pdata,8,(uint64_t)0);
2360
0
      SBIG_UINT(pdata,16,(uint64_t)0);
2361
2362
      /* Default Soft Quota 8 bytes */
2363
0
      SBIG_UINT(pdata,24,quotas.softlim);
2364
2365
      /* Default Hard Quota 8 bytes */
2366
0
      SBIG_UINT(pdata,32,quotas.hardlim);
2367
2368
      /* Quota flag 2 bytes */
2369
0
      SSVAL(pdata,40,quotas.qflags);
2370
2371
      /* Unknown3 6 NULL bytes */
2372
0
      SSVAL(pdata,42,0);
2373
0
      SIVAL(pdata,44,0);
2374
2375
0
      break;
2376
0
    }
2377
0
#endif /* HAVE_SYS_QUOTAS */
2378
0
    case SMB_FS_OBJECTID_INFORMATION:
2379
0
    {
2380
0
      unsigned char objid[16];
2381
0
      struct smb_extended_info extended_info;
2382
0
      memcpy(pdata,create_volume_objectid(conn, objid),16);
2383
0
      samba_extended_info_version (&extended_info);
2384
0
      SIVAL(pdata,16,extended_info.samba_magic);
2385
0
      SIVAL(pdata,20,extended_info.samba_version);
2386
0
      SIVAL(pdata,24,extended_info.samba_subversion);
2387
0
      SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2388
0
      memcpy(pdata+36,extended_info.samba_version_string,28);
2389
0
      data_len = 64;
2390
0
      break;
2391
0
    }
2392
2393
0
    case SMB_FS_SECTOR_SIZE_INFORMATION:
2394
0
    {
2395
0
      uint32_t bps_logical = lp_parm_ulong(
2396
0
        SNUM(conn),
2397
0
        "fs", "logical bytes per sector",
2398
0
        bytes_per_sector);
2399
0
      uint32_t bps_aligned = lp_parm_ulong(
2400
0
        SNUM(conn),
2401
0
        "fs", "aligned bytes per sector",
2402
0
        bytes_per_sector);
2403
0
      uint32_t bps_performance = lp_parm_ulong(
2404
0
        SNUM(conn),
2405
0
        "fs", "performance bytes per sector",
2406
0
        bytes_per_sector);
2407
0
      uint32_t bps_effective = lp_parm_ulong(
2408
0
        SNUM(conn),
2409
0
        "fs", "effective aligned bytes per sector",
2410
0
        bytes_per_sector);
2411
2412
0
      data_len = 28;
2413
      /*
2414
       * These values match a physical Windows Server 2012
2415
       * share backed by NTFS atop spinning rust.
2416
       */
2417
0
      DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2418
      /* logical_bytes_per_sector */
2419
0
      SIVAL(pdata, 0, bps_logical);
2420
      /* phys_bytes_per_sector_atomic */
2421
0
      SIVAL(pdata, 4, bps_aligned);
2422
      /* phys_bytes_per_sector_perf */
2423
0
      SIVAL(pdata, 8, bps_performance);
2424
      /* fs_effective_phys_bytes_per_sector_atomic */
2425
0
      SIVAL(pdata, 12, bps_effective);
2426
      /* flags */
2427
0
      SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2428
0
        | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
2429
      /* byte_off_sector_align */
2430
0
      SIVAL(pdata, 20, 0);
2431
      /* byte_off_partition_align */
2432
0
      SIVAL(pdata, 24, 0);
2433
0
      *fixed_portion = 28;
2434
0
      break;
2435
0
    }
2436
2437
2438
0
#if defined(WITH_SMB1SERVER)
2439
    /*
2440
     * Query the version and capabilities of the CIFS UNIX extensions
2441
     * in use.
2442
     */
2443
2444
0
    case SMB_QUERY_CIFS_UNIX_INFO:
2445
0
    {
2446
0
      bool large_write = lp_min_receive_file_size() &&
2447
0
          !smb1_srv_is_signing_active(xconn);
2448
0
      bool large_read = !smb1_srv_is_signing_active(xconn);
2449
0
      int encrypt_caps = 0;
2450
2451
0
      if (!lp_smb1_unix_extensions()) {
2452
0
        return NT_STATUS_INVALID_LEVEL;
2453
0
      }
2454
2455
0
      switch (conn->encrypt_level) {
2456
0
      case SMB_SIGNING_OFF:
2457
0
        encrypt_caps = 0;
2458
0
        break;
2459
0
      case SMB_SIGNING_DESIRED:
2460
0
      case SMB_SIGNING_IF_REQUIRED:
2461
0
      case SMB_SIGNING_DEFAULT:
2462
0
        encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2463
0
        break;
2464
0
      case SMB_SIGNING_REQUIRED:
2465
0
        encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2466
0
            CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2467
0
        large_write = false;
2468
0
        large_read = false;
2469
0
        break;
2470
0
      }
2471
2472
0
      data_len = 12;
2473
0
      SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2474
0
      SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2475
2476
      /* We have POSIX ACLs, pathname, encryption,
2477
       * large read/write, and locking capability. */
2478
2479
0
      SBIG_UINT(pdata,4,((uint64_t)(
2480
0
          CIFS_UNIX_POSIX_ACLS_CAP|
2481
0
          CIFS_UNIX_POSIX_PATHNAMES_CAP|
2482
0
          CIFS_UNIX_FCNTL_LOCKS_CAP|
2483
0
          CIFS_UNIX_EXTATTR_CAP|
2484
0
          CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2485
0
          encrypt_caps|
2486
0
          (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2487
0
          (large_write ?
2488
0
          CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2489
0
      break;
2490
0
    }
2491
0
#endif
2492
2493
0
    case SMB_QUERY_POSIX_FS_INFO:
2494
0
    case FSCC_FS_POSIX_INFORMATION:
2495
0
    {
2496
0
      int rc;
2497
0
      struct vfs_statvfs_struct svfs;
2498
2499
0
      if (!fsinfo_unix_valid_level(conn, fsp, info_level)) {
2500
0
        return NT_STATUS_INVALID_LEVEL;
2501
0
      }
2502
2503
0
      rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
2504
2505
0
#ifdef EOPNOTSUPP
2506
0
      if (rc == EOPNOTSUPP) {
2507
0
        return NT_STATUS_INVALID_LEVEL;
2508
0
      }
2509
0
#endif
2510
0
      if (rc != 0) {
2511
0
        DBG_ERR("vfs_statvfs() failed for service "
2512
0
          "[%s]\n",
2513
0
          lp_servicename(talloc_tos(),
2514
0
                   lp_sub,
2515
0
                   SNUM(conn)));
2516
0
        return NT_STATUS_DOS(ERRSRV, ERRerror);
2517
0
      }
2518
2519
0
      data_len = 56;
2520
0
      PUSH_LE_U32(pdata, 0, svfs.OptimalTransferSize);
2521
0
      PUSH_LE_U32(pdata, 4, svfs.BlockSize);
2522
0
      PUSH_LE_U64(pdata, 8, svfs.TotalBlocks);
2523
0
      PUSH_LE_U64(pdata, 16, svfs.BlocksAvail);
2524
0
      PUSH_LE_U64(pdata, 24, svfs.UserBlocksAvail);
2525
0
      PUSH_LE_U64(pdata, 32, svfs.TotalFileNodes);
2526
0
      PUSH_LE_U64(pdata, 40, svfs.FreeFileNodes);
2527
0
      PUSH_LE_U64(pdata, 48, svfs.FsIdentifier);
2528
0
      DBG_INFO("SMB_QUERY_POSIX_FS_INFO successful\n");
2529
0
      break;
2530
0
    }
2531
2532
0
    case SMB_QUERY_POSIX_WHOAMI:
2533
0
    {
2534
0
      uint32_t flags = 0;
2535
0
      uint32_t sid_bytes;
2536
0
      uint32_t i;
2537
2538
0
      if (!lp_smb1_unix_extensions()) {
2539
0
        return NT_STATUS_INVALID_LEVEL;
2540
0
      }
2541
2542
0
      if (max_data_bytes < 40) {
2543
0
        return NT_STATUS_BUFFER_TOO_SMALL;
2544
0
      }
2545
2546
0
      if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
2547
0
        flags |= SMB_WHOAMI_GUEST;
2548
0
      }
2549
2550
      /* NOTE: 8 bytes for UID/GID, irrespective of native
2551
       * platform size. This matches
2552
       * SMB_QUERY_FILE_UNIX_BASIC and friends.
2553
       */
2554
0
      data_len = 4 /* flags */
2555
0
          + 4 /* flag mask */
2556
0
          + 8 /* uid */
2557
0
          + 8 /* gid */
2558
0
          + 4 /* ngroups */
2559
0
          + 4 /* num_sids */
2560
0
          + 4 /* SID bytes */
2561
0
          + 4 /* pad/reserved */
2562
0
          + (conn->session_info->unix_token->ngroups * 8)
2563
        /* groups list */
2564
0
          + (conn->session_info->security_token->num_sids *
2565
0
            SID_MAX_SIZE)
2566
0
        /* SID list */;
2567
2568
0
      SIVAL(pdata, 0, flags);
2569
0
      SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2570
0
      SBIG_UINT(pdata, 8,
2571
0
          (uint64_t)conn->session_info->unix_token->uid);
2572
0
      SBIG_UINT(pdata, 16,
2573
0
          (uint64_t)conn->session_info->unix_token->gid);
2574
2575
2576
0
      if (data_len >= max_data_bytes) {
2577
        /* Potential overflow, skip the GIDs and SIDs. */
2578
2579
0
        SIVAL(pdata, 24, 0); /* num_groups */
2580
0
        SIVAL(pdata, 28, 0); /* num_sids */
2581
0
        SIVAL(pdata, 32, 0); /* num_sid_bytes */
2582
0
        SIVAL(pdata, 36, 0); /* reserved */
2583
2584
0
        data_len = 40;
2585
0
        break;
2586
0
      }
2587
2588
0
      SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
2589
0
      SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
2590
2591
      /* We walk the SID list twice, but this call is fairly
2592
       * infrequent, and I don't expect that it's performance
2593
       * sensitive -- jpeach
2594
       */
2595
0
      for (i = 0, sid_bytes = 0;
2596
0
           i < conn->session_info->security_token->num_sids; ++i) {
2597
0
        sid_bytes += ndr_size_dom_sid(
2598
0
          &conn->session_info->security_token->sids[i],
2599
0
          0);
2600
0
      }
2601
2602
      /* SID list byte count */
2603
0
      SIVAL(pdata, 32, sid_bytes);
2604
2605
      /* 4 bytes pad/reserved - must be zero */
2606
0
      SIVAL(pdata, 36, 0);
2607
0
      data_len = 40;
2608
2609
      /* GID list */
2610
0
      for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
2611
0
        SBIG_UINT(pdata, data_len,
2612
0
            (uint64_t)conn->session_info->unix_token->groups[i]);
2613
0
        data_len += 8;
2614
0
      }
2615
2616
      /* SID list */
2617
0
      for (i = 0;
2618
0
          i < conn->session_info->security_token->num_sids; ++i) {
2619
0
        int sid_len = ndr_size_dom_sid(
2620
0
          &conn->session_info->security_token->sids[i],
2621
0
          0);
2622
2623
0
        sid_linearize((uint8_t *)(pdata + data_len),
2624
0
                sid_len,
2625
0
            &conn->session_info->security_token->sids[i]);
2626
0
        data_len += sid_len;
2627
0
      }
2628
2629
0
      break;
2630
0
    }
2631
2632
0
    case SMB_MAC_QUERY_FS_INFO:
2633
      /*
2634
       * Thursby MAC extension... ONLY on NTFS filesystems
2635
       * once we do streams then we don't need this
2636
       */
2637
0
      if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2638
0
        data_len = 88;
2639
0
        SIVAL(pdata,84,0x100); /* Don't support mac... */
2640
0
        break;
2641
0
      }
2642
2643
0
      FALL_THROUGH;
2644
0
    default:
2645
0
      return NT_STATUS_INVALID_LEVEL;
2646
0
  }
2647
2648
0
  *ret_data_len = data_len;
2649
0
  return status;
2650
0
}
2651
2652
NTSTATUS smb_set_fsquota(connection_struct *conn,
2653
       struct smb_request *req,
2654
       files_struct *fsp,
2655
       const DATA_BLOB *qdata)
2656
0
{
2657
0
  const struct loadparm_substitution *lp_sub =
2658
0
    loadparm_s3_global_substitution();
2659
0
  NTSTATUS status;
2660
0
  SMB_NTQUOTA_STRUCT quotas;
2661
2662
0
  ZERO_STRUCT(quotas);
2663
2664
  /* access check */
2665
0
  if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
2666
0
    DBG_NOTICE("access_denied service [%s] user [%s]\n",
2667
0
         lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2668
0
         conn->session_info->unix_info->unix_name);
2669
0
    return NT_STATUS_ACCESS_DENIED;
2670
0
  }
2671
2672
0
  if (!check_fsp_ntquota_handle(conn, req,
2673
0
              fsp)) {
2674
0
    DBG_WARNING("no valid QUOTA HANDLE\n");
2675
0
    return NT_STATUS_INVALID_HANDLE;
2676
0
  }
2677
2678
  /* note: normally there're 48 bytes,
2679
   * but we didn't use the last 6 bytes for now
2680
   * --metze
2681
   */
2682
0
  if (qdata->length < 42) {
2683
0
    DBG_ERR("requires total_data(%zu) >= 42 bytes!\n",
2684
0
      qdata->length);
2685
0
    return NT_STATUS_INVALID_PARAMETER;
2686
0
  }
2687
2688
  /* unknown_1 24 NULL bytes in pdata*/
2689
2690
  /* the soft quotas 8 bytes (uint64_t)*/
2691
0
  quotas.softlim = BVAL(qdata->data,24);
2692
2693
  /* the hard quotas 8 bytes (uint64_t)*/
2694
0
  quotas.hardlim = BVAL(qdata->data,32);
2695
2696
  /* quota_flags 2 bytes **/
2697
0
  quotas.qflags = SVAL(qdata->data,40);
2698
2699
  /* unknown_2 6 NULL bytes follow*/
2700
2701
  /* now set the quotas */
2702
0
  if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2703
0
    DBG_WARNING("vfs_set_ntquota() failed for service [%s]\n",
2704
0
          lp_servicename(talloc_tos(), lp_sub, SNUM(conn)));
2705
0
    status =  map_nt_error_from_unix(errno);
2706
0
  } else {
2707
0
    status = NT_STATUS_OK;
2708
0
  }
2709
0
  return status;
2710
0
}
2711
2712
NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
2713
                                struct smb_request *req,
2714
                                TALLOC_CTX *mem_ctx,
2715
                                uint16_t info_level,
2716
                                files_struct *fsp,
2717
        const DATA_BLOB *pdata)
2718
0
{
2719
0
  switch (info_level) {
2720
0
    case SMB_FS_QUOTA_INFORMATION:
2721
0
    {
2722
0
      return smb_set_fsquota(conn,
2723
0
            req,
2724
0
            fsp,
2725
0
            pdata);
2726
0
    }
2727
2728
0
    default:
2729
0
      break;
2730
0
  }
2731
0
  return NT_STATUS_INVALID_LEVEL;
2732
0
}
2733
2734
/****************************************************************************
2735
 Store the FILE_UNIX_BASIC info.
2736
****************************************************************************/
2737
2738
char *store_file_unix_basic(connection_struct *conn,
2739
          char *pdata,
2740
          files_struct *fsp,
2741
          const SMB_STRUCT_STAT *psbuf)
2742
0
{
2743
0
  dev_t devno;
2744
2745
0
  DBG_DEBUG("SMB_QUERY_FILE_UNIX_BASIC\n");
2746
0
  DBG_NOTICE("st_mode=%o\n", (int)psbuf->st_ex_mode);
2747
2748
0
  SOFF_T(pdata,0,get_file_size_stat(psbuf));             /* File size 64 Bit */
2749
0
  pdata += 8;
2750
2751
0
  SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
2752
0
  pdata += 8;
2753
2754
0
  put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime);       /* Change Time 64 Bit */
2755
0
  put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime);     /* Last access time 64 Bit */
2756
0
  put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime);    /* Last modification time 64 Bit */
2757
0
  pdata += 24;
2758
2759
0
  SIVAL(pdata,0,psbuf->st_ex_uid);               /* user id for the owner */
2760
0
  SIVAL(pdata,4,0);
2761
0
  pdata += 8;
2762
2763
0
  SIVAL(pdata,0,psbuf->st_ex_gid);               /* group id of owner */
2764
0
  SIVAL(pdata,4,0);
2765
0
  pdata += 8;
2766
2767
0
  SIVAL(pdata, 0, unix_filetype_to_wire(psbuf->st_ex_mode));
2768
0
  pdata += 4;
2769
2770
0
  if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
2771
0
    devno = psbuf->st_ex_rdev;
2772
0
  } else {
2773
0
    devno = psbuf->st_ex_dev;
2774
0
  }
2775
2776
0
  SIVAL(pdata,0,unix_dev_major(devno));   /* Major device number if type is device */
2777
0
  SIVAL(pdata,4,0);
2778
0
  pdata += 8;
2779
2780
0
  SIVAL(pdata,0,unix_dev_minor(devno));   /* Minor device number if type is device */
2781
0
  SIVAL(pdata,4,0);
2782
0
  pdata += 8;
2783
2784
0
  SINO_T_VAL(pdata, 0, psbuf->st_ex_ino);   /* inode number */
2785
0
  pdata += 8;
2786
2787
0
  SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode));     /* Standard UNIX file permissions */
2788
0
  SIVAL(pdata,4,0);
2789
0
  pdata += 8;
2790
2791
0
  SIVAL(pdata,0,psbuf->st_ex_nlink);             /* number of hard links */
2792
0
  SIVAL(pdata,4,0);
2793
0
  pdata += 8;
2794
2795
0
  return pdata;
2796
0
}
2797
2798
/* Forward and reverse mappings from the UNIX_INFO2 file flags field and
2799
 * the chflags(2) (or equivalent) flags.
2800
 *
2801
 * XXX: this really should be behind the VFS interface. To do this, we would
2802
 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
2803
 * Each VFS module could then implement its own mapping as appropriate for the
2804
 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
2805
 */
2806
static const struct {unsigned stat_fflag; unsigned smb_fflag;}
2807
  info2_flags_map[] =
2808
{
2809
#ifdef UF_NODUMP
2810
    { UF_NODUMP, EXT_DO_NOT_BACKUP },
2811
#endif
2812
2813
#ifdef UF_IMMUTABLE
2814
    { UF_IMMUTABLE, EXT_IMMUTABLE },
2815
#endif
2816
2817
#ifdef UF_APPEND
2818
    { UF_APPEND, EXT_OPEN_APPEND_ONLY },
2819
#endif
2820
2821
#ifdef UF_HIDDEN
2822
    { UF_HIDDEN, EXT_HIDDEN },
2823
#endif
2824
2825
    /* Do not remove. We need to guarantee that this array has at least one
2826
     * entry to build on HP-UX.
2827
     */
2828
    { 0, 0 }
2829
2830
};
2831
2832
static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
2833
        uint32_t *smb_fflags, uint32_t *smb_fmask)
2834
0
{
2835
0
  size_t i;
2836
2837
0
  for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2838
0
      *smb_fmask |= info2_flags_map[i].smb_fflag;
2839
0
      if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
2840
0
        *smb_fflags |= info2_flags_map[i].smb_fflag;
2841
0
      }
2842
0
  }
2843
0
}
2844
2845
bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
2846
           const uint32_t smb_fflags,
2847
           const uint32_t smb_fmask,
2848
           int *stat_fflags)
2849
0
{
2850
0
  uint32_t max_fmask = 0;
2851
0
  size_t i;
2852
2853
0
  *stat_fflags = psbuf->st_ex_flags;
2854
2855
  /* For each flags requested in smb_fmask, check the state of the
2856
   * corresponding flag in smb_fflags and set or clear the matching
2857
   * stat flag.
2858
   */
2859
2860
0
  for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2861
0
      max_fmask |= info2_flags_map[i].smb_fflag;
2862
0
      if (smb_fmask & info2_flags_map[i].smb_fflag) {
2863
0
        if (smb_fflags & info2_flags_map[i].smb_fflag) {
2864
0
          *stat_fflags |= info2_flags_map[i].stat_fflag;
2865
0
        } else {
2866
0
          *stat_fflags &= ~info2_flags_map[i].stat_fflag;
2867
0
        }
2868
0
      }
2869
0
  }
2870
2871
  /* If smb_fmask is asking to set any bits that are not supported by
2872
   * our flag mappings, we should fail.
2873
   */
2874
0
  if ((smb_fmask & max_fmask) != smb_fmask) {
2875
0
    return False;
2876
0
  }
2877
2878
0
  return True;
2879
0
}
2880
2881
2882
/* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
2883
 * of file flags and birth (create) time.
2884
 */
2885
char *store_file_unix_basic_info2(connection_struct *conn,
2886
          char *pdata,
2887
          files_struct *fsp,
2888
          const SMB_STRUCT_STAT *psbuf)
2889
0
{
2890
0
  uint32_t file_flags = 0;
2891
0
  uint32_t flags_mask = 0;
2892
2893
0
  pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
2894
2895
  /* Create (birth) time 64 bit */
2896
0
  put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
2897
0
  pdata += 8;
2898
2899
0
  map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
2900
0
  SIVAL(pdata, 0, file_flags); /* flags */
2901
0
  SIVAL(pdata, 4, flags_mask); /* mask */
2902
0
  pdata += 8;
2903
2904
0
  return pdata;
2905
0
}
2906
2907
static NTSTATUS marshall_stream_info(unsigned int num_streams,
2908
             const struct stream_struct *streams,
2909
             char *data,
2910
             unsigned int max_data_bytes,
2911
             unsigned int *data_size)
2912
0
{
2913
0
  unsigned int i;
2914
0
  unsigned int ofs = 0;
2915
2916
0
  if (max_data_bytes < 32) {
2917
0
    return NT_STATUS_INFO_LENGTH_MISMATCH;
2918
0
  }
2919
2920
0
  for (i = 0; i < num_streams; i++) {
2921
0
    unsigned int next_offset;
2922
0
    size_t namelen;
2923
0
    smb_ucs2_t *namebuf;
2924
2925
0
    if (!push_ucs2_talloc(talloc_tos(), &namebuf,
2926
0
              streams[i].name, &namelen) ||
2927
0
        namelen <= 2)
2928
0
    {
2929
0
      return NT_STATUS_INVALID_PARAMETER;
2930
0
    }
2931
2932
    /*
2933
     * name_buf is now null-terminated, we need to marshall as not
2934
     * terminated
2935
     */
2936
2937
0
    namelen -= 2;
2938
2939
    /*
2940
     * We cannot overflow ...
2941
     */
2942
0
    if ((ofs + 24 + namelen) > max_data_bytes) {
2943
0
      DEBUG(10, ("refusing to overflow reply at stream %u\n",
2944
0
        i));
2945
0
      TALLOC_FREE(namebuf);
2946
0
      return STATUS_BUFFER_OVERFLOW;
2947
0
    }
2948
2949
0
    SIVAL(data, ofs+4, namelen);
2950
0
    SOFF_T(data, ofs+8, streams[i].size);
2951
0
    SOFF_T(data, ofs+16, streams[i].alloc_size);
2952
0
    memcpy(data+ofs+24, namebuf, namelen);
2953
0
    TALLOC_FREE(namebuf);
2954
2955
0
    next_offset = ofs + 24 + namelen;
2956
2957
0
    if (i == num_streams-1) {
2958
0
      SIVAL(data, ofs, 0);
2959
0
    }
2960
0
    else {
2961
0
      unsigned int align = ndr_align_size(next_offset, 8);
2962
2963
0
      if ((next_offset + align) > max_data_bytes) {
2964
0
        DEBUG(10, ("refusing to overflow align "
2965
0
          "reply at stream %u\n",
2966
0
          i));
2967
0
        TALLOC_FREE(namebuf);
2968
0
        return STATUS_BUFFER_OVERFLOW;
2969
0
      }
2970
2971
0
      memset(data+next_offset, 0, align);
2972
0
      next_offset += align;
2973
2974
0
      SIVAL(data, ofs, next_offset - ofs);
2975
0
      ofs = next_offset;
2976
0
    }
2977
2978
0
    ofs = next_offset;
2979
0
  }
2980
2981
0
  DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
2982
2983
0
  *data_size = ofs;
2984
2985
0
  return NT_STATUS_OK;
2986
0
}
2987
2988
NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
2989
             TALLOC_CTX *mem_ctx,
2990
             struct smb_request *req,
2991
             uint16_t info_level,
2992
             files_struct *fsp,
2993
             struct smb_filename *smb_fname,
2994
             bool delete_pending,
2995
             struct ea_list *ea_list,
2996
             uint16_t flags2,
2997
             unsigned int max_data_bytes,
2998
             size_t *fixed_portion,
2999
             char **ppdata,
3000
             unsigned int *pdata_size)
3001
0
{
3002
0
  char *pdata = *ppdata;
3003
0
  char *dstart, *dend;
3004
0
  unsigned int data_size;
3005
0
  struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
3006
0
  SMB_STRUCT_STAT *psbuf = NULL;
3007
0
  struct files_struct *base_fsp = NULL;
3008
0
  char *p;
3009
0
  char *base_name;
3010
0
  char *dos_fname;
3011
0
  int mode;
3012
0
  int nlink;
3013
0
  NTSTATUS status;
3014
0
  uint64_t file_size = 0;
3015
0
  uint64_t pos = 0;
3016
0
  uint64_t allocation_size = 0;
3017
0
  uint64_t file_id = 0;
3018
0
  uint32_t access_mask = 0;
3019
0
  size_t len = 0;
3020
3021
0
  if (INFO_LEVEL_IS_UNIX(info_level)) {
3022
0
    bool ok = false;
3023
3024
0
    if (lp_smb1_unix_extensions() && req->posix_pathnames) {
3025
0
      DBG_DEBUG("SMB1 unix extensions activated\n");
3026
0
      ok = true;
3027
0
    }
3028
3029
0
    if (conn_using_smb2(conn->sconn) &&
3030
0
        fsp->fsp_flags.posix_open)
3031
0
    {
3032
0
      DBG_DEBUG("SMB2 posix open\n");
3033
0
      ok = true;
3034
0
    }
3035
3036
0
    if (!ok) {
3037
0
      return NT_STATUS_INVALID_LEVEL;
3038
0
    }
3039
0
  }
3040
3041
0
  DBG_INFO("%s (%s) level=%d max_data=%u\n",
3042
0
     smb_fname_str_dbg(smb_fname),
3043
0
     fsp_fnum_dbg(fsp),
3044
0
     info_level, max_data_bytes);
3045
3046
0
  smb_fname = fsp->fsp_name;
3047
0
  mode = fdos_mode(fsp);
3048
0
  psbuf = &smb_fname->st;
3049
3050
0
  nlink = psbuf->st_ex_nlink;
3051
3052
0
  if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
3053
0
    nlink = 1;
3054
0
  }
3055
3056
0
  if ((nlink > 0) && delete_pending) {
3057
0
    nlink -= 1;
3058
0
  }
3059
3060
0
  if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3061
0
    return NT_STATUS_INVALID_PARAMETER;
3062
0
  }
3063
3064
0
  data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3065
0
  *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3066
0
  if (*ppdata == NULL) {
3067
0
    return NT_STATUS_NO_MEMORY;
3068
0
  }
3069
0
  pdata = *ppdata;
3070
0
  dstart = pdata;
3071
0
  dend = dstart + data_size - 1;
3072
3073
0
  create_time_ts = get_create_timespec(conn, fsp, smb_fname);
3074
0
  mtime_ts = psbuf->st_ex_mtime;
3075
0
  atime_ts = psbuf->st_ex_atime;
3076
0
  ctime_ts = psbuf->st_ex_ctime;
3077
3078
0
  if (lp_dos_filetime_resolution(SNUM(conn))) {
3079
0
    dos_filetime_timespec(&create_time_ts);
3080
0
    dos_filetime_timespec(&mtime_ts);
3081
0
    dos_filetime_timespec(&atime_ts);
3082
0
    dos_filetime_timespec(&ctime_ts);
3083
0
  }
3084
3085
0
  p = strrchr_m(smb_fname->base_name,'/');
3086
0
  if (p == NULL) {
3087
0
    base_name = smb_fname->base_name;
3088
0
  } else {
3089
0
    base_name = p+1;
3090
0
  }
3091
3092
  /* NT expects the name to be in an exact form of the *full*
3093
     filename. See the trans2 torture test */
3094
0
  if (ISDOT(base_name)) {
3095
0
    dos_fname = talloc_strdup(mem_ctx, "\\");
3096
0
    if (!dos_fname) {
3097
0
      return NT_STATUS_NO_MEMORY;
3098
0
    }
3099
0
  } else {
3100
0
    dos_fname = talloc_asprintf(mem_ctx,
3101
0
        "\\%s",
3102
0
        smb_fname->base_name);
3103
0
    if (!dos_fname) {
3104
0
      return NT_STATUS_NO_MEMORY;
3105
0
    }
3106
0
    if (is_named_stream(smb_fname)) {
3107
0
      dos_fname = talloc_asprintf(dos_fname, "%s",
3108
0
                smb_fname->stream_name);
3109
0
      if (!dos_fname) {
3110
0
        return NT_STATUS_NO_MEMORY;
3111
0
      }
3112
0
    }
3113
3114
0
    string_replace(dos_fname, '/', '\\');
3115
0
  }
3116
3117
0
  allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
3118
3119
0
  if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
3120
    /* Do we have this path open ? */
3121
0
    struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
3122
0
    files_struct *fsp1 = file_find_di_first(
3123
0
      conn->sconn, fileid, true);
3124
0
    if (fsp1 && fsp1->initial_allocation_size) {
3125
0
      allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
3126
0
    }
3127
0
  }
3128
3129
0
  if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
3130
0
    file_size = get_file_size_stat(psbuf);
3131
0
  }
3132
3133
0
  if (fsp) {
3134
0
    pos = fh_get_position_information(fsp->fh);
3135
0
  }
3136
3137
0
  if (fsp) {
3138
0
    access_mask = fsp->access_mask;
3139
0
  } else {
3140
    /* GENERIC_EXECUTE mapping from Windows */
3141
0
    access_mask = 0x12019F;
3142
0
  }
3143
3144
  /* This should be an index number - looks like
3145
     dev/ino to me :-)
3146
3147
     I think this causes us to fail the IFSKIT
3148
     BasicFileInformationTest. -tpot */
3149
0
  base_fsp = metadata_fsp(fsp);
3150
0
  file_id = SMB_VFS_FS_FILE_ID(conn, &base_fsp->fsp_name->st);
3151
3152
0
  *fixed_portion = 0;
3153
3154
0
  switch (info_level) {
3155
0
    case SMB_INFO_STANDARD:
3156
0
      DBG_DEBUG("SMB_INFO_STANDARD\n");
3157
0
      data_size = 22;
3158
0
      srv_put_dos_date2_ts(pdata,
3159
0
               l1_fdateCreation,
3160
0
               create_time_ts);
3161
0
      srv_put_dos_date2_ts(pdata,
3162
0
               l1_fdateLastAccess,
3163
0
               atime_ts);
3164
0
      srv_put_dos_date2_ts(pdata,
3165
0
               l1_fdateLastWrite,
3166
0
               mtime_ts); /* write time */
3167
0
      SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
3168
0
      SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
3169
0
      SSVAL(pdata,l1_attrFile,mode);
3170
0
      break;
3171
3172
0
    case SMB_INFO_QUERY_EA_SIZE:
3173
0
    {
3174
0
      unsigned int ea_size =
3175
0
          estimate_ea_size(smb_fname->fsp);
3176
0
      DBG_DEBUG("SMB_INFO_QUERY_EA_SIZE\n");
3177
0
      data_size = 26;
3178
0
      srv_put_dos_date2_ts(pdata, 0, create_time_ts);
3179
0
      srv_put_dos_date2_ts(pdata, 4, atime_ts);
3180
0
      srv_put_dos_date2_ts(pdata,
3181
0
               8,
3182
0
               mtime_ts); /* write time */
3183
0
      SIVAL(pdata,12,(uint32_t)file_size);
3184
0
      SIVAL(pdata,16,(uint32_t)allocation_size);
3185
0
      SSVAL(pdata,20,mode);
3186
0
      SIVAL(pdata,22,ea_size);
3187
0
      break;
3188
0
    }
3189
3190
0
    case SMB_INFO_IS_NAME_VALID:
3191
0
      DBG_DEBUG("SMB_INFO_IS_NAME_VALID\n");
3192
0
      if (fsp) {
3193
        /* os/2 needs this ? really ?*/
3194
0
        return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
3195
0
      }
3196
      /* This is only reached for qpathinfo */
3197
0
      data_size = 0;
3198
0
      break;
3199
3200
0
    case SMB_INFO_QUERY_EAS_FROM_LIST:
3201
0
    {
3202
0
      size_t total_ea_len = 0;
3203
0
      struct ea_list *ea_file_list = NULL;
3204
0
      DBG_DEBUG("SMB_INFO_QUERY_EAS_FROM_LIST\n");
3205
3206
0
      status =
3207
0
          get_ea_list_from_fsp(mem_ctx,
3208
0
              smb_fname->fsp,
3209
0
              &total_ea_len, &ea_file_list);
3210
0
      if (!NT_STATUS_IS_OK(status)) {
3211
0
        return status;
3212
0
      }
3213
3214
0
      ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3215
3216
0
      if (!ea_list || (total_ea_len > data_size)) {
3217
0
        data_size = 4;
3218
0
        SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3219
0
        break;
3220
0
      }
3221
3222
0
      data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3223
0
      break;
3224
0
    }
3225
3226
0
    case SMB_INFO_QUERY_ALL_EAS:
3227
0
    {
3228
      /* We have data_size bytes to put EA's into. */
3229
0
      size_t total_ea_len = 0;
3230
0
      DBG_DEBUG(" SMB_INFO_QUERY_ALL_EAS\n");
3231
3232
0
      status = get_ea_list_from_fsp(mem_ctx,
3233
0
              smb_fname->fsp,
3234
0
              &total_ea_len, &ea_list);
3235
0
      if (!NT_STATUS_IS_OK(status)) {
3236
0
        return status;
3237
0
      }
3238
3239
0
      if (!ea_list || (total_ea_len > data_size)) {
3240
0
        data_size = 4;
3241
0
        SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3242
0
        break;
3243
0
      }
3244
3245
0
      data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3246
0
      break;
3247
0
    }
3248
3249
0
    case SMB2_FILE_FULL_EA_INFORMATION:
3250
0
    {
3251
      /* We have data_size bytes to put EA's into. */
3252
0
      size_t total_ea_len = 0;
3253
0
      struct ea_list *ea_file_list = NULL;
3254
3255
0
      DBG_DEBUG("SMB2_INFO_QUERY_ALL_EAS\n");
3256
3257
      /*TODO: add filtering and index handling */
3258
3259
0
      status  =
3260
0
        get_ea_list_from_fsp(mem_ctx,
3261
0
              smb_fname->fsp,
3262
0
              &total_ea_len, &ea_file_list);
3263
0
      if (!NT_STATUS_IS_OK(status)) {
3264
0
        return status;
3265
0
      }
3266
0
      if (!ea_file_list) {
3267
0
        return NT_STATUS_NO_EAS_ON_FILE;
3268
0
      }
3269
3270
0
      status = fill_ea_chained_buffer(mem_ctx,
3271
0
              pdata,
3272
0
              data_size,
3273
0
              &data_size,
3274
0
              conn, ea_file_list);
3275
0
      if (!NT_STATUS_IS_OK(status)) {
3276
0
        return status;
3277
0
      }
3278
0
      break;
3279
0
    }
3280
3281
0
    case SMB_FILE_BASIC_INFORMATION:
3282
0
    case SMB_QUERY_FILE_BASIC_INFO:
3283
3284
0
      if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3285
0
        DBG_DEBUG("SMB_QUERY_FILE_BASIC_INFO\n");
3286
0
        data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3287
0
      } else {
3288
0
        DBG_DEBUG("SMB_FILE_BASIC_INFORMATION\n");
3289
0
        data_size = 40;
3290
0
        SIVAL(pdata,36,0);
3291
0
      }
3292
0
      put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3293
0
      put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3294
0
      put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3295
0
      put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3296
0
      SIVAL(pdata,32,mode);
3297
3298
0
      DBG_INFO("SMB_QFBI - create: %s access: %s "
3299
0
         "write: %s change: %s mode: %x\n",
3300
0
         ctime(&create_time_ts.tv_sec),
3301
0
         ctime(&atime_ts.tv_sec),
3302
0
         ctime(&mtime_ts.tv_sec),
3303
0
         ctime(&ctime_ts.tv_sec),
3304
0
         mode);
3305
0
      *fixed_portion = data_size;
3306
0
      break;
3307
3308
0
    case SMB_FILE_STANDARD_INFORMATION:
3309
0
    case SMB_QUERY_FILE_STANDARD_INFO:
3310
3311
0
      DBG_DEBUG("SMB_FILE_STANDARD_INFORMATION\n");
3312
0
      data_size = 24;
3313
0
      SOFF_T(pdata,0,allocation_size);
3314
0
      SOFF_T(pdata,8,file_size);
3315
0
      SIVAL(pdata,16,nlink);
3316
0
      SCVAL(pdata,20,delete_pending?1:0);
3317
0
      SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3318
0
      SSVAL(pdata,22,0); /* Padding. */
3319
0
      *fixed_portion = 24;
3320
0
      break;
3321
3322
0
    case SMB_FILE_EA_INFORMATION:
3323
0
    case SMB_QUERY_FILE_EA_INFO:
3324
0
    {
3325
0
      unsigned int ea_size =
3326
0
          estimate_ea_size(smb_fname->fsp);
3327
0
      DBG_DEBUG("SMB_FILE_EA_INFORMATION\n");
3328
0
      data_size = 4;
3329
0
      *fixed_portion = 4;
3330
0
      SIVAL(pdata,0,ea_size);
3331
0
      break;
3332
0
    }
3333
3334
    /* Get the 8.3 name - used if NT SMB was negotiated. */
3335
0
    case SMB_QUERY_FILE_ALT_NAME_INFO:
3336
0
    case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3337
0
    {
3338
0
      char mangled_name[13];
3339
0
      DBG_DEBUG("SMB_FILE_ALTERNATE_NAME_INFORMATION\n");
3340
0
      if (!name_to_8_3(base_name,mangled_name,
3341
0
            True,conn->params)) {
3342
0
        return NT_STATUS_NO_MEMORY;
3343
0
      }
3344
0
      status = srvstr_push(dstart, flags2,
3345
0
            pdata+4, mangled_name,
3346
0
            PTR_DIFF(dend, pdata+4),
3347
0
            STR_UNICODE, &len);
3348
0
      if (!NT_STATUS_IS_OK(status)) {
3349
0
        return status;
3350
0
      }
3351
0
      data_size = 4 + len;
3352
0
      SIVAL(pdata,0,len);
3353
0
      *fixed_portion = 8;
3354
0
      break;
3355
0
    }
3356
3357
0
    case SMB_QUERY_FILE_NAME_INFO:
3358
0
    {
3359
      /*
3360
        this must be *exactly* right for ACLs on mapped drives to work
3361
       */
3362
0
      status = srvstr_push(dstart, flags2,
3363
0
            pdata+4, dos_fname,
3364
0
            PTR_DIFF(dend, pdata+4),
3365
0
            STR_UNICODE, &len);
3366
0
      if (!NT_STATUS_IS_OK(status)) {
3367
0
        return status;
3368
0
      }
3369
0
      DBG_DEBUG("SMB_QUERY_FILE_NAME_INFO\n");
3370
0
      data_size = 4 + len;
3371
0
      SIVAL(pdata,0,len);
3372
0
      break;
3373
0
    }
3374
3375
0
    case SMB_FILE_NORMALIZED_NAME_INFORMATION:
3376
0
    {
3377
0
      char *nfname = NULL;
3378
3379
0
      if (fsp == NULL ||
3380
0
          !conn_using_smb2(fsp->conn->sconn)) {
3381
0
        return NT_STATUS_INVALID_LEVEL;
3382
0
      }
3383
3384
0
      nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
3385
0
      if (nfname == NULL) {
3386
0
        return NT_STATUS_NO_MEMORY;
3387
0
      }
3388
3389
0
      if (ISDOT(nfname)) {
3390
0
        nfname[0] = '\0';
3391
0
      }
3392
0
      string_replace(nfname, '/', '\\');
3393
3394
0
      if (fsp_is_alternate_stream(fsp)) {
3395
0
        const char *s = smb_fname->stream_name;
3396
0
        const char *e = NULL;
3397
0
        size_t n;
3398
3399
0
        SMB_ASSERT(s[0] != '\0');
3400
3401
        /*
3402
         * smb_fname->stream_name is in form
3403
         * of ':StrEam:$DATA', but we should only
3404
         * append ':StrEam' here.
3405
         */
3406
3407
0
        e = strchr(&s[1], ':');
3408
0
        if (e == NULL) {
3409
0
          n = strlen(s);
3410
0
        } else {
3411
0
          n = PTR_DIFF(e, s);
3412
0
        }
3413
0
        nfname = talloc_strndup_append(nfname, s, n);
3414
0
        if (nfname == NULL) {
3415
0
          return NT_STATUS_NO_MEMORY;
3416
0
        }
3417
0
      }
3418
3419
0
      status = srvstr_push(dstart, flags2,
3420
0
            pdata+4, nfname,
3421
0
            PTR_DIFF(dend, pdata+4),
3422
0
            STR_UNICODE, &len);
3423
0
      if (!NT_STATUS_IS_OK(status)) {
3424
0
        return status;
3425
0
      }
3426
0
      DBG_DEBUG("SMB_FILE_NORMALIZED_NAME_INFORMATION\n");
3427
0
      data_size = 4 + len;
3428
0
      SIVAL(pdata,0,len);
3429
0
      *fixed_portion = 8;
3430
0
      break;
3431
0
    }
3432
3433
0
    case SMB_FILE_ALLOCATION_INFORMATION:
3434
0
    case SMB_QUERY_FILE_ALLOCATION_INFO:
3435
0
      DBG_DEBUG("SMB_FILE_ALLOCATION_INFORMATION\n");
3436
0
      data_size = 8;
3437
0
      SOFF_T(pdata,0,allocation_size);
3438
0
      break;
3439
3440
0
    case SMB_FILE_END_OF_FILE_INFORMATION:
3441
0
    case SMB_QUERY_FILE_END_OF_FILEINFO:
3442
0
      DBG_DEBUG("SMB_FILE_END_OF_FILE_INFORMATION\n");
3443
0
      data_size = 8;
3444
0
      SOFF_T(pdata,0,file_size);
3445
0
      break;
3446
3447
0
    case SMB_QUERY_FILE_ALL_INFO:
3448
0
    case SMB_FILE_ALL_INFORMATION:
3449
0
    {
3450
0
      unsigned int ea_size =
3451
0
          estimate_ea_size(smb_fname->fsp);
3452
0
      DBG_DEBUG("SMB_FILE_ALL_INFORMATION\n");
3453
0
      put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3454
0
      put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3455
0
      put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3456
0
      put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3457
0
      SIVAL(pdata,32,mode);
3458
0
      SIVAL(pdata,36,0); /* padding. */
3459
0
      pdata += 40;
3460
0
      SOFF_T(pdata,0,allocation_size);
3461
0
      SOFF_T(pdata,8,file_size);
3462
0
      SIVAL(pdata,16,nlink);
3463
0
      SCVAL(pdata,20,delete_pending);
3464
0
      SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3465
0
      SSVAL(pdata,22,0);
3466
0
      pdata += 24;
3467
0
      SIVAL(pdata,0,ea_size);
3468
0
      pdata += 4; /* EA info */
3469
0
      status = srvstr_push(dstart, flags2,
3470
0
            pdata+4, dos_fname,
3471
0
            PTR_DIFF(dend, pdata+4),
3472
0
            STR_UNICODE, &len);
3473
0
      if (!NT_STATUS_IS_OK(status)) {
3474
0
        return status;
3475
0
      }
3476
0
      SIVAL(pdata,0,len);
3477
0
      pdata += 4 + len;
3478
0
      data_size = PTR_DIFF(pdata,(*ppdata));
3479
0
      *fixed_portion = 10;
3480
0
      break;
3481
0
    }
3482
3483
0
    case SMB2_FILE_ALL_INFORMATION:
3484
0
    {
3485
0
      unsigned int ea_size =
3486
0
          estimate_ea_size(smb_fname->fsp);
3487
0
      DBG_DEBUG("SMB2_FILE_ALL_INFORMATION\n");
3488
0
      put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
3489
0
      put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
3490
0
      put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
3491
0
      put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
3492
0
      SIVAL(pdata, 0x20, mode);
3493
0
      SIVAL(pdata, 0x24, 0); /* padding. */
3494
0
      SBVAL(pdata, 0x28, allocation_size);
3495
0
      SBVAL(pdata, 0x30, file_size);
3496
0
      SIVAL(pdata, 0x38, nlink);
3497
0
      SCVAL(pdata, 0x3C, delete_pending);
3498
0
      SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3499
0
      SSVAL(pdata, 0x3E, 0); /* padding */
3500
0
      SBVAL(pdata, 0x40, file_id);
3501
0
      SIVAL(pdata, 0x48, ea_size);
3502
0
      SIVAL(pdata, 0x4C, access_mask);
3503
0
      SBVAL(pdata, 0x50, pos);
3504
0
      SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
3505
0
      SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
3506
3507
0
      pdata += 0x60;
3508
3509
0
      status = srvstr_push(dstart, flags2,
3510
0
            pdata+4, dos_fname,
3511
0
            PTR_DIFF(dend, pdata+4),
3512
0
            STR_UNICODE, &len);
3513
0
      if (!NT_STATUS_IS_OK(status)) {
3514
0
        return status;
3515
0
      }
3516
0
      SIVAL(pdata,0,len);
3517
0
      pdata += 4 + len;
3518
0
      data_size = PTR_DIFF(pdata,(*ppdata));
3519
0
      *fixed_portion = 104;
3520
0
      break;
3521
0
    }
3522
0
    case SMB_FILE_INTERNAL_INFORMATION:
3523
3524
0
      DBG_DEBUG("SMB_FILE_INTERNAL_INFORMATION\n");
3525
0
      SBVAL(pdata, 0, file_id);
3526
0
      data_size = 8;
3527
0
      *fixed_portion = 8;
3528
0
      break;
3529
3530
0
    case SMB_FILE_ACCESS_INFORMATION:
3531
0
      DBG_DEBUG("SMB_FILE_ACCESS_INFORMATION\n");
3532
0
      SIVAL(pdata, 0, access_mask);
3533
0
      data_size = 4;
3534
0
      *fixed_portion = 4;
3535
0
      break;
3536
3537
0
    case SMB_FILE_NAME_INFORMATION:
3538
      /* Pathname with leading '\'. */
3539
0
      {
3540
0
        size_t byte_len;
3541
0
        byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3542
0
        DBG_DEBUG("SMB_FILE_NAME_INFORMATION\n");
3543
0
        SIVAL(pdata,0,byte_len);
3544
0
        data_size = 4 + byte_len;
3545
0
        break;
3546
0
      }
3547
3548
0
    case SMB_FILE_DISPOSITION_INFORMATION:
3549
0
      DBG_DEBUG("SMB_FILE_DISPOSITION_INFORMATION\n");
3550
0
      data_size = 1;
3551
0
      SCVAL(pdata,0,delete_pending);
3552
0
      *fixed_portion = 1;
3553
0
      break;
3554
3555
0
    case SMB_FILE_POSITION_INFORMATION:
3556
0
      DBG_DEBUG("SMB_FILE_POSITION_INFORMATION\n");
3557
0
      data_size = 8;
3558
0
      SOFF_T(pdata,0,pos);
3559
0
      *fixed_portion = 8;
3560
0
      break;
3561
3562
0
    case SMB_FILE_MODE_INFORMATION:
3563
0
      DBG_DEBUG("SMB_FILE_MODE_INFORMATION\n");
3564
0
      SIVAL(pdata,0,mode);
3565
0
      data_size = 4;
3566
0
      *fixed_portion = 4;
3567
0
      break;
3568
3569
0
    case SMB_FILE_ALIGNMENT_INFORMATION:
3570
0
      DBG_DEBUG("SMB_FILE_ALIGNMENT_INFORMATION\n");
3571
0
      SIVAL(pdata,0,0); /* No alignment needed. */
3572
0
      data_size = 4;
3573
0
      *fixed_portion = 4;
3574
0
      break;
3575
3576
    /*
3577
     * NT4 server just returns "invalid query" to this - if we try
3578
     * to answer it then NTws gets a BSOD! (tridge).  W2K seems to
3579
     * want this. JRA.
3580
     */
3581
    /* The first statement above is false - verified using Thursby
3582
     * client against NT4 -- gcolley.
3583
     */
3584
0
    case SMB_QUERY_FILE_STREAM_INFO:
3585
0
    case SMB_FILE_STREAM_INFORMATION: {
3586
0
      unsigned int num_streams = 0;
3587
0
      struct stream_struct *streams = NULL;
3588
3589
0
      DBG_DEBUG("SMB_FILE_STREAM_INFORMATION\n");
3590
3591
0
      if (is_ntfs_stream_smb_fname(smb_fname)) {
3592
0
        return NT_STATUS_INVALID_PARAMETER;
3593
0
      }
3594
3595
0
      status = vfs_fstreaminfo(fsp,
3596
0
            mem_ctx,
3597
0
            &num_streams,
3598
0
            &streams);
3599
3600
0
      if (!NT_STATUS_IS_OK(status)) {
3601
0
        DBG_DEBUG("could not get stream info: %s\n",
3602
0
            nt_errstr(status));
3603
0
        return status;
3604
0
      }
3605
3606
0
      status = marshall_stream_info(num_streams, streams,
3607
0
                  pdata, max_data_bytes,
3608
0
                  &data_size);
3609
3610
0
      if (!NT_STATUS_IS_OK(status)) {
3611
0
        DBG_DEBUG("marshall_stream_info failed: %s\n",
3612
0
            nt_errstr(status));
3613
0
        TALLOC_FREE(streams);
3614
0
        return status;
3615
0
      }
3616
3617
0
      TALLOC_FREE(streams);
3618
3619
0
      *fixed_portion = 32;
3620
3621
0
      break;
3622
0
    }
3623
0
    case SMB_QUERY_COMPRESSION_INFO:
3624
0
    case SMB_FILE_COMPRESSION_INFORMATION:
3625
0
      DBG_DEBUG("SMB_FILE_COMPRESSION_INFORMATION\n");
3626
0
      SOFF_T(pdata,0,file_size);
3627
0
      SIVAL(pdata,8,0); /* ??? */
3628
0
      SIVAL(pdata,12,0); /* ??? */
3629
0
      data_size = 16;
3630
0
      *fixed_portion = 16;
3631
0
      break;
3632
3633
0
    case SMB_FILE_NETWORK_OPEN_INFORMATION:
3634
0
      DBG_DEBUG("SMB_FILE_NETWORK_OPEN_INFORMATION\n");
3635
0
      put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3636
0
      put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3637
0
      put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3638
0
      put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3639
0
      SOFF_T(pdata,32,allocation_size);
3640
0
      SOFF_T(pdata,40,file_size);
3641
0
      SIVAL(pdata,48,mode);
3642
0
      SIVAL(pdata,52,0); /* ??? */
3643
0
      data_size = 56;
3644
0
      *fixed_portion = 56;
3645
0
      break;
3646
3647
0
    case SMB_FILE_ATTRIBUTE_TAG_INFORMATION: {
3648
0
      uint32_t tag = 0;
3649
3650
0
      DBG_DEBUG("SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n");
3651
3652
0
      (void)fsctl_get_reparse_tag(fsp, &tag);
3653
3654
0
      DBG_DEBUG("tag=%"PRIu32"\n", tag);
3655
3656
0
      SIVAL(pdata, 0, mode);
3657
0
      SIVAL(pdata, 4, tag);
3658
0
      data_size = 8;
3659
0
      *fixed_portion = 8;
3660
0
      break;
3661
0
    }
3662
    /*
3663
     * SMB2 UNIX Extensions.
3664
     */
3665
0
    case FSCC_FILE_POSIX_INFORMATION:
3666
0
    {
3667
0
      struct smb3_file_posix_information info = {};
3668
0
      uint8_t buf[sizeof(info)];
3669
0
      struct ndr_push ndr = {
3670
0
        .data = buf,
3671
0
        .alloc_size = sizeof(buf),
3672
0
        .fixed_buf_size = true,
3673
0
      };
3674
0
      enum ndr_err_code ndr_err;
3675
3676
0
      if (!conn_using_smb2(conn->sconn)) {
3677
0
        return NT_STATUS_INVALID_LEVEL;
3678
0
      }
3679
0
      if (fsp == NULL) {
3680
0
        return NT_STATUS_INVALID_HANDLE;
3681
0
      }
3682
0
      if (!fsp->fsp_flags.posix_open) {
3683
0
        return NT_STATUS_INVALID_LEVEL;
3684
0
      }
3685
3686
0
      status = smb3_file_posix_information_init(
3687
0
        conn, smb_fname, mode, &info);
3688
0
      if (!NT_STATUS_IS_OK(status)) {
3689
0
        return status;
3690
0
      }
3691
3692
0
      ndr_err = ndr_push_smb3_file_posix_information(
3693
0
        &ndr, NDR_SCALARS|NDR_BUFFERS, &info);
3694
0
      if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3695
0
        return NT_STATUS_INSUFFICIENT_RESOURCES;
3696
0
      }
3697
3698
0
      memcpy(pdata, buf, ndr.offset);
3699
0
      data_size = ndr.offset;
3700
0
      break;
3701
0
    }
3702
3703
0
    default:
3704
0
      return NT_STATUS_INVALID_LEVEL;
3705
0
  }
3706
3707
0
  *pdata_size = data_size;
3708
0
  return NT_STATUS_OK;
3709
0
}
3710
3711
/****************************************************************************
3712
 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3713
 code.
3714
****************************************************************************/
3715
3716
NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
3717
          connection_struct *conn,
3718
          struct smb_request *req,
3719
          bool overwrite_if_exists,
3720
          struct files_struct *dirfsp_old,
3721
          const struct smb_filename *smb_fname_old,
3722
          struct smb_filename *smb_fname_old_rel,
3723
          struct files_struct *dirfsp_new,
3724
          struct smb_filename *smb_fname_new,
3725
          struct smb_filename *smb_fname_new_rel)
3726
0
{
3727
0
  NTSTATUS status = NT_STATUS_OK;
3728
0
  int ret;
3729
0
  bool ok;
3730
3731
  /* source must already exist. */
3732
0
  if (!VALID_STAT(smb_fname_old->st)) {
3733
0
    status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3734
0
    goto out;
3735
0
  }
3736
3737
  /* No links from a directory. */
3738
0
  if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
3739
0
    status = NT_STATUS_FILE_IS_A_DIRECTORY;
3740
0
    goto out;
3741
0
  }
3742
3743
  /* Setting a hardlink to/from a stream isn't currently supported. */
3744
0
  ok = is_ntfs_stream_smb_fname(smb_fname_old);
3745
0
  if (ok) {
3746
0
    DBG_DEBUG("Old name has streams\n");
3747
0
    status = NT_STATUS_INVALID_PARAMETER;
3748
0
    goto out;
3749
0
  }
3750
0
  ok = is_ntfs_stream_smb_fname(smb_fname_new);
3751
0
  if (ok) {
3752
0
    DBG_DEBUG("New name has streams\n");
3753
0
    status = NT_STATUS_INVALID_PARAMETER;
3754
0
    goto out;
3755
0
  }
3756
3757
0
  if (smb_fname_old->twrp != 0) {
3758
0
    status = NT_STATUS_NOT_SAME_DEVICE;
3759
0
    goto out;
3760
0
  }
3761
3762
0
  if (VALID_STAT(smb_fname_new->st)) {
3763
0
    if (overwrite_if_exists) {
3764
0
      if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
3765
0
        status = NT_STATUS_FILE_IS_A_DIRECTORY;
3766
0
        goto out;
3767
0
      }
3768
0
      status = unlink_internals(conn,
3769
0
            req,
3770
0
            FILE_ATTRIBUTE_NORMAL,
3771
0
            NULL, /* new_dirfsp */
3772
0
            smb_fname_new);
3773
0
      if (!NT_STATUS_IS_OK(status)) {
3774
0
        goto out;
3775
0
      }
3776
0
    } else {
3777
      /* Disallow if newname already exists. */
3778
0
      status = NT_STATUS_OBJECT_NAME_COLLISION;
3779
0
      goto out;
3780
0
    }
3781
0
  }
3782
3783
0
  DBG_DEBUG("doing hard link %s -> %s\n",
3784
0
      smb_fname_old->base_name,
3785
0
      smb_fname_new->base_name);
3786
3787
0
  ret = SMB_VFS_LINKAT(conn,
3788
0
           dirfsp_old,
3789
0
           smb_fname_old_rel,
3790
0
           dirfsp_new,
3791
0
           smb_fname_new_rel,
3792
0
           0);
3793
3794
0
  if (ret != 0) {
3795
0
    status = map_nt_error_from_unix(errno);
3796
0
    DBG_NOTICE("Error %s hard link %s -> %s\n",
3797
0
         nt_errstr(status),
3798
0
         smb_fname_old->base_name,
3799
0
         smb_fname_new->base_name);
3800
0
    goto out;
3801
0
  }
3802
3803
0
  notify_fname(conn,
3804
0
         NOTIFY_ACTION_ADDED |
3805
0
         NOTIFY_ACTION_DIRLEASE_BREAK,
3806
0
         FILE_NOTIFY_CHANGE_FILE_NAME,
3807
0
         smb_fname_new,
3808
0
         fsp_get_smb2_lease(smb_fname_old->fsp));
3809
3810
0
  out:
3811
0
  return status;
3812
0
}
3813
3814
/****************************************************************************
3815
 Deal with setting the time from any of the setfilepathinfo functions.
3816
 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
3817
 calling this function.
3818
****************************************************************************/
3819
3820
NTSTATUS smb_set_file_time(connection_struct *conn,
3821
         files_struct *fsp,
3822
         struct smb_filename *smb_fname,
3823
         struct smb_file_time *ft,
3824
         bool setting_write_time)
3825
0
{
3826
0
  const struct smb2_lease *lease = NULL;
3827
0
  struct files_struct *set_fsp = NULL;
3828
0
  struct timeval_buf tbuf[4];
3829
0
  uint32_t action = NOTIFY_ACTION_MODIFIED;
3830
0
  uint32_t filter =
3831
0
    FILE_NOTIFY_CHANGE_LAST_ACCESS
3832
0
    |FILE_NOTIFY_CHANGE_LAST_WRITE
3833
0
    |FILE_NOTIFY_CHANGE_CREATION;
3834
0
  int ret;
3835
3836
0
  if (!VALID_STAT(smb_fname->st)) {
3837
0
    return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3838
0
  }
3839
3840
0
  if (fsp == NULL) {
3841
    /* A symlink */
3842
0
    return NT_STATUS_OK;
3843
0
  }
3844
3845
0
  set_fsp = metadata_fsp(fsp);
3846
3847
  /* get some defaults (no modifications) if any info is zero or -1. */
3848
0
  if (is_omit_timespec(&ft->create_time)) {
3849
0
    filter &= ~FILE_NOTIFY_CHANGE_CREATION;
3850
0
  }
3851
3852
0
  if (is_omit_timespec(&ft->atime)) {
3853
0
    filter &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
3854
0
  }
3855
3856
0
  if (is_omit_timespec(&ft->mtime)) {
3857
0
    filter &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3858
0
  }
3859
3860
0
  if (!setting_write_time) {
3861
    /* ft->mtime comes from change time, not write time. */
3862
0
    filter &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3863
0
  }
3864
3865
  /* Ensure the resolution is the correct for
3866
   * what we can store on this filesystem. */
3867
3868
0
  round_timespec(conn->ts_res, &ft->create_time);
3869
0
  round_timespec(conn->ts_res, &ft->ctime);
3870
0
  round_timespec(conn->ts_res, &ft->atime);
3871
0
  round_timespec(conn->ts_res, &ft->mtime);
3872
3873
0
  DBG_DEBUG("actime: %s\n ",
3874
0
      timespec_string_buf(&ft->atime, true, &tbuf[0]));
3875
0
  DBG_DEBUG("modtime: %s\n ",
3876
0
      timespec_string_buf(&ft->mtime, true, &tbuf[1]));
3877
0
  DBG_DEBUG("ctime: %s\n ",
3878
0
      timespec_string_buf(&ft->ctime, true, &tbuf[2]));
3879
0
  DBG_DEBUG("createtime: %s\n ",
3880
0
      timespec_string_buf(&ft->create_time, true, &tbuf[3]));
3881
3882
0
  if (setting_write_time) {
3883
    /*
3884
     * This was a Windows setfileinfo on an open file.
3885
     * NT does this a lot. We also need to
3886
     * set the time here, as it can be read by
3887
     * FindFirst/FindNext and with the patch for bug #2045
3888
     * in smbd/fileio.c it ensures that this timestamp is
3889
     * kept sticky even after a write. We save the request
3890
     * away and will set it on file close and after a write. JRA.
3891
     */
3892
3893
0
    DBG_DEBUG("setting pending modtime to %s\n",
3894
0
        timespec_string_buf(&ft->mtime, true, &tbuf[0]));
3895
3896
0
    set_sticky_write_time_fsp(set_fsp, ft->mtime);
3897
0
    action |= NOTIFY_ACTION_DIRLEASE_BREAK;
3898
0
    lease = fsp_get_smb2_lease(fsp);
3899
0
  }
3900
3901
0
  DBG_DEBUG("setting utimes to modified values.\n");
3902
3903
0
  ret = file_ntimes(conn, set_fsp, ft);
3904
0
  if (ret != 0) {
3905
0
    return map_nt_error_from_unix(errno);
3906
0
  }
3907
3908
0
  notify_fname(conn,
3909
0
         action,
3910
0
         filter,
3911
0
         smb_fname,
3912
0
         lease);
3913
0
  return NT_STATUS_OK;
3914
0
}
3915
3916
/****************************************************************************
3917
 Deal with setting the dosmode from any of the setfilepathinfo functions.
3918
 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
3919
 done before calling this function.
3920
****************************************************************************/
3921
3922
static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
3923
             struct files_struct *fsp,
3924
             uint32_t dosmode)
3925
0
{
3926
0
  struct files_struct *dos_fsp = NULL;
3927
0
  uint32_t current_dosmode;
3928
0
  int ret;
3929
3930
0
  if (!VALID_STAT(fsp->fsp_name->st)) {
3931
0
    return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3932
0
  }
3933
3934
0
  dos_fsp = metadata_fsp(fsp);
3935
3936
0
  if (dosmode != 0) {
3937
0
    if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3938
0
      dosmode |= FILE_ATTRIBUTE_DIRECTORY;
3939
0
    } else {
3940
0
      dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
3941
0
    }
3942
0
  }
3943
3944
0
  DBG_DEBUG("dosmode: 0x%" PRIx32 "\n", dosmode);
3945
3946
  /* check the mode isn't different, before changing it */
3947
0
  if (dosmode == 0) {
3948
0
    return NT_STATUS_OK;
3949
0
  }
3950
0
  current_dosmode = fdos_mode(dos_fsp);
3951
0
  if (dosmode == current_dosmode) {
3952
0
    return NT_STATUS_OK;
3953
0
  }
3954
3955
0
  DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32 "\n",
3956
0
      fsp_str_dbg(dos_fsp), dosmode);
3957
3958
0
  ret = file_set_dosmode(conn, dos_fsp->fsp_name, dosmode, NULL, false);
3959
0
  if (ret != 0) {
3960
0
    DBG_WARNING("file_set_dosmode of %s failed: %s\n",
3961
0
          fsp_str_dbg(dos_fsp), strerror(errno));
3962
0
    return map_nt_error_from_unix(errno);
3963
0
  }
3964
3965
0
  return NT_STATUS_OK;
3966
0
}
3967
3968
/****************************************************************************
3969
 Deal with setting the size from any of the setfilepathinfo functions.
3970
****************************************************************************/
3971
3972
NTSTATUS smb_set_file_size(connection_struct *conn,
3973
         struct smb_request *req,
3974
         files_struct *fsp,
3975
         struct smb_filename *smb_fname,
3976
         const SMB_STRUCT_STAT *psbuf,
3977
         off_t size,
3978
         bool fail_after_createfile)
3979
0
{
3980
0
  NTSTATUS status = NT_STATUS_OK;
3981
0
  struct file_modified_state state;
3982
0
  files_struct *new_fsp = NULL;
3983
3984
0
  if (!VALID_STAT(*psbuf)) {
3985
0
    return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3986
0
  }
3987
3988
0
  DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
3989
0
     (uint64_t)size,
3990
0
     get_file_size_stat(psbuf));
3991
3992
0
  if (size == get_file_size_stat(psbuf)) {
3993
    /*
3994
     * MS-FSA 2.1.5.15.4 FileEndOfFileInformation tells us not to
3995
     * update the timestamps, but Windows Server 2022 does it.
3996
     */
3997
0
    trigger_write_time_update_immediate(fsp, true, false);
3998
0
    return NT_STATUS_OK;
3999
0
  }
4000
4001
0
  DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4002
0
      smb_fname_str_dbg(smb_fname), (double)size));
4003
4004
0
  if (fsp &&
4005
0
      !fsp->fsp_flags.is_pathref &&
4006
0
      fsp_get_io_fd(fsp) != -1)
4007
0
  {
4008
    /* Handle based call. */
4009
0
    status = check_any_access_fsp(fsp, FILE_WRITE_DATA);
4010
0
    if (!NT_STATUS_IS_OK(status)) {
4011
0
      return status;
4012
0
    }
4013
4014
0
    prepare_file_modified(fsp, &state);
4015
0
    if (vfs_set_filelen(fsp, size) == -1) {
4016
0
      return map_nt_error_from_unix(errno);
4017
0
    }
4018
0
    mark_file_modified(fsp, false, &state);
4019
0
    return NT_STATUS_OK;
4020
0
  }
4021
4022
0
        status = SMB_VFS_CREATE_FILE(
4023
0
    conn,         /* conn */
4024
0
    req,          /* req */
4025
0
    NULL,         /* dirfsp */
4026
0
    smb_fname,        /* fname */
4027
0
    FILE_WRITE_DATA,      /* access_mask */
4028
0
    (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4029
0
        FILE_SHARE_DELETE),
4030
0
    FILE_OPEN,        /* create_disposition*/
4031
0
    0,          /* create_options */
4032
0
    FILE_ATTRIBUTE_NORMAL,      /* file_attributes */
4033
0
    0,          /* oplock_request */
4034
0
    NULL,         /* lease */
4035
0
    0,          /* allocation_size */
4036
0
    0,          /* private_flags */
4037
0
    NULL,         /* sd */
4038
0
    NULL,         /* ea_list */
4039
0
    &new_fsp,       /* result */
4040
0
    NULL,         /* pinfo */
4041
0
    NULL, NULL);        /* create context */
4042
4043
0
  if (!NT_STATUS_IS_OK(status)) {
4044
    /* NB. We check for open_was_deferred in the caller. */
4045
0
    return status;
4046
0
  }
4047
4048
  /* See RAW-SFILEINFO-END-OF-FILE */
4049
0
  if (fail_after_createfile) {
4050
0
    close_file_free(req, &new_fsp, NORMAL_CLOSE);
4051
0
    return NT_STATUS_INVALID_LEVEL;
4052
0
  }
4053
4054
0
  prepare_file_modified(fsp, &state);
4055
0
  if (vfs_set_filelen(new_fsp, size) == -1) {
4056
0
    status = map_nt_error_from_unix(errno);
4057
0
    close_file_free(req, &new_fsp, NORMAL_CLOSE);
4058
0
    return status;
4059
0
  }
4060
0
  mark_file_modified(fsp, false, &state);
4061
4062
0
  close_file_free(req, &new_fsp, NORMAL_CLOSE);
4063
0
  return NT_STATUS_OK;
4064
0
}
4065
4066
/****************************************************************************
4067
 Deal with SMB_INFO_SET_EA.
4068
****************************************************************************/
4069
4070
static NTSTATUS smb_info_set_ea(connection_struct *conn,
4071
        const char *pdata,
4072
        int total_data,
4073
        files_struct *fsp,
4074
        struct smb_filename *smb_fname)
4075
0
{
4076
0
  struct ea_list *ea_list = NULL;
4077
0
  NTSTATUS status = NT_STATUS_OK;
4078
4079
0
  if (total_data < 10) {
4080
4081
    /* OS/2 workplace shell seems to send SET_EA requests of "null"
4082
       length. They seem to have no effect. Bug #3212. JRA */
4083
4084
0
    if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4085
      /* We're done. We only get EA info in this call. */
4086
0
      return NT_STATUS_OK;
4087
0
    }
4088
4089
0
    return NT_STATUS_INVALID_PARAMETER;
4090
0
  }
4091
4092
0
  if (IVAL(pdata,0) > total_data) {
4093
0
    DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4094
0
      IVAL(pdata,0), (unsigned int)total_data));
4095
0
    return NT_STATUS_INVALID_PARAMETER;
4096
0
  }
4097
4098
0
  ea_list = read_ea_list(talloc_tos() , pdata + 4, total_data - 4);
4099
0
  if (!ea_list) {
4100
0
    return NT_STATUS_INVALID_PARAMETER;
4101
0
  }
4102
4103
0
  status = set_ea(conn, fsp, ea_list);
4104
4105
0
  return status;
4106
0
}
4107
4108
/****************************************************************************
4109
 Deal with SMB_FILE_FULL_EA_INFORMATION set.
4110
****************************************************************************/
4111
4112
static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
4113
        const char *pdata,
4114
        int total_data,
4115
        files_struct *fsp)
4116
0
{
4117
0
  struct ea_list *ea_list = NULL;
4118
0
  NTSTATUS status;
4119
4120
0
  if (!lp_ea_support(SNUM(conn))) {
4121
0
    DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4122
0
      "EA's not supported.\n",
4123
0
      (unsigned int)total_data));
4124
0
    return NT_STATUS_EAS_NOT_SUPPORTED;
4125
0
  }
4126
4127
0
  if (total_data < 10) {
4128
0
    DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4129
0
      "too small.\n",
4130
0
      (unsigned int)total_data));
4131
0
    return NT_STATUS_INVALID_PARAMETER;
4132
0
  }
4133
4134
0
  ea_list = read_nttrans_ea_list(talloc_tos(),
4135
0
        pdata,
4136
0
        total_data);
4137
4138
0
  if (!ea_list) {
4139
0
    return NT_STATUS_INVALID_PARAMETER;
4140
0
  }
4141
4142
0
  status = set_ea(conn, fsp, ea_list);
4143
4144
0
  DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4145
0
    smb_fname_str_dbg(fsp->fsp_name),
4146
0
    nt_errstr(status) ));
4147
4148
0
  return status;
4149
0
}
4150
4151
4152
/****************************************************************************
4153
 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4154
****************************************************************************/
4155
4156
NTSTATUS smb_check_file_disposition_info(struct files_struct *fsp,
4157
           const char *data,
4158
           int total_data,
4159
           bool *_delete_on_close)
4160
0
{
4161
0
  bool delete_on_close;
4162
0
  uint32_t dosmode = 0;
4163
0
  NTSTATUS status;
4164
4165
0
  if (total_data < 1) {
4166
0
    return NT_STATUS_INVALID_PARAMETER;
4167
0
  }
4168
4169
0
  if (fsp == NULL) {
4170
0
    return NT_STATUS_INVALID_HANDLE;
4171
0
  }
4172
4173
0
  delete_on_close = (PULL_LE_U8(data, 0) ? true : false);
4174
0
  *_delete_on_close = delete_on_close;
4175
4176
0
  dosmode = fdos_mode(fsp);
4177
4178
0
  DBG_DEBUG("file [%s] dosmode = %u, delete_on_close = %s\n",
4179
0
      fsp_str_dbg(fsp),
4180
0
      (unsigned int)dosmode,
4181
0
      delete_on_close ? "yes" : "no");
4182
4183
0
  if (!delete_on_close) {
4184
0
    return NT_STATUS_OK;
4185
0
  }
4186
4187
0
  status = can_set_delete_on_close(fsp, dosmode);
4188
0
  if (!NT_STATUS_IS_OK(status)) {
4189
0
    return status;
4190
0
  }
4191
4192
0
  return NT_STATUS_OK;
4193
0
}
4194
4195
NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4196
               const char *pdata,
4197
               int total_data,
4198
               files_struct *fsp,
4199
               struct smb_filename *smb_fname)
4200
0
{
4201
0
  NTSTATUS status;
4202
0
  bool delete_on_close;
4203
4204
0
  status = smb_check_file_disposition_info(fsp,
4205
0
             pdata,
4206
0
             total_data,
4207
0
             &delete_on_close);
4208
0
  if (!NT_STATUS_IS_OK(status)) {
4209
0
    return status;
4210
0
  }
4211
4212
  /* The set is across all open files on this dev/inode pair. */
4213
0
  if (!set_delete_on_close(fsp, delete_on_close,
4214
0
         conn->session_info->security_token,
4215
0
         conn->session_info->unix_token)) {
4216
0
    return NT_STATUS_ACCESS_DENIED;
4217
0
  }
4218
0
  return NT_STATUS_OK;
4219
0
}
4220
4221
/****************************************************************************
4222
 Deal with SMB_FILE_POSITION_INFORMATION.
4223
****************************************************************************/
4224
4225
static NTSTATUS smb_file_position_information(connection_struct *conn,
4226
        const char *pdata,
4227
        int total_data,
4228
        files_struct *fsp)
4229
0
{
4230
0
  uint64_t position_information;
4231
4232
0
  if (total_data < 8) {
4233
0
    return NT_STATUS_INVALID_PARAMETER;
4234
0
  }
4235
4236
0
  position_information = PULL_LE_U64(pdata, 0);
4237
4238
0
  DBG_DEBUG("Set file position information for file %s to %" PRIu64 "\n",
4239
0
      fsp_str_dbg(fsp),
4240
0
      position_information);
4241
0
  fh_set_position_information(fsp->fh, position_information);
4242
0
  return NT_STATUS_OK;
4243
0
}
4244
4245
/****************************************************************************
4246
 Deal with SMB_FILE_MODE_INFORMATION.
4247
****************************************************************************/
4248
4249
static NTSTATUS smb_file_mode_information(connection_struct *conn,
4250
        const char *pdata,
4251
        int total_data)
4252
0
{
4253
0
  uint32_t mode;
4254
4255
0
  if (total_data < 4) {
4256
0
    return NT_STATUS_INVALID_PARAMETER;
4257
0
  }
4258
0
  mode = IVAL(pdata,0);
4259
0
  if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4260
0
    return NT_STATUS_INVALID_PARAMETER;
4261
0
  }
4262
0
  return NT_STATUS_OK;
4263
0
}
4264
4265
/****************************************************************************
4266
 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4267
****************************************************************************/
4268
4269
NTSTATUS smb2_parse_file_rename_information(TALLOC_CTX *ctx,
4270
              struct connection_struct *conn,
4271
              struct smb_request *req,
4272
              const char *pdata,
4273
              int total_data,
4274
              bool posix,
4275
              char **_newname,
4276
              bool *_overwrite)
4277
0
{
4278
0
  char *newname = NULL;
4279
0
  bool overwrite = false;
4280
0
  uint32_t len;
4281
0
  NTSTATUS status;
4282
4283
0
  if (total_data < 20) {
4284
0
    return NT_STATUS_INVALID_PARAMETER;
4285
0
  }
4286
4287
0
  overwrite = (CVAL(pdata,0) ? True : False);
4288
0
  len = IVAL(pdata,16);
4289
4290
0
  if (len > (total_data - 20) || (len == 0)) {
4291
0
    return NT_STATUS_INVALID_PARAMETER;
4292
0
  }
4293
4294
0
  (void)srvstr_pull_talloc(ctx,
4295
0
         pdata,
4296
0
         req->flags2,
4297
0
         &newname,
4298
0
         &pdata[20],
4299
0
         len,
4300
0
         STR_TERMINATE);
4301
4302
0
  if (newname == NULL) {
4303
0
    return NT_STATUS_INVALID_PARAMETER;
4304
0
  }
4305
4306
0
  status = check_path_syntax(newname, posix);
4307
0
  if (!NT_STATUS_IS_OK(status)) {
4308
0
    TALLOC_FREE(newname);
4309
0
    return status;
4310
0
  }
4311
4312
0
  DBG_DEBUG("got name |%s|\n", newname);
4313
4314
0
  *_newname = newname;
4315
0
  *_overwrite = overwrite;
4316
0
  return NT_STATUS_OK;
4317
0
}
4318
4319
static NTSTATUS smb2_file_rename_information(connection_struct *conn,
4320
              struct smb_request *req,
4321
              const char *pdata,
4322
              int total_data,
4323
              files_struct *fsp,
4324
              struct share_mode_lock **lck,
4325
              struct smb_filename *smb_fname_src)
4326
0
{
4327
0
  char *newname = NULL;
4328
0
  bool overwrite;
4329
0
  struct smb_filename *smb_fname_src_parent = NULL;
4330
0
  struct smb_filename *smb_fname_src_rel = NULL;
4331
0
  NTSTATUS status = NT_STATUS_OK;
4332
0
  TALLOC_CTX *ctx = talloc_tos();
4333
4334
0
  status = smb2_parse_file_rename_information(
4335
0
    ctx,
4336
0
    conn,
4337
0
    req,
4338
0
    pdata,
4339
0
    total_data,
4340
0
    fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH,
4341
0
    &newname,
4342
0
    &overwrite);
4343
0
  if (!NT_STATUS_IS_OK(status)) {
4344
0
    return status;
4345
0
  }
4346
4347
0
  DBG_DEBUG("SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4348
0
      fsp_fnum_dbg(fsp),
4349
0
      fsp_str_dbg(fsp),
4350
0
      newname);
4351
4352
0
  status = parent_pathref(talloc_tos(),
4353
0
        conn->cwd_fsp,
4354
0
        fsp->fsp_name,
4355
0
        &smb_fname_src_parent,
4356
0
        &smb_fname_src_rel);
4357
0
  if (!NT_STATUS_IS_OK(status)) {
4358
0
    return status;
4359
0
  }
4360
4361
0
  status = rename_internals_fsp(conn,
4362
0
              smb_fname_src_parent->fsp,
4363
0
              fsp,
4364
0
              smb_fname_src_rel,
4365
0
              lck,
4366
0
              (FILE_ATTRIBUTE_HIDDEN |
4367
0
               FILE_ATTRIBUTE_SYSTEM),
4368
0
              newname,
4369
0
              overwrite);
4370
4371
0
  TALLOC_FREE(smb_fname_src_rel);
4372
0
  TALLOC_FREE(smb_fname_src_parent);
4373
0
  return status;
4374
0
}
4375
4376
static NTSTATUS smb_file_link_information(connection_struct *conn,
4377
            struct smb_request *req,
4378
            const char *pdata,
4379
            int total_data,
4380
            files_struct *fsp,
4381
            struct smb_filename *smb_fname_src)
4382
0
{
4383
0
  bool overwrite;
4384
0
  uint32_t len;
4385
0
  char *newname = NULL;
4386
0
  struct smb_filename *src_parent = NULL;
4387
0
  struct smb_filename *smb_fname_src_rel = NULL;
4388
0
  struct files_struct *dst_dirfsp = NULL;
4389
0
  struct smb_filename *smb_fname_dst = NULL;
4390
0
  struct smb_filename *smb_fname_dst_rel = NULL;
4391
0
  NTSTATUS status = NT_STATUS_OK;
4392
0
  uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4393
0
  NTTIME dst_twrp = 0;
4394
0
  TALLOC_CTX *ctx = talloc_tos();
4395
4396
0
  if (!fsp) {
4397
0
    return NT_STATUS_INVALID_HANDLE;
4398
0
  }
4399
4400
0
  if (total_data < 20) {
4401
0
    return NT_STATUS_INVALID_PARAMETER;
4402
0
  }
4403
4404
0
  overwrite = (CVAL(pdata,0) ? true : false);
4405
0
  len = IVAL(pdata,16);
4406
4407
0
  if (len > (total_data - 20) || (len == 0)) {
4408
0
    return NT_STATUS_INVALID_PARAMETER;
4409
0
  }
4410
4411
0
  if (conn_using_smb2(conn->sconn)) {
4412
0
    int ret;
4413
4414
0
    ret = srvstr_pull_talloc(ctx,
4415
0
           pdata,
4416
0
           req->flags2,
4417
0
           &newname,
4418
0
           &pdata[20],
4419
0
           len,
4420
0
           STR_TERMINATE);
4421
4422
0
    if (ret == (size_t)-1 || newname == NULL) {
4423
0
      return NT_STATUS_INVALID_PARAMETER;
4424
0
    }
4425
4426
0
    status = check_path_syntax(newname,
4427
0
             fsp->fsp_name->flags &
4428
0
               SMB_FILENAME_POSIX_PATH);
4429
0
    if (!NT_STATUS_IS_OK(status)) {
4430
0
      return status;
4431
0
    }
4432
0
  } else {
4433
0
    if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
4434
0
      srvstr_get_path_posix(ctx,
4435
0
                pdata,
4436
0
                req->flags2,
4437
0
                &newname,
4438
0
                &pdata[20],
4439
0
                len,
4440
0
                STR_TERMINATE,
4441
0
                &status);
4442
0
      ucf_flags |= UCF_POSIX_PATHNAMES;
4443
0
    } else {
4444
0
      srvstr_get_path(ctx,
4445
0
          pdata,
4446
0
          req->flags2,
4447
0
          &newname,
4448
0
          &pdata[20],
4449
0
          len,
4450
0
          STR_TERMINATE,
4451
0
          &status);
4452
0
    }
4453
0
    if (!NT_STATUS_IS_OK(status)) {
4454
0
      return status;
4455
0
    }
4456
4457
0
    if (ucf_flags & UCF_GMT_PATHNAME) {
4458
0
      extract_snapshot_token(newname, &dst_twrp);
4459
0
    }
4460
0
  }
4461
4462
  /* hardlink paths are never DFS. */
4463
0
  req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4464
0
  ucf_flags &= ~UCF_DFS_PATHNAME;
4465
4466
0
  DBG_DEBUG("got name |%s|\n", newname);
4467
4468
0
  status = filename_convert_dirfsp_rel(ctx,
4469
0
               conn,
4470
0
               conn->cwd_fsp,
4471
0
               newname,
4472
0
               ucf_flags,
4473
0
               dst_twrp,
4474
0
               &dst_dirfsp,
4475
0
               &smb_fname_dst,
4476
0
               &smb_fname_dst_rel);
4477
0
  if (!NT_STATUS_IS_OK(status)) {
4478
0
    return status;
4479
0
  }
4480
4481
0
  if (fsp_is_alternate_stream(fsp)) {
4482
    /* No hardlink on streams. */
4483
0
    return NT_STATUS_NOT_SUPPORTED;
4484
0
  }
4485
4486
0
  status = parent_pathref(ctx,
4487
0
        conn->cwd_fsp,
4488
0
        fsp->fsp_name,
4489
0
        &src_parent,
4490
0
        &smb_fname_src_rel);
4491
0
  if (!NT_STATUS_IS_OK(status)) {
4492
0
    return status;
4493
0
  }
4494
4495
0
  DBG_DEBUG("SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4496
0
      fsp_fnum_dbg(fsp),
4497
0
      fsp_str_dbg(fsp),
4498
0
      smb_fname_str_dbg(smb_fname_dst));
4499
4500
0
  status = hardlink_internals(ctx,
4501
0
            conn,
4502
0
            req,
4503
0
            overwrite,
4504
0
            src_parent->fsp,
4505
0
            fsp->fsp_name,
4506
0
            smb_fname_src_rel,
4507
0
            dst_dirfsp,
4508
0
            smb_fname_dst,
4509
0
            smb_fname_dst_rel);
4510
4511
0
  TALLOC_FREE(smb_fname_dst);
4512
0
  return status;
4513
0
}
4514
4515
4516
/****************************************************************************
4517
 Deal with SMB_FILE_RENAME_INFORMATION.
4518
****************************************************************************/
4519
4520
static NTSTATUS smb_file_rename_information(connection_struct *conn,
4521
              struct smb_request *req,
4522
              const char *pdata,
4523
              int total_data,
4524
              files_struct *fsp,
4525
              struct smb_filename *smb_fname_src)
4526
0
{
4527
0
  bool overwrite;
4528
0
  uint32_t root_fid;
4529
0
  uint32_t len;
4530
0
  char *newname = NULL;
4531
0
  struct smb_filename *smb_fname_src_parent = NULL;
4532
0
  struct smb_filename *smb_fname_src_rel = NULL;
4533
0
  NTSTATUS status = NT_STATUS_OK;
4534
0
  TALLOC_CTX *ctx = talloc_tos();
4535
4536
0
  if (total_data < 13) {
4537
0
    return NT_STATUS_INVALID_PARAMETER;
4538
0
  }
4539
4540
0
  overwrite = (CVAL(pdata,0) != 0);
4541
0
  root_fid = IVAL(pdata,4);
4542
0
  len = IVAL(pdata,8);
4543
4544
0
  if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4545
0
    return NT_STATUS_INVALID_PARAMETER;
4546
0
  }
4547
4548
0
  if (req->posix_pathnames) {
4549
0
    srvstr_get_path_posix(ctx,
4550
0
        pdata,
4551
0
        req->flags2,
4552
0
        &newname,
4553
0
        &pdata[12],
4554
0
        len,
4555
0
        0,
4556
0
        &status);
4557
0
  } else {
4558
0
    srvstr_get_path(ctx,
4559
0
        pdata,
4560
0
        req->flags2,
4561
0
        &newname,
4562
0
        &pdata[12],
4563
0
        len,
4564
0
        0,
4565
0
        &status);
4566
0
  }
4567
0
  if (!NT_STATUS_IS_OK(status)) {
4568
0
    return status;
4569
0
  }
4570
4571
0
  DBG_DEBUG("got name |%s|\n", newname);
4572
4573
  /* Check the new name has no '/' characters. */
4574
0
  if (strchr_m(newname, '/')) {
4575
0
    return NT_STATUS_NOT_SUPPORTED;
4576
0
  }
4577
4578
0
  status = parent_pathref(ctx,
4579
0
        conn->cwd_fsp,
4580
0
        fsp->fsp_name,
4581
0
        &smb_fname_src_parent,
4582
0
        &smb_fname_src_rel);
4583
0
  if (!NT_STATUS_IS_OK(status)) {
4584
0
    goto out;
4585
0
  }
4586
4587
0
  if (!fsp_is_alternate_stream(fsp)) {
4588
    /*
4589
     * The smb1-level rename information is always
4590
     * relative to the directory of the src name.
4591
     */
4592
0
    newname = full_path_from_dirfsp_at_basename(
4593
0
      ctx, smb_fname_src_parent->fsp, newname);
4594
0
    if (newname == NULL) {
4595
0
      status = NT_STATUS_NO_MEMORY;
4596
0
      goto out;
4597
0
    }
4598
0
  }
4599
4600
0
  if (fsp->fsp_flags.is_fsa) {
4601
0
    DBG_DEBUG("SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4602
0
        fsp_fnum_dbg(fsp),
4603
0
        fsp_str_dbg(fsp),
4604
0
        newname);
4605
4606
    /*
4607
     * If no pathnames are open below this directory,
4608
     * allow the rename.
4609
     */
4610
0
    if (have_file_open_below(fsp)) {
4611
0
      status = NT_STATUS_ACCESS_DENIED;
4612
0
      goto out;
4613
0
    }
4614
4615
0
    status = rename_internals_fsp(conn,
4616
0
                smb_fname_src_parent->fsp,
4617
0
                fsp,
4618
0
                smb_fname_src_rel,
4619
0
                NULL,
4620
0
                0,
4621
0
                newname,
4622
0
                overwrite);
4623
0
  } else {
4624
0
    DBG_DEBUG("SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4625
0
        smb_fname_str_dbg(smb_fname_src),
4626
0
        newname);
4627
0
    status = rename_internals(ctx,
4628
4629
0
            conn,
4630
0
            req,
4631
0
            smb_fname_src_parent->fsp,
4632
0
            smb_fname_src,
4633
0
            smb_fname_src_rel,
4634
0
            0,
4635
0
            newname,
4636
0
            overwrite,
4637
0
            FILE_WRITE_ATTRIBUTES);
4638
0
  }
4639
0
out:
4640
0
  return status;
4641
0
}
4642
4643
/****************************************************************************
4644
 Deal with SMB_SET_FILE_BASIC_INFO.
4645
****************************************************************************/
4646
4647
static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4648
          const char *pdata,
4649
          int total_data,
4650
          files_struct *fsp,
4651
          struct smb_filename *smb_fname)
4652
0
{
4653
  /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4654
0
  struct smb_file_time ft;
4655
0
  uint32_t dosmode = 0;
4656
0
  NTSTATUS status = NT_STATUS_OK;
4657
4658
0
  init_smb_file_time(&ft);
4659
4660
0
  if (total_data < 36) {
4661
0
    return NT_STATUS_INVALID_PARAMETER;
4662
0
  }
4663
4664
0
  status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4665
0
  if (!NT_STATUS_IS_OK(status)) {
4666
0
    return status;
4667
0
  }
4668
4669
  /* Set the attributes */
4670
0
  dosmode = IVAL(pdata,32);
4671
0
  status = smb_set_file_dosmode(conn, fsp, dosmode);
4672
0
  if (!NT_STATUS_IS_OK(status)) {
4673
0
    return status;
4674
0
  }
4675
4676
  /* create time */
4677
0
  ft.create_time = pull_long_date_full_timespec(pdata);
4678
4679
  /* access time */
4680
0
  ft.atime = pull_long_date_full_timespec(pdata+8);
4681
4682
  /* write time. */
4683
0
  ft.mtime = pull_long_date_full_timespec(pdata+16);
4684
4685
  /* change time. */
4686
0
  ft.ctime = pull_long_date_full_timespec(pdata+24);
4687
4688
0
  DEBUG(10, ("smb_set_file_basic_info: file %s\n",
4689
0
       smb_fname_str_dbg(smb_fname)));
4690
4691
0
  status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4692
0
  if (!NT_STATUS_IS_OK(status)) {
4693
0
    return status;
4694
0
  }
4695
4696
0
  return NT_STATUS_OK;
4697
0
}
4698
4699
/****************************************************************************
4700
 Deal with SMB_INFO_STANDARD.
4701
****************************************************************************/
4702
4703
static NTSTATUS smb_set_info_standard(connection_struct *conn,
4704
          const char *pdata,
4705
          int total_data,
4706
          files_struct *fsp,
4707
          struct smb_filename *smb_fname)
4708
0
{
4709
0
  NTSTATUS status;
4710
0
  struct smb_file_time ft;
4711
4712
0
  init_smb_file_time(&ft);
4713
4714
0
  if (total_data < 12) {
4715
0
    return NT_STATUS_INVALID_PARAMETER;
4716
0
  }
4717
4718
  /* create time */
4719
0
  ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
4720
  /* access time */
4721
0
  ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
4722
  /* write time */
4723
0
  ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
4724
4725
0
  DBG_DEBUG("file %s\n", smb_fname_str_dbg(smb_fname));
4726
4727
0
  status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4728
0
  if (!NT_STATUS_IS_OK(status)) {
4729
0
    return status;
4730
0
  }
4731
4732
0
  status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4733
0
  if (!NT_STATUS_IS_OK(status)) {
4734
0
    return status;
4735
0
  }
4736
4737
0
  return NT_STATUS_OK;
4738
0
}
4739
4740
/****************************************************************************
4741
 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4742
****************************************************************************/
4743
4744
static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4745
               struct smb_request *req,
4746
          const char *pdata,
4747
          int total_data,
4748
          files_struct *fsp,
4749
          struct smb_filename *smb_fname)
4750
0
{
4751
0
  uint64_t allocation_size = 0;
4752
0
  NTSTATUS status = NT_STATUS_OK;
4753
0
  files_struct *new_fsp = NULL;
4754
4755
0
  if (!VALID_STAT(smb_fname->st)) {
4756
0
    return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4757
0
  }
4758
4759
0
  if (total_data < 8) {
4760
0
    return NT_STATUS_INVALID_PARAMETER;
4761
0
  }
4762
4763
0
  allocation_size = PULL_LE_U64(pdata, 0);
4764
0
  DBG_DEBUG("Set file allocation info for file %s to %" PRIu64 "\n",
4765
0
      smb_fname_str_dbg(smb_fname),
4766
0
      allocation_size);
4767
4768
0
  if (allocation_size) {
4769
0
    allocation_size = smb_roundup(conn, allocation_size);
4770
0
  }
4771
4772
0
  DBG_DEBUG("file %s : setting new allocation size to %" PRIu64 "\n",
4773
0
      smb_fname_str_dbg(smb_fname),
4774
0
      allocation_size);
4775
4776
0
  if (!fsp->fsp_flags.is_pathref && (fsp_get_io_fd(fsp) != -1)) {
4777
    /* Open file handle. */
4778
0
    status = check_any_access_fsp(fsp, FILE_WRITE_DATA);
4779
0
    if (!NT_STATUS_IS_OK(status)) {
4780
0
      return status;
4781
0
    }
4782
4783
    /* Only change if needed. */
4784
0
    if (allocation_size !=
4785
0
        SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &fsp->fsp_name->st))
4786
0
    {
4787
0
      if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4788
0
        return map_nt_error_from_unix(errno);
4789
0
      }
4790
0
    }
4791
0
    trigger_write_time_update_immediate(fsp, false, true);
4792
0
    return NT_STATUS_OK;
4793
0
  }
4794
4795
  /* Pathname or stat or directory file. */
4796
0
  status = SMB_VFS_CREATE_FILE(
4797
0
    conn,         /* conn */
4798
0
    req,          /* req */
4799
0
    NULL,         /* dirfsp */
4800
0
    smb_fname,        /* fname */
4801
0
    FILE_WRITE_DATA,      /* access_mask */
4802
0
    (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4803
0
        FILE_SHARE_DELETE),
4804
0
    FILE_OPEN,        /* create_disposition*/
4805
0
    0,          /* create_options */
4806
0
    FILE_ATTRIBUTE_NORMAL,      /* file_attributes */
4807
0
    0,          /* oplock_request */
4808
0
    NULL,         /* lease */
4809
0
    0,          /* allocation_size */
4810
0
    0,          /* private_flags */
4811
0
    NULL,         /* sd */
4812
0
    NULL,         /* ea_list */
4813
0
    &new_fsp,       /* result */
4814
0
    NULL,         /* pinfo */
4815
0
    NULL, NULL);        /* create context */
4816
4817
0
  if (!NT_STATUS_IS_OK(status)) {
4818
    /* NB. We check for open_was_deferred in the caller. */
4819
0
    return status;
4820
0
  }
4821
4822
  /* Only change if needed. */
4823
0
  if (allocation_size !=
4824
0
      SMB_VFS_GET_ALLOC_SIZE(conn, new_fsp, &new_fsp->fsp_name->st))
4825
0
  {
4826
0
    if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4827
0
      status = map_nt_error_from_unix(errno);
4828
0
      close_file_free(req, &new_fsp, NORMAL_CLOSE);
4829
0
      return status;
4830
0
    }
4831
0
  }
4832
4833
0
  trigger_write_time_update_immediate(new_fsp, false, true);
4834
0
  close_file_free(req, &new_fsp, NORMAL_CLOSE);
4835
0
  return NT_STATUS_OK;
4836
0
}
4837
4838
/****************************************************************************
4839
 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4840
****************************************************************************/
4841
4842
static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4843
                struct smb_request *req,
4844
          const char *pdata,
4845
          int total_data,
4846
          files_struct *fsp,
4847
          struct smb_filename *smb_fname,
4848
          bool fail_after_createfile)
4849
0
{
4850
0
  off_t size;
4851
4852
0
  if (total_data < 8) {
4853
0
    return NT_STATUS_INVALID_PARAMETER;
4854
0
  }
4855
4856
0
  size = (off_t)PULL_LE_U64(pdata, 0);
4857
0
  DBG_DEBUG("Set end of file info for file %s to %ju\n",
4858
0
      smb_fname_str_dbg(smb_fname),
4859
0
      (uintmax_t)size);
4860
4861
0
  return smb_set_file_size(conn, req,
4862
0
        fsp,
4863
0
        smb_fname,
4864
0
        &smb_fname->st,
4865
0
        size,
4866
0
        fail_after_createfile);
4867
0
}
4868
4869
/**
4870
 * Set an info_level
4871
 *
4872
 * Called from the SMB1 and SMB2 code. For the path-based SMB1 code, there may
4873
 * not be a full fsp from the FSA layer.
4874
 *
4875
 * lck may be NULL, currently only passed for SMB2 rename requests.
4876
 **/
4877
NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
4878
        struct smb_request *req,
4879
        TALLOC_CTX *mem_ctx,
4880
        uint16_t info_level,
4881
        files_struct *fsp,
4882
        struct share_mode_lock **lck,
4883
        struct smb_filename *smb_fname,
4884
        char *pdata,
4885
        int total_data,
4886
        int *ret_data_size)
4887
0
{
4888
0
  NTSTATUS status = NT_STATUS_OK;
4889
0
  int data_return_size = 0;
4890
4891
0
  *ret_data_size = 0;
4892
4893
0
  DBG_NOTICE("%s (%s) info_level=%d totdata=%d\n",
4894
0
       smb_fname_str_dbg(smb_fname),
4895
0
       fsp_fnum_dbg(fsp),
4896
0
       info_level,
4897
0
       total_data);
4898
4899
0
  SMB_ASSERT(fsp != NULL);
4900
4901
0
  switch (info_level) {
4902
4903
0
    case SMB_INFO_STANDARD:
4904
0
    {
4905
0
      status = smb_set_info_standard(conn,
4906
0
          pdata,
4907
0
          total_data,
4908
0
          fsp,
4909
0
          smb_fname);
4910
0
      break;
4911
0
    }
4912
4913
0
    case SMB_INFO_SET_EA:
4914
0
    {
4915
0
      status = smb_info_set_ea(conn,
4916
0
            pdata,
4917
0
            total_data,
4918
0
            fsp,
4919
0
            smb_fname);
4920
0
      break;
4921
0
    }
4922
4923
0
    case SMB_SET_FILE_BASIC_INFO:
4924
0
    case SMB_FILE_BASIC_INFORMATION:
4925
0
    {
4926
0
      status = smb_set_file_basic_info(conn,
4927
0
              pdata,
4928
0
              total_data,
4929
0
              fsp,
4930
0
              smb_fname);
4931
0
      break;
4932
0
    }
4933
4934
0
    case SMB_FILE_ALLOCATION_INFORMATION:
4935
0
    case SMB_SET_FILE_ALLOCATION_INFO:
4936
0
    {
4937
0
      status = smb_set_file_allocation_info(conn, req,
4938
0
                pdata,
4939
0
                total_data,
4940
0
                fsp,
4941
0
                smb_fname);
4942
0
      break;
4943
0
    }
4944
4945
0
    case SMB_FILE_END_OF_FILE_INFORMATION:
4946
0
    case SMB_SET_FILE_END_OF_FILE_INFO:
4947
0
    {
4948
      /*
4949
       * XP/Win7 both fail after the createfile with
4950
       * SMB_SET_FILE_END_OF_FILE_INFO but not
4951
       * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
4952
       * The level is known here, so pass it down
4953
       * appropriately.
4954
       */
4955
0
      bool should_fail =
4956
0
          (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
4957
4958
0
      status = smb_set_file_end_of_file_info(conn, req,
4959
0
                pdata,
4960
0
                total_data,
4961
0
                fsp,
4962
0
                smb_fname,
4963
0
                should_fail);
4964
0
      break;
4965
0
    }
4966
4967
0
    case SMB_FILE_DISPOSITION_INFORMATION:
4968
0
    case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
4969
0
    {
4970
0
      status = smb_set_file_disposition_info(conn,
4971
0
            pdata,
4972
0
            total_data,
4973
0
            fsp,
4974
0
            smb_fname);
4975
0
      break;
4976
0
    }
4977
4978
0
    case SMB_FILE_POSITION_INFORMATION:
4979
0
    {
4980
0
      status = smb_file_position_information(conn,
4981
0
            pdata,
4982
0
            total_data,
4983
0
            fsp);
4984
0
      break;
4985
0
    }
4986
4987
0
    case SMB_FILE_FULL_EA_INFORMATION:
4988
0
    {
4989
0
      status = smb_set_file_full_ea_info(conn,
4990
0
            pdata,
4991
0
            total_data,
4992
0
            fsp);
4993
0
      break;
4994
0
    }
4995
4996
    /* From tridge Samba4 :
4997
     * MODE_INFORMATION in setfileinfo (I have no
4998
     * idea what "mode information" on a file is - it takes a value of 0,
4999
     * 2, 4 or 6. What could it be?).
5000
     */
5001
5002
0
    case SMB_FILE_MODE_INFORMATION:
5003
0
    {
5004
0
      status = smb_file_mode_information(conn,
5005
0
            pdata,
5006
0
            total_data);
5007
0
      break;
5008
0
    }
5009
5010
    /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
5011
0
    case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
5012
0
    case SMB_FILE_SHORT_NAME_INFORMATION:
5013
0
      return NT_STATUS_NOT_SUPPORTED;
5014
5015
0
    case SMB_FILE_RENAME_INFORMATION:
5016
0
    {
5017
0
      status = smb_file_rename_information(conn, req,
5018
0
                   pdata, total_data,
5019
0
                   fsp, smb_fname);
5020
0
      break;
5021
0
    }
5022
5023
0
    case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
5024
0
    {
5025
      /* SMB2 rename information. */
5026
0
      status = smb2_file_rename_information(conn,
5027
0
                    req,
5028
0
                    pdata,
5029
0
                    total_data,
5030
0
                    fsp,
5031
0
                    lck,
5032
0
                    smb_fname);
5033
0
      break;
5034
0
    }
5035
5036
0
    case SMB_FILE_LINK_INFORMATION:
5037
0
    {
5038
0
      status = smb_file_link_information(
5039
0
        conn, req, pdata, total_data, fsp, smb_fname);
5040
5041
0
      break;
5042
0
    }
5043
5044
0
    default:
5045
0
      return NT_STATUS_INVALID_LEVEL;
5046
0
  }
5047
5048
0
  if (!NT_STATUS_IS_OK(status)) {
5049
0
    return status;
5050
0
  }
5051
5052
0
  *ret_data_size = data_return_size;
5053
0
  return NT_STATUS_OK;
5054
0
}
5055
5056
static uint32_t generate_volume_serial_number(
5057
      const struct loadparm_substitution *lp_sub,
5058
      int snum)
5059
0
{
5060
0
  int serial = lp_volume_serial_number(snum);
5061
0
  return serial != -1 ? serial:
5062
0
    str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
5063
0
    (str_checksum(get_local_machine_name())<<16);
5064
0
}