Coverage Report

Created: 2026-06-07 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source3/smbd/smb2_read.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
   Core SMB2 server
4
5
   Copyright (C) Stefan Metzmacher 2009
6
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3 of the License, or
10
   (at your option) any later version.
11
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
17
   You should have received a copy of the GNU General Public License
18
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
*/
20
21
#include "includes.h"
22
#include "system/filesys.h"
23
#include "smbd/smbd.h"
24
#include "smbd/globals.h"
25
#include "../libcli/smb/smb_common.h"
26
#include "libcli/security/security.h"
27
#include "../lib/util/tevent_ntstatus.h"
28
#include "rpc_server/srv_pipe_hnd.h"
29
#include "lib/util/sys_rw_data.h"
30
31
#undef DBGC_CLASS
32
0
#define DBGC_CLASS DBGC_SMB2
33
34
static struct tevent_req *smbd_smb2_read_send(TALLOC_CTX *mem_ctx,
35
                struct tevent_context *ev,
36
                struct smbd_smb2_request *smb2req,
37
                struct files_struct *in_fsp,
38
                uint8_t in_flags,
39
                uint32_t in_length,
40
                uint64_t in_offset,
41
                uint32_t in_minimum,
42
                uint32_t in_remaining);
43
static NTSTATUS smbd_smb2_read_recv(struct tevent_req *req,
44
            TALLOC_CTX *mem_ctx,
45
            DATA_BLOB *out_data,
46
            uint32_t *out_remaining);
47
48
static void smbd_smb2_request_read_done(struct tevent_req *subreq);
49
NTSTATUS smbd_smb2_request_process_read(struct smbd_smb2_request *req)
50
0
{
51
0
  struct smbXsrv_connection *xconn = req->xconn;
52
0
  NTSTATUS status;
53
0
  const uint8_t *inbody;
54
0
  uint8_t in_flags;
55
0
  uint32_t in_length;
56
0
  uint64_t in_offset;
57
0
  uint64_t in_file_id_persistent;
58
0
  uint64_t in_file_id_volatile;
59
0
  struct files_struct *in_fsp;
60
0
  uint32_t in_minimum_count;
61
0
  uint32_t in_remaining_bytes;
62
0
  struct tevent_req *subreq;
63
64
0
  status = smbd_smb2_request_verify_sizes(req, 0x31);
65
0
  if (!NT_STATUS_IS_OK(status)) {
66
0
    return smbd_smb2_request_error(req, status);
67
0
  }
68
0
  inbody = SMBD_SMB2_IN_BODY_PTR(req);
69
70
0
  if (xconn->protocol >= PROTOCOL_SMB3_02) {
71
0
    in_flags    = CVAL(inbody, 0x03);
72
0
  } else {
73
0
    in_flags    = 0;
74
0
  }
75
0
  in_length   = IVAL(inbody, 0x04);
76
0
  in_offset   = BVAL(inbody, 0x08);
77
0
  in_file_id_persistent = BVAL(inbody, 0x10);
78
0
  in_file_id_volatile = BVAL(inbody, 0x18);
79
0
  in_minimum_count  = IVAL(inbody, 0x20);
80
0
  in_remaining_bytes  = IVAL(inbody, 0x28);
81
82
  /* check the max read size */
83
0
  if (in_length > xconn->smb2.server.max_read) {
84
0
    DEBUG(2,("smbd_smb2_request_process_read: "
85
0
       "client ignored max read: %s: 0x%08X: 0x%08X\n",
86
0
      __location__, in_length, xconn->smb2.server.max_read));
87
0
    return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
88
0
  }
89
90
0
  status = smbd_smb2_request_verify_creditcharge(req, in_length);
91
0
  if (!NT_STATUS_IS_OK(status)) {
92
0
    return smbd_smb2_request_error(req, status);
93
0
  }
94
95
0
  in_fsp = file_fsp_smb2(req, in_file_id_persistent, in_file_id_volatile);
96
0
  if (in_fsp == NULL) {
97
0
    return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
98
0
  }
99
100
0
  subreq = smbd_smb2_read_send(req, req->sconn->ev_ctx,
101
0
             req, in_fsp,
102
0
             in_flags,
103
0
             in_length,
104
0
             in_offset,
105
0
             in_minimum_count,
106
0
             in_remaining_bytes);
107
0
  if (subreq == NULL) {
108
0
    return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
109
0
  }
110
0
  tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
111
112
0
  return smbd_smb2_request_pending_queue(req, subreq, 500);
113
0
}
114
115
static void smbd_smb2_request_read_done(struct tevent_req *subreq)
116
0
{
117
0
  struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
118
0
          struct smbd_smb2_request);
119
0
  uint16_t body_size;
120
0
  uint8_t body_padding = req->xconn->smb2.smbtorture.read_body_padding;
121
0
  DATA_BLOB outbody;
122
0
  DATA_BLOB outdyn;
123
0
  uint8_t out_data_offset;
124
0
  DATA_BLOB out_data_buffer = data_blob_null;
125
0
  uint32_t out_data_remaining = 0;
126
0
  NTSTATUS status;
127
0
  NTSTATUS error; /* transport error */
128
129
0
  status = smbd_smb2_read_recv(subreq,
130
0
             req,
131
0
             &out_data_buffer,
132
0
             &out_data_remaining);
133
0
  TALLOC_FREE(subreq);
134
0
  if (!NT_STATUS_IS_OK(status)) {
135
0
    error = smbd_smb2_request_error(req, status);
136
0
    if (!NT_STATUS_IS_OK(error)) {
137
0
      smbd_server_connection_terminate(req->xconn,
138
0
               nt_errstr(error));
139
0
      return;
140
0
    }
141
0
    return;
142
0
  }
143
144
  /*
145
   * Only FSCTL_SMBTORTURE_GLOBAL_READ_RESPONSE_BODY_PADDING8
146
   * sets body_padding to a value different from 0.
147
   */
148
0
  body_size = 0x10 + body_padding;
149
0
  out_data_offset = SMB2_HDR_BODY + body_size;
150
151
0
  outbody = smbd_smb2_generate_outbody(req, body_size);
152
0
  if (outbody.data == NULL) {
153
0
    error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
154
0
    if (!NT_STATUS_IS_OK(error)) {
155
0
      smbd_server_connection_terminate(req->xconn,
156
0
               nt_errstr(error));
157
0
      return;
158
0
    }
159
0
    return;
160
0
  }
161
162
0
  SSVAL(outbody.data, 0x00, 0x10 + 1); /* struct size */
163
0
  SCVAL(outbody.data, 0x02,
164
0
        out_data_offset);     /* data offset */
165
0
  SCVAL(outbody.data, 0x03, 0);    /* reserved */
166
0
  SIVAL(outbody.data, 0x04,
167
0
        out_data_buffer.length);    /* data length */
168
0
  SIVAL(outbody.data, 0x08,
169
0
        out_data_remaining);    /* data remaining */
170
0
  SIVAL(outbody.data, 0x0C, 0);    /* reserved */
171
0
  if (body_padding != 0) {
172
0
    memset(outbody.data + 0x10, 0, body_padding);
173
0
  }
174
175
0
  outdyn = out_data_buffer;
176
177
0
  error = smbd_smb2_request_done(req, outbody, &outdyn);
178
0
  if (!NT_STATUS_IS_OK(error)) {
179
0
    smbd_server_connection_terminate(req->xconn,
180
0
             nt_errstr(error));
181
0
    return;
182
0
  }
183
0
}
184
185
struct smbd_smb2_read_state {
186
  struct smbd_smb2_request *smb2req;
187
  struct smb_request *smbreq;
188
  struct tevent_req *ipc_subreq;
189
  files_struct *fsp;
190
  uint8_t in_flags;
191
  uint32_t in_length;
192
  uint64_t in_offset;
193
  uint32_t in_minimum;
194
  DATA_BLOB out_headers;
195
  uint8_t _out_hdr_buf[NBT_HDR_SIZE + SMB2_HDR_BODY + 0x10];
196
  DATA_BLOB out_data;
197
  uint32_t out_remaining;
198
};
199
200
static int smb2_smb2_read_state_deny_destructor(struct smbd_smb2_read_state *state)
201
0
{
202
0
  return -1;
203
0
}
204
205
/* struct smbd_smb2_read_state destructor. Send the SMB2_READ data. */
206
static int smb2_sendfile_send_data(struct smbd_smb2_read_state *state)
207
0
{
208
0
  uint32_t in_length = state->in_length;
209
0
  uint64_t in_offset = state->in_offset;
210
0
  files_struct *fsp = state->fsp;
211
0
  const DATA_BLOB *hdr = state->smb2req->queue_entry.sendfile_header;
212
0
  NTSTATUS *pstatus = state->smb2req->queue_entry.sendfile_status;
213
0
  struct smbXsrv_connection *xconn = state->smb2req->xconn;
214
0
  ssize_t nread;
215
0
  ssize_t ret;
216
0
  int saved_errno;
217
218
0
  nread = SMB_VFS_SENDFILE(xconn->transport.sock,
219
0
         fsp,
220
0
         hdr,
221
0
         in_offset,
222
0
         in_length);
223
0
  DBG_DEBUG("SMB_VFS_SENDFILE returned %zd on file %s\n",
224
0
      nread,
225
0
      fsp_str_dbg(fsp));
226
227
0
  if (nread == -1) {
228
0
    saved_errno = errno;
229
230
    /*
231
     * Returning ENOSYS means no data at all was sent.
232
       Do this as a normal read. */
233
0
    if (errno == ENOSYS) {
234
0
      goto normal_read;
235
0
    }
236
237
0
    if (errno == ENOTSUP) {
238
0
      set_use_sendfile(SNUM(fsp->conn), false);
239
0
      DBG_WARNING("Disabling sendfile use as sendfile is "
240
0
            "not supported by the system\n");
241
0
      goto normal_read;
242
0
    }
243
244
0
    if (errno == EINTR) {
245
      /*
246
       * Special hack for broken Linux with no working sendfile. If we
247
       * return EINTR we sent the header but not the rest of the data.
248
       * Fake this up by doing read/write calls.
249
       */
250
0
      set_use_sendfile(SNUM(fsp->conn), false);
251
0
      nread = fake_sendfile(xconn, fsp, in_offset, in_length);
252
0
      if (nread == -1) {
253
0
        saved_errno = errno;
254
0
        DBG_ERR("fake_sendfile failed for file %s "
255
0
          "(%s) for client %s. Terminating\n",
256
0
          fsp_str_dbg(fsp),
257
0
          strerror(saved_errno),
258
0
          smbXsrv_connection_dbg(xconn));
259
0
        *pstatus = map_nt_error_from_unix_common(saved_errno);
260
0
        return 0;
261
0
      }
262
0
      goto out;
263
0
    }
264
265
0
    DBG_ERR("sendfile failed for file "
266
0
      "%s (%s) for client %s. Terminating\n",
267
0
      fsp_str_dbg(fsp),
268
0
      strerror(saved_errno),
269
0
      smbXsrv_connection_dbg(xconn));
270
0
    *pstatus = map_nt_error_from_unix_common(saved_errno);
271
0
    return 0;
272
0
  } else if (nread == 0) {
273
    /*
274
     * Some sendfile implementations return 0 to indicate
275
     * that there was a short read, but nothing was
276
     * actually written to the socket.  In this case,
277
     * fallback to the normal read path so the header gets
278
     * the correct byte count.
279
     */
280
0
    DBG_NOTICE("sendfile sent zero bytes "
281
0
         "falling back to the normal read: %s\n",
282
0
         fsp_str_dbg(fsp));
283
0
    goto normal_read;
284
0
  }
285
286
  /*
287
   * We got a short read
288
   */
289
0
  goto out;
290
291
0
normal_read:
292
  /* Send out the header. */
293
0
  ret = write_data(xconn->transport.sock,
294
0
       (const char *)hdr->data, hdr->length);
295
0
  if (ret != hdr->length) {
296
0
    saved_errno = errno;
297
0
    DBG_ERR("write_data failed for file "
298
0
      "%s (%s) for client %s. Terminating\n",
299
0
      fsp_str_dbg(fsp),
300
0
      strerror(saved_errno),
301
0
      smbXsrv_connection_dbg(xconn));
302
0
    *pstatus = map_nt_error_from_unix_common(saved_errno);
303
0
    return 0;
304
0
  }
305
0
  nread = fake_sendfile(xconn, fsp, in_offset, in_length);
306
0
  if (nread == -1) {
307
0
    saved_errno = errno;
308
0
    DBG_ERR("fake_sendfile failed for file %s (%s) for client %s. "
309
0
      "Terminating\n",
310
0
      fsp_str_dbg(fsp),
311
0
      strerror(saved_errno),
312
0
      smbXsrv_connection_dbg(xconn));
313
0
    *pstatus = map_nt_error_from_unix_common(saved_errno);
314
0
    return 0;
315
0
  }
316
317
0
  out:
318
319
0
  if (nread < in_length) {
320
0
    ret = sendfile_short_send(xconn, fsp, nread,
321
0
            hdr->length, in_length);
322
0
    if (ret == -1) {
323
0
      saved_errno = errno;
324
0
      DBG_ERR("sendfile_short_send "
325
0
        "failed for file %s (%s) for client %s. "
326
0
        "Terminating\n",
327
0
        fsp_str_dbg(fsp),
328
0
        strerror(saved_errno),
329
0
        smbXsrv_connection_dbg(xconn));
330
0
      *pstatus = map_nt_error_from_unix_common(saved_errno);
331
0
      return 0;
332
0
    }
333
0
  }
334
335
0
  *pstatus = NT_STATUS_OK;
336
0
  return 0;
337
0
}
338
339
static NTSTATUS schedule_smb2_sendfile_read(struct smbd_smb2_request *smb2req,
340
          struct smbd_smb2_read_state *state)
341
0
{
342
0
  files_struct *fsp = state->fsp;
343
344
  /*
345
   * We cannot use sendfile if...
346
   * We were not configured to do so OR
347
   * Signing is active OR
348
   * This is a compound SMB2 operation OR
349
   * fsp is a STREAM file OR
350
   * It's not a regular file OR
351
   * Requested offset is greater than file size OR
352
   * there's not enough data in the file.
353
   * Phew :-). Luckily this means most
354
   * reads on most normal files. JRA.
355
  */
356
357
0
  if (!lp__use_sendfile(SNUM(fsp->conn)) ||
358
0
      smb2req->do_signing ||
359
0
      smb2req->do_encryption ||
360
0
      smbd_smb2_is_compound(smb2req) ||
361
0
      fsp_is_alternate_stream(fsp) ||
362
0
      (!S_ISREG(fsp->fsp_name->st.st_ex_mode)) ||
363
0
      (state->in_offset >= fsp->fsp_name->st.st_ex_size) ||
364
0
      (fsp->fsp_name->st.st_ex_size < state->in_offset + state->in_length))
365
0
  {
366
0
    return NT_STATUS_RETRY;
367
0
  }
368
369
  /* We've already checked there's this amount of data
370
     to read. */
371
0
  state->out_data.length = state->in_length;
372
0
  state->out_remaining = 0;
373
374
0
  state->out_headers = data_blob_const(state->_out_hdr_buf,
375
0
               sizeof(state->_out_hdr_buf));
376
0
  return NT_STATUS_OK;
377
0
}
378
379
static void smbd_smb2_read_pipe_done(struct tevent_req *subreq);
380
381
/*******************************************************************
382
 Common read complete processing function for both synchronous and
383
 asynchronous reads.
384
*******************************************************************/
385
386
NTSTATUS smb2_read_complete(struct tevent_req *req, ssize_t nread, int err)
387
0
{
388
0
  struct smbd_smb2_read_state *state = tevent_req_data(req,
389
0
          struct smbd_smb2_read_state);
390
0
  files_struct *fsp = state->fsp;
391
392
0
  if (nread < 0) {
393
0
    NTSTATUS status = map_nt_error_from_unix(err);
394
395
0
    DEBUG( 3,( "smb2_read_complete: file %s nread = %d. "
396
0
      "Error = %s (NTSTATUS %s)\n",
397
0
      fsp_str_dbg(fsp),
398
0
      (int)nread,
399
0
      strerror(err),
400
0
      nt_errstr(status)));
401
402
0
    return status;
403
0
  }
404
0
  if (nread == 0 && state->in_length != 0) {
405
0
    DEBUG(5,("smb2_read_complete: read_file[%s] end of file\n",
406
0
      fsp_str_dbg(fsp)));
407
0
    return NT_STATUS_END_OF_FILE;
408
0
  }
409
410
0
  if (nread < state->in_minimum) {
411
0
    DEBUG(5,("smb2_read_complete: read_file[%s] read less %d than "
412
0
      "minimum requested %u. Returning end of file\n",
413
0
      fsp_str_dbg(fsp),
414
0
      (int)nread,
415
0
      (unsigned int)state->in_minimum));
416
0
    return NT_STATUS_END_OF_FILE;
417
0
  }
418
419
0
  DEBUG(3,("smbd_smb2_read: %s, file %s, length=%lu offset=%lu read=%lu\n",
420
0
    fsp_fnum_dbg(fsp),
421
0
    fsp_str_dbg(fsp),
422
0
    (unsigned long)state->in_length,
423
0
    (unsigned long)state->in_offset,
424
0
    (unsigned long)nread));
425
426
0
  state->out_data.length = nread;
427
0
  state->out_remaining = 0;
428
429
0
  return NT_STATUS_OK;
430
0
}
431
432
static bool smbd_smb2_read_ipc_cancel(struct tevent_req *req)
433
0
{
434
0
  struct smbd_smb2_read_state *state =
435
0
    tevent_req_data(req,
436
0
    struct smbd_smb2_read_state);
437
438
0
  TALLOC_FREE(state->ipc_subreq);
439
0
  tevent_req_defer_callback(req, state->smb2req->xconn->client->raw_ev_ctx);
440
0
  if (state->fsp->fsp_flags.closing) {
441
0
    tevent_req_nterror(req, NT_STATUS_PIPE_BROKEN);
442
0
  } else {
443
0
    tevent_req_nterror(req, NT_STATUS_CANCELLED);
444
0
  }
445
0
  return true;
446
0
}
447
448
static bool smbd_smb2_read_cancel(struct tevent_req *req)
449
0
{
450
0
  struct smbd_smb2_read_state *state =
451
0
    tevent_req_data(req,
452
0
    struct smbd_smb2_read_state);
453
454
0
  return cancel_smb2_aio(state->smbreq);
455
0
}
456
457
static struct tevent_req *smbd_smb2_read_send(TALLOC_CTX *mem_ctx,
458
                struct tevent_context *ev,
459
                struct smbd_smb2_request *smb2req,
460
                struct files_struct *fsp,
461
                uint8_t in_flags,
462
                uint32_t in_length,
463
                uint64_t in_offset,
464
                uint32_t in_minimum,
465
                uint32_t in_remaining)
466
0
{
467
0
  NTSTATUS status;
468
0
  struct tevent_req *req = NULL;
469
0
  struct smbd_smb2_read_state *state = NULL;
470
0
  struct smb_request *smbreq = NULL;
471
0
  connection_struct *conn = smb2req->tcon->compat;
472
0
  ssize_t nread = -1;
473
0
  struct lock_struct lock;
474
0
  int saved_errno;
475
476
0
  req = tevent_req_create(mem_ctx, &state,
477
0
        struct smbd_smb2_read_state);
478
0
  if (req == NULL) {
479
0
    return NULL;
480
0
  }
481
0
  state->smb2req = smb2req;
482
0
  state->in_flags = in_flags;
483
0
  state->in_length = in_length;
484
0
  state->in_offset = in_offset;
485
0
  state->in_minimum = in_minimum;
486
0
  state->out_data = data_blob_null;
487
0
  state->out_remaining = 0;
488
489
0
  DEBUG(10,("smbd_smb2_read: %s - %s\n",
490
0
      fsp_str_dbg(fsp), fsp_fnum_dbg(fsp)));
491
492
0
  smbreq = smbd_smb2_fake_smb_request(smb2req, fsp);
493
0
  if (tevent_req_nomem(smbreq, req)) {
494
0
    return tevent_req_post(req, ev);
495
0
  }
496
0
  state->smbreq = smbreq;
497
498
0
  if (fsp->fsp_flags.is_directory) {
499
0
    tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
500
0
    return tevent_req_post(req, ev);
501
0
  }
502
503
0
  state->fsp = fsp;
504
505
0
  if (IS_IPC(smbreq->conn)) {
506
0
    struct tevent_req *subreq = NULL;
507
0
    struct aio_req_fsp_link *aio_lnk = NULL;
508
509
0
    state->out_data = data_blob_talloc(state, NULL, in_length);
510
0
    if (in_length > 0 && tevent_req_nomem(state->out_data.data, req)) {
511
0
      return tevent_req_post(req, ev);
512
0
    }
513
514
0
    if (!fsp_is_np(fsp)) {
515
0
      tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
516
0
      return tevent_req_post(req, ev);
517
0
    }
518
519
0
    subreq = np_read_send(state, ev,
520
0
              fsp->fake_file_handle,
521
0
              state->out_data.data,
522
0
              state->out_data.length);
523
0
    if (tevent_req_nomem(subreq, req)) {
524
0
      return tevent_req_post(req, ev);
525
0
    }
526
0
    tevent_req_set_callback(subreq,
527
0
          smbd_smb2_read_pipe_done,
528
0
          req);
529
530
    /*
531
     * Make sure we mark the fsp as having outstanding async
532
     * activity so we don't crash on shutdown close.
533
     */
534
535
0
    aio_lnk = aio_add_req_to_fsp(fsp, req);
536
0
    if (aio_lnk == NULL) {
537
0
      tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
538
0
      return tevent_req_post(req, ev);
539
0
    }
540
0
    talloc_move(subreq, &aio_lnk);
541
542
0
    state->ipc_subreq = subreq;
543
0
    tevent_req_set_cancel_fn(req, smbd_smb2_read_ipc_cancel);
544
0
    return req;
545
0
  }
546
547
0
  if (!CHECK_READ_SMB2(fsp)) {
548
0
    tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
549
0
    return tevent_req_post(req, ev);
550
0
  }
551
552
0
  status = schedule_smb2_aio_read(fsp->conn,
553
0
        smbreq,
554
0
        fsp,
555
0
        state,
556
0
        &state->out_data,
557
0
        (off_t)in_offset,
558
0
        (size_t)in_length);
559
560
0
  if (NT_STATUS_IS_OK(status)) {
561
    /*
562
     * Doing an async read, allow this
563
     * request to be canceled
564
     */
565
0
    tevent_req_set_cancel_fn(req, smbd_smb2_read_cancel);
566
0
    return req;
567
0
  }
568
569
0
  if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
570
    /* Real error in setting up aio. Fail. */
571
0
    tevent_req_nterror(req, status);
572
0
    return tevent_req_post(req, ev);
573
0
  }
574
575
  /* Fallback to synchronous. */
576
577
0
  init_strict_lock_struct(fsp,
578
0
        fsp->op->global->open_persistent_id,
579
0
        in_offset,
580
0
        in_length,
581
0
        READ_LOCK,
582
0
        &lock);
583
584
0
  if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
585
0
    tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
586
0
    return tevent_req_post(req, ev);
587
0
  }
588
589
  /* Try sendfile in preference. */
590
0
  status = schedule_smb2_sendfile_read(smb2req, state);
591
0
  if (NT_STATUS_IS_OK(status)) {
592
0
    tevent_req_done(req);
593
0
    return tevent_req_post(req, ev);
594
0
  }
595
0
  if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
596
0
    tevent_req_nterror(req, status);
597
0
    return tevent_req_post(req, ev);
598
0
  }
599
600
  /* Ok, read into memory. Allocate the out buffer. */
601
0
  state->out_data = data_blob_talloc(state, NULL, in_length);
602
0
  if (in_length > 0 && tevent_req_nomem(state->out_data.data, req)) {
603
0
    return tevent_req_post(req, ev);
604
0
  }
605
606
0
  nread = read_file(fsp,
607
0
        (char *)state->out_data.data,
608
0
        in_offset,
609
0
        in_length);
610
611
0
  saved_errno = errno;
612
613
0
  DEBUG(10,("smbd_smb2_read: file %s, %s, offset=%llu "
614
0
    "len=%llu returned %lld\n",
615
0
    fsp_str_dbg(fsp),
616
0
    fsp_fnum_dbg(fsp),
617
0
    (unsigned long long)in_offset,
618
0
    (unsigned long long)in_length,
619
0
    (long long)nread));
620
621
0
  status = smb2_read_complete(req, nread, saved_errno);
622
0
  if (!NT_STATUS_IS_OK(status)) {
623
0
    tevent_req_nterror(req, status);
624
0
  } else {
625
    /* Success. */
626
0
    tevent_req_done(req);
627
0
  }
628
0
  return tevent_req_post(req, ev);
629
0
}
630
631
static void smbd_smb2_read_pipe_done(struct tevent_req *subreq)
632
0
{
633
0
  struct tevent_req *req = tevent_req_callback_data(subreq,
634
0
         struct tevent_req);
635
0
  struct smbd_smb2_read_state *state = tevent_req_data(req,
636
0
               struct smbd_smb2_read_state);
637
0
  NTSTATUS status;
638
0
  ssize_t nread = -1;
639
0
  bool is_data_outstanding;
640
641
0
  status = np_read_recv(subreq, &nread, &is_data_outstanding);
642
0
  TALLOC_FREE(subreq);
643
0
  if (!NT_STATUS_IS_OK(status)) {
644
0
    NTSTATUS old = status;
645
0
    status = nt_status_np_pipe(old);
646
0
    tevent_req_nterror(req, status);
647
0
    return;
648
0
  }
649
650
0
  if (nread == 0 && state->out_data.length != 0) {
651
0
    tevent_req_nterror(req, NT_STATUS_END_OF_FILE);
652
0
    return;
653
0
  }
654
655
0
  state->out_data.length = nread;
656
0
  state->out_remaining = 0;
657
658
  /*
659
   * TODO: add STATUS_BUFFER_OVERFLOW handling, once we also
660
   * handle it in SMB1 pipe_read_andx_done().
661
   */
662
663
0
  tevent_req_done(req);
664
0
}
665
666
static NTSTATUS smbd_smb2_read_recv(struct tevent_req *req,
667
            TALLOC_CTX *mem_ctx,
668
            DATA_BLOB *out_data,
669
            uint32_t *out_remaining)
670
0
{
671
0
  NTSTATUS status;
672
0
  struct smbd_smb2_read_state *state = tevent_req_data(req,
673
0
               struct smbd_smb2_read_state);
674
675
0
  if (tevent_req_is_nterror(req, &status)) {
676
0
    tevent_req_received(req);
677
0
    return status;
678
0
  }
679
680
0
  *out_data = state->out_data;
681
0
  talloc_steal(mem_ctx, out_data->data);
682
0
  *out_remaining = state->out_remaining;
683
684
0
  if (state->out_headers.length > 0) {
685
0
    talloc_steal(mem_ctx, state);
686
0
    talloc_set_destructor(state, smb2_smb2_read_state_deny_destructor);
687
0
    tevent_req_received(req);
688
0
    state->smb2req->queue_entry.sendfile_header = &state->out_headers;
689
0
    state->smb2req->queue_entry.sendfile_body_size = state->in_length;
690
0
    talloc_set_destructor(state, smb2_sendfile_send_data);
691
0
  } else {
692
0
    tevent_req_received(req);
693
0
  }
694
695
0
  return NT_STATUS_OK;
696
0
}