s3:smb2_server: optimize smbd_smb2_request_setup_out()
[metze/samba/wip.git] / source3 / smbd / smb2_server.c
1 /*
2    Unix SMB/CIFS implementation.
3    Core SMB2 server
4
5    Copyright (C) Stefan Metzmacher 2009
6    Copyright (C) Jeremy Allison 2010
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "../lib/util/tevent_ntstatus.h"
28 #include "smbprofile.h"
29 #include "../lib/util/bitmap.h"
30 #include "../librpc/gen_ndr/krb5pac.h"
31 #include "auth.h"
32
33 static void smbd_smb2_connection_handler(struct tevent_context *ev,
34                                          struct tevent_fd *fde,
35                                          uint16_t flags,
36                                          void *private_data);
37 static NTSTATUS smbd_smb2_io_handler(struct smbd_server_connection *sconn,
38                                      uint16_t fde_flags);
39
40 static const struct smbd_smb2_dispatch_table {
41         uint16_t opcode;
42         const char *name;
43         bool need_session;
44         bool need_tcon;
45         bool as_root;
46         uint16_t fileid_ofs;
47         bool allow_invalid_fileid;
48 } smbd_smb2_table[] = {
49 #define _OP(o) .opcode = o, .name = #o
50         {
51                 _OP(SMB2_OP_NEGPROT),
52                 .as_root = true,
53         },{
54                 _OP(SMB2_OP_SESSSETUP),
55                 .as_root = true,
56         },{
57                 _OP(SMB2_OP_LOGOFF),
58                 .need_session = true,
59                 .as_root = true,
60         },{
61                 _OP(SMB2_OP_TCON),
62                 .need_session = true,
63                 /*
64                  * This call needs to be run as root.
65                  *
66                  * smbd_smb2_request_process_tcon()
67                  * calls make_connection_snum(), which will call
68                  * change_to_user(), when needed.
69                  */
70                 .as_root = true,
71         },{
72                 _OP(SMB2_OP_TDIS),
73                 .need_session = true,
74                 .need_tcon = true,
75                 .as_root = true,
76         },{
77                 _OP(SMB2_OP_CREATE),
78                 .need_session = true,
79                 .need_tcon = true,
80         },{
81                 _OP(SMB2_OP_CLOSE),
82                 .need_session = true,
83                 .need_tcon = true,
84                 .fileid_ofs = 0x08,
85         },{
86                 _OP(SMB2_OP_FLUSH),
87                 .need_session = true,
88                 .need_tcon = true,
89                 .fileid_ofs = 0x08,
90         },{
91                 _OP(SMB2_OP_READ),
92                 .need_session = true,
93                 .need_tcon = true,
94                 .fileid_ofs = 0x10,
95         },{
96                 _OP(SMB2_OP_WRITE),
97                 .need_session = true,
98                 .need_tcon = true,
99                 .fileid_ofs = 0x10,
100         },{
101                 _OP(SMB2_OP_LOCK),
102                 .need_session = true,
103                 .need_tcon = true,
104                 .fileid_ofs = 0x08,
105         },{
106                 _OP(SMB2_OP_IOCTL),
107                 .need_session = true,
108                 .need_tcon = true,
109                 .fileid_ofs = 0x08,
110                 .allow_invalid_fileid = true,
111         },{
112                 _OP(SMB2_OP_CANCEL),
113                 .as_root = true,
114         },{
115                 _OP(SMB2_OP_KEEPALIVE),
116                 .as_root = true,
117         },{
118                 _OP(SMB2_OP_FIND),
119                 .need_session = true,
120                 .need_tcon = true,
121                 .fileid_ofs = 0x08,
122         },{
123                 _OP(SMB2_OP_NOTIFY),
124                 .need_session = true,
125                 .need_tcon = true,
126                 .fileid_ofs = 0x08,
127         },{
128                 _OP(SMB2_OP_GETINFO),
129                 .need_session = true,
130                 .need_tcon = true,
131                 .fileid_ofs = 0x18,
132         },{
133                 _OP(SMB2_OP_SETINFO),
134                 .need_session = true,
135                 .need_tcon = true,
136                 .fileid_ofs = 0x10,
137         },{
138                 _OP(SMB2_OP_BREAK),
139                 .need_session = true,
140                 .need_tcon = true,
141                 /*
142                  * we do not set
143                  * .fileid_ofs here
144                  * as LEASE breaks does not
145                  * have a file id
146                  */
147         }
148 };
149
150 const char *smb2_opcode_name(uint16_t opcode)
151 {
152         if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
153                 return "Bad SMB2 opcode";
154         }
155         return smbd_smb2_table[opcode].name;
156 }
157
158 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
159 {
160         const struct smbd_smb2_dispatch_table *ret = NULL;
161
162         if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
163                 return NULL;
164         }
165
166         ret = &smbd_smb2_table[opcode];
167
168         SMB_ASSERT(ret->opcode == opcode);
169
170         return ret;
171 }
172
173 static void print_req_vectors(const struct smbd_smb2_request *req)
174 {
175         int i;
176
177         for (i = 0; i < req->in.vector_count; i++) {
178                 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
179                         (unsigned int)i,
180                         (unsigned int)req->in.vector[i].iov_len);
181         }
182         for (i = 0; i < req->out.vector_count; i++) {
183                 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
184                         (unsigned int)i,
185                         (unsigned int)req->out.vector[i].iov_len);
186         }
187 }
188
189 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
190 {
191         if (size < (4 + SMB2_HDR_BODY)) {
192                 return false;
193         }
194
195         if (IVAL(inbuf, 4) != SMB2_MAGIC) {
196                 return false;
197         }
198
199         return true;
200 }
201
202 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
203 {
204         TALLOC_FREE(sconn->smb1.fde);
205
206         sconn->smb2.send_queue = NULL;
207
208         sconn->smb2.seqnum_low = 0;
209         sconn->smb2.seqnum_range = 1;
210         sconn->smb2.credits_granted = 1;
211         sconn->smb2.max_credits = lp_smb2_max_credits();
212         sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
213                                                    sconn->smb2.max_credits);
214         if (sconn->smb2.credits_bitmap == NULL) {
215                 return NT_STATUS_NO_MEMORY;
216         }
217
218         sconn->smb2.fde = tevent_add_fd(sconn->ev_ctx,
219                                         sconn,
220                                         sconn->sock,
221                                         TEVENT_FD_READ,
222                                         smbd_smb2_connection_handler,
223                                         sconn);
224         if (sconn->smb2.fde == NULL) {
225                 return NT_STATUS_NO_MEMORY;
226         }
227
228         /* Ensure child is set to non-blocking mode */
229         set_blocking(sconn->sock, false);
230         return NT_STATUS_OK;
231 }
232
233 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
234 #define _smb2_setlen(_buf,len) do { \
235         uint8_t *buf = (uint8_t *)_buf; \
236         buf[0] = 0; \
237         buf[1] = ((len)&0xFF0000)>>16; \
238         buf[2] = ((len)&0xFF00)>>8; \
239         buf[3] = (len)&0xFF; \
240 } while (0)
241
242 static void smb2_setup_nbt_length(struct iovec *vector, int count)
243 {
244         size_t len = 0;
245         int i;
246
247         for (i=1; i < count; i++) {
248                 len += vector[i].iov_len;
249         }
250
251         _smb2_setlen(vector[0].iov_base, len);
252 }
253
254 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
255 {
256         data_blob_clear_free(&req->first_key);
257         data_blob_clear_free(&req->last_key);
258         return 0;
259 }
260
261 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
262 {
263         TALLOC_CTX *mem_pool;
264         struct smbd_smb2_request *req;
265
266 #if 0
267         /* Enable this to find subtle valgrind errors. */
268         mem_pool = talloc_init("smbd_smb2_request_allocate");
269 #else
270         mem_pool = talloc_tos();
271 #endif
272         if (mem_pool == NULL) {
273                 return NULL;
274         }
275
276         req = talloc_zero(mem_pool, struct smbd_smb2_request);
277         if (req == NULL) {
278                 talloc_free(mem_pool);
279                 return NULL;
280         }
281         talloc_reparent(mem_pool, mem_ctx, req);
282 #if 0
283         TALLOC_FREE(mem_pool);
284 #endif
285
286         req->last_session_id = UINT64_MAX;
287         req->last_tid = UINT32_MAX;
288
289         talloc_set_destructor(req, smbd_smb2_request_destructor);
290
291         return req;
292 }
293
294 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn,
295                                                NTTIME now,
296                                                uint8_t *buf,
297                                                size_t buflen,
298                                                struct smbd_smb2_request *req,
299                                                struct iovec **piov,
300                                                int *pnum_iov)
301 {
302         TALLOC_CTX *mem_ctx = req;
303         struct iovec *iov;
304         int num_iov = 1;
305         size_t taken = 0;
306         uint8_t *first_hdr = buf;
307         size_t verified_buflen = 0;
308         uint8_t *tf = NULL;
309         size_t tf_len = 0;
310
311         /*
312          * Note: index '0' is reserved for the transport protocol
313          */
314         iov = req->in._vector;
315
316         while (taken < buflen) {
317                 size_t len = buflen - taken;
318                 uint8_t *hdr = first_hdr + taken;
319                 struct iovec *cur;
320                 size_t full_size;
321                 size_t next_command_ofs;
322                 uint16_t body_size;
323                 uint8_t *body = NULL;
324                 uint32_t dyn_size;
325                 uint8_t *dyn = NULL;
326
327                 if (verified_buflen > taken) {
328                         len = verified_buflen - taken;
329                 } else {
330                         tf = NULL;
331                         tf_len = 0;
332                 }
333
334                 if (len < 4) {
335                         DEBUG(10, ("%d bytes left, expected at least %d\n",
336                                    (int)len, 4));
337                         goto inval;
338                 }
339                 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
340                         struct smbXsrv_session *s = NULL;
341                         uint64_t uid;
342                         struct iovec tf_iov[2];
343                         NTSTATUS status;
344                         size_t enc_len;
345
346                         if (conn->protocol < PROTOCOL_SMB2_24) {
347                                 DEBUG(10, ("Got SMB2_TRANSFORM header, "
348                                            "but dialect[0x%04X] is used\n",
349                                            conn->smb2.server.dialect));
350                                 goto inval;
351                         }
352
353                         if (!(conn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION)) {
354                                 DEBUG(10, ("Got SMB2_TRANSFORM header, "
355                                            "but not negotiated "
356                                            "client[0x%08X] server[0x%08X]\n",
357                                            conn->smb2.client.capabilities,
358                                            conn->smb2.server.capabilities));
359                                 goto inval;
360                         }
361
362                         if (len < SMB2_TF_HDR_SIZE) {
363                                 DEBUG(1, ("%d bytes left, expected at least %d\n",
364                                            (int)len, SMB2_TF_HDR_SIZE));
365                                 goto inval;
366                         }
367                         tf = hdr;
368                         tf_len = SMB2_TF_HDR_SIZE;
369                         taken += tf_len;
370
371                         hdr = first_hdr + taken;
372                         enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
373                         uid = BVAL(tf, SMB2_TF_SESSION_ID);
374
375                         if (len < SMB2_TF_HDR_SIZE + enc_len) {
376                                 DEBUG(1, ("%d bytes left, expected at least %d\n",
377                                            (int)len,
378                                            (int)(SMB2_TF_HDR_SIZE + enc_len)));
379                                 goto inval;
380                         }
381
382                         status = smb2srv_session_lookup(conn, uid, now, &s);
383                         if (s == NULL) {
384                                 DEBUG(1, ("invalid session[%llu] in "
385                                           "SMB2_TRANSFORM header\n",
386                                            (unsigned long long)uid));
387                                 TALLOC_FREE(iov);
388                                 return NT_STATUS_USER_SESSION_DELETED;
389                         }
390
391                         tf_iov[0].iov_base = (void *)tf;
392                         tf_iov[0].iov_len = tf_len;
393                         tf_iov[1].iov_base = (void *)hdr;
394                         tf_iov[1].iov_len = enc_len;
395
396                         status = smb2_signing_decrypt_pdu(s->global->decryption_key,
397                                                           conn->protocol,
398                                                           tf_iov, 2);
399                         if (!NT_STATUS_IS_OK(status)) {
400                                 TALLOC_FREE(iov);
401                                 return status;
402                         }
403
404                         verified_buflen = taken + enc_len;
405                         len = enc_len;
406                 }
407
408                 /*
409                  * We need the header plus the body length field
410                  */
411
412                 if (len < SMB2_HDR_BODY + 2) {
413                         DEBUG(10, ("%d bytes left, expected at least %d\n",
414                                    (int)len, SMB2_HDR_BODY));
415                         goto inval;
416                 }
417                 if (IVAL(hdr, 0) != SMB2_MAGIC) {
418                         DEBUG(10, ("Got non-SMB2 PDU: %x\n",
419                                    IVAL(hdr, 0)));
420                         goto inval;
421                 }
422                 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
423                         DEBUG(10, ("Got HDR len %d, expected %d\n",
424                                    SVAL(hdr, 4), SMB2_HDR_BODY));
425                         goto inval;
426                 }
427
428                 full_size = len;
429                 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
430                 body_size = SVAL(hdr, SMB2_HDR_BODY);
431
432                 if (next_command_ofs != 0) {
433                         if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
434                                 goto inval;
435                         }
436                         if (next_command_ofs > full_size) {
437                                 goto inval;
438                         }
439                         full_size = next_command_ofs;
440                 }
441                 if (body_size < 2) {
442                         goto inval;
443                 }
444                 body_size &= 0xfffe;
445
446                 if (body_size > (full_size - SMB2_HDR_BODY)) {
447                         /*
448                          * let the caller handle the error
449                          */
450                         body_size = full_size - SMB2_HDR_BODY;
451                 }
452                 body = hdr + SMB2_HDR_BODY;
453                 dyn = body + body_size;
454                 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
455
456                 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
457                         struct iovec *iov_tmp = NULL;
458                         struct iovec *iov_alloc = NULL;
459
460                         if (iov != req->in._vector) {
461                                 iov_alloc = iov;
462                         }
463
464                         iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
465                                                  struct iovec,
466                                                  num_iov +
467                                                  SMBD_SMB2_NUM_IOV_PER_REQ);
468                         if (iov_tmp == NULL) {
469                                 TALLOC_FREE(iov_alloc);
470                                 return NT_STATUS_NO_MEMORY;
471                         }
472
473                         if (iov_alloc == NULL) {
474                                 memcpy(iov_tmp,
475                                        req->in._vector,
476                                        sizeof(req->in._vector));
477                         }
478
479                         iov = iov_tmp;
480                 }
481                 cur = &iov[num_iov];
482                 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
483
484                 cur[SMBD_SMB2_TF_IOV_OFS].iov_base   = tf;
485                 cur[SMBD_SMB2_TF_IOV_OFS].iov_len    = tf_len;
486                 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base  = hdr;
487                 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len   = SMB2_HDR_BODY;
488                 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
489                 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len  = body_size;
490                 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base  = dyn;
491                 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len   = dyn_size;
492
493                 taken += full_size;
494         }
495
496         *piov = iov;
497         *pnum_iov = num_iov;
498         return NT_STATUS_OK;
499
500 inval:
501         if (iov != req->in._vector) {
502                 TALLOC_FREE(iov);
503         }
504         return NT_STATUS_INVALID_PARAMETER;
505 }
506
507 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
508                                          uint8_t *inbuf, size_t size,
509                                          struct smbd_smb2_request **_req)
510 {
511         struct smbd_smb2_request *req;
512         uint32_t protocol_version;
513         const uint8_t *inhdr = NULL;
514         uint16_t cmd;
515         uint32_t next_command_ofs;
516         NTSTATUS status;
517         NTTIME now;
518
519         if (size < (4 + SMB2_HDR_BODY + 2)) {
520                 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
521                 return NT_STATUS_INVALID_PARAMETER;
522         }
523
524         inhdr = inbuf + 4;
525
526         protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
527         if (protocol_version != SMB2_MAGIC) {
528                 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
529                          protocol_version));
530                 return NT_STATUS_INVALID_PARAMETER;
531         }
532
533         cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
534         if (cmd != SMB2_OP_NEGPROT) {
535                 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
536                          cmd));
537                 return NT_STATUS_INVALID_PARAMETER;
538         }
539
540         next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
541         if (next_command_ofs != 0) {
542                 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
543                          next_command_ofs));
544                 return NT_STATUS_INVALID_PARAMETER;
545         }
546
547         req = smbd_smb2_request_allocate(sconn);
548         if (req == NULL) {
549                 return NT_STATUS_NO_MEMORY;
550         }
551         req->sconn = sconn;
552
553         talloc_steal(req, inbuf);
554
555         req->request_time = timeval_current();
556         now = timeval_to_nttime(&req->request_time);
557
558         status = smbd_smb2_inbuf_parse_compound(sconn->conn,
559                                                 now,
560                                                 inbuf + NBT_HDR_SIZE,
561                                                 size - NBT_HDR_SIZE,
562                                                 req, &req->in.vector,
563                                                 &req->in.vector_count);
564         if (!NT_STATUS_IS_OK(status)) {
565                 TALLOC_FREE(req);
566                 return status;
567         }
568
569         req->current_idx = 1;
570
571         *_req = req;
572         return NT_STATUS_OK;
573 }
574
575 static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
576                                           uint64_t message_id, uint64_t seq_id)
577 {
578         struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
579         unsigned int offset;
580
581         if (seq_id < sconn->smb2.seqnum_low) {
582                 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
583                         "%llu (sequence id %llu) "
584                         "(granted = %u, low = %llu, range = %u)\n",
585                         (unsigned long long)message_id,
586                         (unsigned long long)seq_id,
587                         (unsigned int)sconn->smb2.credits_granted,
588                         (unsigned long long)sconn->smb2.seqnum_low,
589                         (unsigned int)sconn->smb2.seqnum_range));
590                 return false;
591         }
592
593         if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) {
594                 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
595                         "%llu (sequence id %llu) "
596                         "(granted = %u, low = %llu, range = %u)\n",
597                         (unsigned long long)message_id,
598                         (unsigned long long)seq_id,
599                         (unsigned int)sconn->smb2.credits_granted,
600                         (unsigned long long)sconn->smb2.seqnum_low,
601                         (unsigned int)sconn->smb2.seqnum_range));
602                 return false;
603         }
604
605         offset = seq_id % sconn->smb2.max_credits;
606
607         if (bitmap_query(credits_bm, offset)) {
608                 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
609                         "%llu (sequence id %llu) "
610                         "(granted = %u, low = %llu, range = %u) "
611                         "(bm offset %u)\n",
612                         (unsigned long long)message_id,
613                         (unsigned long long)seq_id,
614                         (unsigned int)sconn->smb2.credits_granted,
615                         (unsigned long long)sconn->smb2.seqnum_low,
616                         (unsigned int)sconn->smb2.seqnum_range,
617                         offset));
618                 return false;
619         }
620
621         /* Mark the message_ids as seen in the bitmap. */
622         bitmap_set(credits_bm, offset);
623
624         if (seq_id != sconn->smb2.seqnum_low) {
625                 return true;
626         }
627
628         /*
629          * Move the window forward by all the message_id's
630          * already seen.
631          */
632         while (bitmap_query(credits_bm, offset)) {
633                 DEBUG(10,("smb2_validate_sequence_number: clearing "
634                           "id %llu (position %u) from bitmap\n",
635                           (unsigned long long)(sconn->smb2.seqnum_low),
636                           offset));
637                 bitmap_clear(credits_bm, offset);
638
639                 sconn->smb2.seqnum_low += 1;
640                 sconn->smb2.seqnum_range -= 1;
641                 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
642         }
643
644         return true;
645 }
646
647 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
648                                 const uint8_t *inhdr)
649 {
650         uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
651         uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
652         uint16_t credit_charge = 1;
653         uint64_t i;
654
655         if (opcode == SMB2_OP_CANCEL) {
656                 /* SMB2_CANCEL requests by definition resend messageids. */
657                 return true;
658         }
659
660         if (sconn->smb2.supports_multicredit) {
661                 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
662                 credit_charge = MAX(credit_charge, 1);
663         }
664
665         DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
666                    "credits_granted %llu, "
667                    "seqnum low/range: %llu/%llu\n",
668                    (unsigned long long) message_id,
669                    (unsigned long long) credit_charge,
670                    (unsigned long long) sconn->smb2.credits_granted,
671                    (unsigned long long) sconn->smb2.seqnum_low,
672                    (unsigned long long) sconn->smb2.seqnum_range));
673
674         if (sconn->smb2.credits_granted < credit_charge) {
675                 DEBUG(0, ("smb2_validate_message_id: client used more "
676                           "credits than granted, mid %llu, charge %llu, "
677                           "credits_granted %llu, "
678                           "seqnum low/range: %llu/%llu\n",
679                           (unsigned long long) message_id,
680                           (unsigned long long) credit_charge,
681                           (unsigned long long) sconn->smb2.credits_granted,
682                           (unsigned long long) sconn->smb2.seqnum_low,
683                           (unsigned long long) sconn->smb2.seqnum_range));
684                 return false;
685         }
686
687         /*
688          * now check the message ids
689          *
690          * for multi-credit requests we need to check all current mid plus
691          * the implicit mids caused by the credit charge
692          * e.g. current mid = 15, charge 5 => mark 15-19 as used
693          */
694
695         for (i = 0; i <= (credit_charge-1); i++) {
696                 uint64_t id = message_id + i;
697                 bool ok;
698
699                 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
700                            (unsigned long long)message_id,
701                            credit_charge,
702                            (unsigned long long)id));
703
704                 ok = smb2_validate_sequence_number(sconn, message_id, id);
705                 if (!ok) {
706                         return false;
707                 }
708         }
709
710         /* substract used credits */
711         sconn->smb2.credits_granted -= credit_charge;
712
713         return true;
714 }
715
716 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
717 {
718         int count;
719         int idx;
720
721         count = req->in.vector_count;
722
723         if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
724                 /* It's not a SMB2 request */
725                 return NT_STATUS_INVALID_PARAMETER;
726         }
727
728         for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
729                 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
730                 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
731                 const uint8_t *inhdr = NULL;
732
733                 if (hdr->iov_len != SMB2_HDR_BODY) {
734                         return NT_STATUS_INVALID_PARAMETER;
735                 }
736
737                 if (body->iov_len < 2) {
738                         return NT_STATUS_INVALID_PARAMETER;
739                 }
740
741                 inhdr = (const uint8_t *)hdr->iov_base;
742
743                 /* Check the SMB2 header */
744                 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
745                         return NT_STATUS_INVALID_PARAMETER;
746                 }
747
748                 if (!smb2_validate_message_id(req->sconn, inhdr)) {
749                         return NT_STATUS_INVALID_PARAMETER;
750                 }
751         }
752
753         return NT_STATUS_OK;
754 }
755
756 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
757                         const struct iovec *in_vector,
758                         struct iovec *out_vector)
759 {
760         const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
761         uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
762         uint16_t credit_charge = 1;
763         uint16_t credits_requested;
764         uint32_t out_flags;
765         uint16_t cmd;
766         NTSTATUS out_status;
767         uint16_t credits_granted = 0;
768         uint64_t credits_possible;
769         uint16_t current_max_credits;
770
771         /*
772          * first we grant only 1/16th of the max range.
773          *
774          * Windows also starts with the 1/16th and then grants
775          * more later. I was only able to trigger higher
776          * values, when using a very high credit charge.
777          *
778          * TODO: scale up depending on load, free memory
779          *       or other stuff.
780          *       Maybe also on the relationship between number
781          *       of requests and the used sequence number.
782          *       Which means we would grant more credits
783          *       for client which use multi credit requests.
784          */
785         current_max_credits = sconn->smb2.max_credits / 16;
786         current_max_credits = MAX(current_max_credits, 1);
787
788         if (sconn->smb2.supports_multicredit) {
789                 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
790                 credit_charge = MAX(credit_charge, 1);
791         }
792
793         cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
794         credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
795         out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
796         out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
797
798         SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
799
800         if (sconn->smb2.max_credits < credit_charge) {
801                 smbd_server_connection_terminate(sconn,
802                         "client error: credit charge > max credits\n");
803                 return;
804         }
805
806         if (out_flags & SMB2_HDR_FLAG_ASYNC) {
807                 /*
808                  * In case we already send an async interim
809                  * response, we should not grant
810                  * credits on the final response.
811                  */
812                 credits_granted = 0;
813         } else if (credits_requested > 0) {
814                 uint16_t additional_max = 0;
815                 uint16_t additional_credits = credits_requested - 1;
816
817                 switch (cmd) {
818                 case SMB2_OP_NEGPROT:
819                         break;
820                 case SMB2_OP_SESSSETUP:
821                         /*
822                          * Windows 2012 RC1 starts to grant
823                          * additional credits
824                          * with a successful session setup
825                          */
826                         if (NT_STATUS_IS_OK(out_status)) {
827                                 additional_max = 32;
828                         }
829                         break;
830                 default:
831                         /*
832                          * We match windows and only grant additional credits
833                          * in chunks of 32.
834                          */
835                         additional_max = 32;
836                         break;
837                 }
838
839                 additional_credits = MIN(additional_credits, additional_max);
840
841                 credits_granted = credit_charge + additional_credits;
842         } else if (sconn->smb2.credits_granted == 0) {
843                 /*
844                  * Make sure the client has always at least one credit
845                  */
846                 credits_granted = 1;
847         }
848
849         /*
850          * sequence numbers should not wrap
851          *
852          * 1. calculate the possible credits until
853          *    the sequence numbers start to wrap on 64-bit.
854          *
855          * 2. UINT64_MAX is used for Break Notifications.
856          *
857          * 2. truncate the possible credits to the maximum
858          *    credits we want to grant to the client in total.
859          *
860          * 3. remove the range we'll already granted to the client
861          *    this makes sure the client consumes the lowest sequence
862          *    number, before we can grant additional credits.
863          */
864         credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
865         if (credits_possible > 0) {
866                 /* remove UINT64_MAX */
867                 credits_possible -= 1;
868         }
869         credits_possible = MIN(credits_possible, current_max_credits);
870         credits_possible -= sconn->smb2.seqnum_range;
871
872         credits_granted = MIN(credits_granted, credits_possible);
873
874         SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
875         sconn->smb2.credits_granted += credits_granted;
876         sconn->smb2.seqnum_range += credits_granted;
877
878         DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
879                 "granted %u, current possible/max %u/%u, "
880                 "total granted/max/low/range %u/%u/%llu/%u\n",
881                 (unsigned int)credits_requested,
882                 (unsigned int)credit_charge,
883                 (unsigned int)credits_granted,
884                 (unsigned int)credits_possible,
885                 (unsigned int)current_max_credits,
886                 (unsigned int)sconn->smb2.credits_granted,
887                 (unsigned int)sconn->smb2.max_credits,
888                 (unsigned long long)sconn->smb2.seqnum_low,
889                 (unsigned int)sconn->smb2.seqnum_range));
890 }
891
892 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
893                                 struct smbd_smb2_request *outreq)
894 {
895         int count, idx;
896         uint16_t total_credits = 0;
897
898         count = outreq->out.vector_count;
899
900         for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
901                 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
902                 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
903                 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
904
905                 smb2_set_operation_credit(outreq->sconn, inhdr_v, outhdr_v);
906
907                 /* To match Windows, count up what we
908                    just granted. */
909                 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
910                 /* Set to zero in all but the last reply. */
911                 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
912                         SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
913                 } else {
914                         SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
915                 }
916         }
917 }
918
919 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
920 {
921         struct iovec *vector;
922         int count;
923         int idx;
924
925         count = req->in.vector_count;
926         vector = talloc_zero_array(req, struct iovec, count);
927         if (vector == NULL) {
928                 return NT_STATUS_NO_MEMORY;
929         }
930
931         vector[0].iov_base      = req->out.nbt_hdr;
932         vector[0].iov_len       = 4;
933         SIVAL(req->out.nbt_hdr, 0, 0);
934
935         for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
936                 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
937                 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
938                 uint8_t *outhdr = NULL;
939                 uint8_t *outbody = NULL;
940                 uint32_t next_command_ofs = 0;
941                 struct iovec *current = &vector[idx];
942
943                 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
944                         /* we have a next command -
945                          * setup for the error case. */
946                         next_command_ofs = SMB2_HDR_BODY + 9;
947                 }
948
949                 if (idx == 1) {
950                         outhdr = req->out._hdr;
951                 } else {
952                         outhdr = talloc_zero_array(vector, uint8_t,
953                                                    OUTVEC_ALLOC_SIZE);
954                         if (outhdr == NULL) {
955                                 return NT_STATUS_NO_MEMORY;
956                         }
957                 }
958
959                 outbody = outhdr + SMB2_HDR_BODY;
960
961                 /*
962                  * SMBD_SMB2_TF_IOV_OFS might be used later
963                  */
964                 current[SMBD_SMB2_TF_IOV_OFS].iov_base   = NULL;
965                 current[SMBD_SMB2_TF_IOV_OFS].iov_len    = 0;
966
967                 current[SMBD_SMB2_HDR_IOV_OFS].iov_base  = (void *)outhdr;
968                 current[SMBD_SMB2_HDR_IOV_OFS].iov_len   = SMB2_HDR_BODY;
969
970                 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
971                 current[SMBD_SMB2_BODY_IOV_OFS].iov_len  = 8;
972
973                 current[SMBD_SMB2_DYN_IOV_OFS].iov_base  = NULL;
974                 current[SMBD_SMB2_DYN_IOV_OFS].iov_len   = 0;
975
976                 /* setup the SMB2 header */
977                 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID,     SMB2_MAGIC);
978                 SSVAL(outhdr, SMB2_HDR_LENGTH,          SMB2_HDR_BODY);
979                 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
980                       SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
981                 SIVAL(outhdr, SMB2_HDR_STATUS,
982                       NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
983                 SSVAL(outhdr, SMB2_HDR_OPCODE,
984                       SVAL(inhdr, SMB2_HDR_OPCODE));
985                 SIVAL(outhdr, SMB2_HDR_FLAGS,
986                       IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
987                 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND,    next_command_ofs);
988                 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
989                       BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
990                 SIVAL(outhdr, SMB2_HDR_PID,
991                       IVAL(inhdr, SMB2_HDR_PID));
992                 SIVAL(outhdr, SMB2_HDR_TID,
993                       IVAL(inhdr, SMB2_HDR_TID));
994                 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
995                       BVAL(inhdr, SMB2_HDR_SESSION_ID));
996                 memcpy(outhdr + SMB2_HDR_SIGNATURE,
997                        inhdr + SMB2_HDR_SIGNATURE, 16);
998
999                 /* setup error body header */
1000                 SSVAL(outbody, 0x00, 0x08 + 1);
1001                 SSVAL(outbody, 0x02, 0);
1002                 SIVAL(outbody, 0x04, 0);
1003         }
1004
1005         req->out.vector = vector;
1006         req->out.vector_count = count;
1007
1008         /* setup the length of the NBT packet */
1009         smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1010
1011         DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
1012
1013         return NT_STATUS_OK;
1014 }
1015
1016 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
1017                                          const char *reason,
1018                                          const char *location)
1019 {
1020         DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1021                   reason, location));
1022         exit_server_cleanly(reason);
1023 }
1024
1025 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1026                         struct iovec *outvec,
1027                         const struct iovec *srcvec)
1028 {
1029         const uint8_t *srctf;
1030         size_t srctf_len;
1031         const uint8_t *srchdr;
1032         size_t srchdr_len;
1033         const uint8_t *srcbody;
1034         size_t srcbody_len;
1035         const uint8_t *expected_srcbody;
1036         const uint8_t *srcdyn;
1037         size_t srcdyn_len;
1038         const uint8_t *expected_srcdyn;
1039         uint8_t *dsttf;
1040         uint8_t *dsthdr;
1041         uint8_t *dstbody;
1042         uint8_t *dstdyn;
1043
1044         srctf  = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1045         srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1046         srchdr  = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1047         srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1048         srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1049         srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1050         expected_srcbody = srchdr + SMB2_HDR_BODY;
1051         srcdyn  = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1052         srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1053         expected_srcdyn = srcbody + 8;
1054
1055         if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1056                 return false;
1057         }
1058
1059         if (srchdr_len != SMB2_HDR_BODY) {
1060                 return false;
1061         }
1062
1063         if (srctf_len == SMB2_TF_HDR_SIZE) {
1064                 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1065                 if (dsttf == NULL) {
1066                         return false;
1067                 }
1068         } else {
1069                 dsttf = NULL;
1070         }
1071         outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1072         outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1073
1074         /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1075          * be allocated with size OUTVEC_ALLOC_SIZE. */
1076
1077         dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1078         if (dsthdr == NULL) {
1079                 return false;
1080         }
1081         outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1082         outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1083
1084         /*
1085          * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1086          * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1087          * then duplicate this. Else use talloc_memdup().
1088          */
1089
1090         if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1091                 dstbody = dsthdr + SMB2_HDR_BODY;
1092         } else {
1093                 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1094                 if (dstbody == NULL) {
1095                         return false;
1096                 }
1097         }
1098         outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1099         outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1100
1101         /*
1102          * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1103          * pointing to
1104          * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1105          * then duplicate this. Else use talloc_memdup().
1106          */
1107
1108         if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1109                 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1110         } else if (srcdyn == NULL) {
1111                 dstdyn = NULL;
1112         } else {
1113                 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1114                 if (dstdyn == NULL) {
1115                         return false;
1116                 }
1117         }
1118         outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1119         outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1120
1121         return true;
1122 }
1123
1124 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1125 {
1126         struct smbd_smb2_request *newreq = NULL;
1127         struct iovec *outvec = NULL;
1128         int count = req->out.vector_count;
1129         int i;
1130
1131         newreq = smbd_smb2_request_allocate(req->sconn);
1132         if (!newreq) {
1133                 return NULL;
1134         }
1135
1136         newreq->sconn = req->sconn;
1137         newreq->session = req->session;
1138         newreq->do_encryption = req->do_encryption;
1139         newreq->do_signing = req->do_signing;
1140         newreq->current_idx = req->current_idx;
1141
1142         outvec = talloc_zero_array(newreq, struct iovec, count);
1143         if (!outvec) {
1144                 TALLOC_FREE(newreq);
1145                 return NULL;
1146         }
1147         newreq->out.vector = outvec;
1148         newreq->out.vector_count = count;
1149
1150         /* Setup the outvec's identically to req. */
1151         outvec[0].iov_base = newreq->out.nbt_hdr;
1152         outvec[0].iov_len = 4;
1153         memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1154
1155         /* Setup the vectors identically to the ones in req. */
1156         for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1157                 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1158                         break;
1159                 }
1160         }
1161
1162         if (i < count) {
1163                 /* Alloc failed. */
1164                 TALLOC_FREE(newreq);
1165                 return NULL;
1166         }
1167
1168         smb2_setup_nbt_length(newreq->out.vector,
1169                 newreq->out.vector_count);
1170
1171         return newreq;
1172 }
1173
1174 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1175 {
1176         struct smbd_server_connection *sconn = req->sconn;
1177         struct smbXsrv_connection *conn = req->sconn->conn;
1178         int first_idx = 1;
1179         struct iovec *firsttf = NULL;
1180         struct iovec *outhdr_v = NULL;
1181         uint8_t *outhdr = NULL;
1182         struct smbd_smb2_request *nreq = NULL;
1183         NTSTATUS status;
1184
1185         /* Create a new smb2 request we'll use
1186            for the interim return. */
1187         nreq = dup_smb2_req(req);
1188         if (!nreq) {
1189                 return NT_STATUS_NO_MEMORY;
1190         }
1191
1192         /* Lose the last X out vectors. They're the
1193            ones we'll be using for the async reply. */
1194         nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1195
1196         smb2_setup_nbt_length(nreq->out.vector,
1197                 nreq->out.vector_count);
1198
1199         /* Step back to the previous reply. */
1200         nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1201         firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1202         outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1203         outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1204         /* And end the chain. */
1205         SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1206
1207         /* Calculate outgoing credits */
1208         smb2_calculate_credits(req, nreq);
1209
1210         if (DEBUGLEVEL >= 10) {
1211                 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1212                         (unsigned int)nreq->current_idx );
1213                 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1214                         (unsigned int)nreq->out.vector_count );
1215                 print_req_vectors(nreq);
1216         }
1217
1218         /*
1219          * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1220          * we need to sign/encrypt here with the last/first key we remembered
1221          */
1222         if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1223                 status = smb2_signing_encrypt_pdu(req->first_key,
1224                                         conn->protocol,
1225                                         firsttf,
1226                                         nreq->out.vector_count - first_idx);
1227                 if (!NT_STATUS_IS_OK(status)) {
1228                         return status;
1229                 }
1230         } else if (req->last_key.length > 0) {
1231                 status = smb2_signing_sign_pdu(req->last_key,
1232                                                conn->protocol,
1233                                                outhdr_v,
1234                                                SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1235                 if (!NT_STATUS_IS_OK(status)) {
1236                         return status;
1237                 }
1238         }
1239
1240         nreq->queue_entry.mem_ctx = nreq;
1241         nreq->queue_entry.vector = nreq->out.vector;
1242         nreq->queue_entry.count = nreq->out.vector_count;
1243         DLIST_ADD_END(nreq->sconn->smb2.send_queue, &nreq->queue_entry, NULL);
1244         nreq->sconn->smb2.send_queue_len++;
1245
1246         status = smbd_smb2_io_handler(sconn, TEVENT_FD_WRITE);
1247         if (!NT_STATUS_IS_OK(status)) {
1248                 return status;
1249         }
1250
1251         return NT_STATUS_OK;
1252 }
1253
1254 struct smbd_smb2_request_pending_state {
1255         struct smbd_server_connection *sconn;
1256         struct smbd_smb2_send_queue queue_entry;
1257         uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1258         struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1259 };
1260
1261 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1262                                             struct tevent_timer *te,
1263                                             struct timeval current_time,
1264                                             void *private_data);
1265
1266 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1267                                          struct tevent_req *subreq,
1268                                          uint32_t defer_time)
1269 {
1270         NTSTATUS status;
1271         struct timeval defer_endtime;
1272         uint8_t *outhdr = NULL;
1273         uint32_t flags;
1274
1275         if (!tevent_req_is_in_progress(subreq)) {
1276                 /*
1277                  * This is a performance optimization,
1278                  * it avoids one tevent_loop iteration,
1279                  * which means we avoid one
1280                  * talloc_stackframe_pool/talloc_free pair.
1281                  */
1282                 tevent_req_notify_callback(subreq);
1283                 return NT_STATUS_OK;
1284         }
1285
1286         req->subreq = subreq;
1287         subreq = NULL;
1288
1289         if (req->async_te) {
1290                 /* We're already async. */
1291                 return NT_STATUS_OK;
1292         }
1293
1294         outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1295         flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1296         if (flags & SMB2_HDR_FLAG_ASYNC) {
1297                 /* We're already async. */
1298                 return NT_STATUS_OK;
1299         }
1300
1301         if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1302                 /*
1303                  * We're trying to go async in a compound
1304                  * request chain.
1305                  * This is only allowed for opens that
1306                  * cause an oplock break, otherwise it
1307                  * is not allowed. See [MS-SMB2].pdf
1308                  * note <194> on Section 3.3.5.2.7.
1309                  */
1310                 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1311
1312                 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1313                         /*
1314                          * Cancel the outstanding request.
1315                          */
1316                         bool ok = tevent_req_cancel(req->subreq);
1317                         if (ok) {
1318                                 return NT_STATUS_OK;
1319                         }
1320                         TALLOC_FREE(req->subreq);
1321                         return smbd_smb2_request_error(req,
1322                                 NT_STATUS_INTERNAL_ERROR);
1323                 }
1324         }
1325
1326         if (DEBUGLEVEL >= 10) {
1327                 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1328                         (unsigned int)req->current_idx );
1329                 print_req_vectors(req);
1330         }
1331
1332         if (req->current_idx > 1) {
1333                 /*
1334                  * We're going async in a compound
1335                  * chain after the first request has
1336                  * already been processed. Send an
1337                  * interim response containing the
1338                  * set of replies already generated.
1339                  */
1340                 int idx = req->current_idx;
1341
1342                 status = smb2_send_async_interim_response(req);
1343                 if (!NT_STATUS_IS_OK(status)) {
1344                         return status;
1345                 }
1346                 data_blob_clear_free(&req->first_key);
1347
1348                 req->current_idx = 1;
1349
1350                 /*
1351                  * Re-arrange the in.vectors to remove what
1352                  * we just sent.
1353                  */
1354                 memmove(&req->in.vector[1],
1355                         &req->in.vector[idx],
1356                         sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1357                 req->in.vector_count = 1 + (req->in.vector_count - idx);
1358
1359                 /* Re-arrange the out.vectors to match. */
1360                 memmove(&req->out.vector[1],
1361                         &req->out.vector[idx],
1362                         sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1363                 req->out.vector_count = 1 + (req->out.vector_count - idx);
1364
1365                 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1366                         /*
1367                          * We only have one remaining request as
1368                          * we've processed everything else.
1369                          * This is no longer a compound request.
1370                          */
1371                         req->compound_related = false;
1372                         outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1373                         flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1374                         SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1375                 }
1376         }
1377         data_blob_clear_free(&req->last_key);
1378
1379         defer_endtime = timeval_current_ofs_usec(defer_time);
1380         req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1381                                          req, defer_endtime,
1382                                          smbd_smb2_request_pending_timer,
1383                                          req);
1384         if (req->async_te == NULL) {
1385                 return NT_STATUS_NO_MEMORY;
1386         }
1387
1388         return NT_STATUS_OK;
1389 }
1390
1391 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1392                                             struct tevent_timer *te,
1393                                             struct timeval current_time,
1394                                             void *private_data)
1395 {
1396         struct smbd_smb2_request *req =
1397                 talloc_get_type_abort(private_data,
1398                 struct smbd_smb2_request);
1399         struct smbd_server_connection *sconn = req->sconn;
1400         struct smbd_smb2_request_pending_state *state = NULL;
1401         uint8_t *outhdr = NULL;
1402         const uint8_t *inhdr = NULL;
1403         uint8_t *tf = NULL;
1404         size_t tf_len = 0;
1405         uint8_t *hdr = NULL;
1406         uint8_t *body = NULL;
1407         uint8_t *dyn = NULL;
1408         uint32_t flags = 0;
1409         uint64_t session_id = 0;
1410         uint64_t message_id = 0;
1411         uint64_t nonce_high = 0;
1412         uint64_t nonce_low = 0;
1413         uint64_t async_id = 0;
1414         NTSTATUS status;
1415
1416         TALLOC_FREE(req->async_te);
1417
1418         /* Ensure our final reply matches the interim one. */
1419         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1420         outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1421         flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1422         message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1423         session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1424
1425         async_id = message_id; /* keep it simple for now... */
1426
1427         SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1428         SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1429
1430         DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1431                 "going async\n",
1432                 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1433                 (unsigned long long)async_id ));
1434
1435         /*
1436          * What we send is identical to a smbd_smb2_request_error
1437          * packet with an error status of STATUS_PENDING. Make use
1438          * of this fact sometime when refactoring. JRA.
1439          */
1440
1441         state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1442         if (state == NULL) {
1443                 smbd_server_connection_terminate(req->sconn,
1444                                                  nt_errstr(NT_STATUS_NO_MEMORY));
1445                 return;
1446         }
1447         state->sconn = req->sconn;
1448
1449         tf = state->buf + NBT_HDR_SIZE;
1450         tf_len = SMB2_TF_HDR_SIZE;
1451
1452         hdr = tf + SMB2_TF_HDR_SIZE;
1453         body = hdr + SMB2_HDR_BODY;
1454         dyn = body + 8;
1455
1456         if (req->do_encryption) {
1457                 struct smbXsrv_session *x = req->session;
1458
1459                 nonce_high = x->nonce_high;
1460                 nonce_low = x->nonce_low;
1461
1462                 x->nonce_low += 1;
1463                 if (x->nonce_low == 0) {
1464                         x->nonce_low += 1;
1465                         x->nonce_high += 1;
1466                 }
1467         }
1468
1469         SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1470         SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1471         SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1472         SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1473
1474         SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1475         SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1476         SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1477         SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1478         SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1479
1480         SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1481         SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1482         SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1483         SBVAL(hdr, SMB2_HDR_PID, async_id);
1484         SBVAL(hdr, SMB2_HDR_SESSION_ID,
1485                 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1486         memcpy(hdr+SMB2_HDR_SIGNATURE,
1487                outhdr+SMB2_HDR_SIGNATURE, 16);
1488
1489         SSVAL(body, 0x00, 0x08 + 1);
1490
1491         SCVAL(body, 0x02, 0);
1492         SCVAL(body, 0x03, 0);
1493         SIVAL(body, 0x04, 0);
1494         /* Match W2K8R2... */
1495         SCVAL(dyn,  0x00, 0x21);
1496
1497         state->vector[0].iov_base = (void *)state->buf;
1498         state->vector[0].iov_len = NBT_HDR_SIZE;
1499
1500         if (req->do_encryption) {
1501                 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base   = tf;
1502                 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len    = tf_len;
1503         } else {
1504                 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base   = NULL;
1505                 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len    = 0;
1506         }
1507
1508         state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base  = hdr;
1509         state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len   = SMB2_HDR_BODY;
1510
1511         state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1512         state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len  = 8;
1513
1514         state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base  = dyn;
1515         state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len   = 1;
1516
1517         smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1518
1519         /* Ensure we correctly go through crediting. Grant
1520            the credits now, and zero credits on the final
1521            response. */
1522         smb2_set_operation_credit(req->sconn,
1523                         SMBD_SMB2_IN_HDR_IOV(req),
1524                         &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1525
1526         SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1527
1528         if (DEBUGLVL(10)) {
1529                 int i;
1530
1531                 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1532                         dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1533                                 (unsigned int)i,
1534                                 (unsigned int)ARRAY_SIZE(state->vector),
1535                                 (unsigned int)state->vector[i].iov_len);
1536                 }
1537         }
1538
1539         if (req->do_encryption) {
1540                 struct smbXsrv_session *x = req->session;
1541                 struct smbXsrv_connection *conn = x->connection;
1542                 DATA_BLOB encryption_key = x->global->encryption_key;
1543
1544                 status = smb2_signing_encrypt_pdu(encryption_key,
1545                                         conn->protocol,
1546                                         &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1547                                         SMBD_SMB2_NUM_IOV_PER_REQ);
1548                 if (!NT_STATUS_IS_OK(status)) {
1549                         smbd_server_connection_terminate(req->sconn,
1550                                                 nt_errstr(status));
1551                         return;
1552                 }
1553         } else if (req->do_signing) {
1554                 struct smbXsrv_session *x = req->session;
1555                 struct smbXsrv_connection *conn = x->connection;
1556                 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1557
1558                 status = smb2_signing_sign_pdu(signing_key,
1559                                         conn->protocol,
1560                                         &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1561                                         SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1562                 if (!NT_STATUS_IS_OK(status)) {
1563                         smbd_server_connection_terminate(req->sconn,
1564                                                 nt_errstr(status));
1565                         return;
1566                 }
1567         }
1568
1569         state->queue_entry.mem_ctx = state;
1570         state->queue_entry.vector = state->vector;
1571         state->queue_entry.count = ARRAY_SIZE(state->vector);
1572         DLIST_ADD_END(sconn->smb2.send_queue, &state->queue_entry, NULL);
1573         sconn->smb2.send_queue_len++;
1574
1575         status = smbd_smb2_io_handler(sconn, TEVENT_FD_WRITE);
1576         if (!NT_STATUS_IS_OK(status)) {
1577                 smbd_server_connection_terminate(sconn,
1578                                                  nt_errstr(status));
1579                 return;
1580         }
1581 }
1582
1583 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1584 {
1585         struct smbd_server_connection *sconn = req->sconn;
1586         struct smbd_smb2_request *cur;
1587         const uint8_t *inhdr;
1588         uint32_t flags;
1589         uint64_t search_message_id;
1590         uint64_t search_async_id;
1591         uint64_t found_id;
1592
1593         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1594
1595         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1596         search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1597         search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1598
1599         /*
1600          * we don't need the request anymore
1601          * cancel requests never have a response
1602          */
1603         DLIST_REMOVE(req->sconn->smb2.requests, req);
1604         TALLOC_FREE(req);
1605
1606         for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1607                 const uint8_t *outhdr;
1608                 uint64_t message_id;
1609                 uint64_t async_id;
1610
1611                 if (cur->compound_related) {
1612                         /*
1613                          * Never cancel anything in a compound request.
1614                          * Way too hard to deal with the result.
1615                          */
1616                         continue;
1617                 }
1618
1619                 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1620
1621                 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1622                 async_id = BVAL(outhdr, SMB2_HDR_PID);
1623
1624                 if (flags & SMB2_HDR_FLAG_ASYNC) {
1625                         if (search_async_id == async_id) {
1626                                 found_id = async_id;
1627                                 break;
1628                         }
1629                 } else {
1630                         if (search_message_id == message_id) {
1631                                 found_id = message_id;
1632                                 break;
1633                         }
1634                 }
1635         }
1636
1637         if (cur && cur->subreq) {
1638                 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1639                 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1640                         "cancel opcode[%s] mid %llu\n",
1641                         smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1642                         (unsigned long long)found_id ));
1643                 tevent_req_cancel(cur->subreq);
1644         }
1645
1646         return NT_STATUS_OK;
1647 }
1648
1649 /*************************************************************
1650  Ensure an incoming tid is a valid one for us to access.
1651  Change to the associated uid credentials and chdir to the
1652  valid tid directory.
1653 *************************************************************/
1654
1655 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1656 {
1657         const uint8_t *inhdr;
1658         uint32_t in_flags;
1659         uint32_t in_tid;
1660         struct smbXsrv_tcon *tcon;
1661         NTSTATUS status;
1662         NTTIME now = timeval_to_nttime(&req->request_time);
1663
1664         req->tcon = NULL;
1665
1666         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1667
1668         in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1669         in_tid = IVAL(inhdr, SMB2_HDR_TID);
1670
1671         if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1672                 in_tid = req->last_tid;
1673         }
1674
1675         req->last_tid = 0;
1676
1677         status = smb2srv_tcon_lookup(req->session,
1678                                      in_tid, now, &tcon);
1679         if (!NT_STATUS_IS_OK(status)) {
1680                 return status;
1681         }
1682
1683         if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1684                 return NT_STATUS_ACCESS_DENIED;
1685         }
1686
1687         /* should we pass FLAG_CASELESS_PATHNAMES here? */
1688         if (!set_current_service(tcon->compat, 0, true)) {
1689                 return NT_STATUS_ACCESS_DENIED;
1690         }
1691
1692         req->tcon = tcon;
1693         req->last_tid = in_tid;
1694
1695         return NT_STATUS_OK;
1696 }
1697
1698 /*************************************************************
1699  Ensure an incoming session_id is a valid one for us to access.
1700 *************************************************************/
1701
1702 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1703 {
1704         const uint8_t *inhdr;
1705         uint32_t in_flags;
1706         uint16_t in_opcode;
1707         uint64_t in_session_id;
1708         struct smbXsrv_session *session = NULL;
1709         struct auth_session_info *session_info;
1710         NTSTATUS status;
1711         NTTIME now = timeval_to_nttime(&req->request_time);
1712
1713         req->session = NULL;
1714         req->tcon = NULL;
1715
1716         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1717
1718         in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1719         in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1720         in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1721
1722         if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1723                 in_session_id = req->last_session_id;
1724         }
1725
1726         req->last_session_id = 0;
1727
1728         /* lookup an existing session */
1729         status = smb2srv_session_lookup(req->sconn->conn,
1730                                         in_session_id, now,
1731                                         &session);
1732         if (session) {
1733                 req->session = session;
1734                 req->last_session_id = in_session_id;
1735         }
1736         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1737                 switch (in_opcode) {
1738                 case SMB2_OP_SESSSETUP:
1739                         status = NT_STATUS_OK;
1740                         break;
1741                 default:
1742                         break;
1743                 }
1744         }
1745         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1746                 switch (in_opcode) {
1747                 case SMB2_OP_TCON:
1748                 case SMB2_OP_CREATE:
1749                 case SMB2_OP_GETINFO:
1750                 case SMB2_OP_SETINFO:
1751                         return NT_STATUS_INVALID_HANDLE;
1752                 default:
1753                         /*
1754                          * Notice the check for
1755                          * (session_info == NULL)
1756                          * below.
1757                          */
1758                         status = NT_STATUS_OK;
1759                         break;
1760                 }
1761         }
1762         if (!NT_STATUS_IS_OK(status)) {
1763                 return status;
1764         }
1765
1766         session_info = session->global->auth_session_info;
1767         if (session_info == NULL) {
1768                 return NT_STATUS_INVALID_HANDLE;
1769         }
1770
1771         if (in_session_id != req->sconn->conn->last_session_id) {
1772                 req->sconn->conn->last_session_id = in_session_id;
1773                 set_current_user_info(session_info->unix_info->sanitized_username,
1774                                       session_info->unix_info->unix_name,
1775                                       session_info->info->domain_name);
1776         }
1777
1778         return NT_STATUS_OK;
1779 }
1780
1781 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1782                                                 uint32_t data_length)
1783 {
1784         uint16_t needed_charge;
1785         uint16_t credit_charge = 1;
1786         const uint8_t *inhdr;
1787
1788         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1789
1790         if (req->sconn->smb2.supports_multicredit) {
1791                 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1792                 credit_charge = MAX(credit_charge, 1);
1793         }
1794
1795         needed_charge = (data_length - 1)/ 65536 + 1;
1796
1797         DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1798                    (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1799                    credit_charge, needed_charge));
1800
1801         if (needed_charge > credit_charge) {
1802                 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1803                           credit_charge, needed_charge));
1804                 return NT_STATUS_INVALID_PARAMETER;
1805         }
1806
1807         return NT_STATUS_OK;
1808 }
1809
1810 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1811                                         size_t expected_body_size)
1812 {
1813         struct iovec *inhdr_v;
1814         const uint8_t *inhdr;
1815         uint16_t opcode;
1816         const uint8_t *inbody;
1817         size_t body_size;
1818         size_t min_dyn_size = expected_body_size & 0x00000001;
1819         int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1820
1821         /*
1822          * The following should be checked already.
1823          */
1824         if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1825                 return NT_STATUS_INTERNAL_ERROR;
1826         }
1827         if (req->current_idx > max_idx) {
1828                 return NT_STATUS_INTERNAL_ERROR;
1829         }
1830
1831         inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1832         if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1833                 return NT_STATUS_INTERNAL_ERROR;
1834         }
1835         if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1836                 return NT_STATUS_INTERNAL_ERROR;
1837         }
1838
1839         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1840         opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1841
1842         switch (opcode) {
1843         case SMB2_OP_IOCTL:
1844         case SMB2_OP_GETINFO:
1845                 min_dyn_size = 0;
1846                 break;
1847         }
1848
1849         /*
1850          * Now check the expected body size,
1851          * where the last byte might be in the
1852          * dynamic section..
1853          */
1854         if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1855                 return NT_STATUS_INVALID_PARAMETER;
1856         }
1857         if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1858                 return NT_STATUS_INVALID_PARAMETER;
1859         }
1860
1861         inbody = SMBD_SMB2_IN_BODY_PTR(req);
1862
1863         body_size = SVAL(inbody, 0x00);
1864         if (body_size != expected_body_size) {
1865                 return NT_STATUS_INVALID_PARAMETER;
1866         }
1867
1868         return NT_STATUS_OK;
1869 }
1870
1871 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1872 {
1873         struct smbXsrv_connection *conn = req->sconn->conn;
1874         const struct smbd_smb2_dispatch_table *call = NULL;
1875         const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1876         const uint8_t *inhdr;
1877         uint16_t opcode;
1878         uint32_t flags;
1879         uint64_t mid;
1880         NTSTATUS status;
1881         NTSTATUS session_status;
1882         uint32_t allowed_flags;
1883         NTSTATUS return_value;
1884         struct smbXsrv_session *x = NULL;
1885         bool signing_required = false;
1886         bool encryption_required = false;
1887
1888         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1889
1890         /* TODO: verify more things */
1891
1892         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1893         opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1894         mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1895         DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1896                 smb2_opcode_name(opcode),
1897                 (unsigned long long)mid));
1898
1899         if (conn->protocol >= PROTOCOL_SMB2_02) {
1900                 /*
1901                  * once the protocol is negotiated
1902                  * SMB2_OP_NEGPROT is not allowed anymore
1903                  */
1904                 if (opcode == SMB2_OP_NEGPROT) {
1905                         /* drop the connection */
1906                         return NT_STATUS_INVALID_PARAMETER;
1907                 }
1908         } else {
1909                 /*
1910                  * if the protocol is not negotiated yet
1911                  * only SMB2_OP_NEGPROT is allowed.
1912                  */
1913                 if (opcode != SMB2_OP_NEGPROT) {
1914                         /* drop the connection */
1915                         return NT_STATUS_INVALID_PARAMETER;
1916                 }
1917         }
1918
1919         /*
1920          * Check if the client provided a valid session id,
1921          * if so smbd_smb2_request_check_session() calls
1922          * set_current_user_info().
1923          *
1924          * As some command don't require a valid session id
1925          * we defer the check of the session_status
1926          */
1927         session_status = smbd_smb2_request_check_session(req);
1928         x = req->session;
1929         if (x != NULL) {
1930                 signing_required = x->global->signing_required;
1931                 encryption_required = x->global->encryption_required;
1932
1933                 if (opcode == SMB2_OP_SESSSETUP &&
1934                     x->global->channels[0].signing_key.length) {
1935                         signing_required = true;
1936                 }
1937         }
1938
1939         req->do_signing = false;
1940         req->do_encryption = false;
1941         if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1942                 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1943                 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
1944
1945                 if (x != NULL && x->global->session_wire_id != tf_session_id) {
1946                         DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1947                                  "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1948                                  (unsigned long long)x->global->session_wire_id,
1949                                  (unsigned long long)tf_session_id));
1950                         /*
1951                          * TODO: windows allows this...
1952                          * should we drop the connection?
1953                          *
1954                          * For now we just return ACCESS_DENIED
1955                          * (Windows clients never trigger this)
1956                          * and wait for an update of [MS-SMB2].
1957                          */
1958                         return smbd_smb2_request_error(req,
1959                                         NT_STATUS_ACCESS_DENIED);
1960                 }
1961
1962                 req->do_encryption = true;
1963         }
1964
1965         if (encryption_required && !req->do_encryption) {
1966                 return smbd_smb2_request_error(req,
1967                                 NT_STATUS_ACCESS_DENIED);
1968         }
1969
1970         call = smbd_smb2_call(opcode);
1971         if (call == NULL) {
1972                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1973         }
1974
1975         allowed_flags = SMB2_HDR_FLAG_CHAINED |
1976                         SMB2_HDR_FLAG_SIGNED |
1977                         SMB2_HDR_FLAG_DFS;
1978         if (opcode == SMB2_OP_CANCEL) {
1979                 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1980         }
1981         if ((flags & ~allowed_flags) != 0) {
1982                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1983         }
1984
1985         if (flags & SMB2_HDR_FLAG_CHAINED) {
1986                 /*
1987                  * This check is mostly for giving the correct error code
1988                  * for compounded requests.
1989                  */
1990                 if (!NT_STATUS_IS_OK(session_status)) {
1991                         return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1992                 }
1993         } else {
1994                 req->compat_chain_fsp = NULL;
1995         }
1996
1997         if (req->do_encryption) {
1998                 signing_required = false;
1999         } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2000                 DATA_BLOB signing_key;
2001
2002                 if (x == NULL) {
2003                         return smbd_smb2_request_error(
2004                                 req, NT_STATUS_USER_SESSION_DELETED);
2005                 }
2006
2007                 signing_key = x->global->channels[0].signing_key;
2008
2009                 /*
2010                  * If we have a signing key, we should
2011                  * sign the response
2012                  */
2013                 if (signing_key.length > 0) {
2014                         req->do_signing = true;
2015                 }
2016
2017                 status = smb2_signing_check_pdu(signing_key,
2018                                                 conn->protocol,
2019                                                 SMBD_SMB2_IN_HDR_IOV(req),
2020                                                 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2021                 if (!NT_STATUS_IS_OK(status)) {
2022                         return smbd_smb2_request_error(req, status);
2023                 }
2024
2025                 /*
2026                  * Now that we know the request was correctly signed
2027                  * we have to sign the response too.
2028                  */
2029                 req->do_signing = true;
2030
2031                 if (!NT_STATUS_IS_OK(session_status)) {
2032                         return smbd_smb2_request_error(req, session_status);
2033                 }
2034         } else if (opcode == SMB2_OP_CANCEL) {
2035                 /* Cancel requests are allowed to skip the signing */
2036         } else if (signing_required) {
2037                 /*
2038                  * If signing is required we try to sign
2039                  * a possible error response
2040                  */
2041                 req->do_signing = true;
2042                 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2043         }
2044
2045         if (flags & SMB2_HDR_FLAG_CHAINED) {
2046                 req->compound_related = true;
2047         }
2048
2049         if (call->need_session) {
2050                 if (!NT_STATUS_IS_OK(session_status)) {
2051                         return smbd_smb2_request_error(req, session_status);
2052                 }
2053         }
2054
2055         if (call->need_tcon) {
2056                 SMB_ASSERT(call->need_session);
2057
2058                 /*
2059                  * This call needs to be run as user.
2060                  *
2061                  * smbd_smb2_request_check_tcon()
2062                  * calls change_to_user() on success.
2063                  */
2064                 status = smbd_smb2_request_check_tcon(req);
2065                 if (!NT_STATUS_IS_OK(status)) {
2066                         return smbd_smb2_request_error(req, status);
2067                 }
2068                 if (req->tcon->global->encryption_required) {
2069                         encryption_required = true;
2070                 }
2071                 if (encryption_required && !req->do_encryption) {
2072                         return smbd_smb2_request_error(req,
2073                                 NT_STATUS_ACCESS_DENIED);
2074                 }
2075         }
2076
2077         if (call->fileid_ofs != 0) {
2078                 size_t needed = call->fileid_ofs + 16;
2079                 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2080                 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2081                 uint64_t file_id_persistent;
2082                 uint64_t file_id_volatile;
2083                 struct files_struct *fsp;
2084
2085                 SMB_ASSERT(call->need_tcon);
2086
2087                 if (needed > body_size) {
2088                         return smbd_smb2_request_error(req,
2089                                         NT_STATUS_INVALID_PARAMETER);
2090                 }
2091
2092                 file_id_persistent      = BVAL(body, call->fileid_ofs + 0);
2093                 file_id_volatile        = BVAL(body, call->fileid_ofs + 8);
2094
2095                 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2096                 if (fsp == NULL) {
2097                         if (!call->allow_invalid_fileid) {
2098                                 return smbd_smb2_request_error(req,
2099                                                 NT_STATUS_FILE_CLOSED);
2100                         }
2101
2102                         if (file_id_persistent != UINT64_MAX) {
2103                                 return smbd_smb2_request_error(req,
2104                                                 NT_STATUS_FILE_CLOSED);
2105                         }
2106                         if (file_id_volatile != UINT64_MAX) {
2107                                 return smbd_smb2_request_error(req,
2108                                                 NT_STATUS_FILE_CLOSED);
2109                         }
2110                 }
2111         }
2112
2113         if (call->as_root) {
2114                 SMB_ASSERT(call->fileid_ofs == 0);
2115                 /* This call needs to be run as root */
2116                 change_to_root_user();
2117         } else {
2118                 SMB_ASSERT(call->need_tcon);
2119         }
2120
2121         switch (opcode) {
2122         case SMB2_OP_NEGPROT:
2123                 {
2124                         START_PROFILE(smb2_negprot);
2125                         return_value = smbd_smb2_request_process_negprot(req);
2126                         END_PROFILE(smb2_negprot);
2127                 }
2128                 break;
2129
2130         case SMB2_OP_SESSSETUP:
2131                 {
2132                         START_PROFILE(smb2_sesssetup);
2133                         return_value = smbd_smb2_request_process_sesssetup(req);
2134                         END_PROFILE(smb2_sesssetup);
2135                 }
2136                 break;
2137
2138         case SMB2_OP_LOGOFF:
2139                 {
2140                         START_PROFILE(smb2_logoff);
2141                         return_value = smbd_smb2_request_process_logoff(req);
2142                         END_PROFILE(smb2_logoff);
2143                 }
2144                 break;
2145
2146         case SMB2_OP_TCON:
2147                 {
2148                         START_PROFILE(smb2_tcon);
2149                         return_value = smbd_smb2_request_process_tcon(req);
2150                         END_PROFILE(smb2_tcon);
2151                 }
2152                 break;
2153
2154         case SMB2_OP_TDIS:
2155                 {
2156                         START_PROFILE(smb2_tdis);
2157                         return_value = smbd_smb2_request_process_tdis(req);
2158                         END_PROFILE(smb2_tdis);
2159                 }
2160                 break;
2161
2162         case SMB2_OP_CREATE:
2163                 {
2164                         START_PROFILE(smb2_create);
2165                         return_value = smbd_smb2_request_process_create(req);
2166                         END_PROFILE(smb2_create);
2167                 }
2168                 break;
2169
2170         case SMB2_OP_CLOSE:
2171                 {
2172                         START_PROFILE(smb2_close);
2173                         return_value = smbd_smb2_request_process_close(req);
2174                         END_PROFILE(smb2_close);
2175                 }
2176                 break;
2177
2178         case SMB2_OP_FLUSH:
2179                 {
2180                         START_PROFILE(smb2_flush);
2181                         return_value = smbd_smb2_request_process_flush(req);
2182                         END_PROFILE(smb2_flush);
2183                 }
2184                 break;
2185
2186         case SMB2_OP_READ:
2187                 {
2188                         START_PROFILE(smb2_read);
2189                         return_value = smbd_smb2_request_process_read(req);
2190                         END_PROFILE(smb2_read);
2191                 }
2192                 break;
2193
2194         case SMB2_OP_WRITE:
2195                 {
2196                         START_PROFILE(smb2_write);
2197                         return_value = smbd_smb2_request_process_write(req);
2198                         END_PROFILE(smb2_write);
2199                 }
2200                 break;
2201
2202         case SMB2_OP_LOCK:
2203                 {
2204                         START_PROFILE(smb2_lock);
2205                         return_value = smbd_smb2_request_process_lock(req);
2206                         END_PROFILE(smb2_lock);
2207                 }
2208                 break;
2209
2210         case SMB2_OP_IOCTL:
2211                 {
2212                         START_PROFILE(smb2_ioctl);
2213                         return_value = smbd_smb2_request_process_ioctl(req);
2214                         END_PROFILE(smb2_ioctl);
2215                 }
2216                 break;
2217
2218         case SMB2_OP_CANCEL:
2219                 {
2220                         START_PROFILE(smb2_cancel);
2221                         return_value = smbd_smb2_request_process_cancel(req);
2222                         END_PROFILE(smb2_cancel);
2223                 }
2224                 break;
2225
2226         case SMB2_OP_KEEPALIVE:
2227                 {
2228                         START_PROFILE(smb2_keepalive);
2229                         return_value = smbd_smb2_request_process_keepalive(req);
2230                         END_PROFILE(smb2_keepalive);
2231                 }
2232                 break;
2233
2234         case SMB2_OP_FIND:
2235                 {
2236                         START_PROFILE(smb2_find);
2237                         return_value = smbd_smb2_request_process_find(req);
2238                         END_PROFILE(smb2_find);
2239                 }
2240                 break;
2241
2242         case SMB2_OP_NOTIFY:
2243                 {
2244                         START_PROFILE(smb2_notify);
2245                         return_value = smbd_smb2_request_process_notify(req);
2246                         END_PROFILE(smb2_notify);
2247                 }
2248                 break;
2249
2250         case SMB2_OP_GETINFO:
2251                 {
2252                         START_PROFILE(smb2_getinfo);
2253                         return_value = smbd_smb2_request_process_getinfo(req);
2254                         END_PROFILE(smb2_getinfo);
2255                 }
2256                 break;
2257
2258         case SMB2_OP_SETINFO:
2259                 {
2260                         START_PROFILE(smb2_setinfo);
2261                         return_value = smbd_smb2_request_process_setinfo(req);
2262                         END_PROFILE(smb2_setinfo);
2263                 }
2264                 break;
2265
2266         case SMB2_OP_BREAK:
2267                 {
2268                         START_PROFILE(smb2_break);
2269                         return_value = smbd_smb2_request_process_break(req);
2270                         END_PROFILE(smb2_break);
2271                 }
2272                 break;
2273
2274         default:
2275                 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2276                 break;
2277         }
2278         return return_value;
2279 }
2280
2281 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2282 {
2283         struct smbd_server_connection *sconn = req->sconn;
2284         struct smbXsrv_connection *conn = req->sconn->conn;
2285         int first_idx = 1;
2286         struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2287         struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2288         struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2289         NTSTATUS status;
2290
2291         req->subreq = NULL;
2292         TALLOC_FREE(req->async_te);
2293
2294         if (req->do_encryption &&
2295             (firsttf->iov_len == 0) &&
2296             (req->first_key.length == 0) &&
2297             (req->session != NULL) &&
2298             (req->session->global->encryption_key.length != 0))
2299         {
2300                 DATA_BLOB encryption_key = req->session->global->encryption_key;
2301                 uint8_t *tf;
2302                 uint64_t session_id = req->session->global->session_wire_id;
2303                 struct smbXsrv_session *x = req->session;
2304                 uint64_t nonce_high;
2305                 uint64_t nonce_low;
2306
2307                 nonce_high = x->nonce_high;
2308                 nonce_low = x->nonce_low;
2309
2310                 x->nonce_low += 1;
2311                 if (x->nonce_low == 0) {
2312                         x->nonce_low += 1;
2313                         x->nonce_high += 1;
2314                 }
2315
2316                 /*
2317                  * We need to place the SMB2_TRANSFORM header before the
2318                  * first SMB2 header
2319                  */
2320
2321                 /*
2322                  * we need to remember the encryption key
2323                  * and defer the signing/encryption until
2324                  * we are sure that we do not change
2325                  * the header again.
2326                  */
2327                 req->first_key = data_blob_dup_talloc(req, encryption_key);
2328                 if (req->first_key.data == NULL) {
2329                         return NT_STATUS_NO_MEMORY;
2330                 }
2331
2332                 tf = talloc_zero_array(req->out.vector, uint8_t,
2333                                        SMB2_TF_HDR_SIZE);
2334                 if (tf == NULL) {
2335                         return NT_STATUS_NO_MEMORY;
2336                 }
2337
2338                 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2339                 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2340                 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2341                 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2342
2343                 firsttf->iov_base = (void *)tf;
2344                 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2345         }
2346
2347         if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2348             (req->last_key.length > 0) &&
2349             (firsttf->iov_len == 0))
2350         {
2351                 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2352                 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2353
2354                 /*
2355                  * As we are sure the header of the last request in the
2356                  * compound chain will not change, we can to sign here
2357                  * with the last signing key we remembered.
2358                  */
2359                 status = smb2_signing_sign_pdu(req->last_key,
2360                                                conn->protocol,
2361                                                lasthdr,
2362                                                SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2363                 if (!NT_STATUS_IS_OK(status)) {
2364                         return status;
2365                 }
2366         }
2367         data_blob_clear_free(&req->last_key);
2368
2369         req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2370
2371         if (req->current_idx < req->out.vector_count) {
2372                 /*
2373                  * We must process the remaining compound
2374                  * SMB2 requests before any new incoming SMB2
2375                  * requests. This is because incoming SMB2
2376                  * requests may include a cancel for a
2377                  * compound request we haven't processed
2378                  * yet.
2379                  */
2380                 struct tevent_immediate *im = tevent_create_immediate(req);
2381                 if (!im) {
2382                         return NT_STATUS_NO_MEMORY;
2383                 }
2384
2385                 if (req->do_signing && firsttf->iov_len == 0) {
2386                         struct smbXsrv_session *x = req->session;
2387                         DATA_BLOB signing_key = x->global->channels[0].signing_key;
2388
2389                         /*
2390                          * we need to remember the signing key
2391                          * and defer the signing until
2392                          * we are sure that we do not change
2393                          * the header again.
2394                          */
2395                         req->last_key = data_blob_dup_talloc(req, signing_key);
2396                         if (req->last_key.data == NULL) {
2397                                 return NT_STATUS_NO_MEMORY;
2398                         }
2399                 }
2400
2401                 tevent_schedule_immediate(im,
2402                                         req->sconn->ev_ctx,
2403                                         smbd_smb2_request_dispatch_immediate,
2404                                         req);
2405                 return NT_STATUS_OK;
2406         }
2407
2408         if (req->compound_related) {
2409                 req->compound_related = false;
2410         }
2411
2412         smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2413
2414         /* Set credit for these operations (zero credits if this
2415            is a final reply for an async operation). */
2416         smb2_calculate_credits(req, req);
2417
2418         /*
2419          * now check if we need to sign the current response
2420          */
2421         if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2422                 status = smb2_signing_encrypt_pdu(req->first_key,
2423                                         conn->protocol,
2424                                         firsttf,
2425                                         req->out.vector_count - first_idx);
2426                 if (!NT_STATUS_IS_OK(status)) {
2427                         return status;
2428                 }
2429         } else if (req->do_signing) {
2430                 struct smbXsrv_session *x = req->session;
2431                 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2432
2433                 status = smb2_signing_sign_pdu(signing_key,
2434                                                conn->protocol,
2435                                                outhdr,
2436                                                SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2437                 if (!NT_STATUS_IS_OK(status)) {
2438                         return status;
2439                 }
2440         }
2441         data_blob_clear_free(&req->first_key);
2442
2443         /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2444         if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2445             outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2446                 /* Dynamic part is NULL. Chop it off,
2447                    We're going to send it via sendfile. */
2448                 req->out.vector_count -= 1;
2449         }
2450
2451         /*
2452          * We're done with this request -
2453          * move it off the "being processed" queue.
2454          */
2455         DLIST_REMOVE(req->sconn->smb2.requests, req);
2456
2457         req->queue_entry.mem_ctx = req;
2458         req->queue_entry.vector = req->out.vector;
2459         req->queue_entry.count = req->out.vector_count;
2460         DLIST_ADD_END(req->sconn->smb2.send_queue, &req->queue_entry, NULL);
2461         req->sconn->smb2.send_queue_len++;
2462
2463         status = smbd_smb2_io_handler(sconn, TEVENT_FD_WRITE);
2464         if (!NT_STATUS_IS_OK(status)) {
2465                 return status;
2466         }
2467
2468         return NT_STATUS_OK;
2469 }
2470
2471 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2472
2473 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2474                                         struct tevent_immediate *im,
2475                                         void *private_data)
2476 {
2477         struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2478                                         struct smbd_smb2_request);
2479         struct smbd_server_connection *sconn = req->sconn;
2480         NTSTATUS status;
2481
2482         TALLOC_FREE(im);
2483
2484         if (DEBUGLEVEL >= 10) {
2485                 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2486                         req->current_idx, req->in.vector_count));
2487                 print_req_vectors(req);
2488         }
2489
2490         status = smbd_smb2_request_dispatch(req);
2491         if (!NT_STATUS_IS_OK(status)) {
2492                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2493                 return;
2494         }
2495
2496         status = smbd_smb2_request_next_incoming(sconn);
2497         if (!NT_STATUS_IS_OK(status)) {
2498                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2499                 return;
2500         }
2501 }
2502
2503 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2504                                    NTSTATUS status,
2505                                    DATA_BLOB body, DATA_BLOB *dyn,
2506                                    const char *location)
2507 {
2508         uint8_t *outhdr;
2509         struct iovec *outbody_v;
2510         struct iovec *outdyn_v;
2511         uint32_t next_command_ofs;
2512
2513         DEBUG(10,("smbd_smb2_request_done_ex: "
2514                   "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2515                   req->current_idx, nt_errstr(status), (unsigned int)body.length,
2516                   dyn ? "yes": "no",
2517                   (unsigned int)(dyn ? dyn->length : 0),
2518                   location));
2519
2520         if (body.length < 2) {
2521                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2522         }
2523
2524         if ((body.length % 2) != 0) {
2525                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2526         }
2527
2528         outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2529         outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2530         outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2531
2532         next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2533         SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2534
2535         outbody_v->iov_base = (void *)body.data;
2536         outbody_v->iov_len = body.length;
2537
2538         if (dyn) {
2539                 outdyn_v->iov_base = (void *)dyn->data;
2540                 outdyn_v->iov_len = dyn->length;
2541         } else {
2542                 outdyn_v->iov_base = NULL;
2543                 outdyn_v->iov_len = 0;
2544         }
2545
2546         /* see if we need to recalculate the offset to the next response */
2547         if (next_command_ofs > 0) {
2548                 next_command_ofs  = SMB2_HDR_BODY;
2549                 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2550                 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2551         }
2552
2553         if ((next_command_ofs % 8) != 0) {
2554                 size_t pad_size = 8 - (next_command_ofs % 8);
2555                 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2556                         /*
2557                          * if the dyn buffer is empty
2558                          * we can use it to add padding
2559                          */
2560                         uint8_t *pad;
2561
2562                         pad = talloc_zero_array(req->out.vector,
2563                                                 uint8_t, pad_size);
2564                         if (pad == NULL) {
2565                                 return smbd_smb2_request_error(req,
2566                                                 NT_STATUS_NO_MEMORY);
2567                         }
2568
2569                         outdyn_v->iov_base = (void *)pad;
2570                         outdyn_v->iov_len = pad_size;
2571                 } else {
2572                         /*
2573                          * For now we copy the dynamic buffer
2574                          * and add the padding to the new buffer
2575                          */
2576                         size_t old_size;
2577                         uint8_t *old_dyn;
2578                         size_t new_size;
2579                         uint8_t *new_dyn;
2580
2581                         old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2582                         old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2583
2584                         new_size = old_size + pad_size;
2585                         new_dyn = talloc_zero_array(req->out.vector,
2586                                                uint8_t, new_size);
2587                         if (new_dyn == NULL) {
2588                                 return smbd_smb2_request_error(req,
2589                                                 NT_STATUS_NO_MEMORY);
2590                         }
2591
2592                         memcpy(new_dyn, old_dyn, old_size);
2593                         memset(new_dyn + old_size, 0, pad_size);
2594
2595                         outdyn_v->iov_base = (void *)new_dyn;
2596                         outdyn_v->iov_len = new_size;
2597                 }
2598                 next_command_ofs += pad_size;
2599         }
2600
2601         SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2602
2603         return smbd_smb2_request_reply(req);
2604 }
2605
2606 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2607                                     NTSTATUS status,
2608                                     DATA_BLOB *info,
2609                                     const char *location)
2610 {
2611         DATA_BLOB body;
2612         uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2613         size_t unread_bytes = smbd_smb2_unread_bytes(req);
2614
2615         DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2616                   req->current_idx, nt_errstr(status), info ? " +info" : "",
2617                   location));
2618
2619         if (unread_bytes) {
2620                 /* Recvfile error. Drain incoming socket. */
2621                 size_t ret;
2622
2623                 errno = 0;
2624                 ret = drain_socket(req->sconn->sock, unread_bytes);
2625                 if (ret != unread_bytes) {
2626                         NTSTATUS error;
2627
2628                         if (errno == 0) {
2629                                 error = NT_STATUS_IO_DEVICE_ERROR;
2630                         } else {
2631                                 error = map_nt_error_from_unix_common(errno);
2632                         }
2633
2634                         DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2635                                   "ret[%u] errno[%d] => %s\n",
2636                                   (unsigned)unread_bytes,
2637                                   (unsigned)ret, errno, nt_errstr(error)));
2638                         return error;
2639                 }
2640         }
2641
2642         body.data = outhdr + SMB2_HDR_BODY;
2643         body.length = 8;
2644         SSVAL(body.data, 0, 9);
2645
2646         if (info) {
2647                 SIVAL(body.data, 0x04, info->length);
2648         } else {
2649                 /* Allocated size of req->out.vector[i].iov_base
2650                  * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2651                  * 1 byte without having to do an alloc.
2652                  */
2653                 info = talloc_zero_array(req->out.vector,
2654                                         DATA_BLOB,
2655                                         1);
2656                 if (!info) {
2657                         return NT_STATUS_NO_MEMORY;
2658                 }
2659                 info->data = ((uint8_t *)outhdr) +
2660                         OUTVEC_ALLOC_SIZE - 1;
2661                 info->length = 1;
2662                 SCVAL(info->data, 0, 0);
2663         }
2664
2665         /*
2666          * Note: Even if there is an error, continue to process the request.
2667          * per MS-SMB2.
2668          */
2669
2670         return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2671 }
2672
2673
2674 struct smbd_smb2_send_oplock_break_state {
2675         struct smbd_server_connection *sconn;
2676         struct smbd_smb2_send_queue queue_entry;
2677         uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x18];
2678         struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2679 };
2680
2681 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2682                                      struct smbXsrv_session *session,
2683                                      struct smbXsrv_tcon *tcon,
2684                                      struct smbXsrv_open *op,
2685                                      uint8_t oplock_level)
2686 {
2687         struct smbd_smb2_send_oplock_break_state *state;
2688         struct smbXsrv_connection *conn = sconn->conn;
2689         uint8_t *tf;
2690         size_t tf_len;
2691         uint8_t *hdr;
2692         uint8_t *body;
2693         size_t body_len;
2694         uint8_t *dyn;
2695         size_t dyn_len;
2696         bool do_encryption = session->global->encryption_required;
2697         uint64_t nonce_high = 0;
2698         uint64_t nonce_low = 0;
2699         NTSTATUS status;
2700
2701         if (tcon->global->encryption_required) {
2702                 do_encryption = true;
2703         }
2704
2705         state = talloc_zero(sconn, struct smbd_smb2_send_oplock_break_state);
2706         if (state == NULL) {
2707                 return NT_STATUS_NO_MEMORY;
2708         }
2709         state->sconn = sconn;
2710
2711         tf = state->buf + NBT_HDR_SIZE;
2712         tf_len = SMB2_TF_HDR_SIZE;
2713         hdr = tf + tf_len;
2714         body = hdr + SMB2_HDR_BODY;
2715         body_len = 0x18;
2716         dyn = body + body_len;
2717         dyn_len = 0;
2718
2719         if (do_encryption) {
2720                 nonce_high = session->nonce_high;
2721                 nonce_low = session->nonce_low;
2722
2723                 session->nonce_low += 1;
2724                 if (session->nonce_low == 0) {
2725                         session->nonce_low += 1;
2726                         session->nonce_high += 1;
2727                 }
2728         }
2729
2730         SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2731         SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2732         SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2733         SBVAL(tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2734
2735         SIVAL(hdr, 0,                           SMB2_MAGIC);
2736         SSVAL(hdr, SMB2_HDR_LENGTH,             SMB2_HDR_BODY);
2737         SSVAL(hdr, SMB2_HDR_EPOCH,              0);
2738         SIVAL(hdr, SMB2_HDR_STATUS,             0);
2739         SSVAL(hdr, SMB2_HDR_OPCODE,             SMB2_OP_BREAK);
2740         SSVAL(hdr, SMB2_HDR_CREDIT,             0);
2741         SIVAL(hdr, SMB2_HDR_FLAGS,              SMB2_HDR_FLAG_REDIRECT);
2742         SIVAL(hdr, SMB2_HDR_NEXT_COMMAND,       0);
2743         SBVAL(hdr, SMB2_HDR_MESSAGE_ID,         UINT64_MAX);
2744         SIVAL(hdr, SMB2_HDR_PID,                0);
2745         SIVAL(hdr, SMB2_HDR_TID,                0);
2746         SBVAL(hdr, SMB2_HDR_SESSION_ID,         0);
2747         memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2748
2749         SSVAL(body, 0x00, body_len);
2750
2751         SCVAL(body, 0x02, oplock_level);
2752         SCVAL(body, 0x03, 0);           /* reserved */
2753         SIVAL(body, 0x04, 0);           /* reserved */
2754         SBVAL(body, 0x08, op->global->open_persistent_id);
2755         SBVAL(body, 0x10, op->global->open_volatile_id);
2756
2757         state->vector[0].iov_base = (void *)state->buf;
2758         state->vector[0].iov_len = NBT_HDR_SIZE;
2759
2760         if (do_encryption) {
2761                 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base   = tf;
2762                 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len    = tf_len;
2763         } else {
2764                 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base   = NULL;
2765                 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len    = 0;
2766         }
2767
2768         state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base  = hdr;
2769         state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len   = SMB2_HDR_BODY;
2770
2771         state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
2772         state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len  = body_len;
2773
2774         state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base  = dyn;
2775         state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len   = dyn_len;
2776
2777         smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2778
2779         if (do_encryption) {
2780                 DATA_BLOB encryption_key = session->global->encryption_key;
2781
2782                 status = smb2_signing_encrypt_pdu(encryption_key,
2783                                         conn->protocol,
2784                                         &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2785                                         SMBD_SMB2_NUM_IOV_PER_REQ);
2786                 if (!NT_STATUS_IS_OK(status)) {
2787                         return status;
2788                 }
2789         }
2790
2791         state->queue_entry.mem_ctx = state;
2792         state->queue_entry.vector = state->vector;
2793         state->queue_entry.count = ARRAY_SIZE(state->vector);
2794         DLIST_ADD_END(state->sconn->smb2.send_queue, &state->queue_entry, NULL);
2795         state->sconn->smb2.send_queue_len++;
2796
2797         status = smbd_smb2_io_handler(sconn, TEVENT_FD_WRITE);
2798         if (!NT_STATUS_IS_OK(status)) {
2799                 return status;
2800         }
2801
2802         return NT_STATUS_OK;
2803 }
2804
2805 static size_t get_min_receive_file_size(struct smbd_smb2_request *smb2_req)
2806 {
2807         if (smb2_req->do_signing) {
2808                 return 0;
2809         }
2810         if (smb2_req->do_encryption) {
2811                 return 0;
2812         }
2813         return (size_t)lp_min_receive_file_size();
2814 }
2815
2816 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2817 {
2818         uint32_t flags;
2819
2820         if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2821                 /* Transform header. Cannot recvfile. */
2822                 return false;
2823         }
2824         if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2825                 /* Not SMB2. Normal error path will cope. */
2826                 return false;
2827         }
2828         if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2829                 /* Not SMB2. Normal error path will cope. */
2830                 return false;
2831         }
2832         if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2833                 /* Needs to be a WRITE. */
2834                 return false;
2835         }
2836         if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2837                 /* Chained. Cannot recvfile. */
2838                 return false;
2839         }
2840         flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2841         if (flags & SMB2_HDR_FLAG_CHAINED) {
2842                 /* Chained. Cannot recvfile. */
2843                 return false;
2844         }
2845         if (flags & SMB2_HDR_FLAG_SIGNED) {
2846                 /* Signed. Cannot recvfile. */
2847                 return false;
2848         }
2849
2850         DEBUG(10,("Doing recvfile write len = %u\n",
2851                 (unsigned int)(state->pktlen -
2852                 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN)));
2853
2854         return true;
2855 }
2856
2857 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2858 {
2859         struct smbd_smb2_request_read_state *state = &sconn->smb2.request_read_state;
2860         size_t max_send_queue_len;
2861         size_t cur_send_queue_len;
2862
2863         if (!NT_STATUS_IS_OK(sconn->status)) {
2864                 /*
2865                  * we're not supposed to do any io
2866                  */
2867                 return NT_STATUS_OK;
2868         }
2869
2870         if (state->req != NULL) {
2871                 /*
2872                  * if there is already a tstream_readv_pdu
2873                  * pending, we are done.
2874                  */
2875                 return NT_STATUS_OK;
2876         }
2877
2878         max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2879         cur_send_queue_len = sconn->smb2.send_queue_len;
2880
2881         if (cur_send_queue_len > max_send_queue_len) {
2882                 /*
2883                  * if we have a lot of requests to send,
2884                  * we wait until they are on the wire until we
2885                  * ask for the next request.
2886                  */
2887                 return NT_STATUS_OK;
2888         }
2889
2890         /* ask for the next request */
2891         ZERO_STRUCTP(state);
2892         state->req = smbd_smb2_request_allocate(sconn);
2893         if (state->req == NULL) {
2894                 return NT_STATUS_NO_MEMORY;
2895         }
2896         state->req->sconn = sconn;
2897         state->min_recv_size = get_min_receive_file_size(state->req);
2898
2899         TEVENT_FD_READABLE(sconn->smb2.fde);
2900
2901         return NT_STATUS_OK;
2902 }
2903
2904 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2905                              uint8_t *inbuf, size_t size)
2906 {
2907         NTSTATUS status;
2908         struct smbd_smb2_request *req = NULL;
2909
2910         DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2911                  (unsigned int)size));
2912
2913         status = smbd_initialize_smb2(sconn);
2914         if (!NT_STATUS_IS_OK(status)) {
2915                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2916                 return;
2917         }
2918
2919         status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2920         if (!NT_STATUS_IS_OK(status)) {
2921                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2922                 return;
2923         }
2924
2925         status = smbd_smb2_request_validate(req);
2926         if (!NT_STATUS_IS_OK(status)) {
2927                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2928                 return;
2929         }
2930
2931         status = smbd_smb2_request_setup_out(req);
2932         if (!NT_STATUS_IS_OK(status)) {
2933                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2934                 return;
2935         }
2936
2937         status = smbd_smb2_request_dispatch(req);
2938         if (!NT_STATUS_IS_OK(status)) {
2939                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2940                 return;
2941         }
2942
2943         status = smbd_smb2_request_next_incoming(sconn);
2944         if (!NT_STATUS_IS_OK(status)) {
2945                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2946                 return;
2947         }
2948
2949         sconn->num_requests++;
2950 }
2951
2952 static int socket_error_from_errno(int ret,
2953                                    int sys_errno,
2954                                    bool *retry)
2955 {
2956         *retry = false;
2957
2958         if (ret >= 0) {
2959                 return 0;
2960         }
2961
2962         if (ret != -1) {
2963                 return EIO;
2964         }
2965
2966         if (sys_errno == 0) {
2967                 return EIO;
2968         }
2969
2970         if (sys_errno == EINTR) {
2971                 *retry = true;
2972                 return sys_errno;
2973         }
2974
2975         if (sys_errno == EINPROGRESS) {
2976                 *retry = true;
2977                 return sys_errno;
2978         }
2979
2980         if (sys_errno == EAGAIN) {
2981                 *retry = true;
2982                 return sys_errno;
2983         }
2984
2985         /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
2986         if (sys_errno == ENOMEM) {
2987                 *retry = true;
2988                 return sys_errno;
2989         }
2990
2991 #ifdef EWOULDBLOCK
2992 #if EWOULDBLOCK != EAGAIN
2993         if (sys_errno == EWOULDBLOCK) {
2994                 *retry = true;
2995                 return sys_errno;
2996         }
2997 #endif
2998 #endif
2999
3000         return sys_errno;
3001 }
3002
3003 static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn)
3004 {
3005         int ret;
3006         int err;
3007         bool retry;
3008
3009         if (sconn->smb2.send_queue == NULL) {
3010                 TEVENT_FD_NOT_WRITEABLE(sconn->smb2.fde);
3011                 return NT_STATUS_OK;
3012         }
3013
3014         while (sconn->smb2.send_queue != NULL) {
3015                 struct smbd_smb2_send_queue *e = sconn->smb2.send_queue;
3016
3017                 if (e->sendfile_header != NULL) {
3018                         size_t size = 0;
3019                         size_t i = 0;
3020                         uint8_t *buf;
3021
3022                         for (i=0; i < e->count; i++) {
3023                                 size += e->vector[i].iov_len;
3024                         }
3025
3026                         buf = talloc_array(e->mem_ctx, uint8_t, size);
3027                         if (buf == NULL) {
3028                                 return NT_STATUS_NO_MEMORY;
3029                         }
3030
3031                         size = 0;
3032                         for (i=0; i < e->count; i++) {
3033                                 memcpy(buf+size,
3034                                        e->vector[i].iov_base,
3035                                        e->vector[i].iov_len);
3036                                 size += e->vector[i].iov_len;
3037                         }
3038
3039                         e->sendfile_header->data = buf;
3040                         e->sendfile_header->length = size;
3041                         e->count = 0;
3042
3043                         sconn->smb2.send_queue_len--;
3044                         DLIST_REMOVE(sconn->smb2.send_queue, e);
3045                         talloc_free(e->mem_ctx);
3046                         continue;
3047                 }
3048
3049                 ret = writev(sconn->sock, e->vector, e->count);
3050                 if (ret == 0) {
3051                         /* propagate end of file */
3052                         return NT_STATUS_INTERNAL_ERROR;
3053                 }
3054                 err = socket_error_from_errno(ret, errno, &retry);
3055                 if (retry) {
3056                         /* retry later */
3057                         TEVENT_FD_WRITEABLE(sconn->smb2.fde);
3058                         return NT_STATUS_OK;
3059                 }
3060                 if (err != 0) {
3061                         return map_nt_error_from_unix_common(err);
3062                 }
3063                 while (ret > 0) {
3064                         if (ret < e->vector[0].iov_len) {
3065                                 uint8_t *base;
3066                                 base = (uint8_t *)e->vector[0].iov_base;
3067                                 base += ret;
3068                                 e->vector[0].iov_base = (void *)base;
3069                                 e->vector[0].iov_len -= ret;
3070                                 break;
3071                         }
3072                         ret -= e->vector[0].iov_len;
3073                         e->vector += 1;
3074                         e->count -= 1;
3075                 }
3076
3077                 /*
3078                  * there're maybe some empty vectors at the end
3079                  * which we need to skip, otherwise we would get
3080                  * ret == 0 from the readv() call and return EPIPE
3081                  */
3082                 while (e->count > 0) {
3083                         if (e->vector[0].iov_len > 0) {
3084                                 break;
3085                         }
3086                         e->vector += 1;
3087                         e->count -= 1;
3088                 }
3089
3090                 if (e->count > 0) {
3091                         /* we have more to write */
3092                         TEVENT_FD_WRITEABLE(sconn->smb2.fde);
3093                         return NT_STATUS_OK;
3094                 }
3095
3096                 sconn->smb2.send_queue_len--;
3097                 DLIST_REMOVE(sconn->smb2.send_queue, e);
3098                 talloc_free(e->mem_ctx);
3099         }
3100
3101         return NT_STATUS_OK;
3102 }
3103
3104 static NTSTATUS smbd_smb2_io_handler(struct smbd_server_connection *sconn,
3105                                      uint16_t fde_flags)
3106 {
3107         struct smbd_smb2_request_read_state *state = &sconn->smb2.request_read_state;
3108         struct smbd_smb2_request *req = NULL;
3109         size_t min_recvfile_size = UINT32_MAX;
3110         int ret;
3111         int err;
3112         bool retry;
3113         NTSTATUS status;
3114         NTTIME now;
3115
3116         if (!NT_STATUS_IS_OK(sconn->status)) {
3117                 /*
3118                  * we're not supposed to do any io
3119                  */
3120                 TEVENT_FD_NOT_READABLE(sconn->smb2.fde);
3121                 TEVENT_FD_NOT_WRITEABLE(sconn->smb2.fde);
3122                 return NT_STATUS_OK;
3123         }
3124
3125         if (fde_flags & TEVENT_FD_WRITE) {
3126                 status = smbd_smb2_flush_send_queue(sconn);
3127                 if (!NT_STATUS_IS_OK(status)) {
3128                         return status;
3129                 }
3130         }
3131
3132         if (!(fde_flags & TEVENT_FD_READ)) {
3133                 return NT_STATUS_OK;
3134         }
3135
3136         if (state->req == NULL) {
3137                 TEVENT_FD_NOT_READABLE(sconn->smb2.fde);
3138                 return NT_STATUS_OK;
3139         }
3140
3141 again:
3142         if (!state->hdr.done) {
3143                 state->hdr.done = true;
3144
3145                 state->vector.iov_base = (void *)state->hdr.nbt;
3146                 state->vector.iov_len = NBT_HDR_SIZE;
3147         }
3148
3149         ret = readv(sconn->sock, &state->vector, 1);
3150         if (ret == 0) {
3151                 /* propagate end of file */
3152                 return NT_STATUS_END_OF_FILE;
3153         }
3154         err = socket_error_from_errno(ret, errno, &retry);
3155         if (retry) {
3156                 /* retry later */
3157                 TEVENT_FD_READABLE(sconn->smb2.fde);
3158                 return NT_STATUS_OK;
3159         }
3160         if (err != 0) {
3161                 return map_nt_error_from_unix_common(err);
3162         }
3163
3164         if (ret < state->vector.iov_len) {
3165                 uint8_t *base;
3166                 base = (uint8_t *)state->vector.iov_base;
3167                 base += ret;
3168                 state->vector.iov_base = (void *)base;
3169                 state->vector.iov_len -= ret;
3170                 /* we have more to read */
3171                 TEVENT_FD_READABLE(sconn->smb2.fde);
3172                 return NT_STATUS_OK;
3173         }
3174
3175         if (state->pktlen > 0) {
3176                 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3177                         /*
3178                          * Not a possible receivefile write.
3179                          * Read the rest of the data.
3180                          */
3181                         state->doing_receivefile = false;
3182                         state->vector.iov_base = (void *)(state->pktbuf +
3183                                 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN);
3184                         state->vector.iov_len = (state->pktlen -
3185                                 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN);
3186                         goto again;
3187                 }
3188
3189                 /*
3190                  * Either this is a receivefile write so we've
3191                  * done a short read, or if not we have all the data.
3192                  */
3193                 goto got_full;
3194         }
3195
3196         /*
3197          * Now we analyze the NBT header
3198          */
3199         state->pktlen = smb2_len(state->hdr.nbt);
3200         if (state->pktlen == 0) {
3201                 goto got_full;
3202         }
3203
3204         state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3205         if (state->pktbuf == NULL) {
3206                 return NT_STATUS_NO_MEMORY;
3207         }
3208
3209         state->vector.iov_base = (void *)state->pktbuf;
3210
3211         if (state->min_recv_size != 0) {
3212                 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3213                 min_recvfile_size += state->min_recv_size;
3214         }
3215
3216         if (state->pktlen > min_recvfile_size) {
3217                 /*
3218                  * Might be a receivefile write. Read the SMB2 HEADER +
3219                  * SMB2_WRITE header first. Set 'doing_receivefile'
3220                  * as we're *attempting* receivefile write. If this
3221                  * turns out not to be a SMB2_WRITE request or otherwise
3222                  * not suitable then we'll just read the rest of the data
3223                  * the next time this function is called.
3224                  */
3225                 state->vector.iov_len = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3226                 state->doing_receivefile = true;
3227         } else {
3228                 state->vector.iov_len = state->pktlen;
3229         }
3230
3231         goto again;
3232
3233 got_full:
3234
3235         if (state->hdr.nbt[0] != 0x00) {
3236                 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3237                          state->hdr.nbt[0]));
3238
3239                 req = state->req;
3240                 ZERO_STRUCTP(state);
3241                 state->req = req;
3242                 state->min_recv_size = get_min_receive_file_size(state->req);
3243                 req = NULL;
3244                 goto again;
3245         }
3246
3247         req = state->req;
3248         state->req = NULL;
3249
3250         req->request_time = timeval_current();
3251         now = timeval_to_nttime(&req->request_time);
3252
3253         status = smbd_smb2_inbuf_parse_compound(req->sconn->conn,
3254                                                 now,
3255                                                 state->pktbuf,
3256                                                 state->pktlen,
3257                                                 req,
3258                                                 &req->in.vector,
3259                                                 &req->in.vector_count);
3260         if (!NT_STATUS_IS_OK(status)) {
3261                 return status;
3262         }
3263
3264         if (state->doing_receivefile) {
3265                 req->smb1req = talloc_zero(req, struct smb_request);
3266                 if (req->smb1req == NULL) {
3267                         return NT_STATUS_NO_MEMORY;
3268                 }
3269                 req->smb1req->unread_bytes =
3270                         state->pktlen - SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3271         }
3272
3273         ZERO_STRUCTP(state);
3274
3275         req->current_idx = 1;
3276
3277         DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3278                  req->current_idx, req->in.vector_count));
3279
3280         status = smbd_smb2_request_validate(req);
3281         if (!NT_STATUS_IS_OK(status)) {
3282                 return status;
3283         }
3284
3285         status = smbd_smb2_request_setup_out(req);
3286         if (!NT_STATUS_IS_OK(status)) {
3287                 return status;
3288         }
3289
3290         status = smbd_smb2_request_dispatch(req);
3291         if (!NT_STATUS_IS_OK(status)) {
3292                 return status;
3293         }
3294
3295         sconn->num_requests++;
3296
3297         /* The timeout_processing function isn't run nearly
3298            often enough to implement 'max log size' without
3299            overrunning the size of the file by many megabytes.
3300            This is especially true if we are running at debug
3301            level 10.  Checking every 50 SMB2s is a nice
3302            tradeoff of performance vs log file size overrun. */
3303
3304         if ((sconn->num_requests % 50) == 0 &&
3305             need_to_check_log_size()) {
3306                 change_to_root_user();
3307                 check_log_size();
3308         }
3309
3310         status = smbd_smb2_request_next_incoming(sconn);
3311         if (!NT_STATUS_IS_OK(status)) {
3312                 return status;
3313         }
3314
3315         return NT_STATUS_OK;
3316 }
3317
3318 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3319                                          struct tevent_fd *fde,
3320                                          uint16_t flags,
3321                                          void *private_data)
3322 {
3323         struct smbd_server_connection *sconn =
3324                 talloc_get_type_abort(private_data,
3325                 struct smbd_server_connection);
3326         NTSTATUS status;
3327
3328         status = smbd_smb2_io_handler(sconn, flags);
3329         if (!NT_STATUS_IS_OK(status)) {
3330                 smbd_server_connection_terminate(sconn, nt_errstr(status));
3331                 return;
3332         }
3333 }