Coverage Report

Created: 2025-07-23 07:04

/src/samba/source3/smbd/smb1_reply.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
   Unix SMB/CIFS implementation.
3
   Main SMB reply routines
4
   Copyright (C) Andrew Tridgell 1992-1998
5
   Copyright (C) Andrew Bartlett      2001
6
   Copyright (C) Jeremy Allison 1992-2007.
7
   Copyright (C) Volker Lendecke 2007
8
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 3 of the License, or
12
   (at your option) any later version.
13
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
19
   You should have received a copy of the GNU General Public License
20
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
*/
22
/*
23
   This file handles most of the reply_ calls that the server
24
   makes to handle specific protocols
25
*/
26
27
#include "includes.h"
28
#include "libsmb/namequery.h"
29
#include "system/filesys.h"
30
#include "printing.h"
31
#include "locking/share_mode_lock.h"
32
#include "smbd/smbd.h"
33
#include "smbd/globals.h"
34
#include "source3/smbd/smbXsrv_session.h"
35
#include "smbd/smbXsrv_open.h"
36
#include "fake_file.h"
37
#include "rpc_client/rpc_client.h"
38
#include "../librpc/gen_ndr/ndr_spoolss_c.h"
39
#include "rpc_client/cli_spoolss.h"
40
#include "rpc_client/init_spoolss.h"
41
#include "rpc_server/rpc_ncacn_np.h"
42
#include "libcli/security/security.h"
43
#include "libsmb/nmblib.h"
44
#include "auth.h"
45
#include "smbprofile.h"
46
#include "../lib/tsocket/tsocket.h"
47
#include "lib/util/tevent_ntstatus.h"
48
#include "libcli/smb/smb_signing.h"
49
#include "lib/util/sys_rw_data.h"
50
#include "librpc/gen_ndr/open_files.h"
51
#include "libcli/smb/smb2_posix.h"
52
#include "lib/util/string_wrappers.h"
53
#include "source3/printing/rap_jobid.h"
54
#include "source3/lib/substitute.h"
55
#include "source3/smbd/dir.h"
56
57
/****************************************************************************
58
 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
59
****************************************************************************/
60
61
bool check_fsp_open(connection_struct *conn, struct smb_request *req,
62
                    files_struct *fsp)
63
0
{
64
0
  if ((fsp == NULL) || (conn == NULL)) {
65
0
    reply_nterror(req, NT_STATUS_INVALID_HANDLE);
66
0
    return false;
67
0
  }
68
0
  if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
69
0
    reply_nterror(req, NT_STATUS_INVALID_HANDLE);
70
0
    return false;
71
0
  }
72
0
  return true;
73
0
}
74
75
/****************************************************************************
76
 SMB1 version of smb2_strip_dfs_path()
77
 Differs from SMB2 in that all Windows path separator '\' characters
78
 have already been converted to '/' by check_path_syntax().
79
****************************************************************************/
80
81
NTSTATUS smb1_strip_dfs_path(TALLOC_CTX *mem_ctx,
82
           uint32_t *_ucf_flags,
83
           char **in_path)
84
0
{
85
0
  uint32_t ucf_flags = *_ucf_flags;
86
0
  char *path = *in_path;
87
0
  char *return_path = NULL;
88
89
0
  if (!(ucf_flags & UCF_DFS_PATHNAME)) {
90
0
    return NT_STATUS_OK;
91
0
  }
92
93
  /* Strip any leading '/' characters - MacOSX client behavior. */
94
0
  while (*path == '/') {
95
0
    path++;
96
0
  }
97
98
  /* We should now be pointing at the server name. Go past it. */
99
0
  for (;;) {
100
0
    if (*path == '\0') {
101
      /* End of complete path. Exit OK. */
102
0
      goto done;
103
0
    }
104
0
    if (*path == '/') {
105
      /* End of server name. Go past and break. */
106
0
      path++;
107
0
      break;
108
0
    }
109
0
    path++; /* Continue looking for end of server name or string. */
110
0
  }
111
112
  /* We should now be pointing at the share name. Go past it. */
113
0
  for (;;) {
114
0
    if (*path == '\0') {
115
      /* End of complete path. Exit OK. */
116
0
      goto done;
117
0
                }
118
0
    if (*path == '/') {
119
      /* End of share name. Go past and break. */
120
0
      path++;
121
0
      break;
122
0
    }
123
0
    if (*path == ':') {
124
      /* Only invalid character in sharename. */
125
0
      return NT_STATUS_OBJECT_NAME_INVALID;
126
0
    }
127
0
    path++; /* Continue looking for end of share name or string. */
128
0
  }
129
130
0
  done:
131
  /* path now points at the start of the real filename (if any). */
132
  /* Duplicate it first. */
133
0
  return_path = talloc_strdup(mem_ctx, path);
134
0
  if (return_path == NULL) {
135
0
    return NT_STATUS_NO_MEMORY;
136
0
  }
137
138
  /* Now we can free the original (path points to part of this). */
139
0
  TALLOC_FREE(*in_path);
140
141
0
  *in_path = return_path;
142
0
  ucf_flags &= ~UCF_DFS_PATHNAME;
143
0
  *_ucf_flags = ucf_flags;
144
0
  return NT_STATUS_OK;
145
0
}
146
147
/****************************************************************************
148
 Check if we have a correct fsp pointing to a file.
149
****************************************************************************/
150
151
bool check_fsp(connection_struct *conn, struct smb_request *req,
152
               files_struct *fsp)
153
0
{
154
0
  if (!check_fsp_open(conn, req, fsp)) {
155
0
    return false;
156
0
  }
157
0
  if (fsp->fsp_flags.is_directory) {
158
0
    reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
159
0
    return false;
160
0
  }
161
0
  if (fsp_get_pathref_fd(fsp) == -1) {
162
0
    reply_nterror(req, NT_STATUS_ACCESS_DENIED);
163
0
    return false;
164
0
  }
165
0
  fsp->num_smb_operations++;
166
0
  return true;
167
0
}
168
169
/****************************************************************************
170
 Reply to a tcon.
171
 conn POINTER CAN BE NULL HERE !
172
****************************************************************************/
173
174
void reply_tcon(struct smb_request *req)
175
0
{
176
0
  connection_struct *conn = req->conn;
177
0
  const char *service;
178
0
  char *service_buf = NULL;
179
0
  char *password = NULL;
180
0
  char *dev = NULL;
181
0
  int pwlen=0;
182
0
  NTSTATUS nt_status;
183
0
  const uint8_t *p;
184
0
  const char *p2;
185
0
  TALLOC_CTX *ctx = talloc_tos();
186
0
  struct smbXsrv_connection *xconn = req->xconn;
187
0
  NTTIME now = timeval_to_nttime(&req->request_time);
188
189
0
  START_PROFILE(SMBtcon);
190
191
0
  if (req->buflen < 4) {
192
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
193
0
    END_PROFILE(SMBtcon);
194
0
    return;
195
0
  }
196
197
0
  p = req->buf + 1;
198
0
  p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
199
0
  p += 1;
200
0
  pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
201
0
  p += pwlen+1;
202
0
  p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
203
0
  p += 1;
204
205
0
  if (service_buf == NULL || password == NULL || dev == NULL) {
206
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
207
0
    END_PROFILE(SMBtcon);
208
0
    return;
209
0
  }
210
0
  p2 = strrchr_m(service_buf,'\\');
211
0
  if (p2) {
212
0
    service = p2+1;
213
0
  } else {
214
0
    service = service_buf;
215
0
  }
216
217
0
  conn = make_connection(req, now, service, dev,
218
0
             req->vuid,&nt_status);
219
0
  req->conn = conn;
220
221
0
  if (!conn) {
222
0
    reply_nterror(req, nt_status);
223
0
    END_PROFILE(SMBtcon);
224
0
    return;
225
0
  }
226
227
0
  reply_smb1_outbuf(req, 2, 0);
228
0
  SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
229
0
  SSVAL(req->outbuf,smb_vwv1,conn->cnum);
230
0
  SSVAL(req->outbuf,smb_tid,conn->cnum);
231
232
0
  DEBUG(3,("tcon service=%s cnum=%d\n",
233
0
     service, conn->cnum));
234
235
0
  END_PROFILE(SMBtcon);
236
0
  return;
237
0
}
238
239
/****************************************************************************
240
 Reply to a tcon and X.
241
 conn POINTER CAN BE NULL HERE !
242
****************************************************************************/
243
244
void reply_tcon_and_X(struct smb_request *req)
245
0
{
246
0
  const struct loadparm_substitution *lp_sub =
247
0
    loadparm_s3_global_substitution();
248
0
  connection_struct *conn = req->conn;
249
0
  const char *service = NULL;
250
0
  TALLOC_CTX *ctx = talloc_tos();
251
  /* what the client thinks the device is */
252
0
  char *client_devicetype = NULL;
253
  /* what the server tells the client the share represents */
254
0
  const char *server_devicetype;
255
0
  NTSTATUS nt_status;
256
0
  int passlen;
257
0
  char *path = NULL;
258
0
  const uint8_t *p;
259
0
  const char *q;
260
0
  uint16_t tcon_flags;
261
0
  struct smbXsrv_session *session = NULL;
262
0
  NTTIME now = timeval_to_nttime(&req->request_time);
263
0
  bool session_key_updated = false;
264
0
  uint16_t optional_support = 0;
265
0
  struct smbXsrv_connection *xconn = req->xconn;
266
267
0
  START_PROFILE(SMBtconX);
268
269
0
  if (req->wct < 4) {
270
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
271
0
    END_PROFILE(SMBtconX);
272
0
    return;
273
0
  }
274
275
0
  passlen = SVAL(req->vwv+3, 0);
276
0
  tcon_flags = SVAL(req->vwv+2, 0);
277
278
  /* we might have to close an old one */
279
0
  if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
280
0
    struct smbXsrv_tcon *tcon;
281
0
    NTSTATUS status;
282
283
0
    tcon = conn->tcon;
284
0
    req->conn = NULL;
285
0
    conn = NULL;
286
287
    /*
288
     * TODO: cancel all outstanding requests on the tcon
289
     */
290
0
    status = smbXsrv_tcon_disconnect(tcon, req->vuid);
291
0
    if (!NT_STATUS_IS_OK(status)) {
292
0
      DEBUG(0, ("reply_tcon_and_X: "
293
0
          "smbXsrv_tcon_disconnect() failed: %s\n",
294
0
          nt_errstr(status)));
295
      /*
296
       * If we hit this case, there is something completely
297
       * wrong, so we better disconnect the transport connection.
298
       */
299
0
      END_PROFILE(SMBtconX);
300
0
      exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
301
0
      return;
302
0
    }
303
304
0
    TALLOC_FREE(tcon);
305
    /*
306
     * This tree id is gone. Make sure we can't re-use it
307
     * by accident.
308
     */
309
0
    req->tid = 0;
310
0
  }
311
312
0
  if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
313
0
    reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
314
0
    END_PROFILE(SMBtconX);
315
0
    return;
316
0
  }
317
318
0
  if (xconn->smb1.negprot.encrypted_passwords) {
319
0
    p = req->buf + passlen;
320
0
  } else {
321
0
    p = req->buf + passlen + 1;
322
0
  }
323
324
0
  p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
325
326
0
  if (path == NULL) {
327
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
328
0
    END_PROFILE(SMBtconX);
329
0
    return;
330
0
  }
331
332
  /*
333
   * the service name can be either: \\server\share
334
   * or share directly like on the DELL PowerVault 705
335
   */
336
0
  if (*path=='\\') {
337
0
    q = strchr_m(path+2,'\\');
338
0
    if (!q) {
339
0
      reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
340
0
      END_PROFILE(SMBtconX);
341
0
      return;
342
0
    }
343
0
    service = q+1;
344
0
  } else {
345
0
    service = path;
346
0
  }
347
348
0
  p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
349
0
        &client_devicetype, p,
350
0
        MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
351
352
0
  if (client_devicetype == NULL) {
353
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
354
0
    END_PROFILE(SMBtconX);
355
0
    return;
356
0
  }
357
358
0
  DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
359
360
0
  nt_status = smb1srv_session_lookup(xconn,
361
0
             req->vuid, now, &session);
362
0
  if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
363
0
    reply_force_doserror(req, ERRSRV, ERRbaduid);
364
0
    END_PROFILE(SMBtconX);
365
0
    return;
366
0
  }
367
0
  if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
368
0
    reply_nterror(req, nt_status);
369
0
    END_PROFILE(SMBtconX);
370
0
    return;
371
0
  }
372
0
  if (!NT_STATUS_IS_OK(nt_status)) {
373
0
    reply_nterror(req, NT_STATUS_INVALID_HANDLE);
374
0
    END_PROFILE(SMBtconX);
375
0
    return;
376
0
  }
377
378
0
  if (session->global->auth_session_info == NULL) {
379
0
    reply_nterror(req, NT_STATUS_INVALID_HANDLE);
380
0
    END_PROFILE(SMBtconX);
381
0
    return;
382
0
  }
383
384
  /*
385
   * If there is no application key defined yet
386
   * we create one.
387
   *
388
   * This means we setup the application key on the
389
   * first tcon that happens via the given session.
390
   *
391
   * Once the application key is defined, it does not
392
   * change any more.
393
   */
394
0
  if (session->global->application_key_blob.length == 0 &&
395
0
      smb2_signing_key_valid(session->global->signing_key))
396
0
  {
397
0
    struct smbXsrv_session *x = session;
398
0
    struct auth_session_info *session_info =
399
0
      session->global->auth_session_info;
400
0
    uint8_t session_key[16];
401
402
0
    ZERO_STRUCT(session_key);
403
0
    memcpy(session_key, x->global->signing_key->blob.data,
404
0
           MIN(x->global->signing_key->blob.length, sizeof(session_key)));
405
406
    /*
407
     * The application key is truncated/padded to 16 bytes
408
     */
409
0
    x->global->application_key_blob = data_blob_talloc(x->global,
410
0
                   session_key,
411
0
                   sizeof(session_key));
412
0
    ZERO_STRUCT(session_key);
413
0
    if (x->global->application_key_blob.data == NULL) {
414
0
      reply_nterror(req, NT_STATUS_NO_MEMORY);
415
0
      END_PROFILE(SMBtconX);
416
0
      return;
417
0
    }
418
0
    talloc_keep_secret(x->global->application_key_blob.data);
419
420
0
    if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
421
0
      NTSTATUS status;
422
423
0
      status = smb1_key_derivation(x->global->application_key_blob.data,
424
0
                x->global->application_key_blob.length,
425
0
                x->global->application_key_blob.data);
426
0
      if (!NT_STATUS_IS_OK(status)) {
427
0
        DBG_ERR("smb1_key_derivation failed: %s\n",
428
0
          nt_errstr(status));
429
0
        END_PROFILE(SMBtconX);
430
0
        return;
431
0
      }
432
0
      optional_support |= SMB_EXTENDED_SIGNATURES;
433
0
    }
434
435
    /*
436
     * Place the application key into the session_info
437
     */
438
0
    data_blob_clear_free(&session_info->session_key);
439
0
    session_info->session_key = data_blob_dup_talloc(session_info,
440
0
            x->global->application_key_blob);
441
0
    if (session_info->session_key.data == NULL) {
442
0
      data_blob_clear_free(&x->global->application_key_blob);
443
0
      reply_nterror(req, NT_STATUS_NO_MEMORY);
444
0
      END_PROFILE(SMBtconX);
445
0
      return;
446
0
    }
447
0
    talloc_keep_secret(session_info->session_key.data);
448
0
    session_key_updated = true;
449
0
  }
450
451
0
  conn = make_connection(req, now, service, client_devicetype,
452
0
             req->vuid, &nt_status);
453
0
  req->conn =conn;
454
455
0
  if (!conn) {
456
0
    if (session_key_updated) {
457
0
      struct smbXsrv_session *x = session;
458
0
      struct auth_session_info *session_info =
459
0
        session->global->auth_session_info;
460
0
      data_blob_clear_free(&x->global->application_key_blob);
461
0
      data_blob_clear_free(&session_info->session_key);
462
0
    }
463
0
    reply_nterror(req, nt_status);
464
0
    END_PROFILE(SMBtconX);
465
0
    return;
466
0
  }
467
468
0
  if ( IS_IPC(conn) )
469
0
    server_devicetype = "IPC";
470
0
  else if ( IS_PRINT(conn) )
471
0
    server_devicetype = "LPT1:";
472
0
  else
473
0
    server_devicetype = "A:";
474
475
0
  if (xconn->protocol < PROTOCOL_NT1) {
476
0
    reply_smb1_outbuf(req, 2, 0);
477
0
    if (message_push_string(&req->outbuf, server_devicetype,
478
0
          STR_TERMINATE|STR_ASCII) == -1) {
479
0
      reply_nterror(req, NT_STATUS_NO_MEMORY);
480
0
      END_PROFILE(SMBtconX);
481
0
      return;
482
0
    }
483
0
  } else {
484
    /* NT sets the fstype of IPC$ to the null string */
485
0
    const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
486
487
0
    if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
488
      /* Return permissions. */
489
0
      uint32_t perm1 = 0;
490
0
      uint32_t perm2 = 0;
491
492
0
      reply_smb1_outbuf(req, 7, 0);
493
494
0
      if (IS_IPC(conn)) {
495
0
        perm1 = FILE_ALL_ACCESS;
496
0
        perm2 = FILE_ALL_ACCESS;
497
0
      } else {
498
0
        perm1 = conn->share_access;
499
0
      }
500
501
0
      SIVAL(req->outbuf, smb_vwv3, perm1);
502
0
      SIVAL(req->outbuf, smb_vwv5, perm2);
503
0
    } else {
504
0
      reply_smb1_outbuf(req, 3, 0);
505
0
    }
506
507
0
    if ((message_push_string(&req->outbuf, server_devicetype,
508
0
           STR_TERMINATE|STR_ASCII) == -1)
509
0
        || (message_push_string(&req->outbuf, fstype,
510
0
              STR_TERMINATE) == -1)) {
511
0
      reply_nterror(req, NT_STATUS_NO_MEMORY);
512
0
      END_PROFILE(SMBtconX);
513
0
      return;
514
0
    }
515
516
    /* what does setting this bit do? It is set by NT4 and
517
       may affect the ability to autorun mounted cdroms */
518
0
    optional_support |= SMB_SUPPORT_SEARCH_BITS;
519
0
    optional_support |=
520
0
      (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
521
522
0
    if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
523
0
      DEBUG(2,("Serving %s as a Dfs root\n",
524
0
         lp_servicename(ctx, lp_sub, SNUM(conn)) ));
525
0
      optional_support |= SMB_SHARE_IN_DFS;
526
0
    }
527
528
0
    SSVAL(req->outbuf, smb_vwv2, optional_support);
529
0
  }
530
531
0
  SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
532
0
  SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
533
534
0
  DEBUG(3,("tconX service=%s \n",
535
0
     service));
536
537
  /* set the incoming and outgoing tid to the just created one */
538
0
  SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
539
0
  SSVAL(req->outbuf,smb_tid,conn->cnum);
540
541
0
  END_PROFILE(SMBtconX);
542
543
0
  req->tid = conn->cnum;
544
0
}
545
546
/****************************************************************************
547
 Reply to an unknown type.
548
****************************************************************************/
549
550
void reply_unknown_new(struct smb_request *req, uint8_t type)
551
0
{
552
0
  DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
553
0
      smb_fn_name(type), type, type));
554
0
  reply_force_doserror(req, ERRSRV, ERRunknownsmb);
555
0
  return;
556
0
}
557
558
/****************************************************************************
559
 Reply to an ioctl.
560
 conn POINTER CAN BE NULL HERE !
561
****************************************************************************/
562
563
void reply_ioctl(struct smb_request *req)
564
0
{
565
0
  const struct loadparm_substitution *lp_sub =
566
0
    loadparm_s3_global_substitution();
567
0
  connection_struct *conn = req->conn;
568
0
  uint16_t device;
569
0
  uint16_t function;
570
0
  uint32_t ioctl_code;
571
0
  int replysize;
572
0
  char *p;
573
574
0
  START_PROFILE(SMBioctl);
575
576
0
  if (req->wct < 3) {
577
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
578
0
    END_PROFILE(SMBioctl);
579
0
    return;
580
0
  }
581
582
0
  device     = SVAL(req->vwv+1, 0);
583
0
  function   = SVAL(req->vwv+2, 0);
584
0
  ioctl_code = (device << 16) + function;
585
586
0
  DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
587
588
0
  switch (ioctl_code) {
589
0
      case IOCTL_QUERY_JOB_INFO:
590
0
        replysize = 32;
591
0
        break;
592
0
      default:
593
0
        reply_force_doserror(req, ERRSRV, ERRnosupport);
594
0
        END_PROFILE(SMBioctl);
595
0
        return;
596
0
  }
597
598
0
  reply_smb1_outbuf(req, 8, replysize+1);
599
0
  SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
600
0
  SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
601
0
  SSVAL(req->outbuf,smb_vwv6,52);        /* Offset to data */
602
0
  p = smb_buf(req->outbuf);
603
0
  memset(p, '\0', replysize+1); /* valgrind-safe. */
604
0
  p += 1;          /* Allow for alignment */
605
606
0
  switch (ioctl_code) {
607
0
    case IOCTL_QUERY_JOB_INFO:
608
0
    {
609
0
      NTSTATUS status;
610
0
      size_t len = 0;
611
0
      files_struct *fsp = file_fsp(
612
0
        req, SVAL(req->vwv+0, 0));
613
0
      if (!fsp) {
614
0
        reply_nterror(req, NT_STATUS_INVALID_HANDLE);
615
0
        END_PROFILE(SMBioctl);
616
0
        return;
617
0
      }
618
      /* Job number */
619
0
      SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
620
621
0
      status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
622
0
            lp_netbios_name(), 15,
623
0
            STR_TERMINATE|STR_ASCII, &len);
624
0
      if (!NT_STATUS_IS_OK(status)) {
625
0
        reply_nterror(req, status);
626
0
        END_PROFILE(SMBioctl);
627
0
        return;
628
0
      }
629
0
      if (conn) {
630
0
        status = srvstr_push((char *)req->outbuf, req->flags2,
631
0
              p+18,
632
0
              lp_servicename(talloc_tos(),
633
0
                 lp_sub,
634
0
                 SNUM(conn)),
635
0
              13, STR_TERMINATE|STR_ASCII, &len);
636
0
        if (!NT_STATUS_IS_OK(status)) {
637
0
          reply_nterror(req, status);
638
0
          END_PROFILE(SMBioctl);
639
0
          return;
640
0
        }
641
0
      } else {
642
0
        memset(p+18, 0, 13);
643
0
      }
644
0
      break;
645
0
    }
646
0
  }
647
648
0
  END_PROFILE(SMBioctl);
649
0
  return;
650
0
}
651
652
/****************************************************************************
653
 Strange checkpath NTSTATUS mapping.
654
****************************************************************************/
655
656
static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
657
0
{
658
  /* Strange DOS error code semantics only for checkpath... */
659
0
  if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
660
0
    if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
661
      /* We need to map to ERRbadpath */
662
0
      return NT_STATUS_OBJECT_PATH_NOT_FOUND;
663
0
    }
664
0
  }
665
0
  return status;
666
0
}
667
668
/****************************************************************************
669
 Reply to a checkpath.
670
****************************************************************************/
671
672
void reply_checkpath(struct smb_request *req)
673
0
{
674
0
  connection_struct *conn = req->conn;
675
0
  struct smb_filename *smb_fname = NULL;
676
0
  char *name = NULL;
677
0
  NTSTATUS status;
678
0
  struct files_struct *dirfsp = NULL;
679
0
  uint32_t ucf_flags = ucf_flags_from_smb_request(req);
680
0
  NTTIME twrp = 0;
681
0
  TALLOC_CTX *ctx = talloc_tos();
682
683
0
  START_PROFILE(SMBcheckpath);
684
685
0
  srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
686
0
          STR_TERMINATE, &status);
687
688
0
  if (!NT_STATUS_IS_OK(status)) {
689
0
    status = map_checkpath_error(req->flags2, status);
690
0
    reply_nterror(req, status);
691
0
    END_PROFILE(SMBcheckpath);
692
0
    return;
693
0
  }
694
695
0
  DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
696
697
0
  if (ucf_flags & UCF_GMT_PATHNAME) {
698
0
    extract_snapshot_token(name, &twrp);
699
0
  }
700
0
  status = smb1_strip_dfs_path(ctx, &ucf_flags, &name);
701
0
  if (!NT_STATUS_IS_OK(status)) {
702
0
    reply_nterror(req, status);
703
0
    goto out;
704
0
  }
705
706
0
  status = filename_convert_dirfsp(ctx,
707
0
           conn,
708
0
           name,
709
0
           ucf_flags,
710
0
           twrp,
711
0
           &dirfsp,
712
0
           &smb_fname);
713
0
  if (!NT_STATUS_IS_OK(status)) {
714
0
    if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
715
0
      reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
716
0
          ERRSRV, ERRbadpath);
717
0
      END_PROFILE(SMBcheckpath);
718
0
      return;
719
0
    }
720
0
    goto path_err;
721
0
  }
722
723
0
  if (!VALID_STAT(smb_fname->st)) {
724
0
    DBG_NOTICE("%s not found\n", smb_fname_str_dbg(smb_fname));
725
0
    status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
726
0
    goto path_err;
727
0
  }
728
729
0
  if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
730
0
    reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
731
0
        ERRDOS, ERRbadpath);
732
0
    goto out;
733
0
  }
734
735
0
  reply_smb1_outbuf(req, 0, 0);
736
737
0
 path_err:
738
  /* We special case this - as when a Windows machine
739
    is parsing a path is steps through the components
740
    one at a time - if a component fails it expects
741
    ERRbadpath, not ERRbadfile.
742
  */
743
0
  status = map_checkpath_error(req->flags2, status);
744
0
  if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
745
    /*
746
     * Windows returns different error codes if
747
     * the parent directory is valid but not the
748
     * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
749
     * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
750
     * if the path is invalid.
751
     */
752
0
    reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
753
0
        ERRDOS, ERRbadpath);
754
0
    goto out;
755
0
  }
756
757
0
  reply_nterror(req, status);
758
759
0
 out:
760
0
  TALLOC_FREE(smb_fname);
761
0
  END_PROFILE(SMBcheckpath);
762
0
  return;
763
0
}
764
765
/****************************************************************************
766
 Reply to a getatr.
767
****************************************************************************/
768
769
void reply_getatr(struct smb_request *req)
770
0
{
771
0
  struct smbXsrv_connection *xconn = req->xconn;
772
0
  connection_struct *conn = req->conn;
773
0
  struct smb_filename *smb_fname = NULL;
774
0
  char *fname = NULL;
775
0
  int mode=0;
776
0
  off_t size=0;
777
0
  time_t mtime=0;
778
0
  const char *p;
779
0
  NTSTATUS status;
780
0
  TALLOC_CTX *ctx = talloc_tos();
781
782
0
  START_PROFILE(SMBgetatr);
783
784
0
  p = (const char *)req->buf + 1;
785
0
  p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
786
0
  if (!NT_STATUS_IS_OK(status)) {
787
0
    reply_nterror(req, status);
788
0
    goto out;
789
0
  }
790
791
  /*
792
   * dos sometimes asks for a stat of "" - it returns a "hidden
793
   * directory" under WfWg - weird!
794
   */
795
0
  if (*fname == '\0') {
796
0
    mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
797
0
    if (!CAN_WRITE(conn)) {
798
0
      mode |= FILE_ATTRIBUTE_READONLY;
799
0
    }
800
0
    size = 0;
801
0
    mtime = 0;
802
0
  } else {
803
0
    struct files_struct *dirfsp = NULL;
804
0
    uint32_t ucf_flags = ucf_flags_from_smb_request(req);
805
0
    NTTIME twrp = 0;
806
807
0
    if (ucf_flags & UCF_GMT_PATHNAME) {
808
0
      extract_snapshot_token(fname, &twrp);
809
0
    }
810
0
    status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
811
0
    if (!NT_STATUS_IS_OK(status)) {
812
0
      reply_nterror(req, status);
813
0
      goto out;
814
0
    }
815
0
    status = filename_convert_dirfsp(ctx,
816
0
             conn,
817
0
             fname,
818
0
             ucf_flags,
819
0
             twrp,
820
0
             &dirfsp,
821
0
             &smb_fname);
822
0
    if (!NT_STATUS_IS_OK(status)) {
823
0
      if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
824
0
        reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
825
0
            ERRSRV, ERRbadpath);
826
0
        goto out;
827
0
      }
828
0
      reply_nterror(req, status);
829
0
      goto out;
830
0
    }
831
0
    if (!VALID_STAT(smb_fname->st)) {
832
0
      DBG_NOTICE("File %s not found\n",
833
0
           smb_fname_str_dbg(smb_fname));
834
0
      reply_nterror(req,  map_nt_error_from_unix(errno));
835
0
      goto out;
836
0
    }
837
838
0
    mode = fdos_mode(smb_fname->fsp);
839
0
    size = smb_fname->st.st_ex_size;
840
841
0
    mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
842
0
    if (mode & FILE_ATTRIBUTE_DIRECTORY) {
843
0
      size = 0;
844
0
    }
845
0
  }
846
847
0
  reply_smb1_outbuf(req, 10, 0);
848
849
0
  SSVAL(req->outbuf,smb_vwv0,mode);
850
0
  if(lp_dos_filetime_resolution(SNUM(conn)) ) {
851
0
    srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
852
0
  } else {
853
0
    srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
854
0
  }
855
0
  SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
856
857
0
  if (xconn->protocol >= PROTOCOL_NT1) {
858
0
    SSVAL(req->outbuf, smb_flg2,
859
0
          SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
860
0
  }
861
862
0
  DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
863
0
     smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
864
865
0
 out:
866
0
  TALLOC_FREE(smb_fname);
867
0
  TALLOC_FREE(fname);
868
0
  END_PROFILE(SMBgetatr);
869
0
  return;
870
0
}
871
872
/****************************************************************************
873
 Reply to a setatr.
874
****************************************************************************/
875
876
void reply_setatr(struct smb_request *req)
877
0
{
878
0
  struct smb_file_time ft;
879
0
  connection_struct *conn = req->conn;
880
0
  struct smb_filename *smb_fname = NULL;
881
0
  struct files_struct *dirfsp = NULL;
882
0
  char *fname = NULL;
883
0
  int mode;
884
0
  time_t mtime;
885
0
  const char *p;
886
0
  NTSTATUS status;
887
0
  uint32_t ucf_flags = ucf_flags_from_smb_request(req);
888
0
  NTTIME twrp = 0;
889
0
  TALLOC_CTX *ctx = talloc_tos();
890
891
0
  START_PROFILE(SMBsetatr);
892
0
  init_smb_file_time(&ft);
893
894
0
  if (req->wct < 2) {
895
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
896
0
    goto out;
897
0
  }
898
899
0
  p = (const char *)req->buf + 1;
900
0
  p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
901
0
  if (!NT_STATUS_IS_OK(status)) {
902
0
    reply_nterror(req, status);
903
0
    goto out;
904
0
  }
905
906
0
  if (ucf_flags & UCF_GMT_PATHNAME) {
907
0
    extract_snapshot_token(fname, &twrp);
908
0
  }
909
0
  status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
910
0
  if (!NT_STATUS_IS_OK(status)) {
911
0
    reply_nterror(req, status);
912
0
    goto out;
913
0
  }
914
0
  status = filename_convert_dirfsp(ctx,
915
0
           conn,
916
0
           fname,
917
0
           ucf_flags,
918
0
           twrp,
919
0
           &dirfsp,
920
0
           &smb_fname);
921
0
  if (!NT_STATUS_IS_OK(status)) {
922
0
    if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
923
0
      reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
924
0
          ERRSRV, ERRbadpath);
925
0
      goto out;
926
0
    }
927
0
    reply_nterror(req, status);
928
0
    goto out;
929
0
  }
930
931
0
  if (ISDOT(smb_fname->base_name)) {
932
    /*
933
     * Not sure here is the right place to catch this
934
     * condition. Might be moved to somewhere else later -- vl
935
     */
936
0
    reply_nterror(req, NT_STATUS_ACCESS_DENIED);
937
0
    goto out;
938
0
  }
939
940
0
  if (smb_fname->fsp == NULL) {
941
    /*
942
     * filename_convert_dirfsp only returns a NULL fsp for
943
     * new files.
944
     */
945
0
    reply_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
946
0
    goto out;
947
0
  }
948
949
0
  mode = SVAL(req->vwv+0, 0);
950
0
  mtime = srv_make_unix_date3(req->vwv+1);
951
952
0
  if (mode != FILE_ATTRIBUTE_NORMAL) {
953
0
    if (VALID_STAT_OF_DIR(smb_fname->st))
954
0
      mode |= FILE_ATTRIBUTE_DIRECTORY;
955
0
    else
956
0
      mode &= ~FILE_ATTRIBUTE_DIRECTORY;
957
958
0
    status = smbd_check_access_rights_fsp(conn->cwd_fsp,
959
0
          smb_fname->fsp,
960
0
          false,
961
0
          FILE_WRITE_ATTRIBUTES);
962
0
    if (!NT_STATUS_IS_OK(status)) {
963
0
      reply_nterror(req, status);
964
0
      goto out;
965
0
    }
966
967
0
    if (file_set_dosmode(conn, smb_fname, mode, NULL,
968
0
             false) != 0) {
969
0
      reply_nterror(req, map_nt_error_from_unix(errno));
970
0
      goto out;
971
0
    }
972
0
  }
973
974
0
  ft.mtime = time_t_to_full_timespec(mtime);
975
976
0
  status = smb_set_file_time(conn, smb_fname->fsp, smb_fname, &ft, true);
977
0
  if (!NT_STATUS_IS_OK(status)) {
978
0
    reply_nterror(req, status);
979
0
    goto out;
980
0
  }
981
982
0
  reply_smb1_outbuf(req, 0, 0);
983
984
0
  DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
985
0
     mode));
986
0
 out:
987
0
  TALLOC_FREE(smb_fname);
988
0
  END_PROFILE(SMBsetatr);
989
0
  return;
990
0
}
991
992
/****************************************************************************
993
 Reply to a dskattr.
994
****************************************************************************/
995
996
void reply_dskattr(struct smb_request *req)
997
0
{
998
0
  struct smbXsrv_connection *xconn = req->xconn;
999
0
  connection_struct *conn = req->conn;
1000
0
  uint64_t ret;
1001
0
  uint64_t dfree,dsize,bsize;
1002
0
  struct smb_filename smb_fname;
1003
0
  START_PROFILE(SMBdskattr);
1004
1005
0
  ZERO_STRUCT(smb_fname);
1006
0
  smb_fname.base_name = discard_const_p(char, ".");
1007
1008
0
  if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1009
0
    reply_nterror(req, map_nt_error_from_unix(errno));
1010
0
    DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1011
0
    END_PROFILE(SMBdskattr);
1012
0
    return;
1013
0
  }
1014
1015
0
  ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1016
0
  if (ret == (uint64_t)-1) {
1017
0
    reply_nterror(req, map_nt_error_from_unix(errno));
1018
0
    END_PROFILE(SMBdskattr);
1019
0
    return;
1020
0
  }
1021
1022
  /*
1023
   * Force max to fit in 16 bit fields.
1024
   */
1025
0
  while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1026
0
    dfree /= 2;
1027
0
    dsize /= 2;
1028
0
    bsize *= 2;
1029
0
    if (bsize > (WORDMAX*512)) {
1030
0
      bsize = (WORDMAX*512);
1031
0
      if (dsize > WORDMAX)
1032
0
        dsize = WORDMAX;
1033
0
      if (dfree >  WORDMAX)
1034
0
        dfree = WORDMAX;
1035
0
      break;
1036
0
    }
1037
0
  }
1038
1039
0
  reply_smb1_outbuf(req, 5, 0);
1040
1041
0
  if (xconn->protocol <= PROTOCOL_LANMAN2) {
1042
0
    double total_space, free_space;
1043
    /* we need to scale this to a number that DOS6 can handle. We
1044
       use floating point so we can handle large drives on systems
1045
       that don't have 64 bit integers
1046
1047
       we end up displaying a maximum of 2G to DOS systems
1048
    */
1049
0
    total_space = dsize * (double)bsize;
1050
0
    free_space = dfree * (double)bsize;
1051
1052
0
    dsize = (uint64_t)((total_space+63*512) / (64*512));
1053
0
    dfree = (uint64_t)((free_space+63*512) / (64*512));
1054
1055
0
    if (dsize > 0xFFFF) dsize = 0xFFFF;
1056
0
    if (dfree > 0xFFFF) dfree = 0xFFFF;
1057
1058
0
    SSVAL(req->outbuf,smb_vwv0,dsize);
1059
0
    SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1060
0
    SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1061
0
    SSVAL(req->outbuf,smb_vwv3,dfree);
1062
0
  } else {
1063
0
    SSVAL(req->outbuf,smb_vwv0,dsize);
1064
0
    SSVAL(req->outbuf,smb_vwv1,bsize/512);
1065
0
    SSVAL(req->outbuf,smb_vwv2,512);
1066
0
    SSVAL(req->outbuf,smb_vwv3,dfree);
1067
0
  }
1068
1069
0
  DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1070
1071
0
  END_PROFILE(SMBdskattr);
1072
0
  return;
1073
0
}
1074
1075
/****************************************************************************
1076
 Make a dir struct.
1077
****************************************************************************/
1078
1079
static void make_dir_struct(char *buf,
1080
          const char *mask,
1081
          const char *fname,
1082
          off_t size,
1083
          uint32_t mode,
1084
          time_t date,
1085
          bool uc)
1086
0
{
1087
0
  char *p;
1088
1089
0
  if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1090
0
    size = 0;
1091
0
  }
1092
1093
0
  memset(buf+1,' ',11);
1094
0
  if ((p = strchr_m(mask, '.')) != NULL) {
1095
0
    char name[p - mask + 1];
1096
0
    strlcpy(name, mask, sizeof(name));
1097
0
    push_ascii(buf + 1, name, 8, 0);
1098
0
    push_ascii(buf+9,p+1,3, 0);
1099
0
  } else {
1100
0
    push_ascii(buf + 1, mask, 11, 0);
1101
0
  }
1102
1103
0
  memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1104
0
  SCVAL(buf,21,mode);
1105
0
  srv_put_dos_date(buf,22,date);
1106
0
  SSVAL(buf,26,size & 0xFFFF);
1107
0
  SSVAL(buf,28,(size >> 16)&0xFFFF);
1108
  /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1109
     Strange, but verified on W2K3. Needed for OS/2. JRA. */
1110
0
  push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1111
0
  DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1112
0
}
1113
1114
/*******************************************************************
1115
 A wrapper that handles case sensitivity and the special handling
1116
 of the ".." name.
1117
*******************************************************************/
1118
1119
static bool mask_match_search(const char *string,
1120
            const char *pattern,
1121
            bool is_case_sensitive)
1122
0
{
1123
0
  if (ISDOTDOT(string)) {
1124
0
    string = ".";
1125
0
  }
1126
0
  if (ISDOT(pattern)) {
1127
0
    return False;
1128
0
  }
1129
1130
0
  return ms_fnmatch(pattern, string, True, is_case_sensitive) == 0;
1131
0
}
1132
1133
static bool mangle_mask_match(connection_struct *conn,
1134
            const char *filename,
1135
            const char *mask)
1136
0
{
1137
0
  char mname[13];
1138
1139
0
  if (!name_to_8_3(filename, mname, False, conn->params)) {
1140
0
    return False;
1141
0
  }
1142
0
  return mask_match_search(mname, mask, False);
1143
0
}
1144
1145
/****************************************************************************
1146
 Get an 8.3 directory entry.
1147
****************************************************************************/
1148
1149
static bool smbd_dirptr_8_3_match_fn(TALLOC_CTX *ctx,
1150
             void *private_data,
1151
             const char *dname,
1152
             const char *mask,
1153
             char **_fname)
1154
0
{
1155
0
  connection_struct *conn = (connection_struct *)private_data;
1156
1157
0
  if ((strcmp(mask, "*.*") == 0) ||
1158
0
      mask_match_search(dname, mask, false) ||
1159
0
      mangle_mask_match(conn, dname, mask)) {
1160
0
    char mname[13];
1161
0
    const char *fname;
1162
    /*
1163
     * Ensure we can push the original name as UCS2. If
1164
     * not, then just don't return this name.
1165
     */
1166
0
    NTSTATUS status;
1167
0
    size_t ret_len = 0;
1168
0
    size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1169
0
    uint8_t *tmp = talloc_array(talloc_tos(), uint8_t, len);
1170
1171
0
    status = srvstr_push(NULL,
1172
0
             FLAGS2_UNICODE_STRINGS,
1173
0
             tmp,
1174
0
             dname,
1175
0
             len,
1176
0
             STR_TERMINATE,
1177
0
             &ret_len);
1178
1179
0
    TALLOC_FREE(tmp);
1180
1181
0
    if (!NT_STATUS_IS_OK(status)) {
1182
0
      return false;
1183
0
    }
1184
1185
0
    if (!mangle_is_8_3(dname, false, conn->params)) {
1186
0
      bool ok =
1187
0
        name_to_8_3(dname, mname, false, conn->params);
1188
0
      if (!ok) {
1189
0
        return false;
1190
0
      }
1191
0
      fname = mname;
1192
0
    } else {
1193
0
      fname = dname;
1194
0
    }
1195
1196
0
    *_fname = talloc_strdup(ctx, fname);
1197
0
    if (*_fname == NULL) {
1198
0
      return false;
1199
0
    }
1200
1201
0
    return true;
1202
0
  }
1203
1204
0
  return false;
1205
0
}
1206
1207
static bool get_dir_entry(TALLOC_CTX *ctx,
1208
        connection_struct *conn,
1209
        struct dptr_struct *dirptr,
1210
        const char *mask,
1211
        uint32_t dirtype,
1212
        char **_fname,
1213
        off_t *_size,
1214
        uint32_t *_mode,
1215
        struct timespec *_date,
1216
        bool check_descend)
1217
0
{
1218
0
  char *fname = NULL;
1219
0
  struct smb_filename *smb_fname = NULL;
1220
0
  uint32_t mode = 0;
1221
0
  bool ok;
1222
1223
0
again:
1224
0
  ok = smbd_dirptr_get_entry(ctx,
1225
0
           dirptr,
1226
0
           mask,
1227
0
           dirtype,
1228
0
           check_descend,
1229
0
           true,
1230
0
           smbd_dirptr_8_3_match_fn,
1231
0
           conn,
1232
0
           &fname,
1233
0
           &smb_fname,
1234
0
           &mode);
1235
0
  if (!ok) {
1236
0
    return false;
1237
0
  }
1238
0
  if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1239
    /* hide reparse points from ancient clients */
1240
0
    TALLOC_FREE(fname);
1241
0
    TALLOC_FREE(smb_fname);
1242
0
    goto again;
1243
0
  }
1244
1245
0
  *_fname = talloc_move(ctx, &fname);
1246
0
  *_size = smb_fname->st.st_ex_size;
1247
0
  *_mode = mode;
1248
0
  *_date = smb_fname->st.st_ex_mtime;
1249
0
  TALLOC_FREE(smb_fname);
1250
0
  return true;
1251
0
}
1252
1253
/****************************************************************************
1254
 Reply to a search.
1255
 Can be called from SMBsearch, SMBffirst or SMBfunique.
1256
****************************************************************************/
1257
1258
void reply_search(struct smb_request *req)
1259
0
{
1260
0
  connection_struct *conn = req->conn;
1261
0
  char *path = NULL;
1262
0
  char *mask = NULL;
1263
0
  char *directory = NULL;
1264
0
  struct smb_filename *smb_fname = NULL;
1265
0
  char *fname = NULL;
1266
0
  off_t size;
1267
0
  uint32_t mode;
1268
0
  struct timespec date;
1269
0
  uint32_t dirtype;
1270
0
  unsigned int numentries = 0;
1271
0
  unsigned int maxentries = 0;
1272
0
  bool finished = False;
1273
0
  const char *p;
1274
0
  int status_len;
1275
0
  char status[21];
1276
0
  int dptr_num= -1;
1277
0
  bool check_descend = False;
1278
0
  bool expect_close = False;
1279
0
  NTSTATUS nt_status;
1280
0
  bool mask_contains_wcard = False;
1281
0
  bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1282
0
  TALLOC_CTX *ctx = talloc_tos();
1283
0
  struct smbXsrv_connection *xconn = req->xconn;
1284
0
  struct smbd_server_connection *sconn = req->sconn;
1285
0
  files_struct *fsp = NULL;
1286
0
  const struct loadparm_substitution *lp_sub =
1287
0
    loadparm_s3_global_substitution();
1288
1289
0
  START_PROFILE(SMBsearch);
1290
1291
0
  if (req->wct < 2) {
1292
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1293
0
    goto out;
1294
0
  }
1295
1296
0
  if (req->posix_pathnames) {
1297
0
    reply_unknown_new(req, req->cmd);
1298
0
    goto out;
1299
0
  }
1300
1301
  /* If we were called as SMBffirst then we must expect close. */
1302
0
  if(req->cmd == SMBffirst) {
1303
0
    expect_close = True;
1304
0
  }
1305
1306
0
  reply_smb1_outbuf(req, 1, 3);
1307
0
  maxentries = SVAL(req->vwv+0, 0);
1308
0
  dirtype = SVAL(req->vwv+1, 0);
1309
0
  p = (const char *)req->buf + 1;
1310
0
  p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
1311
0
               &nt_status);
1312
0
  if (!NT_STATUS_IS_OK(nt_status)) {
1313
0
    reply_nterror(req, nt_status);
1314
0
    goto out;
1315
0
  }
1316
1317
0
  if (smbreq_bufrem(req, p) < 3) {
1318
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1319
0
    goto out;
1320
0
  }
1321
1322
0
  p++;
1323
0
  status_len = SVAL(p, 0);
1324
0
  p += 2;
1325
1326
  /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1327
1328
0
  if (status_len == 0) {
1329
0
    const char *dirpath;
1330
0
    struct files_struct *dirfsp = NULL;
1331
0
    struct smb_filename *smb_dname = NULL;
1332
0
    uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1333
1334
0
    nt_status = smb1_strip_dfs_path(ctx, &ucf_flags, &path);
1335
0
    if (!NT_STATUS_IS_OK(nt_status)) {
1336
0
      reply_nterror(req, nt_status);
1337
0
      goto out;
1338
0
    }
1339
1340
0
    nt_status = filename_convert_smb1_search_path(ctx,
1341
0
          conn,
1342
0
          path,
1343
0
          ucf_flags,
1344
0
          &dirfsp,
1345
0
          &smb_dname,
1346
0
          &mask);
1347
1348
0
    if (!NT_STATUS_IS_OK(nt_status)) {
1349
0
      if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1350
0
        reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1351
0
            ERRSRV, ERRbadpath);
1352
0
        goto out;
1353
0
      }
1354
0
      reply_nterror(req, nt_status);
1355
0
      goto out;
1356
0
    }
1357
1358
0
    memset((char *)status,'\0',21);
1359
0
    SCVAL(status,0,(dirtype & 0x1F));
1360
1361
    /*
1362
     * Open an fsp on this directory for the dptr.
1363
     */
1364
0
    nt_status = SMB_VFS_CREATE_FILE(
1365
0
        conn, /* conn */
1366
0
        req, /* req */
1367
0
        dirfsp, /* dirfsp */
1368
0
        smb_dname, /* dname */
1369
0
        FILE_LIST_DIRECTORY, /* access_mask */
1370
0
        FILE_SHARE_READ|
1371
0
        FILE_SHARE_WRITE, /* share_access */
1372
0
        FILE_OPEN, /* create_disposition*/
1373
0
        FILE_DIRECTORY_FILE, /* create_options */
1374
0
        FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1375
0
        NO_OPLOCK, /* oplock_request */
1376
0
        NULL, /* lease */
1377
0
        0, /* allocation_size */
1378
0
        0, /* private_flags */
1379
0
        NULL, /* sd */
1380
0
        NULL, /* ea_list */
1381
0
        &fsp, /* result */
1382
0
        NULL, /* pinfo */
1383
0
        NULL, /* in_context */
1384
0
        NULL);/* out_context */
1385
1386
0
    if (!NT_STATUS_IS_OK(nt_status)) {
1387
0
      DBG_ERR("failed to open directory %s\n",
1388
0
        smb_fname_str_dbg(smb_dname));
1389
0
      reply_nterror(req, nt_status);
1390
0
      goto out;
1391
0
    }
1392
1393
0
    nt_status = dptr_create(conn,
1394
0
          NULL, /* req */
1395
0
          fsp, /* fsp */
1396
0
          True,
1397
0
          mask,
1398
0
          dirtype,
1399
0
          &fsp->dptr);
1400
1401
0
    TALLOC_FREE(smb_dname);
1402
1403
0
    if (!NT_STATUS_IS_OK(nt_status)) {
1404
      /*
1405
       * Use NULL here for the first parameter (req)
1406
       * as this is not a client visible handle so
1407
       * can't be part of an SMB1 chain.
1408
       */
1409
0
      close_file_free(NULL, &fsp, NORMAL_CLOSE);
1410
0
      reply_nterror(req, nt_status);
1411
0
      goto out;
1412
0
    }
1413
1414
0
    dptr_num = dptr_dnum(fsp->dptr);
1415
0
    dirpath = dptr_path(sconn, dptr_num);
1416
0
    directory = talloc_strdup(ctx, dirpath);
1417
0
    if (!directory) {
1418
0
      reply_nterror(req, NT_STATUS_NO_MEMORY);
1419
0
      goto out;
1420
0
    }
1421
1422
0
  } else {
1423
0
    int status_dirtype;
1424
0
    const char *dirpath;
1425
0
    unsigned int dptr_filenum;
1426
0
    uint32_t resume_key_index;
1427
1428
0
    if (smbreq_bufrem(req, p) < 21) {
1429
0
      reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1430
0
      goto out;
1431
0
    }
1432
1433
0
    memcpy(status,p,21);
1434
0
    status_dirtype = CVAL(status,0) & 0x1F;
1435
0
    if (status_dirtype != (dirtype & 0x1F)) {
1436
0
      dirtype = status_dirtype;
1437
0
    }
1438
1439
0
    dptr_num = CVAL(status, 12);
1440
0
    fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
1441
0
    if (fsp == NULL) {
1442
0
      goto SearchEmpty;
1443
0
    }
1444
1445
0
    resume_key_index = PULL_LE_U32(status, 13);
1446
0
    dptr_filenum = dptr_FileNumber(fsp->dptr);
1447
1448
0
    if (resume_key_index > dptr_filenum) {
1449
      /*
1450
       * Haven't seen this resume key yet. Just stop
1451
       * the search.
1452
       */
1453
0
      goto SearchEmpty;
1454
0
    }
1455
1456
0
    if (resume_key_index < dptr_filenum) {
1457
      /*
1458
       * The resume key was not the last one we
1459
       * sent, rewind and skip to what the client
1460
       * sent.
1461
       */
1462
0
      dptr_RewindDir(fsp->dptr);
1463
1464
0
      dptr_filenum = dptr_FileNumber(fsp->dptr);
1465
0
      SMB_ASSERT(dptr_filenum == 0);
1466
1467
0
      while (dptr_filenum < resume_key_index) {
1468
0
        bool ok = get_dir_entry(
1469
0
          ctx,
1470
0
          conn,
1471
0
          fsp->dptr,
1472
0
          dptr_wcard(sconn, dptr_num),
1473
0
          dirtype,
1474
0
          &fname,
1475
0
          &size,
1476
0
          &mode,
1477
0
          &date,
1478
0
          check_descend);
1479
0
        TALLOC_FREE(fname);
1480
0
        if (!ok) {
1481
0
          goto SearchEmpty;
1482
0
        }
1483
1484
0
        dptr_filenum = dptr_FileNumber(fsp->dptr);
1485
0
      }
1486
0
    }
1487
1488
0
    dirpath = dptr_path(sconn, dptr_num);
1489
0
    directory = talloc_strdup(ctx, dirpath);
1490
0
    if (!directory) {
1491
0
      reply_nterror(req, NT_STATUS_NO_MEMORY);
1492
0
      goto out;
1493
0
    }
1494
1495
0
    mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1496
0
    if (!mask) {
1497
0
      goto SearchEmpty;
1498
0
    }
1499
0
    dirtype = dptr_attr(sconn, dptr_num);
1500
0
  }
1501
1502
0
  mask_contains_wcard = dptr_has_wild(fsp->dptr);
1503
1504
0
  DEBUG(4,("dptr_num is %d\n",dptr_num));
1505
1506
0
  if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1507
0
    char buf[DIR_STRUCT_SIZE];
1508
0
    memcpy(buf,status,21);
1509
0
    make_dir_struct(buf,
1510
0
        "???????????",
1511
0
        volume_label(ctx, SNUM(conn)),
1512
0
        0,
1513
0
        FILE_ATTRIBUTE_VOLUME,
1514
0
        0,
1515
0
        !allow_long_path_components);
1516
0
    SCVAL(buf, 12, dptr_num);
1517
0
    numentries = 1;
1518
0
    if (message_push_blob(&req->outbuf,
1519
0
              data_blob_const(buf, sizeof(buf)))
1520
0
        == -1) {
1521
0
      reply_nterror(req, NT_STATUS_NO_MEMORY);
1522
0
      goto out;
1523
0
    }
1524
0
  } else {
1525
0
    unsigned int i;
1526
0
    size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1527
0
    size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1528
1529
0
    maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1530
1531
0
    DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1532
0
       directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
1533
0
    if (in_list(directory, lp_dont_descend(ctx, lp_sub, SNUM(conn)),True)) {
1534
0
      check_descend = True;
1535
0
    }
1536
1537
0
    for (i=numentries;(i<maxentries) && !finished;i++) {
1538
0
      finished = !get_dir_entry(ctx,
1539
0
              conn,
1540
0
              fsp->dptr,
1541
0
              mask,
1542
0
              dirtype,
1543
0
              &fname,
1544
0
              &size,
1545
0
              &mode,
1546
0
              &date,
1547
0
              check_descend);
1548
0
      if (!finished) {
1549
0
        char buf[DIR_STRUCT_SIZE];
1550
0
        memcpy(buf,status,21);
1551
0
        make_dir_struct(buf,
1552
0
            mask,
1553
0
            fname,
1554
0
            size,
1555
0
            mode,
1556
0
            convert_timespec_to_time_t(
1557
0
              date),
1558
0
            !allow_long_path_components);
1559
0
        SCVAL(buf, 12, dptr_num);
1560
0
        PUSH_LE_U32(buf,
1561
0
              13,
1562
0
              dptr_FileNumber(fsp->dptr));
1563
0
        if (message_push_blob(&req->outbuf,
1564
0
                  data_blob_const(buf, sizeof(buf)))
1565
0
            == -1) {
1566
0
          reply_nterror(req, NT_STATUS_NO_MEMORY);
1567
0
          goto out;
1568
0
        }
1569
0
        numentries++;
1570
0
      }
1571
0
      TALLOC_FREE(fname);
1572
0
    }
1573
0
  }
1574
1575
0
  SearchEmpty:
1576
1577
  /* If we were called as SMBffirst with smb_search_id == NULL
1578
    and no entries were found then return error and close fsp->dptr
1579
    (X/Open spec) */
1580
1581
0
  if (numentries == 0) {
1582
0
    dptr_num = -1;
1583
0
    if (fsp != NULL) {
1584
0
      close_file_free(NULL, &fsp, NORMAL_CLOSE);
1585
0
    }
1586
0
  } else if(expect_close && status_len == 0) {
1587
    /* Close the dptr - we know it's gone */
1588
0
    dptr_num = -1;
1589
0
    if (fsp != NULL) {
1590
0
      close_file_free(NULL, &fsp, NORMAL_CLOSE);
1591
0
    }
1592
0
  }
1593
1594
  /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
1595
0
  if(dptr_num >= 0 && req->cmd == SMBfunique) {
1596
0
    dptr_num = -1;
1597
    /* fsp may have been closed above. */
1598
0
    if (fsp != NULL) {
1599
0
      close_file_free(NULL, &fsp, NORMAL_CLOSE);
1600
0
    }
1601
0
  }
1602
1603
0
  if ((numentries == 0) && !mask_contains_wcard) {
1604
0
    reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1605
0
    goto out;
1606
0
  }
1607
1608
0
  SSVAL(req->outbuf,smb_vwv0,numentries);
1609
0
  SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1610
0
  SCVAL(smb_buf(req->outbuf),0,5);
1611
0
  SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1612
1613
  /* The replies here are never long name. */
1614
0
  SSVAL(req->outbuf, smb_flg2,
1615
0
        SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1616
0
  if (!allow_long_path_components) {
1617
0
    SSVAL(req->outbuf, smb_flg2,
1618
0
          SVAL(req->outbuf, smb_flg2)
1619
0
          & (~FLAGS2_LONG_PATH_COMPONENTS));
1620
0
  }
1621
1622
  /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1623
0
  SSVAL(req->outbuf, smb_flg2,
1624
0
        (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1625
1626
0
  DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1627
0
    smb_fn_name(req->cmd),
1628
0
    mask,
1629
0
    directory,
1630
0
    dirtype,
1631
0
    numentries,
1632
0
    maxentries ));
1633
0
 out:
1634
0
  TALLOC_FREE(directory);
1635
0
  TALLOC_FREE(mask);
1636
0
  TALLOC_FREE(smb_fname);
1637
0
  END_PROFILE(SMBsearch);
1638
0
  return;
1639
0
}
1640
1641
/****************************************************************************
1642
 Reply to a fclose (stop directory search).
1643
****************************************************************************/
1644
1645
void reply_fclose(struct smb_request *req)
1646
0
{
1647
0
  int status_len;
1648
0
  int dptr_num= -2;
1649
0
  const char *p;
1650
0
  char *path = NULL;
1651
0
  NTSTATUS err;
1652
0
  TALLOC_CTX *ctx = talloc_tos();
1653
0
  struct smbd_server_connection *sconn = req->sconn;
1654
0
  files_struct *fsp = NULL;
1655
1656
0
  START_PROFILE(SMBfclose);
1657
1658
0
  if (req->posix_pathnames) {
1659
0
    reply_unknown_new(req, req->cmd);
1660
0
    END_PROFILE(SMBfclose);
1661
0
    return;
1662
0
  }
1663
1664
0
  p = (const char *)req->buf + 1;
1665
0
  p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
1666
0
               &err);
1667
0
  if (!NT_STATUS_IS_OK(err)) {
1668
0
    reply_nterror(req, err);
1669
0
    END_PROFILE(SMBfclose);
1670
0
    return;
1671
0
  }
1672
1673
0
  if (smbreq_bufrem(req, p) < 3) {
1674
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1675
0
    END_PROFILE(SMBfclose);
1676
0
    return;
1677
0
  }
1678
1679
0
  p++;
1680
0
  status_len = SVAL(p,0);
1681
0
  p += 2;
1682
1683
0
  if (status_len == 0) {
1684
0
    reply_force_doserror(req, ERRSRV, ERRsrverror);
1685
0
    END_PROFILE(SMBfclose);
1686
0
    return;
1687
0
  }
1688
1689
0
  if (smbreq_bufrem(req, p) < 21) {
1690
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1691
0
    END_PROFILE(SMBfclose);
1692
0
    return;
1693
0
  }
1694
1695
0
  dptr_num = CVAL(p, 12);
1696
1697
0
  fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
1698
0
  if(fsp != NULL) {
1699
    /*  Close the file - we know it's gone */
1700
0
    close_file_free(NULL, &fsp, NORMAL_CLOSE);
1701
0
    dptr_num = -1;
1702
0
  }
1703
1704
0
  reply_smb1_outbuf(req, 1, 0);
1705
0
  SSVAL(req->outbuf,smb_vwv0,0);
1706
1707
0
  DEBUG(3,("search close\n"));
1708
1709
0
  END_PROFILE(SMBfclose);
1710
0
  return;
1711
0
}
1712
1713
/****************************************************************************
1714
 Reply to an open.
1715
****************************************************************************/
1716
1717
void reply_open(struct smb_request *req)
1718
0
{
1719
0
  connection_struct *conn = req->conn;
1720
0
  struct smb_filename *smb_fname = NULL;
1721
0
  char *fname = NULL;
1722
0
  uint32_t fattr=0;
1723
0
  off_t size = 0;
1724
0
  time_t mtime=0;
1725
0
  int info;
1726
0
  struct files_struct *dirfsp = NULL;
1727
0
  files_struct *fsp;
1728
0
  int oplock_request;
1729
0
  int deny_mode;
1730
0
  uint32_t dos_attr;
1731
0
  uint32_t access_mask;
1732
0
  uint32_t share_mode;
1733
0
  uint32_t create_disposition;
1734
0
  uint32_t create_options = 0;
1735
0
  uint32_t private_flags = 0;
1736
0
  NTSTATUS status;
1737
0
  uint32_t ucf_flags;
1738
0
  NTTIME twrp = 0;
1739
0
  TALLOC_CTX *ctx = talloc_tos();
1740
1741
0
  START_PROFILE(SMBopen);
1742
1743
0
  if (req->wct < 2) {
1744
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1745
0
    goto out;
1746
0
  }
1747
1748
0
  oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1749
0
  deny_mode = SVAL(req->vwv+0, 0);
1750
0
  dos_attr = SVAL(req->vwv+1, 0);
1751
1752
0
  srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1753
0
          STR_TERMINATE, &status);
1754
0
  if (!NT_STATUS_IS_OK(status)) {
1755
0
    reply_nterror(req, status);
1756
0
    goto out;
1757
0
  }
1758
1759
0
  if (!map_open_params_to_ntcreate(fname, deny_mode,
1760
0
           OPENX_FILE_EXISTS_OPEN, &access_mask,
1761
0
           &share_mode, &create_disposition,
1762
0
           &create_options, &private_flags)) {
1763
0
    reply_force_doserror(req, ERRDOS, ERRbadaccess);
1764
0
    goto out;
1765
0
  }
1766
1767
0
  ucf_flags = filename_create_ucf_flags(req,
1768
0
                create_disposition,
1769
0
                create_options);
1770
1771
0
  if (ucf_flags & UCF_GMT_PATHNAME) {
1772
0
    extract_snapshot_token(fname, &twrp);
1773
0
  }
1774
0
  status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
1775
0
  if (!NT_STATUS_IS_OK(status)) {
1776
0
    reply_nterror(req, status);
1777
0
    goto out;
1778
0
  }
1779
0
  status = filename_convert_dirfsp(ctx,
1780
0
           conn,
1781
0
           fname,
1782
0
           ucf_flags,
1783
0
           twrp,
1784
0
           &dirfsp,
1785
0
           &smb_fname);
1786
0
  if (!NT_STATUS_IS_OK(status)) {
1787
0
    if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1788
0
      reply_botherror(req,
1789
0
          NT_STATUS_PATH_NOT_COVERED,
1790
0
          ERRSRV, ERRbadpath);
1791
0
      goto out;
1792
0
    }
1793
0
    reply_nterror(req, status);
1794
0
    goto out;
1795
0
  }
1796
1797
0
  status = SMB_VFS_CREATE_FILE(
1798
0
    conn,         /* conn */
1799
0
    req,          /* req */
1800
0
    dirfsp,         /* dirfsp */
1801
0
    smb_fname,        /* fname */
1802
0
    access_mask,        /* access_mask */
1803
0
    share_mode,       /* share_access */
1804
0
    create_disposition,     /* create_disposition*/
1805
0
    create_options,       /* create_options */
1806
0
    dos_attr,       /* file_attributes */
1807
0
    oplock_request,       /* oplock_request */
1808
0
    NULL,         /* lease */
1809
0
    0,          /* allocation_size */
1810
0
    private_flags,
1811
0
    NULL,         /* sd */
1812
0
    NULL,         /* ea_list */
1813
0
    &fsp,         /* result */
1814
0
    &info,          /* pinfo */
1815
0
    NULL, NULL);        /* create context */
1816
1817
0
  if (!NT_STATUS_IS_OK(status)) {
1818
0
    if (open_was_deferred(req->xconn, req->mid)) {
1819
      /* We have re-scheduled this call. */
1820
0
      goto out;
1821
0
    }
1822
1823
0
    if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1824
0
      reply_openerror(req, status);
1825
0
      goto out;
1826
0
    }
1827
1828
0
    fsp = fcb_or_dos_open(
1829
0
      req,
1830
0
      smb_fname,
1831
0
      access_mask,
1832
0
      create_options,
1833
0
      private_flags);
1834
0
    if (fsp == NULL) {
1835
0
      bool ok = defer_smb1_sharing_violation(req);
1836
0
      if (ok) {
1837
0
        goto out;
1838
0
      }
1839
0
      reply_openerror(req, status);
1840
0
      goto out;
1841
0
    }
1842
0
  }
1843
1844
  /* Ensure we're pointing at the correct stat struct. */
1845
0
  TALLOC_FREE(smb_fname);
1846
0
  smb_fname = fsp->fsp_name;
1847
1848
0
  size = smb_fname->st.st_ex_size;
1849
0
  fattr = fdos_mode(fsp);
1850
1851
0
  mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1852
1853
0
  if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1854
0
    DEBUG(3,("attempt to open a directory %s\n",
1855
0
       fsp_str_dbg(fsp)));
1856
0
    close_file_free(req, &fsp, ERROR_CLOSE);
1857
0
    reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1858
0
      ERRDOS, ERRnoaccess);
1859
0
    goto out;
1860
0
  }
1861
1862
0
  reply_smb1_outbuf(req, 7, 0);
1863
0
  SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1864
0
  SSVAL(req->outbuf,smb_vwv1,fattr);
1865
0
  if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1866
0
    srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1867
0
  } else {
1868
0
    srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1869
0
  }
1870
0
  SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
1871
0
  SSVAL(req->outbuf,smb_vwv6,deny_mode);
1872
1873
0
  if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1874
0
    SCVAL(req->outbuf,smb_flg,
1875
0
          CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1876
0
  }
1877
1878
0
  if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1879
0
    SCVAL(req->outbuf,smb_flg,
1880
0
          CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1881
0
  }
1882
0
 out:
1883
0
  END_PROFILE(SMBopen);
1884
0
  return;
1885
0
}
1886
1887
/****************************************************************************
1888
 Reply to an open and X.
1889
****************************************************************************/
1890
1891
void reply_open_and_X(struct smb_request *req)
1892
0
{
1893
0
  connection_struct *conn = req->conn;
1894
0
  struct smb_filename *smb_fname = NULL;
1895
0
  char *fname = NULL;
1896
0
  uint16_t open_flags;
1897
0
  int deny_mode;
1898
0
  uint32_t smb_attr;
1899
  /* Breakout the oplock request bits so we can set the
1900
    reply bits separately. */
1901
0
  int ex_oplock_request;
1902
0
  int core_oplock_request;
1903
0
  int oplock_request;
1904
#if 0
1905
  int smb_sattr = SVAL(req->vwv+4, 0);
1906
  uint32_t smb_time = make_unix_date3(req->vwv+6);
1907
#endif
1908
0
  int smb_ofun;
1909
0
  uint32_t fattr=0;
1910
0
  time_t mtime=0;
1911
0
  int smb_action = 0;
1912
0
  struct files_struct *dirfsp = NULL;
1913
0
  files_struct *fsp;
1914
0
  NTSTATUS status;
1915
0
  uint64_t allocation_size;
1916
0
  ssize_t retval = -1;
1917
0
  uint32_t access_mask;
1918
0
  uint32_t share_mode;
1919
0
  uint32_t create_disposition;
1920
0
  uint32_t create_options = 0;
1921
0
  uint32_t private_flags = 0;
1922
0
  uint32_t ucf_flags;
1923
0
  NTTIME twrp = 0;
1924
0
  TALLOC_CTX *ctx = talloc_tos();
1925
1926
0
  START_PROFILE(SMBopenX);
1927
1928
0
  if (req->wct < 15) {
1929
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1930
0
    goto out;
1931
0
  }
1932
1933
0
  open_flags = SVAL(req->vwv+2, 0);
1934
0
  deny_mode = SVAL(req->vwv+3, 0);
1935
0
  smb_attr = SVAL(req->vwv+5, 0);
1936
0
  ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1937
0
  core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1938
0
  oplock_request = ex_oplock_request | core_oplock_request;
1939
0
  smb_ofun = SVAL(req->vwv+8, 0);
1940
0
  allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1941
1942
  /* If it's an IPC, pass off the pipe handler. */
1943
0
  if (IS_IPC(conn)) {
1944
0
    if (lp_nt_pipe_support()) {
1945
0
      reply_open_pipe_and_X(conn, req);
1946
0
    } else {
1947
0
      reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1948
0
    }
1949
0
    goto out;
1950
0
  }
1951
1952
  /* XXXX we need to handle passed times, sattr and flags */
1953
0
  srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1954
0
      STR_TERMINATE, &status);
1955
0
  if (!NT_STATUS_IS_OK(status)) {
1956
0
    reply_nterror(req, status);
1957
0
    goto out;
1958
0
  }
1959
1960
0
  if (!map_open_params_to_ntcreate(fname, deny_mode,
1961
0
           smb_ofun,
1962
0
           &access_mask, &share_mode,
1963
0
           &create_disposition,
1964
0
           &create_options,
1965
0
           &private_flags)) {
1966
0
    reply_force_doserror(req, ERRDOS, ERRbadaccess);
1967
0
    goto out;
1968
0
  }
1969
1970
0
  ucf_flags = filename_create_ucf_flags(req,
1971
0
                create_disposition,
1972
0
                create_options);
1973
1974
0
  if (ucf_flags & UCF_GMT_PATHNAME) {
1975
0
    extract_snapshot_token(fname, &twrp);
1976
0
  }
1977
0
  status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
1978
0
  if (!NT_STATUS_IS_OK(status)) {
1979
0
    reply_nterror(req, status);
1980
0
    goto out;
1981
0
  }
1982
1983
0
  status = filename_convert_dirfsp(ctx,
1984
0
           conn,
1985
0
           fname,
1986
0
           ucf_flags,
1987
0
           twrp,
1988
0
           &dirfsp,
1989
0
           &smb_fname);
1990
0
  if (!NT_STATUS_IS_OK(status)) {
1991
0
    if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1992
0
      reply_botherror(req,
1993
0
          NT_STATUS_PATH_NOT_COVERED,
1994
0
          ERRSRV, ERRbadpath);
1995
0
      goto out;
1996
0
    }
1997
0
    reply_nterror(req, status);
1998
0
    goto out;
1999
0
  }
2000
2001
0
  status = SMB_VFS_CREATE_FILE(
2002
0
    conn,         /* conn */
2003
0
    req,          /* req */
2004
0
    dirfsp,         /* dirfsp */
2005
0
    smb_fname,        /* fname */
2006
0
    access_mask,        /* access_mask */
2007
0
    share_mode,       /* share_access */
2008
0
    create_disposition,     /* create_disposition*/
2009
0
    create_options,       /* create_options */
2010
0
    smb_attr,       /* file_attributes */
2011
0
    oplock_request,       /* oplock_request */
2012
0
    NULL,         /* lease */
2013
0
    0,          /* allocation_size */
2014
0
    private_flags,
2015
0
    NULL,         /* sd */
2016
0
    NULL,         /* ea_list */
2017
0
    &fsp,         /* result */
2018
0
    &smb_action,        /* pinfo */
2019
0
    NULL, NULL);        /* create context */
2020
2021
0
  if (!NT_STATUS_IS_OK(status)) {
2022
0
    if (open_was_deferred(req->xconn, req->mid)) {
2023
      /* We have re-scheduled this call. */
2024
0
      goto out;
2025
0
    }
2026
2027
0
    if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2028
0
      reply_openerror(req, status);
2029
0
      goto out;
2030
0
    }
2031
2032
0
    fsp = fcb_or_dos_open(
2033
0
      req,
2034
0
      smb_fname,
2035
0
      access_mask,
2036
0
      create_options,
2037
0
      private_flags);
2038
0
    if (fsp == NULL) {
2039
0
      bool ok = defer_smb1_sharing_violation(req);
2040
0
      if (ok) {
2041
0
        goto out;
2042
0
      }
2043
0
      reply_openerror(req, status);
2044
0
      goto out;
2045
0
    }
2046
2047
2048
0
    smb_action = FILE_WAS_OPENED;
2049
0
  }
2050
2051
  /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2052
     if the file is truncated or created. */
2053
0
  if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2054
0
    fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2055
0
    if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2056
0
      close_file_free(req, &fsp, ERROR_CLOSE);
2057
0
      reply_nterror(req, NT_STATUS_DISK_FULL);
2058
0
      goto out;
2059
0
    }
2060
0
    retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2061
0
    if (retval < 0) {
2062
0
      close_file_free(req, &fsp, ERROR_CLOSE);
2063
0
      reply_nterror(req, NT_STATUS_DISK_FULL);
2064
0
      goto out;
2065
0
    }
2066
0
    status = vfs_stat_fsp(fsp);
2067
0
    if (!NT_STATUS_IS_OK(status)) {
2068
0
      close_file_free(req, &fsp, ERROR_CLOSE);
2069
0
      reply_nterror(req, status);
2070
0
      goto out;
2071
0
    }
2072
0
  }
2073
2074
0
  fattr = fdos_mode(fsp);
2075
0
  if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2076
0
    close_file_free(req, &fsp, ERROR_CLOSE);
2077
0
    reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2078
0
    goto out;
2079
0
  }
2080
0
  mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2081
2082
  /* If the caller set the extended oplock request bit
2083
    and we granted one (by whatever means) - set the
2084
    correct bit for extended oplock reply.
2085
  */
2086
2087
0
  if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2088
0
    smb_action |= EXTENDED_OPLOCK_GRANTED;
2089
0
  }
2090
2091
0
  if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2092
0
    smb_action |= EXTENDED_OPLOCK_GRANTED;
2093
0
  }
2094
2095
  /* If the caller set the core oplock request bit
2096
    and we granted one (by whatever means) - set the
2097
    correct bit for core oplock reply.
2098
  */
2099
2100
0
  if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2101
0
    reply_smb1_outbuf(req, 19, 0);
2102
0
  } else {
2103
0
    reply_smb1_outbuf(req, 15, 0);
2104
0
  }
2105
2106
0
  SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2107
0
  SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
2108
2109
0
  if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2110
0
    SCVAL(req->outbuf, smb_flg,
2111
0
          CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2112
0
  }
2113
2114
0
  if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2115
0
    SCVAL(req->outbuf, smb_flg,
2116
0
          CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2117
0
  }
2118
2119
0
  SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2120
0
  SSVAL(req->outbuf,smb_vwv3,fattr);
2121
0
  if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2122
0
    srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2123
0
  } else {
2124
0
    srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2125
0
  }
2126
0
  SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2127
0
  SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2128
0
  SSVAL(req->outbuf,smb_vwv11,smb_action);
2129
2130
0
  if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2131
0
    SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2132
0
  }
2133
2134
0
 out:
2135
0
  TALLOC_FREE(smb_fname);
2136
0
  END_PROFILE(SMBopenX);
2137
0
  return;
2138
0
}
2139
2140
/****************************************************************************
2141
 Reply to a SMBulogoffX.
2142
****************************************************************************/
2143
2144
static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2145
        struct smbXsrv_session *session);
2146
static void reply_ulogoffX_done(struct tevent_req *req);
2147
2148
void reply_ulogoffX(struct smb_request *smb1req)
2149
0
{
2150
0
  struct timeval now = timeval_current();
2151
0
  struct smbXsrv_session *session = NULL;
2152
0
  struct tevent_req *req;
2153
0
  NTSTATUS status;
2154
2155
  /*
2156
   * Don't setup the profile charge here, take
2157
   * it in reply_ulogoffX_done(). Not strictly correct
2158
   * but better than the other SMB1 async
2159
   * code that double-charges at the moment.
2160
   */
2161
2162
0
  status = smb1srv_session_lookup(smb1req->xconn,
2163
0
          smb1req->vuid,
2164
0
          timeval_to_nttime(&now),
2165
0
          &session);
2166
0
  if (!NT_STATUS_IS_OK(status)) {
2167
    /* Not going async, profile here. */
2168
0
    START_PROFILE(SMBulogoffX);
2169
0
    DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
2170
0
       (unsigned long long)smb1req->vuid);
2171
2172
0
    smb1req->vuid = UID_FIELD_INVALID;
2173
0
    reply_force_doserror(smb1req, ERRSRV, ERRbaduid);
2174
0
    END_PROFILE(SMBulogoffX);
2175
0
    return;
2176
0
  }
2177
2178
0
  req = reply_ulogoffX_send(smb1req, session);
2179
0
  if (req == NULL) {
2180
    /* Not going async, profile here. */
2181
0
    START_PROFILE(SMBulogoffX);
2182
0
    reply_force_doserror(smb1req, ERRDOS, ERRnomem);
2183
0
    END_PROFILE(SMBulogoffX);
2184
0
    return;
2185
0
  }
2186
2187
  /* We're async. This will complete later. */
2188
0
  tevent_req_set_callback(req, reply_ulogoffX_done, smb1req);
2189
0
  return;
2190
0
}
2191
2192
struct reply_ulogoffX_state {
2193
  struct tevent_queue *wait_queue;
2194
  struct smbXsrv_session *session;
2195
};
2196
2197
static void reply_ulogoffX_wait_done(struct tevent_req *subreq);
2198
2199
/****************************************************************************
2200
 Async SMB1 ulogoffX.
2201
 Note, on failure here we deallocate and return NULL to allow the caller to
2202
 SMB1 return an error of ERRnomem immediately.
2203
****************************************************************************/
2204
2205
static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2206
          struct smbXsrv_session *session)
2207
0
{
2208
0
  struct tevent_req *req;
2209
0
  struct reply_ulogoffX_state *state;
2210
0
  struct tevent_req *subreq;
2211
0
  files_struct *fsp;
2212
0
  struct smbd_server_connection *sconn = session->client->sconn;
2213
0
  uint64_t vuid = session->global->session_wire_id;
2214
2215
0
  req = tevent_req_create(smb1req, &state,
2216
0
      struct reply_ulogoffX_state);
2217
0
  if (req == NULL) {
2218
0
    return NULL;
2219
0
  }
2220
0
  state->wait_queue = tevent_queue_create(state,
2221
0
        "reply_ulogoffX_wait_queue");
2222
0
  if (tevent_req_nomem(state->wait_queue, req)) {
2223
0
    TALLOC_FREE(req);
2224
0
    return NULL;
2225
0
  }
2226
0
  state->session = session;
2227
2228
  /*
2229
   * Make sure that no new request will be able to use this session.
2230
   * This ensures that once all outstanding fsp->aio_requests
2231
   * on this session are done, we are safe to close it.
2232
   */
2233
0
  session->status = NT_STATUS_USER_SESSION_DELETED;
2234
2235
0
  for (fsp = sconn->files; fsp; fsp = fsp->next) {
2236
0
    if (fsp->vuid != vuid) {
2237
0
      continue;
2238
0
    }
2239
    /*
2240
     * Flag the file as close in progress.
2241
     * This will prevent any more IO being
2242
     * done on it.
2243
     */
2244
0
    fsp->fsp_flags.closing = true;
2245
2246
0
    if (fsp->num_aio_requests > 0) {
2247
      /*
2248
       * Now wait until all aio requests on this fsp are
2249
       * finished.
2250
       *
2251
       * We don't set a callback, as we just want to block the
2252
       * wait queue and the talloc_free() of fsp->aio_request
2253
       * will remove the item from the wait queue.
2254
       */
2255
0
      subreq = tevent_queue_wait_send(fsp->aio_requests,
2256
0
            sconn->ev_ctx,
2257
0
            state->wait_queue);
2258
0
      if (tevent_req_nomem(subreq, req)) {
2259
0
        TALLOC_FREE(req);
2260
0
        return NULL;
2261
0
      }
2262
0
    }
2263
0
  }
2264
2265
  /*
2266
   * Now we add our own waiter to the end of the queue,
2267
   * this way we get notified when all pending requests are finished
2268
   * and reply to the outstanding SMB1 request.
2269
   */
2270
0
  subreq = tevent_queue_wait_send(state,
2271
0
        sconn->ev_ctx,
2272
0
        state->wait_queue);
2273
0
  if (tevent_req_nomem(subreq, req)) {
2274
0
    TALLOC_FREE(req);
2275
0
    return NULL;
2276
0
  }
2277
2278
  /*
2279
   * We're really going async - move the SMB1 request from
2280
   * a talloc stackframe above us to the sconn talloc-context.
2281
   * We need this to stick around until the wait_done
2282
   * callback is invoked.
2283
   */
2284
0
  smb1req = talloc_move(sconn, &smb1req);
2285
2286
0
  tevent_req_set_callback(subreq, reply_ulogoffX_wait_done, req);
2287
2288
0
  return req;
2289
0
}
2290
2291
static void reply_ulogoffX_wait_done(struct tevent_req *subreq)
2292
0
{
2293
0
  struct tevent_req *req = tevent_req_callback_data(
2294
0
    subreq, struct tevent_req);
2295
2296
0
  tevent_queue_wait_recv(subreq);
2297
0
  TALLOC_FREE(subreq);
2298
0
  tevent_req_done(req);
2299
0
}
2300
2301
static NTSTATUS reply_ulogoffX_recv(struct tevent_req *req)
2302
0
{
2303
0
  return tevent_req_simple_recv_ntstatus(req);
2304
0
}
2305
2306
static void reply_ulogoffX_done(struct tevent_req *req)
2307
0
{
2308
0
  struct smb_request *smb1req = tevent_req_callback_data(
2309
0
    req, struct smb_request);
2310
0
  struct reply_ulogoffX_state *state = tevent_req_data(req,
2311
0
            struct reply_ulogoffX_state);
2312
0
  struct smbXsrv_session *session = state->session;
2313
0
  NTSTATUS status;
2314
2315
  /*
2316
   * Take the profile charge here. Not strictly
2317
   * correct but better than the other SMB1 async
2318
   * code that double-charges at the moment.
2319
   */
2320
0
  START_PROFILE(SMBulogoffX);
2321
2322
0
  status = reply_ulogoffX_recv(req);
2323
0
  TALLOC_FREE(req);
2324
0
  if (!NT_STATUS_IS_OK(status)) {
2325
0
    TALLOC_FREE(smb1req);
2326
0
    END_PROFILE(SMBulogoffX);
2327
0
    exit_server(__location__ ": reply_ulogoffX_recv failed");
2328
0
    return;
2329
0
  }
2330
2331
0
  status = smbXsrv_session_logoff(session);
2332
0
  if (!NT_STATUS_IS_OK(status)) {
2333
0
    TALLOC_FREE(smb1req);
2334
0
    END_PROFILE(SMBulogoffX);
2335
0
    exit_server(__location__ ": smbXsrv_session_logoff failed");
2336
0
    return;
2337
0
  }
2338
2339
0
  TALLOC_FREE(session);
2340
2341
0
  reply_smb1_outbuf(smb1req, 2, 0);
2342
0
  SSVAL(smb1req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2343
0
  SSVAL(smb1req->outbuf, smb_vwv1, 0);    /* no andx offset */
2344
2345
0
  DBG_NOTICE("ulogoffX vuid=%llu\n",
2346
0
      (unsigned long long)smb1req->vuid);
2347
2348
0
  smb1req->vuid = UID_FIELD_INVALID;
2349
  /*
2350
   * The following call is needed to push the
2351
   * reply data back out the socket after async
2352
   * return. Plus it frees smb1req.
2353
   */
2354
0
  smb_request_done(smb1req);
2355
0
  END_PROFILE(SMBulogoffX);
2356
0
}
2357
2358
/****************************************************************************
2359
 Reply to a mknew or a create.
2360
****************************************************************************/
2361
2362
void reply_mknew(struct smb_request *req)
2363
0
{
2364
0
  connection_struct *conn = req->conn;
2365
0
  struct smb_filename *smb_fname = NULL;
2366
0
  char *fname = NULL;
2367
0
  uint32_t fattr = 0;
2368
0
  struct smb_file_time ft;
2369
0
  struct files_struct *dirfsp = NULL;
2370
0
  files_struct *fsp;
2371
0
  int oplock_request = 0;
2372
0
  NTSTATUS status;
2373
0
  uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2374
0
  uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2375
0
  uint32_t create_disposition;
2376
0
  uint32_t create_options = 0;
2377
0
  uint32_t ucf_flags;
2378
0
  NTTIME twrp = 0;
2379
0
  TALLOC_CTX *ctx = talloc_tos();
2380
2381
0
  START_PROFILE(SMBcreate);
2382
0
  init_smb_file_time(&ft);
2383
2384
0
        if (req->wct < 3) {
2385
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2386
0
    goto out;
2387
0
  }
2388
2389
0
  fattr = SVAL(req->vwv+0, 0);
2390
0
  oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2391
2392
0
  if (req->cmd == SMBmknew) {
2393
    /* We should fail if file exists. */
2394
0
    create_disposition = FILE_CREATE;
2395
0
  } else {
2396
    /* Create if file doesn't exist, truncate if it does. */
2397
0
    create_disposition = FILE_OVERWRITE_IF;
2398
0
  }
2399
2400
  /* mtime. */
2401
0
  ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
2402
2403
0
  srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2404
0
          STR_TERMINATE, &status);
2405
0
  if (!NT_STATUS_IS_OK(status)) {
2406
0
    reply_nterror(req, status);
2407
0
    goto out;
2408
0
  }
2409
2410
0
  ucf_flags = filename_create_ucf_flags(req,
2411
0
                create_disposition,
2412
0
                create_options);
2413
0
  if (ucf_flags & UCF_GMT_PATHNAME) {
2414
0
    extract_snapshot_token(fname, &twrp);
2415
0
  }
2416
0
  status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
2417
0
  if (!NT_STATUS_IS_OK(status)) {
2418
0
    reply_nterror(req, status);
2419
0
    goto out;
2420
0
  }
2421
2422
0
  status = filename_convert_dirfsp(ctx,
2423
0
           conn,
2424
0
           fname,
2425
0
           ucf_flags,
2426
0
           twrp,
2427
0
           &dirfsp,
2428
0
           &smb_fname);
2429
0
  if (!NT_STATUS_IS_OK(status)) {
2430
0
    if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2431
0
      reply_botherror(req,
2432
0
          NT_STATUS_PATH_NOT_COVERED,
2433
0
          ERRSRV, ERRbadpath);
2434
0
      goto out;
2435
0
    }
2436
0
    reply_nterror(req, status);
2437
0
    goto out;
2438
0
  }
2439
2440
0
  if (fattr & FILE_ATTRIBUTE_VOLUME) {
2441
0
    DEBUG(0,("Attempt to create file (%s) with volid set - "
2442
0
       "please report this\n",
2443
0
       smb_fname_str_dbg(smb_fname)));
2444
0
  }
2445
2446
0
  status = SMB_VFS_CREATE_FILE(
2447
0
    conn,         /* conn */
2448
0
    req,          /* req */
2449
0
    dirfsp,         /* dirfsp */
2450
0
    smb_fname,        /* fname */
2451
0
    access_mask,        /* access_mask */
2452
0
    share_mode,       /* share_access */
2453
0
    create_disposition,     /* create_disposition*/
2454
0
    create_options,       /* create_options */
2455
0
    fattr,          /* file_attributes */
2456
0
    oplock_request,       /* oplock_request */
2457
0
    NULL,         /* lease */
2458
0
    0,          /* allocation_size */
2459
0
    0,          /* private_flags */
2460
0
    NULL,         /* sd */
2461
0
    NULL,         /* ea_list */
2462
0
    &fsp,         /* result */
2463
0
    NULL,         /* pinfo */
2464
0
    NULL, NULL);        /* create context */
2465
2466
0
  if (!NT_STATUS_IS_OK(status)) {
2467
0
    if (open_was_deferred(req->xconn, req->mid)) {
2468
      /* We have re-scheduled this call. */
2469
0
      goto out;
2470
0
    }
2471
0
    if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2472
0
      bool ok = defer_smb1_sharing_violation(req);
2473
0
      if (ok) {
2474
0
        goto out;
2475
0
      }
2476
0
    }
2477
0
    reply_openerror(req, status);
2478
0
    goto out;
2479
0
  }
2480
2481
0
  ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2482
0
  status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2483
0
  if (!NT_STATUS_IS_OK(status)) {
2484
0
    END_PROFILE(SMBcreate);
2485
0
    goto out;
2486
0
  }
2487
2488
0
  reply_smb1_outbuf(req, 1, 0);
2489
0
  SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2490
2491
0
  if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2492
0
    SCVAL(req->outbuf,smb_flg,
2493
0
        CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2494
0
  }
2495
2496
0
  if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2497
0
    SCVAL(req->outbuf,smb_flg,
2498
0
        CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2499
0
  }
2500
2501
0
  DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2502
0
  DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2503
0
      smb_fname_str_dbg(smb_fname), fsp_get_io_fd(fsp),
2504
0
      (unsigned int)fattr));
2505
2506
0
 out:
2507
0
  TALLOC_FREE(smb_fname);
2508
0
  END_PROFILE(SMBcreate);
2509
0
  return;
2510
0
}
2511
2512
/****************************************************************************
2513
 Reply to a create temporary file.
2514
****************************************************************************/
2515
2516
void reply_ctemp(struct smb_request *req)
2517
0
{
2518
0
  connection_struct *conn = req->conn;
2519
0
  struct smb_filename *smb_fname = NULL;
2520
0
  char *wire_name = NULL;
2521
0
  char *fname = NULL;
2522
0
  uint32_t fattr;
2523
0
  struct files_struct *dirfsp = NULL;
2524
0
  files_struct *fsp;
2525
0
  int oplock_request;
2526
0
  char *s;
2527
0
  NTSTATUS status;
2528
0
  int i;
2529
0
  uint32_t ucf_flags;
2530
0
  NTTIME twrp = 0;
2531
0
  TALLOC_CTX *ctx = talloc_tos();
2532
2533
0
  START_PROFILE(SMBctemp);
2534
2535
0
  if (req->wct < 3) {
2536
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2537
0
    goto out;
2538
0
  }
2539
2540
0
  fattr = SVAL(req->vwv+0, 0);
2541
0
  oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2542
2543
0
  srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2544
0
          STR_TERMINATE, &status);
2545
0
  if (!NT_STATUS_IS_OK(status)) {
2546
0
    reply_nterror(req, status);
2547
0
    goto out;
2548
0
  }
2549
2550
0
  for (i = 0; i < 10; i++) {
2551
0
    char rand_str[6];
2552
2553
0
    generate_random_str_list_buf(rand_str,
2554
0
               sizeof(rand_str),
2555
0
               "0123456789");
2556
2557
0
    if (*wire_name) {
2558
0
      fname = talloc_asprintf(ctx,
2559
0
            "%s/TMP%s",
2560
0
            wire_name,
2561
0
            rand_str);
2562
0
    } else {
2563
0
      fname = talloc_asprintf(ctx, "TMP%s", rand_str);
2564
0
    }
2565
2566
0
    if (!fname) {
2567
0
      reply_nterror(req, NT_STATUS_NO_MEMORY);
2568
0
      goto out;
2569
0
    }
2570
2571
0
    ucf_flags = filename_create_ucf_flags(req, FILE_CREATE, 0);
2572
0
    if (ucf_flags & UCF_GMT_PATHNAME) {
2573
0
      extract_snapshot_token(fname, &twrp);
2574
0
    }
2575
0
    status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
2576
0
    if (!NT_STATUS_IS_OK(status)) {
2577
0
      reply_nterror(req, status);
2578
0
      goto out;
2579
0
    }
2580
2581
0
    status = filename_convert_dirfsp(ctx,
2582
0
             conn,
2583
0
             fname,
2584
0
             ucf_flags,
2585
0
             twrp,
2586
0
             &dirfsp,
2587
0
             &smb_fname);
2588
0
    if (!NT_STATUS_IS_OK(status)) {
2589
0
      if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2590
0
        reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2591
0
          ERRSRV, ERRbadpath);
2592
0
        goto out;
2593
0
      }
2594
0
      reply_nterror(req, status);
2595
0
      goto out;
2596
0
    }
2597
2598
    /* Create the file. */
2599
0
    status = SMB_VFS_CREATE_FILE(
2600
0
      conn,         /* conn */
2601
0
      req,          /* req */
2602
0
      dirfsp,         /* dirfsp */
2603
0
      smb_fname,        /* fname */
2604
0
      FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2605
0
      FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2606
0
      FILE_CREATE,        /* create_disposition*/
2607
0
      0,          /* create_options */
2608
0
      fattr,          /* file_attributes */
2609
0
      oplock_request,       /* oplock_request */
2610
0
      NULL,         /* lease */
2611
0
      0,          /* allocation_size */
2612
0
      0,          /* private_flags */
2613
0
      NULL,         /* sd */
2614
0
      NULL,         /* ea_list */
2615
0
      &fsp,         /* result */
2616
0
      NULL,         /* pinfo */
2617
0
      NULL, NULL);        /* create context */
2618
2619
0
    if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2620
0
      TALLOC_FREE(fname);
2621
0
      TALLOC_FREE(dirfsp);
2622
0
      TALLOC_FREE(smb_fname);
2623
0
      continue;
2624
0
    }
2625
2626
0
    if (!NT_STATUS_IS_OK(status)) {
2627
0
      if (open_was_deferred(req->xconn, req->mid)) {
2628
        /* We have re-scheduled this call. */
2629
0
        goto out;
2630
0
      }
2631
0
      if (NT_STATUS_EQUAL(
2632
0
            status, NT_STATUS_SHARING_VIOLATION)) {
2633
0
        bool ok = defer_smb1_sharing_violation(req);
2634
0
        if (ok) {
2635
0
          goto out;
2636
0
        }
2637
0
      }
2638
0
      reply_openerror(req, status);
2639
0
      goto out;
2640
0
    }
2641
2642
0
    break;
2643
0
  }
2644
2645
0
  if (i == 10) {
2646
    /* Collision after 10 times... */
2647
0
    reply_nterror(req, status);
2648
0
    goto out;
2649
0
  }
2650
2651
0
  reply_smb1_outbuf(req, 1, 0);
2652
0
  SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2653
2654
  /* the returned filename is relative to the directory */
2655
0
  s = strrchr_m(fsp->fsp_name->base_name, '/');
2656
0
  if (!s) {
2657
0
    s = fsp->fsp_name->base_name;
2658
0
  } else {
2659
0
    s++;
2660
0
  }
2661
2662
#if 0
2663
  /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2664
     thing in the byte section. JRA */
2665
  SSVALS(p, 0, -1); /* what is this? not in spec */
2666
#endif
2667
0
  if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2668
0
      == -1) {
2669
0
    reply_nterror(req, NT_STATUS_NO_MEMORY);
2670
0
    goto out;
2671
0
  }
2672
2673
0
  if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2674
0
    SCVAL(req->outbuf, smb_flg,
2675
0
          CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2676
0
  }
2677
2678
0
  if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2679
0
    SCVAL(req->outbuf, smb_flg,
2680
0
          CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2681
0
  }
2682
2683
0
  DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2684
0
  DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2685
0
        fsp_get_io_fd(fsp), (unsigned int)smb_fname->st.st_ex_mode));
2686
0
 out:
2687
0
  TALLOC_FREE(smb_fname);
2688
0
  TALLOC_FREE(wire_name);
2689
0
  END_PROFILE(SMBctemp);
2690
0
  return;
2691
0
}
2692
2693
/****************************************************************************
2694
 Reply to a unlink
2695
****************************************************************************/
2696
2697
void reply_unlink(struct smb_request *req)
2698
0
{
2699
0
  connection_struct *conn = req->conn;
2700
0
  char *name = NULL;
2701
0
  struct files_struct *dirfsp = NULL;
2702
0
  struct smb_filename *smb_fname = NULL;
2703
0
  uint32_t dirtype;
2704
0
  NTSTATUS status;
2705
0
  uint32_t ucf_flags = ucf_flags_from_smb_request(req);
2706
0
  NTTIME twrp = 0;
2707
0
  TALLOC_CTX *ctx = talloc_tos();
2708
2709
0
  START_PROFILE(SMBunlink);
2710
2711
0
  if (req->wct < 1) {
2712
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2713
0
    goto out;
2714
0
  }
2715
2716
0
  dirtype = SVAL(req->vwv+0, 0);
2717
2718
0
  srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
2719
0
          STR_TERMINATE, &status);
2720
0
  if (!NT_STATUS_IS_OK(status)) {
2721
0
    reply_nterror(req, status);
2722
0
    goto out;
2723
0
  }
2724
2725
0
  if (ucf_flags & UCF_GMT_PATHNAME) {
2726
0
    extract_snapshot_token(name, &twrp);
2727
0
  }
2728
0
  status = smb1_strip_dfs_path(ctx, &ucf_flags, &name);
2729
0
  if (!NT_STATUS_IS_OK(status)) {
2730
0
    reply_nterror(req, status);
2731
0
    goto out;
2732
0
  }
2733
0
  status = filename_convert_dirfsp(ctx,
2734
0
           conn,
2735
0
           name,
2736
0
           ucf_flags | UCF_LCOMP_LNK_OK,
2737
0
           twrp,
2738
0
           &dirfsp,
2739
0
           &smb_fname);
2740
0
  if (!NT_STATUS_IS_OK(status)) {
2741
0
    if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2742
0
      reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2743
0
          ERRSRV, ERRbadpath);
2744
0
      goto out;
2745
0
    }
2746
0
    reply_nterror(req, status);
2747
0
    goto out;
2748
0
  }
2749
2750
0
  DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2751
2752
0
  status = unlink_internals(conn, req, dirtype, dirfsp, smb_fname);
2753
0
  if (!NT_STATUS_IS_OK(status)) {
2754
0
    if (open_was_deferred(req->xconn, req->mid)) {
2755
      /* We have re-scheduled this call. */
2756
0
      goto out;
2757
0
    }
2758
0
    if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2759
0
      bool ok = defer_smb1_sharing_violation(req);
2760
0
      if (ok) {
2761
0
        goto out;
2762
0
      }
2763
0
    }
2764
0
    reply_nterror(req, status);
2765
0
    goto out;
2766
0
  }
2767
2768
0
  reply_smb1_outbuf(req, 0, 0);
2769
0
 out:
2770
0
  TALLOC_FREE(smb_fname);
2771
0
  END_PROFILE(SMBunlink);
2772
0
  return;
2773
0
}
2774
2775
/****************************************************************************
2776
 Fail for readbraw.
2777
****************************************************************************/
2778
2779
static void fail_readraw(void)
2780
0
{
2781
0
  const char *errstr = talloc_asprintf(talloc_tos(),
2782
0
      "FAIL ! reply_readbraw: socket write fail (%s)",
2783
0
      strerror(errno));
2784
0
  if (!errstr) {
2785
0
    errstr = "";
2786
0
  }
2787
0
  exit_server_cleanly(errstr);
2788
0
}
2789
2790
/****************************************************************************
2791
 Return a readbraw error (4 bytes of zero).
2792
****************************************************************************/
2793
2794
static void reply_readbraw_error(struct smbXsrv_connection *xconn)
2795
0
{
2796
0
  char header[4];
2797
2798
0
  SIVAL(header,0,0);
2799
2800
0
  smbd_lock_socket(xconn);
2801
0
  if (write_data(xconn->transport.sock,header,4) != 4) {
2802
0
    int saved_errno = errno;
2803
    /*
2804
     * Try and give an error message saying what
2805
     * client failed.
2806
     */
2807
0
    DEBUG(0, ("write_data failed for client %s. "
2808
0
        "Error %s\n",
2809
0
        smbXsrv_connection_dbg(xconn),
2810
0
        strerror(saved_errno)));
2811
0
    errno = saved_errno;
2812
2813
0
    fail_readraw();
2814
0
  }
2815
0
  smbd_unlock_socket(xconn);
2816
0
}
2817
2818
/*******************************************************************
2819
 Ensure we don't use sendfile if server smb signing is active.
2820
********************************************************************/
2821
2822
static bool lp_use_sendfile(struct smbXsrv_connection *xconn,
2823
          int snum,
2824
          struct smb1_signing_state *signing_state)
2825
0
{
2826
0
  bool sign_active = false;
2827
2828
  /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
2829
0
  if (xconn->protocol < PROTOCOL_NT1) {
2830
0
    return false;
2831
0
  }
2832
0
  if (signing_state) {
2833
0
    sign_active = smb1_signing_is_active(signing_state);
2834
0
  }
2835
0
  return (lp__use_sendfile(snum) &&
2836
0
      (get_remote_arch() != RA_WIN95) &&
2837
0
      !sign_active);
2838
0
}
2839
/****************************************************************************
2840
 Use sendfile in readbraw.
2841
****************************************************************************/
2842
2843
static void send_file_readbraw(connection_struct *conn,
2844
             struct smb_request *req,
2845
             files_struct *fsp,
2846
             off_t startpos,
2847
             size_t nread,
2848
             ssize_t mincount)
2849
0
{
2850
0
  struct smbXsrv_connection *xconn = req->xconn;
2851
0
  char *outbuf = NULL;
2852
0
  ssize_t ret=0;
2853
2854
  /*
2855
   * We can only use sendfile on a non-chained packet
2856
   * but we can use on a non-oplocked file. tridge proved this
2857
   * on a train in Germany :-). JRA.
2858
   * reply_readbraw has already checked the length.
2859
   */
2860
2861
0
  if ( !req_is_in_chain(req) &&
2862
0
       (nread > 0) &&
2863
0
       !fsp_is_alternate_stream(fsp) &&
2864
0
       lp_use_sendfile(xconn, SNUM(conn), xconn->smb1.signing_state) ) {
2865
0
    ssize_t sendfile_read = -1;
2866
0
    char header[4];
2867
0
    DATA_BLOB header_blob;
2868
2869
0
    _smb_setlen(header,nread);
2870
0
    header_blob = data_blob_const(header, 4);
2871
2872
0
    sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
2873
0
             &header_blob, startpos,
2874
0
             nread);
2875
0
    if (sendfile_read == -1) {
2876
      /* Returning ENOSYS means no data at all was sent.
2877
       * Do this as a normal read. */
2878
0
      if (errno == ENOSYS) {
2879
0
        goto normal_readbraw;
2880
0
      }
2881
2882
      /*
2883
       * Special hack for broken Linux with no working sendfile. If we
2884
       * return EINTR we sent the header but not the rest of the data.
2885
       * Fake this up by doing read/write calls.
2886
       */
2887
0
      if (errno == EINTR) {
2888
        /* Ensure we don't do this again. */
2889
0
        set_use_sendfile(SNUM(conn), False);
2890
0
        DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2891
2892
0
        if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
2893
0
          DEBUG(0,("send_file_readbraw: "
2894
0
             "fake_sendfile failed for "
2895
0
             "file %s (%s).\n",
2896
0
             fsp_str_dbg(fsp),
2897
0
             strerror(errno)));
2898
0
          exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2899
0
        }
2900
0
        return;
2901
0
      }
2902
2903
0
      DEBUG(0,("send_file_readbraw: sendfile failed for "
2904
0
         "file %s (%s). Terminating\n",
2905
0
         fsp_str_dbg(fsp), strerror(errno)));
2906
0
      exit_server_cleanly("send_file_readbraw sendfile failed");
2907
0
    } else if (sendfile_read == 0) {
2908
      /*
2909
       * Some sendfile implementations return 0 to indicate
2910
       * that there was a short read, but nothing was
2911
       * actually written to the socket.  In this case,
2912
       * fallback to the normal read path so the header gets
2913
       * the correct byte count.
2914
       */
2915
0
      DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2916
0
          "bytes falling back to the normal read: "
2917
0
          "%s\n", fsp_str_dbg(fsp)));
2918
0
      goto normal_readbraw;
2919
0
    }
2920
2921
    /* Deal with possible short send. */
2922
0
    if (sendfile_read != 4+nread) {
2923
0
      ret = sendfile_short_send(xconn, fsp,
2924
0
              sendfile_read, 4, nread);
2925
0
      if (ret == -1) {
2926
0
        fail_readraw();
2927
0
      }
2928
0
    }
2929
0
    return;
2930
0
  }
2931
2932
0
normal_readbraw:
2933
2934
0
  outbuf = talloc_array(NULL, char, nread+4);
2935
0
  if (!outbuf) {
2936
0
    DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
2937
0
      (unsigned)(nread+4)));
2938
0
    reply_readbraw_error(xconn);
2939
0
    return;
2940
0
  }
2941
2942
0
  if (nread > 0) {
2943
0
    ret = read_file(fsp,outbuf+4,startpos,nread);
2944
#if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2945
    if (ret < mincount)
2946
      ret = 0;
2947
#else
2948
0
    if (ret < nread)
2949
0
      ret = 0;
2950
0
#endif
2951
0
  }
2952
2953
0
  _smb_setlen(outbuf,ret);
2954
0
  if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
2955
0
    int saved_errno = errno;
2956
    /*
2957
     * Try and give an error message saying what
2958
     * client failed.
2959
     */
2960
0
    DEBUG(0, ("write_data failed for client %s. Error %s\n",
2961
0
        smbXsrv_connection_dbg(xconn),
2962
0
        strerror(saved_errno)));
2963
0
    errno = saved_errno;
2964
2965
0
    fail_readraw();
2966
0
  }
2967
2968
0
  TALLOC_FREE(outbuf);
2969
0
}
2970
2971
/****************************************************************************
2972
 Reply to a readbraw (core+ protocol).
2973
****************************************************************************/
2974
2975
void reply_readbraw(struct smb_request *req)
2976
0
{
2977
0
  connection_struct *conn = req->conn;
2978
0
  struct smbXsrv_connection *xconn = req->xconn;
2979
0
  ssize_t maxcount,mincount;
2980
0
  size_t nread = 0;
2981
0
  off_t startpos;
2982
0
  files_struct *fsp;
2983
0
  struct lock_struct lock;
2984
0
  off_t size = 0;
2985
0
  NTSTATUS status;
2986
2987
0
  START_PROFILE(SMBreadbraw);
2988
2989
0
  if (smb1_srv_is_signing_active(xconn) || req->encrypted) {
2990
0
    exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2991
0
      "raw reads/writes are disallowed.");
2992
0
  }
2993
2994
0
  if (req->wct < 8) {
2995
0
    reply_readbraw_error(xconn);
2996
0
    END_PROFILE(SMBreadbraw);
2997
0
    return;
2998
0
  }
2999
3000
0
  if (xconn->smb1.echo_handler.trusted_fde) {
3001
0
    DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3002
0
       "'async smb echo handler = yes'\n"));
3003
0
    reply_readbraw_error(xconn);
3004
0
    END_PROFILE(SMBreadbraw);
3005
0
    return;
3006
0
  }
3007
3008
  /*
3009
   * Special check if an oplock break has been issued
3010
   * and the readraw request croses on the wire, we must
3011
   * return a zero length response here.
3012
   */
3013
3014
0
  fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3015
3016
  /*
3017
   * We have to do a check_fsp by hand here, as
3018
   * we must always return 4 zero bytes on error,
3019
   * not a NTSTATUS.
3020
   */
3021
3022
0
  if (fsp == NULL ||
3023
0
      conn == NULL ||
3024
0
      conn != fsp->conn ||
3025
0
      req->vuid != fsp->vuid ||
3026
0
      fsp->fsp_flags.is_directory ||
3027
0
      fsp_get_io_fd(fsp) == -1)
3028
0
  {
3029
    /*
3030
     * fsp could be NULL here so use the value from the packet. JRA.
3031
     */
3032
0
    DEBUG(3,("reply_readbraw: fnum %d not valid "
3033
0
      "- cache prime?\n",
3034
0
      (int)SVAL(req->vwv+0, 0)));
3035
0
    reply_readbraw_error(xconn);
3036
0
    END_PROFILE(SMBreadbraw);
3037
0
    return;
3038
0
  }
3039
3040
  /* Do a "by hand" version of CHECK_READ. */
3041
0
  if (!(fsp->fsp_flags.can_read ||
3042
0
      ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3043
0
        (fsp->access_mask & FILE_EXECUTE)))) {
3044
0
    DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3045
0
        (int)SVAL(req->vwv+0, 0)));
3046
0
    reply_readbraw_error(xconn);
3047
0
    END_PROFILE(SMBreadbraw);
3048
0
    return;
3049
0
  }
3050
3051
0
  startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3052
0
  if(req->wct == 10) {
3053
    /*
3054
     * This is a large offset (64 bit) read.
3055
     */
3056
3057
0
    startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3058
3059
0
    if(startpos < 0) {
3060
0
      DEBUG(0,("reply_readbraw: negative 64 bit "
3061
0
        "readraw offset (%.0f) !\n",
3062
0
        (double)startpos ));
3063
0
      reply_readbraw_error(xconn);
3064
0
      END_PROFILE(SMBreadbraw);
3065
0
      return;
3066
0
    }
3067
0
  }
3068
3069
0
  maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3070
0
  mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3071
3072
  /* ensure we don't overrun the packet size */
3073
0
  maxcount = MIN(65535,maxcount);
3074
3075
0
  init_strict_lock_struct(fsp,
3076
0
      (uint64_t)req->smbpid,
3077
0
      (uint64_t)startpos,
3078
0
      (uint64_t)maxcount,
3079
0
      READ_LOCK,
3080
0
      &lock);
3081
3082
0
  if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3083
0
    reply_readbraw_error(xconn);
3084
0
    END_PROFILE(SMBreadbraw);
3085
0
    return;
3086
0
  }
3087
3088
0
  status = vfs_stat_fsp(fsp);
3089
0
  if (NT_STATUS_IS_OK(status)) {
3090
0
    size = fsp->fsp_name->st.st_ex_size;
3091
0
  }
3092
3093
0
  if (startpos >= size) {
3094
0
    nread = 0;
3095
0
  } else {
3096
0
    nread = MIN(maxcount,(size - startpos));
3097
0
  }
3098
3099
#if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3100
  if (nread < mincount)
3101
    nread = 0;
3102
#endif
3103
3104
0
  DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3105
0
    "min=%lu nread=%lu\n",
3106
0
    fsp_fnum_dbg(fsp), (double)startpos,
3107
0
    (unsigned long)maxcount,
3108
0
    (unsigned long)mincount,
3109
0
    (unsigned long)nread ) );
3110
3111
0
  send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3112
3113
0
  DEBUG(5,("reply_readbraw finished\n"));
3114
3115
0
  END_PROFILE(SMBreadbraw);
3116
0
  return;
3117
0
}
3118
3119
#undef DBGC_CLASS
3120
0
#define DBGC_CLASS DBGC_LOCKING
3121
3122
/****************************************************************************
3123
 Reply to a lockread (core+ protocol).
3124
****************************************************************************/
3125
3126
static void reply_lockread_locked(struct tevent_req *subreq);
3127
3128
void reply_lockread(struct smb_request *req)
3129
0
{
3130
0
  struct tevent_req *subreq = NULL;
3131
0
  connection_struct *conn = req->conn;
3132
0
  files_struct *fsp;
3133
0
  struct smbd_lock_element *lck = NULL;
3134
3135
0
  START_PROFILE(SMBlockread);
3136
3137
0
  if (req->wct < 5) {
3138
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3139
0
    END_PROFILE(SMBlockread);
3140
0
    return;
3141
0
  }
3142
3143
0
  fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3144
3145
0
  if (!check_fsp(conn, req, fsp)) {
3146
0
    END_PROFILE(SMBlockread);
3147
0
    return;
3148
0
  }
3149
3150
0
  if (!CHECK_READ(fsp,req)) {
3151
0
    reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3152
0
    END_PROFILE(SMBlockread);
3153
0
    return;
3154
0
  }
3155
3156
0
  lck = talloc(req, struct smbd_lock_element);
3157
0
  if (lck == NULL) {
3158
0
    reply_nterror(req, NT_STATUS_NO_MEMORY);
3159
0
    END_PROFILE(SMBlockread);
3160
0
    return;
3161
0
  }
3162
3163
  /*
3164
   * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3165
   * protocol request that predates the read/write lock concept.
3166
   * Thus instead of asking for a read lock here we need to ask
3167
   * for a write lock. JRA.
3168
   * Note that the requested lock size is unaffected by max_send.
3169
   */
3170
3171
0
  *lck = (struct smbd_lock_element) {
3172
0
    .req_guid = smbd_request_guid(req, 0),
3173
0
    .smblctx = req->smbpid,
3174
0
    .brltype = WRITE_LOCK,
3175
0
    .lock_flav = WINDOWS_LOCK,
3176
0
    .count = SVAL(req->vwv+1, 0),
3177
0
    .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
3178
0
  };
3179
3180
0
  subreq = smbd_smb1_do_locks_send(
3181
0
    fsp,
3182
0
    req->sconn->ev_ctx,
3183
0
    &req,
3184
0
    fsp,
3185
0
    0,
3186
0
    false,    /* large_offset */
3187
0
    1,
3188
0
    lck);
3189
0
  if (subreq == NULL) {
3190
0
    reply_nterror(req, NT_STATUS_NO_MEMORY);
3191
0
    END_PROFILE(SMBlockread);
3192
0
    return;
3193
0
  }
3194
0
  tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
3195
0
  END_PROFILE(SMBlockread);
3196
0
}
3197
3198
static void reply_lockread_locked(struct tevent_req *subreq)
3199
0
{
3200
0
  struct smb_request *req = NULL;
3201
0
  ssize_t nread = -1;
3202
0
  char *data = NULL;
3203
0
  NTSTATUS status;
3204
0
  bool ok;
3205
0
  off_t startpos;
3206
0
  size_t numtoread, maxtoread;
3207
0
  struct files_struct *fsp = NULL;
3208
0
  char *p = NULL;
3209
3210
0
  START_PROFILE(SMBlockread);
3211
3212
0
  ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
3213
0
  SMB_ASSERT(ok);
3214
3215
0
  status = smbd_smb1_do_locks_recv(subreq);
3216
0
  TALLOC_FREE(subreq);
3217
3218
0
  if (!NT_STATUS_IS_OK(status)) {
3219
0
    reply_nterror(req, status);
3220
0
    goto send;
3221
0
  }
3222
3223
0
  fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3224
0
  if (fsp == NULL) {
3225
0
    reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
3226
0
    goto send;
3227
0
  }
3228
3229
0
  numtoread = SVAL(req->vwv+1, 0);
3230
0
  startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3231
3232
  /*
3233
   * However the requested READ size IS affected by max_send. Insanity.... JRA.
3234
   */
3235
0
  maxtoread = req->xconn->smb1.sessions.max_send - (MIN_SMB_SIZE + 5*2 + 3);
3236
3237
0
  if (numtoread > maxtoread) {
3238
0
    DBG_WARNING("requested read size (%zu) is greater than "
3239
0
          "maximum allowed (%zu/%d). "
3240
0
          "Returning short read of maximum allowed for "
3241
0
          "compatibility with Windows 2000.\n",
3242
0
          numtoread,
3243
0
          maxtoread,
3244
0
          req->xconn->smb1.sessions.max_send);
3245
0
    numtoread = maxtoread;
3246
0
  }
3247
3248
0
  reply_smb1_outbuf(req, 5, numtoread + 3);
3249
3250
0
  data = smb_buf(req->outbuf) + 3;
3251
3252
0
  nread = read_file(fsp,data,startpos,numtoread);
3253
3254
0
  if (nread < 0) {
3255
0
    reply_nterror(req, map_nt_error_from_unix(errno));
3256
0
    goto send;
3257
0
  }
3258
3259
0
  srv_smb1_set_message((char *)req->outbuf, 5, nread+3, False);
3260
3261
0
  SSVAL(req->outbuf,smb_vwv0,nread);
3262
0
  SSVAL(req->outbuf,smb_vwv5,nread+3);
3263
0
  p = smb_buf(req->outbuf);
3264
0
  SCVAL(p,0,0); /* pad byte. */
3265
0
  SSVAL(p,1,nread);
3266
3267
0
  DEBUG(3,("lockread %s num=%d nread=%d\n",
3268
0
     fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3269
3270
0
send:
3271
0
  ok = smb1_srv_send(req->xconn,
3272
0
         (char *)req->outbuf,
3273
0
         true,
3274
0
         req->seqnum + 1,
3275
0
         IS_CONN_ENCRYPTED(req->conn));
3276
0
  if (!ok) {
3277
0
    exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
3278
0
  }
3279
0
  TALLOC_FREE(req);
3280
0
  END_PROFILE(SMBlockread);
3281
0
  return;
3282
0
}
3283
3284
#undef DBGC_CLASS
3285
0
#define DBGC_CLASS DBGC_ALL
3286
3287
/****************************************************************************
3288
 Reply to a read.
3289
****************************************************************************/
3290
3291
void reply_read(struct smb_request *req)
3292
0
{
3293
0
  connection_struct *conn = req->conn;
3294
0
  size_t numtoread;
3295
0
  size_t maxtoread;
3296
0
  ssize_t nread = 0;
3297
0
  char *data;
3298
0
  off_t startpos;
3299
0
  files_struct *fsp;
3300
0
  struct lock_struct lock;
3301
0
  struct smbXsrv_connection *xconn = req->xconn;
3302
3303
0
  START_PROFILE(SMBread);
3304
3305
0
  if (req->wct < 3) {
3306
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3307
0
    END_PROFILE(SMBread);
3308
0
    return;
3309
0
  }
3310
3311
0
  fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3312
3313
0
  if (!check_fsp(conn, req, fsp)) {
3314
0
    END_PROFILE(SMBread);
3315
0
    return;
3316
0
  }
3317
3318
0
  if (!CHECK_READ(fsp,req)) {
3319
0
    reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3320
0
    END_PROFILE(SMBread);
3321
0
    return;
3322
0
  }
3323
3324
0
  numtoread = SVAL(req->vwv+1, 0);
3325
0
  startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3326
3327
  /*
3328
   * The requested read size cannot be greater than max_send. JRA.
3329
   */
3330
0
  maxtoread = xconn->smb1.sessions.max_send - (MIN_SMB_SIZE + 5*2 + 3);
3331
3332
0
  if (numtoread > maxtoread) {
3333
0
    DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3334
0
Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3335
0
      (unsigned int)numtoread, (unsigned int)maxtoread,
3336
0
      (unsigned int)xconn->smb1.sessions.max_send));
3337
0
    numtoread = maxtoread;
3338
0
  }
3339
3340
0
  reply_smb1_outbuf(req, 5, numtoread+3);
3341
3342
0
  data = smb_buf(req->outbuf) + 3;
3343
3344
0
  init_strict_lock_struct(fsp,
3345
0
      (uint64_t)req->smbpid,
3346
0
      (uint64_t)startpos,
3347
0
      (uint64_t)numtoread,
3348
0
      READ_LOCK,
3349
0
      &lock);
3350
3351
0
  if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3352
0
    reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3353
0
    END_PROFILE(SMBread);
3354
0
    return;
3355
0
  }
3356
3357
0
  if (numtoread > 0)
3358
0
    nread = read_file(fsp,data,startpos,numtoread);
3359
3360
0
  if (nread < 0) {
3361
0
    reply_nterror(req, map_nt_error_from_unix(errno));
3362
0
    goto out;
3363
0
  }
3364
3365
0
  srv_smb1_set_message((char *)req->outbuf, 5, nread+3, False);
3366
3367
0
  SSVAL(req->outbuf,smb_vwv0,nread);
3368
0
  SSVAL(req->outbuf,smb_vwv5,nread+3);
3369
0
  SCVAL(smb_buf(req->outbuf),0,1);
3370
0
  SSVAL(smb_buf(req->outbuf),1,nread);
3371
3372
0
  DEBUG(3, ("read %s num=%d nread=%d\n",
3373
0
      fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3374
3375
0
out:
3376
0
  END_PROFILE(SMBread);
3377
0
  return;
3378
0
}
3379
3380
/****************************************************************************
3381
 Setup readX header.
3382
****************************************************************************/
3383
3384
size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
3385
0
{
3386
0
  size_t outsize;
3387
3388
0
  outsize = srv_smb1_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
3389
0
          False);
3390
3391
0
  memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3392
3393
0
  SCVAL(outbuf,smb_vwv0,0xFF);
3394
0
  SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3395
0
  SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3396
0
  SSVAL(outbuf,smb_vwv6,
3397
0
        (smb_wct - 4) /* offset from smb header to wct */
3398
0
        + 1     /* the wct field */
3399
0
        + 12 * sizeof(uint16_t) /* vwv */
3400
0
        + 2   /* the buflen field */
3401
0
        + 1);   /* padding byte */
3402
0
  SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3403
0
  SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
3404
  /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3405
0
  _smb_setlen_large(outbuf,
3406
0
        smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
3407
0
  return outsize;
3408
0
}
3409
3410
/****************************************************************************
3411
 Reply to a read and X - possibly using sendfile.
3412
****************************************************************************/
3413
3414
static void send_file_readX(connection_struct *conn, struct smb_request *req,
3415
          files_struct *fsp, off_t startpos,
3416
          size_t smb_maxcnt)
3417
0
{
3418
0
  struct smbXsrv_connection *xconn = req->xconn;
3419
0
  ssize_t nread = -1;
3420
0
  struct lock_struct lock;
3421
0
  int saved_errno = 0;
3422
0
  NTSTATUS status;
3423
3424
0
  init_strict_lock_struct(fsp,
3425
0
      (uint64_t)req->smbpid,
3426
0
      (uint64_t)startpos,
3427
0
      (uint64_t)smb_maxcnt,
3428
0
      READ_LOCK,
3429
0
      &lock);
3430
3431
0
  if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3432
0
    reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3433
0
    return;
3434
0
  }
3435
3436
  /*
3437
   * We can only use sendfile on a non-chained packet
3438
   * but we can use on a non-oplocked file. tridge proved this
3439
   * on a train in Germany :-). JRA.
3440
   */
3441
3442
0
  if (!req_is_in_chain(req) &&
3443
0
      !req->encrypted &&
3444
0
      !fsp_is_alternate_stream(fsp) &&
3445
0
      lp_use_sendfile(xconn, SNUM(conn), xconn->smb1.signing_state) ) {
3446
0
    uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
3447
0
    DATA_BLOB header;
3448
3449
0
    status = vfs_stat_fsp(fsp);
3450
0
    if (!NT_STATUS_IS_OK(status)) {
3451
0
      reply_nterror(req, status);
3452
0
      goto out;
3453
0
    }
3454
3455
0
    if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3456
0
        (startpos > fsp->fsp_name->st.st_ex_size) ||
3457
0
        (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3458
      /*
3459
       * We already know that we would do a short read, so don't
3460
       * try the sendfile() path.
3461
       */
3462
0
      goto nosendfile_read;
3463
0
    }
3464
3465
    /*
3466
     * Set up the packet header before send. We
3467
     * assume here the sendfile will work (get the
3468
     * correct amount of data).
3469
     */
3470
3471
0
    header = data_blob_const(headerbuf, sizeof(headerbuf));
3472
3473
0
    construct_smb1_reply_common_req(req, (char *)headerbuf);
3474
0
    setup_readX_header((char *)headerbuf, smb_maxcnt);
3475
3476
0
    nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
3477
0
           startpos, smb_maxcnt);
3478
0
    if (nread == -1) {
3479
0
      saved_errno = errno;
3480
3481
      /* Returning ENOSYS means no data at all was sent.
3482
         Do this as a normal read. */
3483
0
      if (errno == ENOSYS) {
3484
0
        goto normal_read;
3485
0
      }
3486
3487
      /*
3488
       * Special hack for broken Linux with no working sendfile. If we
3489
       * return EINTR we sent the header but not the rest of the data.
3490
       * Fake this up by doing read/write calls.
3491
       */
3492
3493
0
      if (errno == EINTR) {
3494
        /* Ensure we don't do this again. */
3495
0
        set_use_sendfile(SNUM(conn), False);
3496
0
        DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3497
0
        nread = fake_sendfile(xconn, fsp, startpos,
3498
0
                  smb_maxcnt);
3499
0
        if (nread == -1) {
3500
0
          saved_errno = errno;
3501
0
          DEBUG(0,("send_file_readX: "
3502
0
             "fake_sendfile failed for "
3503
0
             "file %s (%s) for client %s. "
3504
0
             "Terminating\n",
3505
0
             fsp_str_dbg(fsp),
3506
0
             smbXsrv_connection_dbg(xconn),
3507
0
             strerror(saved_errno)));
3508
0
          errno = saved_errno;
3509
0
          exit_server_cleanly("send_file_readX: fake_sendfile failed");
3510
0
        }
3511
0
        DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3512
0
            fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3513
        /* No outbuf here means successful sendfile. */
3514
0
        goto out;
3515
0
      }
3516
3517
0
      DEBUG(0,("send_file_readX: sendfile failed for file "
3518
0
         "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3519
0
         strerror(errno)));
3520
0
      exit_server_cleanly("send_file_readX sendfile failed");
3521
0
    } else if (nread == 0) {
3522
      /*
3523
       * Some sendfile implementations return 0 to indicate
3524
       * that there was a short read, but nothing was
3525
       * actually written to the socket.  In this case,
3526
       * fallback to the normal read path so the header gets
3527
       * the correct byte count.
3528
       */
3529
0
      DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3530
0
          "falling back to the normal read: %s\n",
3531
0
          fsp_str_dbg(fsp)));
3532
0
      goto normal_read;
3533
0
    }
3534
3535
0
    DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3536
0
        fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3537
3538
    /* Deal with possible short send. */
3539
0
    if (nread != smb_maxcnt + sizeof(headerbuf)) {
3540
0
      ssize_t ret;
3541
3542
0
      ret = sendfile_short_send(xconn, fsp, nread,
3543
0
              sizeof(headerbuf), smb_maxcnt);
3544
0
      if (ret == -1) {
3545
0
        const char *r;
3546
0
        r = "send_file_readX: sendfile_short_send failed";
3547
0
        DEBUG(0,("%s for file %s (%s).\n",
3548
0
           r, fsp_str_dbg(fsp), strerror(errno)));
3549
0
        exit_server_cleanly(r);
3550
0
      }
3551
0
    }
3552
    /* No outbuf here means successful sendfile. */
3553
0
    goto out;
3554
0
  }
3555
3556
0
normal_read:
3557
3558
0
  if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3559
0
    uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
3560
0
    ssize_t ret;
3561
3562
0
    if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3563
0
        (startpos > fsp->fsp_name->st.st_ex_size) ||
3564
0
        (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3565
      /*
3566
       * We already know that we would do a short
3567
       * read, so don't try the sendfile() path.
3568
       */
3569
0
      goto nosendfile_read;
3570
0
    }
3571
3572
0
    construct_smb1_reply_common_req(req, (char *)headerbuf);
3573
0
    setup_readX_header((char *)headerbuf, smb_maxcnt);
3574
3575
    /* Send out the header. */
3576
0
    ret = write_data(xconn->transport.sock, (char *)headerbuf,
3577
0
         sizeof(headerbuf));
3578
0
    if (ret != sizeof(headerbuf)) {
3579
0
      saved_errno = errno;
3580
      /*
3581
       * Try and give an error message saying what
3582
       * client failed.
3583
       */
3584
0
      DEBUG(0,("send_file_readX: write_data failed for file "
3585
0
         "%s (%s) for client %s. Terminating\n",
3586
0
         fsp_str_dbg(fsp),
3587
0
         smbXsrv_connection_dbg(xconn),
3588
0
         strerror(saved_errno)));
3589
0
      errno = saved_errno;
3590
0
      exit_server_cleanly("send_file_readX sendfile failed");
3591
0
    }
3592
0
    nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
3593
0
    if (nread == -1) {
3594
0
      saved_errno = errno;
3595
0
      DEBUG(0,("send_file_readX: fake_sendfile failed for file "
3596
0
         "%s (%s) for client %s. Terminating\n",
3597
0
         fsp_str_dbg(fsp),
3598
0
         smbXsrv_connection_dbg(xconn),
3599
0
         strerror(saved_errno)));
3600
0
      errno = saved_errno;
3601
0
      exit_server_cleanly("send_file_readX: fake_sendfile failed");
3602
0
    }
3603
0
    goto out;
3604
0
  }
3605
3606
0
nosendfile_read:
3607
3608
0
  reply_smb1_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
3609
0
  SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3610
0
  SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
3611
3612
0
  nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
3613
0
        startpos, smb_maxcnt);
3614
0
  saved_errno = errno;
3615
3616
0
  if (nread < 0) {
3617
0
    reply_nterror(req, map_nt_error_from_unix(saved_errno));
3618
0
    return;
3619
0
  }
3620
3621
0
  setup_readX_header((char *)req->outbuf, nread);
3622
3623
0
  DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3624
0
      fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3625
0
  return;
3626
3627
0
out:
3628
0
  TALLOC_FREE(req->outbuf);
3629
0
  return;
3630
0
}
3631
3632
/****************************************************************************
3633
 Work out how much space we have for a read return.
3634
****************************************************************************/
3635
3636
static size_t calc_max_read_pdu(const struct smb_request *req)
3637
0
{
3638
0
  struct smbXsrv_connection *xconn = req->xconn;
3639
3640
0
  if (xconn->protocol < PROTOCOL_NT1) {
3641
0
    return xconn->smb1.sessions.max_send;
3642
0
  }
3643
3644
0
  if (!lp_large_readwrite()) {
3645
0
    return xconn->smb1.sessions.max_send;
3646
0
  }
3647
3648
0
  if (req_is_in_chain(req)) {
3649
0
    return xconn->smb1.sessions.max_send;
3650
0
  }
3651
3652
0
  if (req->encrypted) {
3653
    /*
3654
     * Don't take encrypted traffic up to the
3655
     * limit. There are padding considerations
3656
     * that make that tricky.
3657
     */
3658
0
    return xconn->smb1.sessions.max_send;
3659
0
  }
3660
3661
0
  if (smb1_srv_is_signing_active(xconn)) {
3662
0
    return 0x1FFFF;
3663
0
  }
3664
3665
0
  if (!lp_smb1_unix_extensions()) {
3666
0
    return 0x1FFFF;
3667
0
  }
3668
3669
  /*
3670
   * We can do ultra-large POSIX reads.
3671
   */
3672
0
  return 0xFFFFFF;
3673
0
}
3674
3675
/****************************************************************************
3676
 Calculate how big a read can be. Copes with all clients. It's always
3677
 safe to return a short read - Windows does this.
3678
****************************************************************************/
3679
3680
static size_t calc_read_size(const struct smb_request *req,
3681
           size_t upper_size,
3682
           size_t lower_size)
3683
0
{
3684
0
  struct smbXsrv_connection *xconn = req->xconn;
3685
0
  size_t max_pdu = calc_max_read_pdu(req);
3686
0
  size_t total_size = 0;
3687
0
  size_t hdr_len = MIN_SMB_SIZE + VWV(12);
3688
0
  size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
3689
3690
  /*
3691
   * Windows explicitly ignores upper size of 0xFFFF.
3692
   * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
3693
   * We must do the same as these will never fit even in
3694
   * an extended size NetBIOS packet.
3695
   */
3696
0
  if (upper_size == 0xFFFF) {
3697
0
    upper_size = 0;
3698
0
  }
3699
3700
0
  if (xconn->protocol < PROTOCOL_NT1) {
3701
0
    upper_size = 0;
3702
0
  }
3703
3704
0
  total_size = ((upper_size<<16) | lower_size);
3705
3706
  /*
3707
   * LARGE_READX test shows it's always safe to return
3708
   * a short read. Windows does so.
3709
   */
3710
0
  return MIN(total_size, max_len);
3711
0
}
3712
3713
/****************************************************************************
3714
 Reply to a read and X.
3715
****************************************************************************/
3716
3717
void reply_read_and_X(struct smb_request *req)
3718
0
{
3719
0
  connection_struct *conn = req->conn;
3720
0
  files_struct *fsp;
3721
0
  off_t startpos;
3722
0
  size_t smb_maxcnt;
3723
0
  size_t upper_size;
3724
0
  bool big_readX = False;
3725
#if 0
3726
  size_t smb_mincnt = SVAL(req->vwv+6, 0);
3727
#endif
3728
3729
0
  START_PROFILE(SMBreadX);
3730
3731
0
  if ((req->wct != 10) && (req->wct != 12)) {
3732
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3733
0
    return;
3734
0
  }
3735
3736
0
  fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3737
0
  startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3738
0
  smb_maxcnt = SVAL(req->vwv+5, 0);
3739
3740
  /* If it's an IPC, pass off the pipe handler. */
3741
0
  if (IS_IPC(conn)) {
3742
0
    reply_pipe_read_and_X(req);
3743
0
    END_PROFILE(SMBreadX);
3744
0
    return;
3745
0
  }
3746
3747
0
  if (!check_fsp(conn, req, fsp)) {
3748
0
    END_PROFILE(SMBreadX);
3749
0
    return;
3750
0
  }
3751
3752
0
  if (!CHECK_READ(fsp,req)) {
3753
0
    reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3754
0
    END_PROFILE(SMBreadX);
3755
0
    return;
3756
0
  }
3757
3758
0
  upper_size = SVAL(req->vwv+7, 0);
3759
0
  smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
3760
0
  if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
3761
    /*
3762
     * This is a heuristic to avoid keeping large
3763
     * outgoing buffers around over long-lived aio
3764
     * requests.
3765
     */
3766
0
    big_readX = True;
3767
0
  }
3768
3769
0
  if (req->wct == 12) {
3770
    /*
3771
     * This is a large offset (64 bit) read.
3772
     */
3773
0
    startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
3774
3775
0
  }
3776
3777
0
  if (!big_readX) {
3778
0
    NTSTATUS status = schedule_aio_read_and_X(conn,
3779
0
          req,
3780
0
          fsp,
3781
0
          startpos,
3782
0
          smb_maxcnt);
3783
0
    if (NT_STATUS_IS_OK(status)) {
3784
      /* Read scheduled - we're done. */
3785
0
      goto out;
3786
0
    }
3787
0
    if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3788
      /* Real error - report to client. */
3789
0
      END_PROFILE(SMBreadX);
3790
0
      reply_nterror(req, status);
3791
0
      return;
3792
0
    }
3793
    /* NT_STATUS_RETRY - fall back to sync read. */
3794
0
  }
3795
3796
0
  smbd_lock_socket(req->xconn);
3797
0
  send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3798
0
  smbd_unlock_socket(req->xconn);
3799
3800
0
 out:
3801
0
  END_PROFILE(SMBreadX);
3802
0
  return;
3803
0
}
3804
3805
/****************************************************************************
3806
 Error replies to writebraw must have smb_wct == 1. Fix this up.
3807
****************************************************************************/
3808
3809
void error_to_writebrawerr(struct smb_request *req)
3810
0
{
3811
0
  uint8_t *old_outbuf = req->outbuf;
3812
3813
0
  reply_smb1_outbuf(req, 1, 0);
3814
3815
0
  memcpy(req->outbuf, old_outbuf, smb_size);
3816
0
  TALLOC_FREE(old_outbuf);
3817
0
}
3818
3819
/****************************************************************************
3820
 Read 4 bytes of a smb packet and return the smb length of the packet.
3821
 Store the result in the buffer. This version of the function will
3822
 never return a session keepalive (length of zero).
3823
 Timeout is in milliseconds.
3824
****************************************************************************/
3825
3826
static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3827
        size_t *len)
3828
0
{
3829
0
  uint8_t msgtype = NBSSkeepalive;
3830
3831
0
  while (msgtype == NBSSkeepalive) {
3832
0
    NTSTATUS status;
3833
3834
0
    status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3835
0
                len);
3836
0
    if (!NT_STATUS_IS_OK(status)) {
3837
0
      char addr[INET6_ADDRSTRLEN];
3838
      /* Try and give an error message
3839
       * saying what client failed. */
3840
0
      DEBUG(0, ("read_smb_length_return_keepalive failed for "
3841
0
          "client %s read error = %s.\n",
3842
0
          get_peer_addr(fd,addr,sizeof(addr)),
3843
0
          nt_errstr(status)));
3844
0
      return status;
3845
0
    }
3846
3847
0
    msgtype = CVAL(inbuf, 0);
3848
0
  }
3849
3850
0
  DEBUG(10,("read_smb_length: got smb length of %lu\n",
3851
0
      (unsigned long)len));
3852
3853
0
  return NT_STATUS_OK;
3854
0
}
3855
3856
/****************************************************************************
3857
 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3858
****************************************************************************/
3859
3860
void reply_writebraw(struct smb_request *req)
3861
0
{
3862
0
  connection_struct *conn = req->conn;
3863
0
  struct smbXsrv_connection *xconn = req->xconn;
3864
0
  char *buf = NULL;
3865
0
  ssize_t nwritten=0;
3866
0
  ssize_t total_written=0;
3867
0
  size_t numtowrite=0;
3868
0
  size_t tcount;
3869
0
  off_t startpos;
3870
0
  const char *data=NULL;
3871
0
  bool write_through;
3872
0
  files_struct *fsp;
3873
0
  struct lock_struct lock;
3874
0
  NTSTATUS status;
3875
3876
0
  START_PROFILE(SMBwritebraw);
3877
3878
  /*
3879
   * If we ever reply with an error, it must have the SMB command
3880
   * type of SMBwritec, not SMBwriteBraw, as this tells the client
3881
   * we're finished.
3882
   */
3883
0
  SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
3884
3885
0
  if (smb1_srv_is_signing_active(xconn)) {
3886
0
    END_PROFILE(SMBwritebraw);
3887
0
    exit_server_cleanly("reply_writebraw: SMB signing is active - "
3888
0
        "raw reads/writes are disallowed.");
3889
0
  }
3890
3891
0
  if (req->wct < 12) {
3892
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3893
0
    error_to_writebrawerr(req);
3894
0
    END_PROFILE(SMBwritebraw);
3895
0
    return;
3896
0
  }
3897
3898
0
  if (xconn->smb1.echo_handler.trusted_fde) {
3899
0
    DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3900
0
       "'async smb echo handler = yes'\n"));
3901
0
    reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3902
0
    error_to_writebrawerr(req);
3903
0
    END_PROFILE(SMBwritebraw);
3904
0
    return;
3905
0
  }
3906
3907
0
  fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3908
0
  if (!check_fsp(conn, req, fsp)) {
3909
0
    error_to_writebrawerr(req);
3910
0
    END_PROFILE(SMBwritebraw);
3911
0
    return;
3912
0
  }
3913
3914
0
  status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
3915
0
  if (!NT_STATUS_IS_OK(status)) {
3916
0
    reply_nterror(req, status);
3917
0
    error_to_writebrawerr(req);
3918
0
    END_PROFILE(SMBwritebraw);
3919
0
    return;
3920
0
  }
3921
3922
0
  tcount = IVAL(req->vwv+1, 0);
3923
0
  startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3924
0
  write_through = BITSETW(req->vwv+7,0);
3925
3926
  /* We have to deal with slightly different formats depending
3927
    on whether we are using the core+ or lanman1.0 protocol */
3928
3929
0
  if(xconn->protocol <= PROTOCOL_COREPLUS) {
3930
0
    numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
3931
0
    data = smb_buf_const(req->inbuf);
3932
0
  } else {
3933
0
    numtowrite = SVAL(req->vwv+10, 0);
3934
0
    data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3935
0
  }
3936
3937
  /* Ensure we don't write bytes past the end of this packet. */
3938
  /*
3939
   * This already protects us against CVE-2017-12163.
3940
   */
3941
0
  if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3942
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3943
0
    error_to_writebrawerr(req);
3944
0
    END_PROFILE(SMBwritebraw);
3945
0
    return;
3946
0
  }
3947
3948
0
  if (!fsp->print_file) {
3949
0
    init_strict_lock_struct(fsp,
3950
0
        (uint64_t)req->smbpid,
3951
0
        (uint64_t)startpos,
3952
0
        (uint64_t)tcount,
3953
0
        WRITE_LOCK,
3954
0
        &lock);
3955
3956
0
    if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3957
0
      reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3958
0
      error_to_writebrawerr(req);
3959
0
      END_PROFILE(SMBwritebraw);
3960
0
      return;
3961
0
    }
3962
0
  }
3963
3964
0
  if (numtowrite>0) {
3965
0
    nwritten = write_file(req,fsp,data,startpos,numtowrite);
3966
0
  }
3967
3968
0
  DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
3969
0
      "wrote=%d sync=%d\n",
3970
0
    fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
3971
0
    (int)nwritten, (int)write_through));
3972
3973
0
  if (nwritten < (ssize_t)numtowrite)  {
3974
0
    reply_nterror(req, NT_STATUS_DISK_FULL);
3975
0
    error_to_writebrawerr(req);
3976
0
    goto out;
3977
0
  }
3978
3979
0
  total_written = nwritten;
3980
3981
  /* Allocate a buffer of 64k + length. */
3982
0
  buf = talloc_array(NULL, char, 65540);
3983
0
  if (!buf) {
3984
0
    reply_nterror(req, NT_STATUS_NO_MEMORY);
3985
0
    error_to_writebrawerr(req);
3986
0
    goto out;
3987
0
  }
3988
3989
  /* Return a SMBwritebraw message to the redirector to tell
3990
   * it to send more bytes */
3991
3992
0
  memcpy(buf, req->inbuf, smb_size);
3993
0
  srv_smb1_set_message(buf,xconn->protocol>PROTOCOL_COREPLUS?1:0,0,True);
3994
0
  SCVAL(buf,smb_com,SMBwritebraw);
3995
0
  SSVALS(buf,smb_vwv0,0xFFFF);
3996
0
  show_msg(buf);
3997
0
  if (!smb1_srv_send(req->xconn,
3998
0
         buf,
3999
0
         false,
4000
0
         0, /* no signing */
4001
0
         IS_CONN_ENCRYPTED(conn))) {
4002
0
    exit_server_cleanly("reply_writebraw: smb1_srv_send "
4003
0
      "failed.");
4004
0
  }
4005
4006
  /* Now read the raw data into the buffer and write it */
4007
0
  status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4008
0
         &numtowrite);
4009
0
  if (!NT_STATUS_IS_OK(status)) {
4010
0
    exit_server_cleanly("secondary writebraw failed");
4011
0
  }
4012
4013
  /* Set up outbuf to return the correct size */
4014
0
  reply_smb1_outbuf(req, 1, 0);
4015
4016
0
  if (numtowrite != 0) {
4017
4018
0
    if (numtowrite > 0xFFFF) {
4019
0
      DEBUG(0,("reply_writebraw: Oversize secondary write "
4020
0
        "raw requested (%u). Terminating\n",
4021
0
        (unsigned int)numtowrite ));
4022
0
      exit_server_cleanly("secondary writebraw failed");
4023
0
    }
4024
4025
0
    if (tcount > nwritten+numtowrite) {
4026
0
      DEBUG(3,("reply_writebraw: Client overestimated the "
4027
0
        "write %d %d %d\n",
4028
0
        (int)tcount,(int)nwritten,(int)numtowrite));
4029
0
    }
4030
4031
0
    status = read_data_ntstatus(xconn->transport.sock, buf+4,
4032
0
              numtowrite);
4033
4034
0
    if (!NT_STATUS_IS_OK(status)) {
4035
      /* Try and give an error message
4036
       * saying what client failed. */
4037
0
      DEBUG(0, ("reply_writebraw: Oversize secondary write "
4038
0
          "raw read failed (%s) for client %s. "
4039
0
          "Terminating\n", nt_errstr(status),
4040
0
          smbXsrv_connection_dbg(xconn)));
4041
0
      exit_server_cleanly("secondary writebraw failed");
4042
0
    }
4043
4044
    /*
4045
     * We are not vulnerable to CVE-2017-12163
4046
     * here as we are guaranteed to have numtowrite
4047
     * bytes available - we just read from the client.
4048
     */
4049
0
    nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4050
0
    if (nwritten == -1) {
4051
0
      TALLOC_FREE(buf);
4052
0
      reply_nterror(req, map_nt_error_from_unix(errno));
4053
0
      error_to_writebrawerr(req);
4054
0
      goto out;
4055
0
    }
4056
4057
0
    if (nwritten < (ssize_t)numtowrite) {
4058
0
      SCVAL(req->outbuf,smb_rcls,ERRHRD);
4059
0
      SSVAL(req->outbuf,smb_err,ERRdiskfull);
4060
0
    }
4061
4062
0
    if (nwritten > 0) {
4063
0
      total_written += nwritten;
4064
0
    }
4065
0
  }
4066
4067
0
  TALLOC_FREE(buf);
4068
0
  SSVAL(req->outbuf,smb_vwv0,total_written);
4069
4070
0
  status = sync_file(conn, fsp, write_through);
4071
0
  if (!NT_STATUS_IS_OK(status)) {
4072
0
    DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4073
0
       fsp_str_dbg(fsp), nt_errstr(status)));
4074
0
    reply_nterror(req, status);
4075
0
    error_to_writebrawerr(req);
4076
0
    goto out;
4077
0
  }
4078
4079
0
  DEBUG(3,("reply_writebraw: secondary write %s start=%.0f num=%d "
4080
0
    "wrote=%d\n",
4081
0
    fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4082
0
    (int)total_written));
4083
4084
  /* We won't return a status if write through is not selected - this
4085
   * follows what WfWg does */
4086
0
  END_PROFILE(SMBwritebraw);
4087
4088
0
  if (!write_through && total_written==tcount) {
4089
4090
0
#if RABBIT_PELLET_FIX
4091
    /*
4092
     * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4093
     * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4094
     * JRA.
4095
     */
4096
0
    if (!send_keepalive(xconn->transport.sock)) {
4097
0
      exit_server_cleanly("reply_writebraw: send of "
4098
0
        "keepalive failed");
4099
0
    }
4100
0
#endif
4101
0
    TALLOC_FREE(req->outbuf);
4102
0
  }
4103
0
  return;
4104
4105
0
out:
4106
0
  END_PROFILE(SMBwritebraw);
4107
0
  return;
4108
0
}
4109
4110
#undef DBGC_CLASS
4111
0
#define DBGC_CLASS DBGC_LOCKING
4112
4113
/****************************************************************************
4114
 Reply to a writeunlock (core+).
4115
****************************************************************************/
4116
4117
void reply_writeunlock(struct smb_request *req)
4118
0
{
4119
0
  connection_struct *conn = req->conn;
4120
0
  ssize_t nwritten = -1;
4121
0
  size_t numtowrite;
4122
0
  size_t remaining;
4123
0
  off_t startpos;
4124
0
  const char *data;
4125
0
  NTSTATUS status = NT_STATUS_OK;
4126
0
  files_struct *fsp;
4127
0
  struct lock_struct lock;
4128
0
  int saved_errno = 0;
4129
4130
0
  START_PROFILE(SMBwriteunlock);
4131
4132
0
  if (req->wct < 5) {
4133
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4134
0
    END_PROFILE(SMBwriteunlock);
4135
0
    return;
4136
0
  }
4137
4138
0
  fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4139
4140
0
  if (!check_fsp(conn, req, fsp)) {
4141
0
    END_PROFILE(SMBwriteunlock);
4142
0
    return;
4143
0
  }
4144
4145
0
  status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
4146
0
  if (!NT_STATUS_IS_OK(status)) {
4147
0
    reply_nterror(req, status);
4148
0
    END_PROFILE(SMBwriteunlock);
4149
0
    return;
4150
0
  }
4151
4152
0
  numtowrite = SVAL(req->vwv+1, 0);
4153
0
  startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4154
0
  data = (const char *)req->buf + 3;
4155
4156
  /*
4157
   * Ensure client isn't asking us to write more than
4158
   * they sent. CVE-2017-12163.
4159
   */
4160
0
  remaining = smbreq_bufrem(req, data);
4161
0
  if (numtowrite > remaining) {
4162
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4163
0
    END_PROFILE(SMBwriteunlock);
4164
0
    return;
4165
0
  }
4166
4167
0
  if (!fsp->print_file && numtowrite > 0) {
4168
0
    init_strict_lock_struct(fsp,
4169
0
        (uint64_t)req->smbpid,
4170
0
        (uint64_t)startpos,
4171
0
        (uint64_t)numtowrite,
4172
0
        WRITE_LOCK,
4173
0
        &lock);
4174
4175
0
    if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4176
0
      reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4177
0
      END_PROFILE(SMBwriteunlock);
4178
0
      return;
4179
0
    }
4180
0
  }
4181
4182
  /* The special X/Open SMB protocol handling of
4183
     zero length writes is *NOT* done for
4184
     this call */
4185
0
  if(numtowrite == 0) {
4186
0
    nwritten = 0;
4187
0
  } else {
4188
0
    nwritten = write_file(req,fsp,data,startpos,numtowrite);
4189
0
    saved_errno = errno;
4190
0
  }
4191
4192
0
  status = sync_file(conn, fsp, False /* write through */);
4193
0
  if (!NT_STATUS_IS_OK(status)) {
4194
0
    DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4195
0
       fsp_str_dbg(fsp), nt_errstr(status)));
4196
0
    reply_nterror(req, status);
4197
0
    goto out;
4198
0
  }
4199
4200
0
  if(nwritten < 0) {
4201
0
    reply_nterror(req, map_nt_error_from_unix(saved_errno));
4202
0
    goto out;
4203
0
  }
4204
4205
0
  if((nwritten < numtowrite) && (numtowrite != 0)) {
4206
0
    reply_nterror(req, NT_STATUS_DISK_FULL);
4207
0
    goto out;
4208
0
  }
4209
4210
0
  if (numtowrite && !fsp->print_file) {
4211
0
    struct smbd_lock_element l = {
4212
0
      .req_guid = smbd_request_guid(req, 0),
4213
0
      .smblctx = req->smbpid,
4214
0
      .brltype = UNLOCK_LOCK,
4215
0
      .lock_flav = WINDOWS_LOCK,
4216
0
      .offset = startpos,
4217
0
      .count = numtowrite,
4218
0
    };
4219
0
    status = smbd_do_unlocking(req, fsp, 1, &l);
4220
0
    if (NT_STATUS_V(status)) {
4221
0
      reply_nterror(req, status);
4222
0
      goto out;
4223
0
    }
4224
0
  }
4225
4226
0
  reply_smb1_outbuf(req, 1, 0);
4227
4228
0
  SSVAL(req->outbuf,smb_vwv0,nwritten);
4229
4230
0
  DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4231
0
      fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4232
4233
0
out:
4234
0
  END_PROFILE(SMBwriteunlock);
4235
0
  return;
4236
0
}
4237
4238
#undef DBGC_CLASS
4239
0
#define DBGC_CLASS DBGC_ALL
4240
4241
/****************************************************************************
4242
 Reply to a write.
4243
****************************************************************************/
4244
4245
void reply_write(struct smb_request *req)
4246
0
{
4247
0
  connection_struct *conn = req->conn;
4248
0
  size_t numtowrite;
4249
0
  size_t remaining;
4250
0
  ssize_t nwritten = -1;
4251
0
  off_t startpos;
4252
0
  const char *data;
4253
0
  files_struct *fsp;
4254
0
  struct lock_struct lock;
4255
0
  NTSTATUS status;
4256
0
  int saved_errno = 0;
4257
4258
0
  START_PROFILE(SMBwrite);
4259
4260
0
  if (req->wct < 5) {
4261
0
    END_PROFILE(SMBwrite);
4262
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4263
0
    return;
4264
0
  }
4265
4266
  /* If it's an IPC, pass off the pipe handler. */
4267
0
  if (IS_IPC(conn)) {
4268
0
    reply_pipe_write(req);
4269
0
    END_PROFILE(SMBwrite);
4270
0
    return;
4271
0
  }
4272
4273
0
  fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4274
4275
0
  if (!check_fsp(conn, req, fsp)) {
4276
0
    END_PROFILE(SMBwrite);
4277
0
    return;
4278
0
  }
4279
4280
0
  status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
4281
0
  if (!NT_STATUS_IS_OK(status)) {
4282
0
    reply_nterror(req, status);
4283
0
    END_PROFILE(SMBwrite);
4284
0
    return;
4285
0
  }
4286
4287
0
  numtowrite = SVAL(req->vwv+1, 0);
4288
0
  startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4289
0
  data = (const char *)req->buf + 3;
4290
4291
  /*
4292
   * Ensure client isn't asking us to write more than
4293
   * they sent. CVE-2017-12163.
4294
   */
4295
0
  remaining = smbreq_bufrem(req, data);
4296
0
  if (numtowrite > remaining) {
4297
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4298
0
    END_PROFILE(SMBwrite);
4299
0
    return;
4300
0
  }
4301
4302
0
  if (!fsp->print_file) {
4303
0
    init_strict_lock_struct(fsp,
4304
0
        (uint64_t)req->smbpid,
4305
0
        (uint64_t)startpos,
4306
0
        (uint64_t)numtowrite,
4307
0
        WRITE_LOCK,
4308
0
        &lock);
4309
4310
0
    if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4311
0
      reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4312
0
      END_PROFILE(SMBwrite);
4313
0
      return;
4314
0
    }
4315
0
  }
4316
4317
  /*
4318
   * X/Open SMB protocol says that if smb_vwv1 is
4319
   * zero then the file size should be extended or
4320
   * truncated to the size given in smb_vwv[2-3].
4321
   */
4322
4323
0
  if(numtowrite == 0) {
4324
0
    struct file_modified_state state;
4325
4326
    /*
4327
     * This is actually an allocate call, and set EOF. JRA.
4328
     */
4329
0
    prepare_file_modified(fsp, &state);
4330
0
    nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4331
0
    if (nwritten < 0) {
4332
0
      reply_nterror(req, NT_STATUS_DISK_FULL);
4333
0
      goto out;
4334
0
    }
4335
0
    nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4336
0
    if (nwritten < 0) {
4337
0
      reply_nterror(req, NT_STATUS_DISK_FULL);
4338
0
      goto out;
4339
0
    }
4340
0
    mark_file_modified(fsp, true, &state);
4341
0
  } else {
4342
0
    nwritten = write_file(req,fsp,data,startpos,numtowrite);
4343
0
  }
4344
4345
0
  status = sync_file(conn, fsp, False);
4346
0
  if (!NT_STATUS_IS_OK(status)) {
4347
0
    DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4348
0
       fsp_str_dbg(fsp), nt_errstr(status)));
4349
0
    reply_nterror(req, status);
4350
0
    goto out;
4351
0
  }
4352
4353
0
  if(nwritten < 0) {
4354
0
    reply_nterror(req, map_nt_error_from_unix(saved_errno));
4355
0
    goto out;
4356
0
  }
4357
4358
0
  if((nwritten == 0) && (numtowrite != 0)) {
4359
0
    reply_nterror(req, NT_STATUS_DISK_FULL);
4360
0
    goto out;
4361
0
  }
4362
4363
0
  reply_smb1_outbuf(req, 1, 0);
4364
4365
0
  SSVAL(req->outbuf,smb_vwv0,nwritten);
4366
4367
0
  if (nwritten < (ssize_t)numtowrite) {
4368
0
    SCVAL(req->outbuf,smb_rcls,ERRHRD);
4369
0
    SSVAL(req->outbuf,smb_err,ERRdiskfull);
4370
0
  }
4371
4372
0
  DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4373
4374
0
out:
4375
0
  END_PROFILE(SMBwrite);
4376
0
  return;
4377
0
}
4378
4379
/****************************************************************************
4380
 Ensure a buffer is a valid writeX for recvfile purposes.
4381
****************************************************************************/
4382
4383
0
#define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4384
0
            (2*14) + /* word count (including bcc) */ \
4385
0
            1 /* pad byte */)
4386
4387
bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4388
          const uint8_t *inbuf)
4389
0
{
4390
0
  size_t numtowrite;
4391
0
  unsigned int doff = 0;
4392
0
  size_t len = smb_len_large(inbuf);
4393
0
  uint16_t fnum;
4394
0
  struct smbXsrv_open *op = NULL;
4395
0
  struct files_struct *fsp = NULL;
4396
0
  NTSTATUS status;
4397
4398
0
  if (is_encrypted_packet(inbuf)) {
4399
    /* Can't do this on encrypted
4400
     * connections. */
4401
0
    return false;
4402
0
  }
4403
4404
0
  if (CVAL(inbuf,smb_com) != SMBwriteX) {
4405
0
    return false;
4406
0
  }
4407
4408
0
  if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4409
0
      CVAL(inbuf,smb_wct) != 14) {
4410
0
    DEBUG(10,("is_valid_writeX_buffer: chained or "
4411
0
      "invalid word length.\n"));
4412
0
    return false;
4413
0
  }
4414
4415
0
  fnum = SVAL(inbuf, smb_vwv2);
4416
0
  status = smb1srv_open_lookup(xconn,
4417
0
             fnum,
4418
0
             0, /* now */
4419
0
             &op);
4420
0
  if (!NT_STATUS_IS_OK(status)) {
4421
0
    DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4422
0
    return false;
4423
0
  }
4424
0
  fsp = op->compat;
4425
0
  if (fsp == NULL) {
4426
0
    DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4427
0
    return false;
4428
0
  }
4429
0
  if (fsp->conn == NULL) {
4430
0
    DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4431
0
    return false;
4432
0
  }
4433
4434
0
  if (IS_IPC(fsp->conn)) {
4435
0
    DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4436
0
    return false;
4437
0
  }
4438
0
  if (IS_PRINT(fsp->conn)) {
4439
0
    DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4440
0
    return false;
4441
0
  }
4442
0
  if (fsp_is_alternate_stream(fsp)) {
4443
0
    DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
4444
0
    return false;
4445
0
  }
4446
0
  doff = SVAL(inbuf,smb_vwv11);
4447
4448
0
  numtowrite = SVAL(inbuf,smb_vwv10);
4449
4450
0
  if (len > doff && len - doff > 0xFFFF) {
4451
0
    numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4452
0
  }
4453
4454
0
  if (numtowrite == 0) {
4455
0
    DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4456
0
    return false;
4457
0
  }
4458
4459
  /* Ensure the sizes match up. */
4460
0
  if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4461
    /* no pad byte...old smbclient :-( */
4462
0
    DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4463
0
      (unsigned int)doff,
4464
0
      (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4465
0
    return false;
4466
0
  }
4467
4468
0
  if (len - doff != numtowrite) {
4469
0
    DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4470
0
      "len = %u, doff = %u, numtowrite = %u\n",
4471
0
      (unsigned int)len,
4472
0
      (unsigned int)doff,
4473
0
      (unsigned int)numtowrite ));
4474
0
    return false;
4475
0
  }
4476
4477
0
  DEBUG(10,("is_valid_writeX_buffer: true "
4478
0
    "len = %u, doff = %u, numtowrite = %u\n",
4479
0
    (unsigned int)len,
4480
0
    (unsigned int)doff,
4481
0
    (unsigned int)numtowrite ));
4482
4483
0
  return true;
4484
0
}
4485
4486
/****************************************************************************
4487
 Reply to a write and X.
4488
****************************************************************************/
4489
4490
void reply_write_and_X(struct smb_request *req)
4491
0
{
4492
0
  connection_struct *conn = req->conn;
4493
0
  struct smbXsrv_connection *xconn = req->xconn;
4494
0
  files_struct *fsp;
4495
0
  struct lock_struct lock;
4496
0
  off_t startpos;
4497
0
  size_t numtowrite;
4498
0
  bool write_through;
4499
0
  ssize_t nwritten;
4500
0
  unsigned int smb_doff;
4501
0
  unsigned int smblen;
4502
0
  const char *data;
4503
0
  NTSTATUS status;
4504
0
  int saved_errno = 0;
4505
4506
0
  START_PROFILE(SMBwriteX);
4507
4508
0
  if ((req->wct != 12) && (req->wct != 14)) {
4509
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4510
0
    goto out;
4511
0
  }
4512
4513
0
  numtowrite = SVAL(req->vwv+10, 0);
4514
0
  smb_doff = SVAL(req->vwv+11, 0);
4515
0
  smblen = smb_len(req->inbuf);
4516
4517
0
  if (req->unread_bytes > 0xFFFF ||
4518
0
      (smblen > smb_doff &&
4519
0
        smblen - smb_doff > 0xFFFF)) {
4520
0
    numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4521
0
  }
4522
4523
0
  if (req->unread_bytes) {
4524
    /* Can't do a recvfile write on IPC$ */
4525
0
    if (IS_IPC(conn)) {
4526
0
      reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4527
0
      goto out;
4528
0
    }
4529
0
          if (numtowrite != req->unread_bytes) {
4530
0
      reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4531
0
      goto out;
4532
0
    }
4533
0
  } else {
4534
    /*
4535
     * This already protects us against CVE-2017-12163.
4536
     */
4537
0
    if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4538
0
        smb_doff + numtowrite > smblen) {
4539
0
      reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4540
0
      goto out;
4541
0
    }
4542
0
  }
4543
4544
  /* If it's an IPC, pass off the pipe handler. */
4545
0
  if (IS_IPC(conn)) {
4546
0
    if (req->unread_bytes) {
4547
0
      reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4548
0
      goto out;
4549
0
    }
4550
0
    reply_pipe_write_and_X(req);
4551
0
    goto out;
4552
0
  }
4553
4554
0
  fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4555
0
  startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4556
0
  write_through = BITSETW(req->vwv+7,0);
4557
4558
0
  if (!check_fsp(conn, req, fsp)) {
4559
0
    goto out;
4560
0
  }
4561
4562
0
  status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
4563
0
  if (!NT_STATUS_IS_OK(status)) {
4564
0
    reply_nterror(req, status);
4565
0
    goto out;
4566
0
  }
4567
4568
0
  data = smb_base(req->inbuf) + smb_doff;
4569
4570
0
  if(req->wct == 14) {
4571
    /*
4572
     * This is a large offset (64 bit) write.
4573
     */
4574
0
    startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4575
4576
0
  }
4577
4578
  /* X/Open SMB protocol says that, unlike SMBwrite
4579
  if the length is zero then NO truncation is
4580
  done, just a write of zero. To truncate a file,
4581
  use SMBwrite. */
4582
4583
0
  if(numtowrite == 0) {
4584
0
    nwritten = 0;
4585
0
  } else {
4586
0
    if (req->unread_bytes == 0) {
4587
0
      status = schedule_aio_write_and_X(conn,
4588
0
            req,
4589
0
            fsp,
4590
0
            data,
4591
0
            startpos,
4592
0
            numtowrite);
4593
4594
0
      if (NT_STATUS_IS_OK(status)) {
4595
        /* write scheduled - we're done. */
4596
0
        goto out;
4597
0
      }
4598
0
      if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4599
        /* Real error - report to client. */
4600
0
        reply_nterror(req, status);
4601
0
        goto out;
4602
0
      }
4603
      /* NT_STATUS_RETRY - fall through to sync write. */
4604
0
    }
4605
4606
0
    init_strict_lock_struct(fsp,
4607
0
        (uint64_t)req->smbpid,
4608
0
        (uint64_t)startpos,
4609
0
        (uint64_t)numtowrite,
4610
0
        WRITE_LOCK,
4611
0
        &lock);
4612
4613
0
    if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4614
0
      reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4615
0
      goto out;
4616
0
    }
4617
4618
0
    nwritten = write_file(req,fsp,data,startpos,numtowrite);
4619
0
    saved_errno = errno;
4620
0
  }
4621
4622
0
  if(nwritten < 0) {
4623
0
    reply_nterror(req, map_nt_error_from_unix(saved_errno));
4624
0
    goto out;
4625
0
  }
4626
4627
0
  if((nwritten == 0) && (numtowrite != 0)) {
4628
0
    reply_nterror(req, NT_STATUS_DISK_FULL);
4629
0
    goto out;
4630
0
  }
4631
4632
0
  reply_smb1_outbuf(req, 6, 0);
4633
0
  SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4634
0
  SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
4635
0
  SSVAL(req->outbuf,smb_vwv2,nwritten);
4636
0
  SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4637
4638
0
  DEBUG(3,("writeX %s num=%d wrote=%d\n",
4639
0
    fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4640
4641
0
  status = sync_file(conn, fsp, write_through);
4642
0
  if (!NT_STATUS_IS_OK(status)) {
4643
0
    DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4644
0
       fsp_str_dbg(fsp), nt_errstr(status)));
4645
0
    reply_nterror(req, status);
4646
0
    goto out;
4647
0
  }
4648
4649
0
  END_PROFILE(SMBwriteX);
4650
0
  return;
4651
4652
0
out:
4653
0
  if (req->unread_bytes) {
4654
    /* writeX failed. drain socket. */
4655
0
    if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
4656
0
        req->unread_bytes) {
4657
0
      smb_panic("failed to drain pending bytes");
4658
0
    }
4659
0
    req->unread_bytes = 0;
4660
0
  }
4661
4662
0
  END_PROFILE(SMBwriteX);
4663
0
  return;
4664
0
}
4665
4666
/****************************************************************************
4667
 Reply to a lseek.
4668
****************************************************************************/
4669
4670
void reply_lseek(struct smb_request *req)
4671
0
{
4672
0
  connection_struct *conn = req->conn;
4673
0
  off_t startpos;
4674
0
  off_t res= -1;
4675
0
  int mode,umode;
4676
0
  files_struct *fsp;
4677
0
  NTSTATUS status;
4678
4679
0
  START_PROFILE(SMBlseek);
4680
4681
0
  if (req->wct < 4) {
4682
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4683
0
    END_PROFILE(SMBlseek);
4684
0
    return;
4685
0
  }
4686
4687
0
  fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4688
4689
0
  if (!check_fsp(conn, req, fsp)) {
4690
0
    return;
4691
0
  }
4692
4693
0
  mode = SVAL(req->vwv+1, 0) & 3;
4694
  /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4695
0
  startpos = (off_t)IVALS(req->vwv+2, 0);
4696
4697
0
  switch (mode) {
4698
0
    case 0:
4699
0
      umode = SEEK_SET;
4700
0
      res = startpos;
4701
0
      break;
4702
0
    case 1:
4703
0
      umode = SEEK_CUR;
4704
0
      res = fh_get_pos(fsp->fh) + startpos;
4705
0
      break;
4706
0
    case 2:
4707
0
      umode = SEEK_END;
4708
0
      break;
4709
0
    default:
4710
0
      umode = SEEK_SET;
4711
0
      res = startpos;
4712
0
      break;
4713
0
  }
4714
4715
0
  if (umode == SEEK_END) {
4716
0
    if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4717
0
      if(errno == EINVAL) {
4718
0
        off_t current_pos = startpos;
4719
4720
0
        status = vfs_stat_fsp(fsp);
4721
0
        if (!NT_STATUS_IS_OK(status)) {
4722
0
          reply_nterror(req, status);
4723
0
          END_PROFILE(SMBlseek);
4724
0
          return;
4725
0
        }
4726
4727
0
        current_pos += fsp->fsp_name->st.st_ex_size;
4728
0
        if(current_pos < 0)
4729
0
          res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4730
0
      }
4731
0
    }
4732
4733
0
    if(res == -1) {
4734
0
      reply_nterror(req, map_nt_error_from_unix(errno));
4735
0
      END_PROFILE(SMBlseek);
4736
0
      return;
4737
0
    }
4738
0
  }
4739
4740
0
  fh_set_pos(fsp->fh, res);
4741
4742
0
  reply_smb1_outbuf(req, 2, 0);
4743
0
  SIVAL(req->outbuf,smb_vwv0,res);
4744
4745
0
  DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4746
0
    fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
4747
4748
0
  END_PROFILE(SMBlseek);
4749
0
  return;
4750
0
}
4751
4752
static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
4753
               void *private_data)
4754
0
{
4755
0
  connection_struct *conn = talloc_get_type_abort(
4756
0
    private_data, connection_struct);
4757
4758
0
  if (conn != fsp->conn) {
4759
0
    return NULL;
4760
0
  }
4761
0
  if (fsp_get_io_fd(fsp) == -1) {
4762
0
    return NULL;
4763
0
  }
4764
0
  sync_file(conn, fsp, True /* write through */);
4765
4766
0
  return NULL;
4767
0
}
4768
4769
/****************************************************************************
4770
 Reply to a flush.
4771
****************************************************************************/
4772
4773
void reply_flush(struct smb_request *req)
4774
0
{
4775
0
  connection_struct *conn = req->conn;
4776
0
  uint16_t fnum;
4777
0
  files_struct *fsp;
4778
4779
0
  START_PROFILE(SMBflush);
4780
4781
0
  if (req->wct < 1) {
4782
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4783
0
    return;
4784
0
  }
4785
4786
0
  fnum = SVAL(req->vwv+0, 0);
4787
0
  fsp = file_fsp(req, fnum);
4788
4789
0
  if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4790
0
    return;
4791
0
  }
4792
4793
0
  if (!fsp) {
4794
0
    files_forall(req->sconn, file_sync_one_fn, conn);
4795
0
  } else {
4796
0
    NTSTATUS status = sync_file(conn, fsp, True);
4797
0
    if (!NT_STATUS_IS_OK(status)) {
4798
0
      DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4799
0
        fsp_str_dbg(fsp), nt_errstr(status)));
4800
0
      reply_nterror(req, status);
4801
0
      END_PROFILE(SMBflush);
4802
0
      return;
4803
0
    }
4804
0
  }
4805
4806
0
  reply_smb1_outbuf(req, 0, 0);
4807
4808
0
  DEBUG(3,("flush\n"));
4809
0
  END_PROFILE(SMBflush);
4810
0
  return;
4811
0
}
4812
4813
/****************************************************************************
4814
 Reply to a exit.
4815
 conn POINTER CAN BE NULL HERE !
4816
****************************************************************************/
4817
4818
static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
4819
static void reply_exit_done(struct tevent_req *req);
4820
4821
void reply_exit(struct smb_request *smb1req)
4822
0
{
4823
0
  struct tevent_req *req;
4824
4825
  /*
4826
   * Don't setup the profile charge here, take
4827
   * it in reply_exit_done(). Not strictly correct
4828
   * but better than the other SMB1 async
4829
   * code that double-charges at the moment.
4830
   */
4831
0
  req = reply_exit_send(smb1req);
4832
0
  if (req == NULL) {
4833
    /* Not going async, profile here. */
4834
0
    START_PROFILE(SMBexit);
4835
0
    reply_force_doserror(smb1req, ERRDOS, ERRnomem);
4836
0
    END_PROFILE(SMBexit);
4837
0
    return;
4838
0
  }
4839
4840
  /* We're async. This will complete later. */
4841
0
  tevent_req_set_callback(req, reply_exit_done, smb1req);
4842
0
  return;
4843
0
}
4844
4845
struct reply_exit_state {
4846
  struct tevent_queue *wait_queue;
4847
};
4848
4849
static void reply_exit_wait_done(struct tevent_req *subreq);
4850
4851
/****************************************************************************
4852
 Async SMB1 exit.
4853
 Note, on failure here we deallocate and return NULL to allow the caller to
4854
 SMB1 return an error of ERRnomem immediately.
4855
****************************************************************************/
4856
4857
static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
4858
0
{
4859
0
  struct tevent_req *req;
4860
0
  struct reply_exit_state *state;
4861
0
  struct tevent_req *subreq;
4862
0
  files_struct *fsp;
4863
0
  struct smbd_server_connection *sconn = smb1req->sconn;
4864
4865
0
  req = tevent_req_create(smb1req, &state,
4866
0
      struct reply_exit_state);
4867
0
  if (req == NULL) {
4868
0
    return NULL;
4869
0
  }
4870
0
  state->wait_queue = tevent_queue_create(state,
4871
0
        "reply_exit_wait_queue");
4872
0
  if (tevent_req_nomem(state->wait_queue, req)) {
4873
0
    TALLOC_FREE(req);
4874
0
    return NULL;
4875
0
  }
4876
4877
0
  for (fsp = sconn->files; fsp; fsp = fsp->next) {
4878
0
    if (fsp->file_pid != smb1req->smbpid) {
4879
0
      continue;
4880
0
    }
4881
0
    if (fsp->vuid != smb1req->vuid) {
4882
0
      continue;
4883
0
    }
4884
    /*
4885
     * Flag the file as close in progress.
4886
     * This will prevent any more IO being
4887
     * done on it.
4888
     */
4889
0
    fsp->fsp_flags.closing = true;
4890
4891
0
    if (fsp->num_aio_requests > 0) {
4892
      /*
4893
       * Now wait until all aio requests on this fsp are
4894
       * finished.
4895
       *
4896
       * We don't set a callback, as we just want to block the
4897
       * wait queue and the talloc_free() of fsp->aio_request
4898
       * will remove the item from the wait queue.
4899
       */
4900
0
      subreq = tevent_queue_wait_send(fsp->aio_requests,
4901
0
            sconn->ev_ctx,
4902
0
            state->wait_queue);
4903
0
      if (tevent_req_nomem(subreq, req)) {
4904
0
        TALLOC_FREE(req);
4905
0
        return NULL;
4906
0
      }
4907
0
    }
4908
0
  }
4909
4910
  /*
4911
   * Now we add our own waiter to the end of the queue,
4912
   * this way we get notified when all pending requests are finished
4913
   * and reply to the outstanding SMB1 request.
4914
   */
4915
0
  subreq = tevent_queue_wait_send(state,
4916
0
        sconn->ev_ctx,
4917
0
        state->wait_queue);
4918
0
  if (tevent_req_nomem(subreq, req)) {
4919
0
    TALLOC_FREE(req);
4920
0
    return NULL;
4921
0
  }
4922
4923
  /*
4924
   * We're really going async - move the SMB1 request from
4925
   * a talloc stackframe above us to the conn talloc-context.
4926
   * We need this to stick around until the wait_done
4927
   * callback is invoked.
4928
   */
4929
0
  smb1req = talloc_move(sconn, &smb1req);
4930
4931
0
  tevent_req_set_callback(subreq, reply_exit_wait_done, req);
4932
4933
0
  return req;
4934
0
}
4935
4936
static void reply_exit_wait_done(struct tevent_req *subreq)
4937
0
{
4938
0
  struct tevent_req *req = tevent_req_callback_data(
4939
0
    subreq, struct tevent_req);
4940
4941
0
  tevent_queue_wait_recv(subreq);
4942
0
  TALLOC_FREE(subreq);
4943
0
  tevent_req_done(req);
4944
0
}
4945
4946
static NTSTATUS reply_exit_recv(struct tevent_req *req)
4947
0
{
4948
0
  return tevent_req_simple_recv_ntstatus(req);
4949
0
}
4950
4951
static void reply_exit_done(struct tevent_req *req)
4952
0
{
4953
0
  struct smb_request *smb1req = tevent_req_callback_data(
4954
0
    req, struct smb_request);
4955
0
  struct smbd_server_connection *sconn = smb1req->sconn;
4956
0
  struct smbXsrv_connection *xconn = smb1req->xconn;
4957
0
  NTTIME now = timeval_to_nttime(&smb1req->request_time);
4958
0
  struct smbXsrv_session *session = NULL;
4959
0
  files_struct *fsp, *next;
4960
0
  NTSTATUS status;
4961
4962
  /*
4963
   * Take the profile charge here. Not strictly
4964
   * correct but better than the other SMB1 async
4965
   * code that double-charges at the moment.
4966
   */
4967
0
  START_PROFILE(SMBexit);
4968
4969
0
  status = reply_exit_recv(req);
4970
0
  TALLOC_FREE(req);
4971
0
  if (!NT_STATUS_IS_OK(status)) {
4972
0
    TALLOC_FREE(smb1req);
4973
0
    END_PROFILE(SMBexit);
4974
0
    exit_server(__location__ ": reply_exit_recv failed");
4975
0
    return;
4976
0
  }
4977
4978
  /*
4979
   * Ensure the session is still valid.
4980
   */
4981
0
  status = smb1srv_session_lookup(xconn,
4982
0
          smb1req->vuid,
4983
0
          now,
4984
0
          &session);
4985
0
  if (!NT_STATUS_IS_OK(status)) {
4986
0
    reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
4987
0
    smb_request_done(smb1req);
4988
0
    END_PROFILE(SMBexit);
4989
0
    return;
4990
0
  }
4991
4992
  /*
4993
   * Ensure the vuid is still valid - no one
4994
   * called reply_ulogoffX() in the meantime.
4995
   * reply_exit() doesn't have AS_USER set, so
4996
   * use set_current_user_info() directly.
4997
   * This is the same logic as in switch_message().
4998
   */
4999
0
  if (session->global->auth_session_info != NULL) {
5000
0
    set_current_user_info(
5001
0
      session->global->auth_session_info->unix_info->sanitized_username,
5002
0
      session->global->auth_session_info->unix_info->unix_name,
5003
0
      session->global->auth_session_info->info->domain_name);
5004
0
  }
5005
5006
  /* No more aio - do the actual closes. */
5007
0
  for (fsp = sconn->files; fsp; fsp = next) {
5008
0
    bool ok;
5009
0
    next = fsp->next;
5010
5011
0
    if (fsp->file_pid != smb1req->smbpid) {
5012
0
      continue;
5013
0
    }
5014
0
    if (fsp->vuid != smb1req->vuid) {
5015
0
      continue;
5016
0
    }
5017
0
    if (!fsp->fsp_flags.closing) {
5018
0
      continue;
5019
0
    }
5020
5021
    /*
5022
     * reply_exit() has the DO_CHDIR flag set.
5023
     */
5024
0
    ok = chdir_current_service(fsp->conn);
5025
0
    if (!ok) {
5026
0
      reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5027
0
      smb_request_done(smb1req);
5028
0
      END_PROFILE(SMBexit);
5029
0
      return;
5030
0
    }
5031
0
    close_file_free(NULL, &fsp, SHUTDOWN_CLOSE);
5032
0
  }
5033
5034
0
  reply_smb1_outbuf(smb1req, 0, 0);
5035
  /*
5036
   * The following call is needed to push the
5037
   * reply data back out the socket after async
5038
   * return. Plus it frees smb1req.
5039
   */
5040
0
  smb_request_done(smb1req);
5041
0
  DBG_INFO("reply_exit complete\n");
5042
0
  END_PROFILE(SMBexit);
5043
0
  return;
5044
0
}
5045
5046
static struct tevent_req *reply_close_send(struct smb_request *smb1req,
5047
        files_struct *fsp);
5048
static void reply_close_done(struct tevent_req *req);
5049
5050
void reply_close(struct smb_request *smb1req)
5051
0
{
5052
0
  connection_struct *conn = smb1req->conn;
5053
0
  NTSTATUS status = NT_STATUS_OK;
5054
0
  files_struct *fsp = NULL;
5055
0
  START_PROFILE(SMBclose);
5056
5057
0
  if (smb1req->wct < 3) {
5058
0
    reply_nterror(smb1req, NT_STATUS_INVALID_PARAMETER);
5059
0
    END_PROFILE(SMBclose);
5060
0
    return;
5061
0
  }
5062
5063
0
  fsp = file_fsp(smb1req, SVAL(smb1req->vwv+0, 0));
5064
5065
  /*
5066
   * We can only use check_fsp if we know it's not a directory.
5067
   */
5068
5069
0
  if (!check_fsp_open(conn, smb1req, fsp)) {
5070
0
    END_PROFILE(SMBclose);
5071
0
    return;
5072
0
  }
5073
5074
0
  DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
5075
0
      fsp->fsp_flags.is_directory ?
5076
0
      "directory" : "file",
5077
0
      fsp_get_pathref_fd(fsp), fsp_fnum_dbg(fsp),
5078
0
      conn->num_files_open);
5079
5080
0
  if (!fsp->fsp_flags.is_directory) {
5081
0
    time_t t;
5082
5083
    /*
5084
     * Take care of any time sent in the close.
5085
     */
5086
5087
0
    t = srv_make_unix_date3(smb1req->vwv+1);
5088
0
    set_close_write_time(fsp, time_t_to_full_timespec(t));
5089
0
  }
5090
5091
0
  if (fsp->num_aio_requests != 0) {
5092
0
    struct tevent_req *req;
5093
5094
0
    req = reply_close_send(smb1req, fsp);
5095
0
    if (req == NULL) {
5096
0
      status = NT_STATUS_NO_MEMORY;
5097
0
      goto done;
5098
0
    }
5099
    /* We're async. This will complete later. */
5100
0
    tevent_req_set_callback(req, reply_close_done, smb1req);
5101
0
    END_PROFILE(SMBclose);
5102
0
    return;
5103
0
  }
5104
5105
  /*
5106
   * close_file_free() returns the unix errno if an error was detected on
5107
   * close - normally this is due to a disk full error. If not then it
5108
   * was probably an I/O error.
5109
   */
5110
5111
0
  status = close_file_free(smb1req, &fsp, NORMAL_CLOSE);
5112
0
done:
5113
0
  if (!NT_STATUS_IS_OK(status)) {
5114
0
    reply_nterror(smb1req, status);
5115
0
    END_PROFILE(SMBclose);
5116
0
    return;
5117
0
  }
5118
5119
0
  reply_smb1_outbuf(smb1req, 0, 0);
5120
0
  END_PROFILE(SMBclose);
5121
0
  return;
5122
0
}
5123
5124
struct reply_close_state {
5125
  files_struct *fsp;
5126
  struct tevent_queue *wait_queue;
5127
};
5128
5129
static void reply_close_wait_done(struct tevent_req *subreq);
5130
5131
/****************************************************************************
5132
 Async SMB1 close.
5133
 Note, on failure here we deallocate and return NULL to allow the caller to
5134
 SMB1 return an error of ERRnomem immediately.
5135
****************************************************************************/
5136
5137
static struct tevent_req *reply_close_send(struct smb_request *smb1req,
5138
        files_struct *fsp)
5139
0
{
5140
0
  struct tevent_req *req;
5141
0
  struct reply_close_state *state;
5142
0
  struct tevent_req *subreq;
5143
0
  struct smbd_server_connection *sconn = smb1req->sconn;
5144
5145
0
  req = tevent_req_create(smb1req, &state,
5146
0
      struct reply_close_state);
5147
0
  if (req == NULL) {
5148
0
    return NULL;
5149
0
  }
5150
0
  state->wait_queue = tevent_queue_create(state,
5151
0
        "reply_close_wait_queue");
5152
0
  if (tevent_req_nomem(state->wait_queue, req)) {
5153
0
    TALLOC_FREE(req);
5154
0
    return NULL;
5155
0
  }
5156
5157
  /*
5158
   * Flag the file as close in progress.
5159
   * This will prevent any more IO being
5160
   * done on it.
5161
   */
5162
0
  fsp->fsp_flags.closing = true;
5163
5164
  /*
5165
   * Now wait until all aio requests on this fsp are
5166
   * finished.
5167
   *
5168
   * We don't set a callback, as we just want to block the
5169
   * wait queue and the talloc_free() of fsp->aio_request
5170
   * will remove the item from the wait queue.
5171
   */
5172
0
  subreq = tevent_queue_wait_send(fsp->aio_requests,
5173
0
          sconn->ev_ctx,
5174
0
          state->wait_queue);
5175
0
  if (tevent_req_nomem(subreq, req)) {
5176
0
    TALLOC_FREE(req);
5177
0
    return NULL;
5178
0
  }
5179
5180
  /*
5181
   * Now we add our own waiter to the end of the queue,
5182
   * this way we get notified when all pending requests are finished
5183
   * and reply to the outstanding SMB1 request.
5184
   */
5185
0
  subreq = tevent_queue_wait_send(state,
5186
0
        sconn->ev_ctx,
5187
0
        state->wait_queue);
5188
0
  if (tevent_req_nomem(subreq, req)) {
5189
0
    TALLOC_FREE(req);
5190
0
    return NULL;
5191
0
  }
5192
5193
  /*
5194
   * We're really going async - move the SMB1 request from
5195
   * a talloc stackframe above us to the conn talloc-context.
5196
   * We need this to stick around until the wait_done
5197
   * callback is invoked.
5198
   */
5199
0
  smb1req = talloc_move(sconn, &smb1req);
5200
5201
0
  tevent_req_set_callback(subreq, reply_close_wait_done, req);
5202
5203
0
  return req;
5204
0
}
5205
5206
static void reply_close_wait_done(struct tevent_req *subreq)
5207
0
{
5208
0
  struct tevent_req *req = tevent_req_callback_data(
5209
0
    subreq, struct tevent_req);
5210
5211
0
  tevent_queue_wait_recv(subreq);
5212
0
  TALLOC_FREE(subreq);
5213
0
  tevent_req_done(req);
5214
0
}
5215
5216
static NTSTATUS reply_close_recv(struct tevent_req *req)
5217
0
{
5218
0
  return tevent_req_simple_recv_ntstatus(req);
5219
0
}
5220
5221
static void reply_close_done(struct tevent_req *req)
5222
0
{
5223
0
  struct smb_request *smb1req = tevent_req_callback_data(
5224
0
      req, struct smb_request);
5225
0
        struct reply_close_state *state = tevent_req_data(req,
5226
0
                                                struct reply_close_state);
5227
0
  NTSTATUS status;
5228
5229
0
  status = reply_close_recv(req);
5230
0
  TALLOC_FREE(req);
5231
0
  if (!NT_STATUS_IS_OK(status)) {
5232
0
    TALLOC_FREE(smb1req);
5233
0
    exit_server(__location__ ": reply_close_recv failed");
5234
0
    return;
5235
0
  }
5236
5237
0
  status = close_file_free(smb1req, &state->fsp, NORMAL_CLOSE);
5238
0
  if (NT_STATUS_IS_OK(status)) {
5239
0
    reply_smb1_outbuf(smb1req, 0, 0);
5240
0
  } else {
5241
0
    reply_nterror(smb1req, status);
5242
0
  }
5243
  /*
5244
   * The following call is needed to push the
5245
   * reply data back out the socket after async
5246
   * return. Plus it frees smb1req.
5247
   */
5248
0
  smb_request_done(smb1req);
5249
0
}
5250
5251
/****************************************************************************
5252
 Reply to a writeclose (Core+ protocol).
5253
****************************************************************************/
5254
5255
void reply_writeclose(struct smb_request *req)
5256
0
{
5257
0
  connection_struct *conn = req->conn;
5258
0
  size_t numtowrite;
5259
0
  size_t remaining;
5260
0
  ssize_t nwritten = -1;
5261
0
  NTSTATUS close_status = NT_STATUS_OK;
5262
0
  off_t startpos;
5263
0
  const char *data;
5264
0
  struct timespec mtime;
5265
0
  files_struct *fsp;
5266
0
  struct lock_struct lock;
5267
0
  NTSTATUS status;
5268
5269
0
  START_PROFILE(SMBwriteclose);
5270
5271
0
  if (req->wct < 6) {
5272
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5273
0
    END_PROFILE(SMBwriteclose);
5274
0
    return;
5275
0
  }
5276
5277
0
  fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5278
5279
0
  if (!check_fsp(conn, req, fsp)) {
5280
0
    END_PROFILE(SMBwriteclose);
5281
0
    return;
5282
0
  }
5283
0
  status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
5284
0
  if (!NT_STATUS_IS_OK(status)) {
5285
0
    reply_nterror(req, status);
5286
0
    END_PROFILE(SMBwriteclose);
5287
0
    return;
5288
0
  }
5289
5290
0
  numtowrite = SVAL(req->vwv+1, 0);
5291
0
  startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5292
0
  mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
5293
0
  data = (const char *)req->buf + 1;
5294
5295
  /*
5296
   * Ensure client isn't asking us to write more than
5297
   * they sent. CVE-2017-12163.
5298
   */
5299
0
  remaining = smbreq_bufrem(req, data);
5300
0
  if (numtowrite > remaining) {
5301
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5302
0
    END_PROFILE(SMBwriteclose);
5303
0
    return;
5304
0
  }
5305
5306
0
  if (fsp->print_file == NULL) {
5307
0
    init_strict_lock_struct(fsp,
5308
0
        (uint64_t)req->smbpid,
5309
0
        (uint64_t)startpos,
5310
0
        (uint64_t)numtowrite,
5311
0
        WRITE_LOCK,
5312
0
        &lock);
5313
5314
0
    if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5315
0
      reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5316
0
      END_PROFILE(SMBwriteclose);
5317
0
      return;
5318
0
    }
5319
0
  }
5320
5321
0
  nwritten = write_file(req,fsp,data,startpos,numtowrite);
5322
5323
0
  set_close_write_time(fsp, mtime);
5324
5325
  /*
5326
   * More insanity. W2K only closes the file if writelen > 0.
5327
   * JRA.
5328
   */
5329
5330
0
  DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5331
0
    fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5332
0
    (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5333
5334
0
  if (numtowrite) {
5335
0
    DEBUG(3,("reply_writeclose: zero length write doesn't close "
5336
0
       "file %s\n", fsp_str_dbg(fsp)));
5337
0
    close_status = close_file_free(req, &fsp, NORMAL_CLOSE);
5338
0
  }
5339
5340
0
  if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5341
0
    reply_nterror(req, NT_STATUS_DISK_FULL);
5342
0
    goto out;
5343
0
  }
5344
5345
0
  if(!NT_STATUS_IS_OK(close_status)) {
5346
0
    reply_nterror(req, close_status);
5347
0
    goto out;
5348
0
  }
5349
5350
0
  reply_smb1_outbuf(req, 1, 0);
5351
5352
0
  SSVAL(req->outbuf,smb_vwv0,nwritten);
5353
5354
0
out:
5355
5356
0
  END_PROFILE(SMBwriteclose);
5357
0
  return;
5358
0
}
5359
5360
#undef DBGC_CLASS
5361
0
#define DBGC_CLASS DBGC_LOCKING
5362
5363
/****************************************************************************
5364
 Reply to a lock.
5365
****************************************************************************/
5366
5367
static void reply_lock_done(struct tevent_req *subreq);
5368
5369
void reply_lock(struct smb_request *req)
5370
0
{
5371
0
  struct tevent_req *subreq = NULL;
5372
0
  connection_struct *conn = req->conn;
5373
0
  files_struct *fsp;
5374
0
  struct smbd_lock_element *lck = NULL;
5375
5376
0
  START_PROFILE(SMBlock);
5377
5378
0
  if (req->wct < 5) {
5379
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5380
0
    END_PROFILE(SMBlock);
5381
0
    return;
5382
0
  }
5383
5384
0
  fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5385
5386
0
  if (!check_fsp(conn, req, fsp)) {
5387
0
    END_PROFILE(SMBlock);
5388
0
    return;
5389
0
  }
5390
5391
0
  lck = talloc(req, struct smbd_lock_element);
5392
0
  if (lck == NULL) {
5393
0
    reply_nterror(req, NT_STATUS_NO_MEMORY);
5394
0
    END_PROFILE(SMBlock);
5395
0
    return;
5396
0
  }
5397
5398
0
  *lck = (struct smbd_lock_element) {
5399
0
    .req_guid = smbd_request_guid(req, 0),
5400
0
    .smblctx = req->smbpid,
5401
0
    .brltype = WRITE_LOCK,
5402
0
    .lock_flav = WINDOWS_LOCK,
5403
0
    .count = IVAL(req->vwv+1, 0),
5404
0
    .offset = IVAL(req->vwv+3, 0),
5405
0
  };
5406
5407
0
  DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5408
0
       fsp_get_io_fd(fsp),
5409
0
       fsp_fnum_dbg(fsp),
5410
0
       lck->offset,
5411
0
       lck->count);
5412
5413
0
  subreq = smbd_smb1_do_locks_send(
5414
0
    fsp,
5415
0
    req->sconn->ev_ctx,
5416
0
    &req,
5417
0
    fsp,
5418
0
    0,
5419
0
    false,    /* large_offset */
5420
0
    1,
5421
0
    lck);
5422
0
  if (subreq == NULL) {
5423
0
    reply_nterror(req, NT_STATUS_NO_MEMORY);
5424
0
    END_PROFILE(SMBlock);
5425
0
    return;
5426
0
  }
5427
0
  tevent_req_set_callback(subreq, reply_lock_done, NULL);
5428
0
  END_PROFILE(SMBlock);
5429
0
}
5430
5431
static void reply_lock_done(struct tevent_req *subreq)
5432
0
{
5433
0
  struct smb_request *req = NULL;
5434
0
  NTSTATUS status;
5435
0
  bool ok;
5436
5437
0
  START_PROFILE(SMBlock);
5438
5439
0
  ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
5440
0
  SMB_ASSERT(ok);
5441
5442
0
  status = smbd_smb1_do_locks_recv(subreq);
5443
0
  TALLOC_FREE(subreq);
5444
5445
0
  if (NT_STATUS_IS_OK(status)) {
5446
0
    reply_smb1_outbuf(req, 0, 0);
5447
0
  } else {
5448
0
    reply_nterror(req, status);
5449
0
  }
5450
5451
0
  ok = smb1_srv_send(req->xconn,
5452
0
         (char *)req->outbuf,
5453
0
         true,
5454
0
         req->seqnum + 1,
5455
0
         IS_CONN_ENCRYPTED(req->conn));
5456
0
  if (!ok) {
5457
0
    exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
5458
0
  }
5459
0
  TALLOC_FREE(req);
5460
0
  END_PROFILE(SMBlock);
5461
0
}
5462
5463
/****************************************************************************
5464
 Reply to a unlock.
5465
****************************************************************************/
5466
5467
void reply_unlock(struct smb_request *req)
5468
0
{
5469
0
  connection_struct *conn = req->conn;
5470
0
  NTSTATUS status;
5471
0
  files_struct *fsp;
5472
0
  struct smbd_lock_element lck;
5473
5474
0
  START_PROFILE(SMBunlock);
5475
5476
0
  if (req->wct < 5) {
5477
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5478
0
    END_PROFILE(SMBunlock);
5479
0
    return;
5480
0
  }
5481
5482
0
  fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5483
5484
0
  if (!check_fsp(conn, req, fsp)) {
5485
0
    END_PROFILE(SMBunlock);
5486
0
    return;
5487
0
  }
5488
5489
0
  lck = (struct smbd_lock_element) {
5490
0
    .req_guid = smbd_request_guid(req, 0),
5491
0
    .smblctx = req->smbpid,
5492
0
    .brltype = UNLOCK_LOCK,
5493
0
    .lock_flav = WINDOWS_LOCK,
5494
0
    .offset = IVAL(req->vwv+3, 0),
5495
0
    .count = IVAL(req->vwv+1, 0),
5496
0
  };
5497
5498
0
  status = smbd_do_unlocking(req, fsp, 1, &lck);
5499
5500
0
  if (!NT_STATUS_IS_OK(status)) {
5501
0
    reply_nterror(req, status);
5502
0
    END_PROFILE(SMBunlock);
5503
0
    return;
5504
0
  }
5505
5506
0
  DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5507
0
       fsp_get_io_fd(fsp),
5508
0
       fsp_fnum_dbg(fsp),
5509
0
       lck.offset,
5510
0
       lck.count);
5511
5512
0
  reply_smb1_outbuf(req, 0, 0);
5513
5514
0
  END_PROFILE(SMBunlock);
5515
0
  return;
5516
0
}
5517
5518
#undef DBGC_CLASS
5519
0
#define DBGC_CLASS DBGC_ALL
5520
5521
/****************************************************************************
5522
 Reply to a tdis.
5523
 conn POINTER CAN BE NULL HERE !
5524
****************************************************************************/
5525
5526
static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
5527
static void reply_tdis_done(struct tevent_req *req);
5528
5529
void reply_tdis(struct smb_request *smb1req)
5530
0
{
5531
0
  connection_struct *conn = smb1req->conn;
5532
0
  struct tevent_req *req;
5533
5534
  /*
5535
   * Don't setup the profile charge here, take
5536
   * it in reply_tdis_done(). Not strictly correct
5537
   * but better than the other SMB1 async
5538
   * code that double-charges at the moment.
5539
   */
5540
5541
0
  if (conn == NULL) {
5542
    /* Not going async, profile here. */
5543
0
    START_PROFILE(SMBtdis);
5544
0
    DBG_INFO("Invalid connection in tdis\n");
5545
0
    reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5546
0
    END_PROFILE(SMBtdis);
5547
0
    return;
5548
0
  }
5549
5550
0
  req = reply_tdis_send(smb1req);
5551
0
  if (req == NULL) {
5552
    /* Not going async, profile here. */
5553
0
    START_PROFILE(SMBtdis);
5554
0
    reply_force_doserror(smb1req, ERRDOS, ERRnomem);
5555
0
    END_PROFILE(SMBtdis);
5556
0
    return;
5557
0
  }
5558
  /* We're async. This will complete later. */
5559
0
  tevent_req_set_callback(req, reply_tdis_done, smb1req);
5560
0
  return;
5561
0
}
5562
5563
struct reply_tdis_state {
5564
  struct tevent_queue *wait_queue;
5565
};
5566
5567
static void reply_tdis_wait_done(struct tevent_req *subreq);
5568
5569
/****************************************************************************
5570
 Async SMB1 tdis.
5571
 Note, on failure here we deallocate and return NULL to allow the caller to
5572
 SMB1 return an error of ERRnomem immediately.
5573
****************************************************************************/
5574
5575
static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
5576
0
{
5577
0
  struct tevent_req *req;
5578
0
  struct reply_tdis_state *state;
5579
0
  struct tevent_req *subreq;
5580
0
  connection_struct *conn = smb1req->conn;
5581
0
  files_struct *fsp;
5582
5583
0
  req = tevent_req_create(smb1req, &state,
5584
0
      struct reply_tdis_state);
5585
0
  if (req == NULL) {
5586
0
    return NULL;
5587
0
  }
5588
0
  state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
5589
0
  if (tevent_req_nomem(state->wait_queue, req)) {
5590
0
    TALLOC_FREE(req);
5591
0
    return NULL;
5592
0
  }
5593
5594
  /*
5595
   * Make sure that no new request will be able to use this tcon.
5596
   * This ensures that once all outstanding fsp->aio_requests
5597
   * on this tcon are done, we are safe to close it.
5598
   */
5599
0
  conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
5600
5601
0
  for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
5602
0
    if (fsp->conn != conn) {
5603
0
      continue;
5604
0
    }
5605
    /*
5606
     * Flag the file as close in progress.
5607
     * This will prevent any more IO being
5608
     * done on it. Not strictly needed, but
5609
     * doesn't hurt to flag it as closing.
5610
     */
5611
0
    fsp->fsp_flags.closing = true;
5612
5613
0
    if (fsp->num_aio_requests > 0) {
5614
      /*
5615
       * Now wait until all aio requests on this fsp are
5616
       * finished.
5617
       *
5618
       * We don't set a callback, as we just want to block the
5619
       * wait queue and the talloc_free() of fsp->aio_request
5620
       * will remove the item from the wait queue.
5621
       */
5622
0
      subreq = tevent_queue_wait_send(fsp->aio_requests,
5623
0
            conn->sconn->ev_ctx,
5624
0
            state->wait_queue);
5625
0
      if (tevent_req_nomem(subreq, req)) {
5626
0
        TALLOC_FREE(req);
5627
0
        return NULL;
5628
0
      }
5629
0
    }
5630
0
  }
5631
5632
  /*
5633
   * Now we add our own waiter to the end of the queue,
5634
   * this way we get notified when all pending requests are finished
5635
   * and reply to the outstanding SMB1 request.
5636
   */
5637
0
  subreq = tevent_queue_wait_send(state,
5638
0
        conn->sconn->ev_ctx,
5639
0
        state->wait_queue);
5640
0
  if (tevent_req_nomem(subreq, req)) {
5641
0
    TALLOC_FREE(req);
5642
0
    return NULL;
5643
0
  }
5644
5645
  /*
5646
   * We're really going async - move the SMB1 request from
5647
   * a talloc stackframe above us to the sconn talloc-context.
5648
   * We need this to stick around until the wait_done
5649
   * callback is invoked.
5650
   */
5651
0
  smb1req = talloc_move(smb1req->sconn, &smb1req);
5652
5653
0
  tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
5654
5655
0
  return req;
5656
0
}
5657
5658
static void reply_tdis_wait_done(struct tevent_req *subreq)
5659
0
{
5660
0
  struct tevent_req *req = tevent_req_callback_data(
5661
0
    subreq, struct tevent_req);
5662
5663
0
  tevent_queue_wait_recv(subreq);
5664
0
  TALLOC_FREE(subreq);
5665
0
  tevent_req_done(req);
5666
0
}
5667
5668
static NTSTATUS reply_tdis_recv(struct tevent_req *req)
5669
0
{
5670
0
  return tevent_req_simple_recv_ntstatus(req);
5671
0
}
5672
5673
static void reply_tdis_done(struct tevent_req *req)
5674
0
{
5675
0
  struct smb_request *smb1req = tevent_req_callback_data(
5676
0
    req, struct smb_request);
5677
0
  NTSTATUS status;
5678
0
  struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
5679
0
  bool ok;
5680
5681
  /*
5682
   * Take the profile charge here. Not strictly
5683
   * correct but better than the other SMB1 async
5684
   * code that double-charges at the moment.
5685
   */
5686
0
  START_PROFILE(SMBtdis);
5687
5688
0
  status = reply_tdis_recv(req);
5689
0
  TALLOC_FREE(req);
5690
0
  if (!NT_STATUS_IS_OK(status)) {
5691
0
    TALLOC_FREE(smb1req);
5692
0
    END_PROFILE(SMBtdis);
5693
0
    exit_server(__location__ ": reply_tdis_recv failed");
5694
0
    return;
5695
0
  }
5696
5697
  /*
5698
   * As we've been awoken, we may have changed
5699
   * directory in the meantime.
5700
   * reply_tdis() has the DO_CHDIR flag set.
5701
   */
5702
0
  ok = chdir_current_service(smb1req->conn);
5703
0
  if (!ok) {
5704
0
    reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5705
0
    smb_request_done(smb1req);
5706
0
    END_PROFILE(SMBtdis);
5707
0
  }
5708
5709
0
  status = smbXsrv_tcon_disconnect(tcon,
5710
0
           smb1req->vuid);
5711
0
  if (!NT_STATUS_IS_OK(status)) {
5712
0
    TALLOC_FREE(smb1req);
5713
0
    END_PROFILE(SMBtdis);
5714
0
    exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5715
0
    return;
5716
0
  }
5717
5718
  /* smbXsrv_tcon_disconnect frees smb1req->conn. */
5719
0
  smb1req->conn = NULL;
5720
5721
0
  TALLOC_FREE(tcon);
5722
5723
0
  reply_smb1_outbuf(smb1req, 0, 0);
5724
  /*
5725
   * The following call is needed to push the
5726
   * reply data back out the socket after async
5727
   * return. Plus it frees smb1req.
5728
   */
5729
0
  smb_request_done(smb1req);
5730
0
  END_PROFILE(SMBtdis);
5731
0
}
5732
5733
/****************************************************************************
5734
 Reply to a echo.
5735
 conn POINTER CAN BE NULL HERE !
5736
****************************************************************************/
5737
5738
void reply_echo(struct smb_request *req)
5739
0
{
5740
0
  connection_struct *conn = req->conn;
5741
0
  int smb_reverb;
5742
0
  int seq_num;
5743
5744
0
  START_PROFILE(SMBecho);
5745
5746
0
  if (req->wct < 1) {
5747
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5748
0
    END_PROFILE(SMBecho);
5749
0
    return;
5750
0
  }
5751
5752
0
  smb_reverb = SVAL(req->vwv+0, 0);
5753
5754
0
  reply_smb1_outbuf(req, 1, req->buflen);
5755
5756
  /* copy any incoming data back out */
5757
0
  if (req->buflen > 0) {
5758
0
    memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5759
0
  }
5760
5761
0
  if (smb_reverb > 100) {
5762
0
    DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5763
0
    smb_reverb = 100;
5764
0
  }
5765
5766
0
  for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5767
5768
0
    SSVAL(req->outbuf,smb_vwv0,seq_num);
5769
5770
0
    show_msg((char *)req->outbuf);
5771
0
    if (!smb1_srv_send(req->xconn,
5772
0
           (char *)req->outbuf,
5773
0
           true,
5774
0
           req->seqnum + 1,
5775
0
           IS_CONN_ENCRYPTED(conn) || req->encrypted))
5776
0
      exit_server_cleanly("reply_echo: smb1_srv_send failed.");
5777
0
  }
5778
5779
0
  DEBUG(3,("echo %d times\n", smb_reverb));
5780
5781
0
  TALLOC_FREE(req->outbuf);
5782
5783
0
  END_PROFILE(SMBecho);
5784
0
  return;
5785
0
}
5786
5787
/****************************************************************************
5788
 Reply to a printopen.
5789
****************************************************************************/
5790
5791
void reply_printopen(struct smb_request *req)
5792
0
{
5793
0
  connection_struct *conn = req->conn;
5794
0
  files_struct *fsp;
5795
0
  NTSTATUS status;
5796
5797
0
  START_PROFILE(SMBsplopen);
5798
5799
0
  if (req->wct < 2) {
5800
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5801
0
    END_PROFILE(SMBsplopen);
5802
0
    return;
5803
0
  }
5804
5805
0
  if (!CAN_PRINT(conn)) {
5806
0
    reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5807
0
    END_PROFILE(SMBsplopen);
5808
0
    return;
5809
0
  }
5810
5811
0
  status = file_new(req, conn, &fsp);
5812
0
  if(!NT_STATUS_IS_OK(status)) {
5813
0
    reply_nterror(req, status);
5814
0
    END_PROFILE(SMBsplopen);
5815
0
    return;
5816
0
  }
5817
5818
  /* Open for exclusive use, write only. */
5819
0
  status = print_spool_open(fsp, NULL, req->vuid);
5820
5821
0
  if (!NT_STATUS_IS_OK(status)) {
5822
0
    file_free(req, fsp);
5823
0
    reply_nterror(req, status);
5824
0
    END_PROFILE(SMBsplopen);
5825
0
    return;
5826
0
  }
5827
5828
0
  reply_smb1_outbuf(req, 1, 0);
5829
0
  SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5830
5831
0
  DEBUG(3,("openprint fd=%d %s\n",
5832
0
     fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
5833
5834
0
  END_PROFILE(SMBsplopen);
5835
0
  return;
5836
0
}
5837
5838
/****************************************************************************
5839
 Reply to a printclose.
5840
****************************************************************************/
5841
5842
void reply_printclose(struct smb_request *req)
5843
0
{
5844
0
  connection_struct *conn = req->conn;
5845
0
  files_struct *fsp;
5846
0
  NTSTATUS status;
5847
5848
0
  START_PROFILE(SMBsplclose);
5849
5850
0
  if (req->wct < 1) {
5851
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5852
0
    END_PROFILE(SMBsplclose);
5853
0
    return;
5854
0
  }
5855
5856
0
  fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5857
5858
0
  if (!check_fsp(conn, req, fsp)) {
5859
0
    END_PROFILE(SMBsplclose);
5860
0
                return;
5861
0
        }
5862
5863
0
  if (!CAN_PRINT(conn)) {
5864
0
    reply_force_doserror(req, ERRSRV, ERRerror);
5865
0
    END_PROFILE(SMBsplclose);
5866
0
    return;
5867
0
  }
5868
5869
0
  DEBUG(3,("printclose fd=%d %s\n",
5870
0
     fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
5871
5872
0
  status = close_file_free(req, &fsp, NORMAL_CLOSE);
5873
5874
0
  if(!NT_STATUS_IS_OK(status)) {
5875
0
    reply_nterror(req, status);
5876
0
    END_PROFILE(SMBsplclose);
5877
0
    return;
5878
0
  }
5879
5880
0
  reply_smb1_outbuf(req, 0, 0);
5881
5882
0
  END_PROFILE(SMBsplclose);
5883
0
  return;
5884
0
}
5885
5886
/****************************************************************************
5887
 Reply to a printqueue.
5888
****************************************************************************/
5889
5890
void reply_printqueue(struct smb_request *req)
5891
0
{
5892
0
  const struct loadparm_substitution *lp_sub =
5893
0
    loadparm_s3_global_substitution();
5894
0
  connection_struct *conn = req->conn;
5895
0
  int max_count;
5896
0
  int start_index;
5897
5898
0
  START_PROFILE(SMBsplretq);
5899
5900
0
  if (req->wct < 2) {
5901
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5902
0
    END_PROFILE(SMBsplretq);
5903
0
    return;
5904
0
  }
5905
5906
0
  max_count = SVAL(req->vwv+0, 0);
5907
0
  start_index = SVAL(req->vwv+1, 0);
5908
5909
  /* we used to allow the client to get the cnum wrong, but that
5910
     is really quite gross and only worked when there was only
5911
     one printer - I think we should now only accept it if they
5912
     get it right (tridge) */
5913
0
  if (!CAN_PRINT(conn)) {
5914
0
    reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5915
0
    END_PROFILE(SMBsplretq);
5916
0
    return;
5917
0
  }
5918
5919
0
  reply_smb1_outbuf(req, 2, 3);
5920
0
  SSVAL(req->outbuf,smb_vwv0,0);
5921
0
  SSVAL(req->outbuf,smb_vwv1,0);
5922
0
  SCVAL(smb_buf(req->outbuf),0,1);
5923
0
  SSVAL(smb_buf(req->outbuf),1,0);
5924
5925
0
  DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5926
0
     start_index, max_count));
5927
5928
0
  {
5929
0
    TALLOC_CTX *mem_ctx = talloc_tos();
5930
0
    NTSTATUS status;
5931
0
    WERROR werr;
5932
0
    const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
5933
0
    struct rpc_pipe_client *cli = NULL;
5934
0
    struct dcerpc_binding_handle *b = NULL;
5935
0
    struct policy_handle handle;
5936
0
    struct spoolss_DevmodeContainer devmode_ctr;
5937
0
    union spoolss_JobInfo *info;
5938
0
    uint32_t count;
5939
0
    uint32_t num_to_get;
5940
0
    uint32_t first;
5941
0
    uint32_t i;
5942
5943
0
    ZERO_STRUCT(handle);
5944
5945
0
    status = rpc_pipe_open_interface(mem_ctx,
5946
0
             &ndr_table_spoolss,
5947
0
             conn->session_info,
5948
0
             conn->sconn->remote_address,
5949
0
             conn->sconn->local_address,
5950
0
             conn->sconn->msg_ctx,
5951
0
             &cli);
5952
0
    if (!NT_STATUS_IS_OK(status)) {
5953
0
      DEBUG(0, ("reply_printqueue: "
5954
0
          "could not connect to spoolss: %s\n",
5955
0
          nt_errstr(status)));
5956
0
      reply_nterror(req, status);
5957
0
      goto out;
5958
0
    }
5959
0
    b = cli->binding_handle;
5960
5961
0
    ZERO_STRUCT(devmode_ctr);
5962
5963
0
    status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5964
0
            sharename,
5965
0
            NULL, devmode_ctr,
5966
0
            SEC_FLAG_MAXIMUM_ALLOWED,
5967
0
            &handle,
5968
0
            &werr);
5969
0
    if (!NT_STATUS_IS_OK(status)) {
5970
0
      reply_nterror(req, status);
5971
0
      goto out;
5972
0
    }
5973
0
    if (!W_ERROR_IS_OK(werr)) {
5974
0
      reply_nterror(req, werror_to_ntstatus(werr));
5975
0
      goto out;
5976
0
    }
5977
5978
0
    werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5979
0
                 &handle,
5980
0
                 0, /* firstjob */
5981
0
                 0xff, /* numjobs */
5982
0
                 2, /* level */
5983
0
                 0, /* offered */
5984
0
                 &count,
5985
0
                 &info);
5986
0
    if (!W_ERROR_IS_OK(werr)) {
5987
0
      reply_nterror(req, werror_to_ntstatus(werr));
5988
0
      goto out;
5989
0
    }
5990
5991
0
    if (max_count > 0) {
5992
0
      first = start_index;
5993
0
    } else {
5994
0
      first = start_index + max_count + 1;
5995
0
    }
5996
5997
0
    if (first >= count) {
5998
0
      num_to_get = first;
5999
0
    } else {
6000
0
      num_to_get = first + MIN(ABS(max_count), count - first);
6001
0
    }
6002
6003
0
    for (i = first; i < num_to_get; i++) {
6004
0
      char blob[28];
6005
0
      char *p = blob;
6006
0
      struct timespec qtime = {
6007
0
        .tv_sec = spoolss_Time_to_time_t(
6008
0
          &info[i].info2.submitted),
6009
0
      };
6010
0
      int qstatus;
6011
0
      size_t len = 0;
6012
0
      uint16_t qrapjobid = pjobid_to_rap(sharename,
6013
0
              info[i].info2.job_id);
6014
6015
0
      if (info[i].info2.status == JOB_STATUS_PRINTING) {
6016
0
        qstatus = 2;
6017
0
      } else {
6018
0
        qstatus = 3;
6019
0
      }
6020
6021
0
      srv_put_dos_date2_ts(p, 0, qtime);
6022
0
      SCVAL(p, 4, qstatus);
6023
0
      SSVAL(p, 5, qrapjobid);
6024
0
      SIVAL(p, 7, info[i].info2.size);
6025
0
      SCVAL(p, 11, 0);
6026
0
      status = srvstr_push(blob, req->flags2, p+12,
6027
0
            info[i].info2.notify_name, 16, STR_ASCII, &len);
6028
0
      if (!NT_STATUS_IS_OK(status)) {
6029
0
        reply_nterror(req, status);
6030
0
        goto out;
6031
0
      }
6032
0
      if (message_push_blob(
6033
0
            &req->outbuf,
6034
0
            data_blob_const(
6035
0
              blob, sizeof(blob))) == -1) {
6036
0
        reply_nterror(req, NT_STATUS_NO_MEMORY);
6037
0
        goto out;
6038
0
      }
6039
0
    }
6040
6041
0
    if (count > 0) {
6042
0
      SSVAL(req->outbuf,smb_vwv0,count);
6043
0
      SSVAL(req->outbuf,smb_vwv1,
6044
0
            (max_count>0?first+count:first-1));
6045
0
      SCVAL(smb_buf(req->outbuf),0,1);
6046
0
      SSVAL(smb_buf(req->outbuf),1,28*count);
6047
0
    }
6048
6049
6050
0
    DEBUG(3, ("%u entries returned in queue\n",
6051
0
        (unsigned)count));
6052
6053
0
out:
6054
0
    if (b && is_valid_policy_hnd(&handle)) {
6055
0
      dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6056
0
    }
6057
6058
0
  }
6059
6060
0
  END_PROFILE(SMBsplretq);
6061
0
  return;
6062
0
}
6063
6064
/****************************************************************************
6065
 Reply to a printwrite.
6066
****************************************************************************/
6067
6068
void reply_printwrite(struct smb_request *req)
6069
0
{
6070
0
  connection_struct *conn = req->conn;
6071
0
  int numtowrite;
6072
0
  const char *data;
6073
0
  files_struct *fsp;
6074
0
  NTSTATUS status;
6075
6076
0
  START_PROFILE(SMBsplwr);
6077
6078
0
  if (req->wct < 1) {
6079
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6080
0
    END_PROFILE(SMBsplwr);
6081
0
    return;
6082
0
  }
6083
6084
0
  fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6085
6086
0
  if (!check_fsp(conn, req, fsp)) {
6087
0
    END_PROFILE(SMBsplwr);
6088
0
                return;
6089
0
        }
6090
6091
0
  if (!fsp->print_file) {
6092
0
    reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6093
0
    END_PROFILE(SMBsplwr);
6094
0
    return;
6095
0
  }
6096
6097
0
  status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
6098
0
  if (!NT_STATUS_IS_OK(status)) {
6099
0
    reply_nterror(req, status);
6100
0
    END_PROFILE(SMBsplwr);
6101
0
    return;
6102
0
  }
6103
6104
0
  numtowrite = SVAL(req->buf, 1);
6105
6106
  /*
6107
   * This already protects us against CVE-2017-12163.
6108
   */
6109
0
  if (req->buflen < numtowrite + 3) {
6110
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6111
0
    END_PROFILE(SMBsplwr);
6112
0
    return;
6113
0
  }
6114
6115
0
  data = (const char *)req->buf + 3;
6116
6117
0
  if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6118
0
    reply_nterror(req, map_nt_error_from_unix(errno));
6119
0
    END_PROFILE(SMBsplwr);
6120
0
    return;
6121
0
  }
6122
6123
0
  DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6124
6125
0
  reply_smb1_outbuf(req, 0, 0);
6126
6127
0
  END_PROFILE(SMBsplwr);
6128
0
  return;
6129
0
}
6130
6131
/****************************************************************************
6132
 Reply to a mkdir.
6133
****************************************************************************/
6134
6135
void reply_mkdir(struct smb_request *req)
6136
0
{
6137
0
  connection_struct *conn = req->conn;
6138
0
  struct files_struct *dirfsp = NULL;
6139
0
  struct smb_filename *smb_dname = NULL;
6140
0
  char *directory = NULL;
6141
0
  NTSTATUS status;
6142
0
  uint32_t ucf_flags;
6143
0
  NTTIME twrp = 0;
6144
0
  TALLOC_CTX *ctx = talloc_tos();
6145
6146
0
  START_PROFILE(SMBmkdir);
6147
6148
0
  srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6149
0
          STR_TERMINATE, &status);
6150
0
  if (!NT_STATUS_IS_OK(status)) {
6151
0
    reply_nterror(req, status);
6152
0
    goto out;
6153
0
  }
6154
6155
0
  ucf_flags = filename_create_ucf_flags(req, FILE_CREATE, 0);
6156
0
  if (ucf_flags & UCF_GMT_PATHNAME) {
6157
0
    extract_snapshot_token(directory, &twrp);
6158
0
  }
6159
0
  status = smb1_strip_dfs_path(ctx, &ucf_flags, &directory);
6160
0
  if (!NT_STATUS_IS_OK(status)) {
6161
0
    reply_nterror(req, status);
6162
0
    goto out;
6163
0
  }
6164
6165
0
  status = filename_convert_dirfsp(ctx,
6166
0
           conn,
6167
0
           directory,
6168
0
           ucf_flags,
6169
0
           twrp,
6170
0
           &dirfsp,
6171
0
           &smb_dname);
6172
0
  if (!NT_STATUS_IS_OK(status)) {
6173
0
    if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6174
0
      reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6175
0
          ERRSRV, ERRbadpath);
6176
0
      goto out;
6177
0
    }
6178
0
    reply_nterror(req, status);
6179
0
    goto out;
6180
0
  }
6181
6182
0
  status = create_directory(conn, req, dirfsp, smb_dname);
6183
6184
0
  DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6185
6186
0
  if (!NT_STATUS_IS_OK(status)) {
6187
6188
0
    if (!use_nt_status()
6189
0
        && NT_STATUS_EQUAL(status,
6190
0
               NT_STATUS_OBJECT_NAME_COLLISION)) {
6191
      /*
6192
       * Yes, in the DOS error code case we get a
6193
       * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6194
       * samba4 torture test.
6195
       */
6196
0
      status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6197
0
    }
6198
6199
0
    reply_nterror(req, status);
6200
0
    goto out;
6201
0
  }
6202
6203
0
  reply_smb1_outbuf(req, 0, 0);
6204
6205
0
  DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6206
0
 out:
6207
0
  TALLOC_FREE(smb_dname);
6208
0
  END_PROFILE(SMBmkdir);
6209
0
  return;
6210
0
}
6211
6212
/****************************************************************************
6213
 Reply to a rmdir.
6214
****************************************************************************/
6215
6216
void reply_rmdir(struct smb_request *req)
6217
0
{
6218
0
  connection_struct *conn = req->conn;
6219
0
  struct smb_filename *smb_dname = NULL;
6220
0
  char *directory = NULL;
6221
0
  NTSTATUS status;
6222
0
  TALLOC_CTX *ctx = talloc_tos();
6223
0
  struct files_struct *dirfsp = NULL;
6224
0
  files_struct *fsp = NULL;
6225
0
  int info = 0;
6226
0
  NTTIME twrp = 0;
6227
0
  uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6228
6229
0
  START_PROFILE(SMBrmdir);
6230
6231
0
  srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6232
0
          STR_TERMINATE, &status);
6233
0
  if (!NT_STATUS_IS_OK(status)) {
6234
0
    reply_nterror(req, status);
6235
0
    goto out;
6236
0
  }
6237
6238
0
  if (ucf_flags & UCF_GMT_PATHNAME) {
6239
0
    extract_snapshot_token(directory, &twrp);
6240
0
  }
6241
0
  status = smb1_strip_dfs_path(ctx, &ucf_flags, &directory);
6242
0
  if (!NT_STATUS_IS_OK(status)) {
6243
0
    reply_nterror(req, status);
6244
0
    goto out;
6245
0
  }
6246
6247
0
  status = filename_convert_dirfsp(ctx,
6248
0
           conn,
6249
0
           directory,
6250
0
           ucf_flags,
6251
0
           twrp,
6252
0
           &dirfsp,
6253
0
           &smb_dname);
6254
0
  if (!NT_STATUS_IS_OK(status)) {
6255
0
    if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6256
0
      reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6257
0
          ERRSRV, ERRbadpath);
6258
0
      goto out;
6259
0
    }
6260
0
    reply_nterror(req, status);
6261
0
    goto out;
6262
0
  }
6263
6264
0
  status = SMB_VFS_CREATE_FILE(
6265
0
    conn,                                   /* conn */
6266
0
    req,                                    /* req */
6267
0
    dirfsp,         /* dirfsp */
6268
0
    smb_dname,                              /* fname */
6269
0
    DELETE_ACCESS,                          /* access_mask */
6270
0
    (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
6271
0
      FILE_SHARE_DELETE),
6272
0
    FILE_OPEN,                              /* create_disposition*/
6273
0
    FILE_DIRECTORY_FILE |
6274
0
      FILE_OPEN_REPARSE_POINT,  /* create_options */
6275
0
    FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
6276
0
    0,                                      /* oplock_request */
6277
0
    NULL,         /* lease */
6278
0
    0,                                      /* allocation_size */
6279
0
    0,          /* private_flags */
6280
0
    NULL,                                   /* sd */
6281
0
    NULL,                                   /* ea_list */
6282
0
    &fsp,                                   /* result */
6283
0
    &info,                                  /* pinfo */
6284
0
    NULL, NULL);        /* create context */
6285
6286
0
  if (!NT_STATUS_IS_OK(status)) {
6287
0
    if (open_was_deferred(req->xconn, req->mid)) {
6288
      /* We have re-scheduled this call. */
6289
0
      goto out;
6290
0
    }
6291
0
    if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6292
0
      bool ok = defer_smb1_sharing_violation(req);
6293
0
      if (ok) {
6294
0
        goto out;
6295
0
      }
6296
0
    }
6297
0
    reply_nterror(req, status);
6298
0
    goto out;
6299
0
  }
6300
6301
0
  status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6302
0
  if (!NT_STATUS_IS_OK(status)) {
6303
0
    close_file_free(req, &fsp, ERROR_CLOSE);
6304
0
    reply_nterror(req, status);
6305
0
    goto out;
6306
0
  }
6307
6308
0
  if (!set_delete_on_close(fsp, true,
6309
0
      conn->session_info->security_token,
6310
0
      conn->session_info->unix_token)) {
6311
0
    close_file_free(req, &fsp, ERROR_CLOSE);
6312
0
    reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6313
0
    goto out;
6314
0
  }
6315
6316
0
  status = close_file_free(req, &fsp, NORMAL_CLOSE);
6317
0
  if (!NT_STATUS_IS_OK(status)) {
6318
0
    reply_nterror(req, status);
6319
0
  } else {
6320
0
    reply_smb1_outbuf(req, 0, 0);
6321
0
  }
6322
6323
0
  DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6324
0
 out:
6325
0
  TALLOC_FREE(smb_dname);
6326
0
  END_PROFILE(SMBrmdir);
6327
0
  return;
6328
0
}
6329
6330
/****************************************************************************
6331
 Reply to a mv.
6332
****************************************************************************/
6333
6334
void reply_mv(struct smb_request *req)
6335
0
{
6336
0
  connection_struct *conn = req->conn;
6337
0
  char *name = NULL;
6338
0
  char *newname = NULL;
6339
0
  const char *p;
6340
0
  uint32_t attrs;
6341
0
  NTSTATUS status;
6342
0
  TALLOC_CTX *ctx = talloc_tos();
6343
0
  struct files_struct *src_dirfsp = NULL;
6344
0
  struct smb_filename *smb_fname_src = NULL;
6345
0
  struct files_struct *dst_dirfsp = NULL;
6346
0
  struct smb_filename *smb_fname_dst = NULL;
6347
0
  const char *dst_original_lcomp = NULL;
6348
0
  uint32_t src_ucf_flags = ucf_flags_from_smb_request(req);
6349
0
  NTTIME src_twrp = 0;
6350
0
  uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req);
6351
0
  NTTIME dst_twrp = 0;
6352
0
  bool stream_rename = false;
6353
6354
0
  START_PROFILE(SMBmv);
6355
6356
0
  if (req->wct < 1) {
6357
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6358
0
    goto out;
6359
0
  }
6360
6361
0
  attrs = SVAL(req->vwv+0, 0);
6362
6363
0
  p = (const char *)req->buf + 1;
6364
0
  p += srvstr_get_path_req(ctx, req, &name, p, STR_TERMINATE,
6365
0
               &status);
6366
0
  if (!NT_STATUS_IS_OK(status)) {
6367
0
    reply_nterror(req, status);
6368
0
    goto out;
6369
0
  }
6370
0
  p++;
6371
0
  p += srvstr_get_path_req(ctx, req, &newname, p, STR_TERMINATE,
6372
0
               &status);
6373
0
  if (!NT_STATUS_IS_OK(status)) {
6374
0
    reply_nterror(req, status);
6375
0
    goto out;
6376
0
  }
6377
6378
0
  if (!req->posix_pathnames) {
6379
    /* The newname must begin with a ':' if the
6380
       name contains a ':'. */
6381
0
    if (strchr_m(name, ':')) {
6382
0
      if (newname[0] != ':') {
6383
0
        reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6384
0
        goto out;
6385
0
      }
6386
0
      stream_rename = true;
6387
0
    }
6388
0
        }
6389
6390
0
  if (src_ucf_flags & UCF_GMT_PATHNAME) {
6391
0
    extract_snapshot_token(name, &src_twrp);
6392
0
  }
6393
0
  status = smb1_strip_dfs_path(ctx, &src_ucf_flags, &name);
6394
0
  if (!NT_STATUS_IS_OK(status)) {
6395
0
    reply_nterror(req, status);
6396
0
    goto out;
6397
0
  }
6398
0
  status = filename_convert_dirfsp(ctx,
6399
0
           conn,
6400
0
           name,
6401
0
           src_ucf_flags,
6402
0
           src_twrp,
6403
0
           &src_dirfsp,
6404
0
           &smb_fname_src);
6405
6406
0
  if (!NT_STATUS_IS_OK(status)) {
6407
0
    if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6408
0
      reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6409
0
          ERRSRV, ERRbadpath);
6410
0
      goto out;
6411
0
    }
6412
0
    reply_nterror(req, status);
6413
0
    goto out;
6414
0
  }
6415
6416
0
  if (dst_ucf_flags & UCF_GMT_PATHNAME) {
6417
0
    extract_snapshot_token(newname, &dst_twrp);
6418
0
  }
6419
0
  status = smb1_strip_dfs_path(ctx, &dst_ucf_flags, &newname);
6420
0
  if (!NT_STATUS_IS_OK(status)) {
6421
0
    reply_nterror(req, status);
6422
0
    goto out;
6423
0
  }
6424
0
  status = filename_convert_dirfsp(ctx,
6425
0
           conn,
6426
0
           newname,
6427
0
           dst_ucf_flags,
6428
0
           dst_twrp,
6429
0
           &dst_dirfsp,
6430
0
           &smb_fname_dst);
6431
6432
0
  if (!NT_STATUS_IS_OK(status)) {
6433
0
    if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6434
0
      reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6435
0
          ERRSRV, ERRbadpath);
6436
0
      goto out;
6437
0
    }
6438
0
    reply_nterror(req, status);
6439
0
    goto out;
6440
0
  }
6441
6442
  /* Get the last component of the destination for rename_internals(). */
6443
0
  dst_original_lcomp = get_original_lcomp(ctx,
6444
0
          conn,
6445
0
          newname,
6446
0
          dst_ucf_flags);
6447
0
  if (dst_original_lcomp == NULL) {
6448
0
    reply_nterror(req, NT_STATUS_NO_MEMORY);
6449
0
    goto out;
6450
0
  }
6451
6452
0
  if (stream_rename) {
6453
    /* smb_fname_dst->base_name must be the same as
6454
       smb_fname_src->base_name. */
6455
0
    TALLOC_FREE(smb_fname_dst->base_name);
6456
0
    smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6457
0
            smb_fname_src->base_name);
6458
0
    if (!smb_fname_dst->base_name) {
6459
0
      reply_nterror(req, NT_STATUS_NO_MEMORY);
6460
0
      goto out;
6461
0
    }
6462
0
  }
6463
6464
0
  DBG_NOTICE("%s -> %s\n",
6465
0
       smb_fname_str_dbg(smb_fname_src),
6466
0
       smb_fname_str_dbg(smb_fname_dst));
6467
6468
0
  status = rename_internals(ctx,
6469
0
        conn,
6470
0
        req,
6471
0
        src_dirfsp, /* src_dirfsp */
6472
0
        smb_fname_src,
6473
0
        smb_fname_dst,
6474
0
        dst_original_lcomp,
6475
0
        attrs,
6476
0
        false,
6477
0
        DELETE_ACCESS);
6478
0
  if (!NT_STATUS_IS_OK(status)) {
6479
0
    if (open_was_deferred(req->xconn, req->mid)) {
6480
      /* We have re-scheduled this call. */
6481
0
      goto out;
6482
0
    }
6483
0
    if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6484
0
      bool ok = defer_smb1_sharing_violation(req);
6485
0
      if (ok) {
6486
0
        goto out;
6487
0
      }
6488
0
    }
6489
0
    reply_nterror(req, status);
6490
0
    goto out;
6491
0
  }
6492
6493
0
  reply_smb1_outbuf(req, 0, 0);
6494
0
 out:
6495
0
  TALLOC_FREE(smb_fname_src);
6496
0
  TALLOC_FREE(smb_fname_dst);
6497
0
  END_PROFILE(SMBmv);
6498
0
  return;
6499
0
}
6500
6501
/****************************************************************************
6502
 Reply to a file copy.
6503
6504
 From MS-CIFS.
6505
6506
 This command was introduced in the LAN Manager 1.0 dialect
6507
 It was rendered obsolete in the NT LAN Manager dialect.
6508
 This command was used to perform server-side file copies, but
6509
 is no longer used. Clients SHOULD
6510
 NOT send requests using this command code.
6511
 Servers receiving requests with this command code
6512
 SHOULD return STATUS_NOT_IMPLEMENTED (ERRDOS/ERRbadfunc).
6513
****************************************************************************/
6514
6515
void reply_copy(struct smb_request *req)
6516
0
{
6517
0
  START_PROFILE(SMBcopy);
6518
0
  reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
6519
0
  END_PROFILE(SMBcopy);
6520
0
  return;
6521
0
}
6522
6523
#undef DBGC_CLASS
6524
0
#define DBGC_CLASS DBGC_LOCKING
6525
6526
/****************************************************************************
6527
 Get a lock pid, dealing with large count requests.
6528
****************************************************************************/
6529
6530
uint64_t get_lock_pid(const uint8_t *data, int data_offset,
6531
        bool large_file_format)
6532
0
{
6533
0
  if(!large_file_format)
6534
0
    return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
6535
0
  else
6536
0
    return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6537
0
}
6538
6539
/****************************************************************************
6540
 Get a lock count, dealing with large count requests.
6541
****************************************************************************/
6542
6543
uint64_t get_lock_count(const uint8_t *data, int data_offset,
6544
      bool large_file_format)
6545
0
{
6546
0
  uint64_t count = 0;
6547
6548
0
  if(!large_file_format) {
6549
0
    count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6550
0
  } else {
6551
    /*
6552
     * No BVAL, this is reversed!
6553
     */
6554
0
    count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6555
0
      ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6556
0
  }
6557
6558
0
  return count;
6559
0
}
6560
6561
/****************************************************************************
6562
 Reply to a lockingX request.
6563
****************************************************************************/
6564
6565
static void reply_lockingx_done(struct tevent_req *subreq);
6566
6567
void reply_lockingX(struct smb_request *req)
6568
0
{
6569
0
  connection_struct *conn = req->conn;
6570
0
  files_struct *fsp;
6571
0
  unsigned char locktype;
6572
0
  enum brl_type brltype;
6573
0
  unsigned char oplocklevel;
6574
0
  uint16_t num_ulocks;
6575
0
  uint16_t num_locks;
6576
0
  int32_t lock_timeout;
6577
0
  uint16_t i;
6578
0
  const uint8_t *data;
6579
0
  bool large_file_format;
6580
0
  NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6581
0
  struct smbd_lock_element *locks = NULL;
6582
0
  struct tevent_req *subreq = NULL;
6583
6584
0
  START_PROFILE(SMBlockingX);
6585
6586
0
  if (req->wct < 8) {
6587
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6588
0
    END_PROFILE(SMBlockingX);
6589
0
    return;
6590
0
  }
6591
6592
0
  fsp = file_fsp(req, SVAL(req->vwv+2, 0));
6593
0
  locktype = CVAL(req->vwv+3, 0);
6594
0
  oplocklevel = CVAL(req->vwv+3, 1);
6595
0
  num_ulocks = SVAL(req->vwv+6, 0);
6596
0
  num_locks = SVAL(req->vwv+7, 0);
6597
0
  lock_timeout = IVAL(req->vwv+4, 0);
6598
0
  large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
6599
6600
0
  if (!check_fsp(conn, req, fsp)) {
6601
0
    END_PROFILE(SMBlockingX);
6602
0
    return;
6603
0
  }
6604
6605
0
  data = req->buf;
6606
6607
0
  if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6608
    /* we don't support these - and CANCEL_LOCK makes w2k
6609
       and XP reboot so I don't really want to be
6610
       compatible! (tridge) */
6611
0
    reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
6612
0
    END_PROFILE(SMBlockingX);
6613
0
    return;
6614
0
  }
6615
6616
  /* Check if this is an oplock break on a file
6617
     we have granted an oplock on.
6618
  */
6619
0
  if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
6620
    /* Client can insist on breaking to none. */
6621
0
    bool break_to_none = (oplocklevel == 0);
6622
0
    bool result;
6623
6624
0
    DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6625
0
       "for %s\n", (unsigned int)oplocklevel,
6626
0
       fsp_fnum_dbg(fsp)));
6627
6628
    /*
6629
     * Make sure we have granted an exclusive or batch oplock on
6630
     * this file.
6631
     */
6632
6633
0
    if (fsp->oplock_type == 0) {
6634
6635
      /* The Samba4 nbench simulator doesn't understand
6636
         the difference between break to level2 and break
6637
         to none from level2 - it sends oplock break
6638
         replies in both cases. Don't keep logging an error
6639
         message here - just ignore it. JRA. */
6640
6641
0
      DEBUG(5,("reply_lockingX: Error : oplock break from "
6642
0
         "client for %s (oplock=%d) and no "
6643
0
         "oplock granted on this file (%s).\n",
6644
0
         fsp_fnum_dbg(fsp), fsp->oplock_type,
6645
0
         fsp_str_dbg(fsp)));
6646
6647
      /* if this is a pure oplock break request then don't
6648
       * send a reply */
6649
0
      if (num_locks == 0 && num_ulocks == 0) {
6650
0
        END_PROFILE(SMBlockingX);
6651
0
        return;
6652
0
      }
6653
6654
0
      END_PROFILE(SMBlockingX);
6655
0
      reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
6656
0
      return;
6657
0
    }
6658
6659
0
    if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
6660
0
        (break_to_none)) {
6661
0
      result = remove_oplock(fsp);
6662
0
    } else {
6663
0
      result = downgrade_oplock(fsp);
6664
0
    }
6665
6666
0
    if (!result) {
6667
0
      DEBUG(0, ("reply_lockingX: error in removing "
6668
0
          "oplock on file %s\n", fsp_str_dbg(fsp)));
6669
      /* Hmmm. Is this panic justified? */
6670
0
      smb_panic("internal tdb error");
6671
0
    }
6672
6673
    /* if this is a pure oplock break request then don't send a
6674
     * reply */
6675
0
    if (num_locks == 0 && num_ulocks == 0) {
6676
      /* Sanity check - ensure a pure oplock break is not a
6677
         chained request. */
6678
0
      if (CVAL(req->vwv+0, 0) != 0xff) {
6679
0
        DEBUG(0,("reply_lockingX: Error : pure oplock "
6680
0
           "break is a chained %d request !\n",
6681
0
           (unsigned int)CVAL(req->vwv+0, 0)));
6682
0
      }
6683
0
      END_PROFILE(SMBlockingX);
6684
0
      return;
6685
0
    }
6686
0
  }
6687
6688
0
  if (req->buflen <
6689
0
      (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
6690
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6691
0
    END_PROFILE(SMBlockingX);
6692
0
    return;
6693
0
  }
6694
6695
0
  if (num_ulocks != 0) {
6696
0
    struct smbd_lock_element *ulocks = NULL;
6697
0
    bool ok;
6698
6699
0
    ulocks = talloc_array(
6700
0
      req, struct smbd_lock_element, num_ulocks);
6701
0
    if (ulocks == NULL) {
6702
0
      reply_nterror(req, NT_STATUS_NO_MEMORY);
6703
0
      END_PROFILE(SMBlockingX);
6704
0
      return;
6705
0
    }
6706
6707
    /*
6708
     * Data now points at the beginning of the list of
6709
     * smb_unlkrng structs
6710
     */
6711
0
    for (i = 0; i < num_ulocks; i++) {
6712
0
      ulocks[i].req_guid = smbd_request_guid(req,
6713
0
        UINT16_MAX - i),
6714
0
      ulocks[i].smblctx = get_lock_pid(
6715
0
        data, i, large_file_format);
6716
0
      ulocks[i].count = get_lock_count(
6717
0
        data, i, large_file_format);
6718
0
      ulocks[i].offset = get_lock_offset(
6719
0
        data, i, large_file_format);
6720
0
      ulocks[i].brltype = UNLOCK_LOCK;
6721
0
      ulocks[i].lock_flav = WINDOWS_LOCK;
6722
0
    }
6723
6724
    /*
6725
     * Unlock cancels pending locks
6726
     */
6727
6728
0
    ok = smbd_smb1_brl_finish_by_lock(
6729
0
      fsp,
6730
0
      large_file_format,
6731
0
      ulocks[0],
6732
0
      NT_STATUS_OK);
6733
0
    if (ok) {
6734
0
      reply_smb1_outbuf(req, 2, 0);
6735
0
      SSVAL(req->outbuf, smb_vwv0, 0xff);
6736
0
      SSVAL(req->outbuf, smb_vwv1, 0);
6737
0
      END_PROFILE(SMBlockingX);
6738
0
      return;
6739
0
    }
6740
6741
0
    status = smbd_do_unlocking(
6742
0
      req, fsp, num_ulocks, ulocks);
6743
0
    TALLOC_FREE(ulocks);
6744
0
    if (!NT_STATUS_IS_OK(status)) {
6745
0
      END_PROFILE(SMBlockingX);
6746
0
      reply_nterror(req, status);
6747
0
      return;
6748
0
    }
6749
0
  }
6750
6751
  /* Now do any requested locks */
6752
0
  data += ((large_file_format ? 20 : 10)*num_ulocks);
6753
6754
  /* Data now points at the beginning of the list
6755
     of smb_lkrng structs */
6756
6757
0
  if (locktype & LOCKING_ANDX_SHARED_LOCK) {
6758
0
    brltype = READ_LOCK;
6759
0
  } else {
6760
0
    brltype = WRITE_LOCK;
6761
0
  }
6762
6763
0
  locks = talloc_array(req, struct smbd_lock_element, num_locks);
6764
0
  if (locks == NULL) {
6765
0
    reply_nterror(req, NT_STATUS_NO_MEMORY);
6766
0
    END_PROFILE(SMBlockingX);
6767
0
    return;
6768
0
  }
6769
6770
0
  for (i = 0; i < num_locks; i++) {
6771
0
    locks[i].req_guid = smbd_request_guid(req, i),
6772
0
    locks[i].smblctx = get_lock_pid(data, i, large_file_format);
6773
0
    locks[i].count = get_lock_count(data, i, large_file_format);
6774
0
    locks[i].offset = get_lock_offset(data, i, large_file_format);
6775
0
    locks[i].brltype = brltype;
6776
0
    locks[i].lock_flav = WINDOWS_LOCK;
6777
0
  }
6778
6779
0
  if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
6780
6781
0
    bool ok;
6782
6783
0
    if (num_locks == 0) {
6784
      /* See smbtorture3 lock11 test */
6785
0
      reply_smb1_outbuf(req, 2, 0);
6786
      /* andx chain ends */
6787
0
      SSVAL(req->outbuf, smb_vwv0, 0xff);
6788
0
      SSVAL(req->outbuf, smb_vwv1, 0);
6789
0
      END_PROFILE(SMBlockingX);
6790
0
      return;
6791
0
    }
6792
6793
0
    ok = smbd_smb1_brl_finish_by_lock(
6794
0
      fsp,
6795
0
      large_file_format,
6796
0
      locks[0], /* Windows only cancels the first lock */
6797
0
      NT_STATUS_FILE_LOCK_CONFLICT);
6798
6799
0
    if (!ok) {
6800
0
      reply_force_doserror(req, ERRDOS, ERRcancelviolation);
6801
0
      END_PROFILE(SMBlockingX);
6802
0
      return;
6803
0
    }
6804
6805
0
    reply_smb1_outbuf(req, 2, 0);
6806
0
    SSVAL(req->outbuf, smb_vwv0, 0xff);
6807
0
    SSVAL(req->outbuf, smb_vwv1, 0);
6808
0
    END_PROFILE(SMBlockingX);
6809
0
    return;
6810
0
  }
6811
6812
0
  subreq = smbd_smb1_do_locks_send(
6813
0
    fsp,
6814
0
    req->sconn->ev_ctx,
6815
0
    &req,
6816
0
    fsp,
6817
0
    lock_timeout,
6818
0
    large_file_format,
6819
0
    num_locks,
6820
0
    locks);
6821
0
  if (subreq == NULL) {
6822
0
    reply_nterror(req, NT_STATUS_NO_MEMORY);
6823
0
    END_PROFILE(SMBlockingX);
6824
0
    return;
6825
0
  }
6826
0
  tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
6827
0
  END_PROFILE(SMBlockingX);
6828
0
}
6829
6830
static void reply_lockingx_done(struct tevent_req *subreq)
6831
0
{
6832
0
  struct smb_request *req = NULL;
6833
0
  NTSTATUS status;
6834
0
  bool ok;
6835
6836
0
  START_PROFILE(SMBlockingX);
6837
6838
0
  ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
6839
0
  SMB_ASSERT(ok);
6840
6841
0
  status = smbd_smb1_do_locks_recv(subreq);
6842
0
  TALLOC_FREE(subreq);
6843
6844
0
  DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
6845
6846
0
  if (NT_STATUS_IS_OK(status)) {
6847
0
    reply_smb1_outbuf(req, 2, 0);
6848
0
    SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
6849
0
    SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
6850
0
  } else {
6851
0
    reply_nterror(req, status);
6852
0
  }
6853
6854
0
  ok = smb1_srv_send(req->xconn,
6855
0
         (char *)req->outbuf,
6856
0
         true,
6857
0
         req->seqnum + 1,
6858
0
         IS_CONN_ENCRYPTED(req->conn));
6859
0
  if (!ok) {
6860
0
    exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
6861
0
  }
6862
0
  TALLOC_FREE(req);
6863
0
  END_PROFILE(SMBlockingX);
6864
0
}
6865
6866
#undef DBGC_CLASS
6867
0
#define DBGC_CLASS DBGC_ALL
6868
6869
/****************************************************************************
6870
 Reply to a SMBreadbmpx (read block multiplex) request.
6871
 Always reply with an error, if someone has a platform really needs this,
6872
 please contact vl@samba.org
6873
****************************************************************************/
6874
6875
void reply_readbmpx(struct smb_request *req)
6876
0
{
6877
0
  START_PROFILE(SMBreadBmpx);
6878
0
  reply_force_doserror(req, ERRSRV, ERRuseSTD);
6879
0
  END_PROFILE(SMBreadBmpx);
6880
0
  return;
6881
0
}
6882
6883
/****************************************************************************
6884
 Reply to a SMBreadbs (read block multiplex secondary) request.
6885
 Always reply with an error, if someone has a platform really needs this,
6886
 please contact vl@samba.org
6887
****************************************************************************/
6888
6889
void reply_readbs(struct smb_request *req)
6890
0
{
6891
0
  START_PROFILE(SMBreadBs);
6892
0
  reply_force_doserror(req, ERRSRV, ERRuseSTD);
6893
0
  END_PROFILE(SMBreadBs);
6894
0
  return;
6895
0
}
6896
6897
/****************************************************************************
6898
 Reply to a SMBsetattrE.
6899
****************************************************************************/
6900
6901
void reply_setattrE(struct smb_request *req)
6902
0
{
6903
0
  connection_struct *conn = req->conn;
6904
0
  struct smb_file_time ft;
6905
0
  files_struct *fsp;
6906
0
  NTSTATUS status;
6907
6908
0
  START_PROFILE(SMBsetattrE);
6909
0
  init_smb_file_time(&ft);
6910
6911
0
  if (req->wct < 7) {
6912
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6913
0
    goto out;
6914
0
  }
6915
6916
0
  fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6917
6918
0
  if(!fsp || (fsp->conn != conn)) {
6919
0
    reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6920
0
    goto out;
6921
0
  }
6922
6923
  /*
6924
   * Convert the DOS times into unix times.
6925
   */
6926
6927
0
  ft.atime = time_t_to_full_timespec(
6928
0
      srv_make_unix_date2(req->vwv+3));
6929
0
  ft.mtime = time_t_to_full_timespec(
6930
0
      srv_make_unix_date2(req->vwv+5));
6931
0
  ft.create_time = time_t_to_full_timespec(
6932
0
      srv_make_unix_date2(req->vwv+1));
6933
6934
0
  reply_smb1_outbuf(req, 0, 0);
6935
6936
  /* Ensure we have a valid stat struct for the source. */
6937
0
  status = vfs_stat_fsp(fsp);
6938
0
  if (!NT_STATUS_IS_OK(status)) {
6939
0
    reply_nterror(req, status);
6940
0
    goto out;
6941
0
  }
6942
6943
0
  status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
6944
0
  if (!NT_STATUS_IS_OK(status)) {
6945
0
    reply_nterror(req, status);
6946
0
    goto out;
6947
0
  }
6948
6949
0
  status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
6950
0
  if (!NT_STATUS_IS_OK(status)) {
6951
0
    reply_nterror(req, status);
6952
0
    goto out;
6953
0
  }
6954
6955
0
  DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
6956
0
         " createtime=%u\n",
6957
0
    fsp_fnum_dbg(fsp),
6958
0
    (unsigned int)ft.atime.tv_sec,
6959
0
    (unsigned int)ft.mtime.tv_sec,
6960
0
    (unsigned int)ft.create_time.tv_sec
6961
0
    ));
6962
0
 out:
6963
0
  END_PROFILE(SMBsetattrE);
6964
0
  return;
6965
0
}
6966
6967
6968
/* Back from the dead for OS/2..... JRA. */
6969
6970
/****************************************************************************
6971
 Reply to a SMBwritebmpx (write block multiplex primary) request.
6972
 Always reply with an error, if someone has a platform really needs this,
6973
 please contact vl@samba.org
6974
****************************************************************************/
6975
6976
void reply_writebmpx(struct smb_request *req)
6977
0
{
6978
0
  START_PROFILE(SMBwriteBmpx);
6979
0
  reply_force_doserror(req, ERRSRV, ERRuseSTD);
6980
0
  END_PROFILE(SMBwriteBmpx);
6981
0
  return;
6982
0
}
6983
6984
/****************************************************************************
6985
 Reply to a SMBwritebs (write block multiplex secondary) request.
6986
 Always reply with an error, if someone has a platform really needs this,
6987
 please contact vl@samba.org
6988
****************************************************************************/
6989
6990
void reply_writebs(struct smb_request *req)
6991
0
{
6992
0
  START_PROFILE(SMBwriteBs);
6993
0
  reply_force_doserror(req, ERRSRV, ERRuseSTD);
6994
0
  END_PROFILE(SMBwriteBs);
6995
0
  return;
6996
0
}
6997
6998
/****************************************************************************
6999
 Reply to a SMBgetattrE.
7000
****************************************************************************/
7001
7002
void reply_getattrE(struct smb_request *req)
7003
0
{
7004
0
  connection_struct *conn = req->conn;
7005
0
  int mode;
7006
0
  files_struct *fsp;
7007
0
  struct timespec create_ts;
7008
0
  NTSTATUS status;
7009
7010
0
  START_PROFILE(SMBgetattrE);
7011
7012
0
  if (req->wct < 1) {
7013
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7014
0
    END_PROFILE(SMBgetattrE);
7015
0
    return;
7016
0
  }
7017
7018
0
  fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7019
7020
0
  if(!fsp || (fsp->conn != conn)) {
7021
0
    reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7022
0
    END_PROFILE(SMBgetattrE);
7023
0
    return;
7024
0
  }
7025
7026
  /* Do an fstat on this file */
7027
0
  status = vfs_stat_fsp(fsp);
7028
0
  if (!NT_STATUS_IS_OK(status)) {
7029
0
    reply_nterror(req, status);
7030
0
    END_PROFILE(SMBgetattrE);
7031
0
    return;
7032
0
  }
7033
7034
0
  mode = fdos_mode(fsp);
7035
7036
  /*
7037
   * Convert the times into dos times. Set create
7038
   * date to be last modify date as UNIX doesn't save
7039
   * this.
7040
   */
7041
7042
0
  reply_smb1_outbuf(req, 11, 0);
7043
7044
0
  create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7045
0
  srv_put_dos_date2_ts((char *)req->outbuf, smb_vwv0, create_ts);
7046
0
  srv_put_dos_date2_ts((char *)req->outbuf,
7047
0
           smb_vwv2,
7048
0
           fsp->fsp_name->st.st_ex_atime);
7049
  /* Should we check pending modtime here ? JRA */
7050
0
  srv_put_dos_date2_ts((char *)req->outbuf,
7051
0
           smb_vwv4,
7052
0
           fsp->fsp_name->st.st_ex_mtime);
7053
7054
0
  if (mode & FILE_ATTRIBUTE_DIRECTORY) {
7055
0
    SIVAL(req->outbuf, smb_vwv6, 0);
7056
0
    SIVAL(req->outbuf, smb_vwv8, 0);
7057
0
  } else {
7058
0
    uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7059
0
    SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
7060
0
    SIVAL(req->outbuf, smb_vwv8, allocation_size);
7061
0
  }
7062
0
  SSVAL(req->outbuf,smb_vwv10, mode);
7063
7064
0
  DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
7065
7066
0
  END_PROFILE(SMBgetattrE);
7067
0
  return;
7068
0
}
7069
7070
/****************************************************************************
7071
 Reply to a SMBfindclose (stop trans2 directory search).
7072
****************************************************************************/
7073
7074
void reply_findclose(struct smb_request *req)
7075
0
{
7076
0
  int dptr_num;
7077
0
  struct smbd_server_connection *sconn = req->sconn;
7078
0
  files_struct *fsp = NULL;
7079
7080
0
  START_PROFILE(SMBfindclose);
7081
7082
0
  if (req->wct < 1) {
7083
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7084
0
    END_PROFILE(SMBfindclose);
7085
0
    return;
7086
0
  }
7087
7088
0
  dptr_num = SVALS(req->vwv+0, 0);
7089
7090
0
  DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7091
7092
  /*
7093
   * OS/2 seems to use -1 to indicate "close all directories"
7094
   * This has to mean on this specific connection struct.
7095
   */
7096
0
  if (dptr_num == -1) {
7097
0
    dptr_closecnum(req->conn);
7098
0
  } else {
7099
0
    fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
7100
0
    dptr_num = -1;
7101
0
    if (fsp != NULL) {
7102
0
      close_file_free(NULL, &fsp, NORMAL_CLOSE);
7103
0
    }
7104
0
  }
7105
7106
0
  reply_smb1_outbuf(req, 0, 0);
7107
7108
0
  DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7109
7110
0
  END_PROFILE(SMBfindclose);
7111
0
  return;
7112
0
}
7113
7114
/****************************************************************************
7115
 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7116
****************************************************************************/
7117
7118
void reply_findnclose(struct smb_request *req)
7119
0
{
7120
0
  int dptr_num;
7121
7122
0
  START_PROFILE(SMBfindnclose);
7123
7124
0
  if (req->wct < 1) {
7125
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7126
0
    END_PROFILE(SMBfindnclose);
7127
0
    return;
7128
0
  }
7129
7130
0
  dptr_num = SVAL(req->vwv+0, 0);
7131
7132
0
  DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7133
7134
  /* We never give out valid handles for a
7135
     findnotifyfirst - so any dptr_num is ok here.
7136
     Just ignore it. */
7137
7138
0
  reply_smb1_outbuf(req, 0, 0);
7139
7140
0
  DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7141
7142
0
  END_PROFILE(SMBfindnclose);
7143
0
  return;
7144
0
}