Final fix for #7331 - Compound async SMB 2 requests don't work right.
[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
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "smbd/globals.h"
23 #include "../libcli/smb/smb_common.h"
24 #include "../lib/tsocket/tsocket.h"
25
26 static const char *smb2_names[] = {
27         "SMB2_NEGPROT",
28         "SMB2_SESSSETUP",
29         "SMB2_LOGOFF",
30         "SMB2_TCON",
31         "SMB2_TDIS",
32         "SMB2_CREATE",
33         "SMB2_CLOSE",
34         "SMB2_FLUSH",
35         "SMB2_READ",
36         "SMB2_WRITE",
37         "SMB2_LOCK",
38         "SMB2_IOCTL",
39         "SMB2_CANCEL",
40         "SMB2_KEEPALIVE",
41         "SMB2_FIND",
42         "SMB2_NOTIFY",
43         "SMB2_GETINFO",
44         "SMB2_SETINFO",
45         "SMB2_BREAK"
46 };
47
48 const char *smb2_opcode_name(uint16_t opcode)
49 {
50         if (opcode >= 0x12) {
51                 return "Bad SMB2 opcode";
52         }
53         return smb2_names[opcode];
54 }
55
56 static void print_req_vectors(struct smbd_smb2_request *req)
57 {
58         int i;
59
60         for (i = 0; i < req->in.vector_count; i++) {
61                 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
62                         (unsigned int)i,
63                         (unsigned int)req->in.vector[i].iov_len);
64         }
65         for (i = 0; i < req->out.vector_count; i++) {
66                 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
67                         (unsigned int)i,
68                         (unsigned int)req->out.vector[i].iov_len);
69         }
70 }
71
72 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
73 {
74         if (size < (4 + SMB2_HDR_BODY)) {
75                 return false;
76         }
77
78         if (IVAL(inbuf, 4) != SMB2_MAGIC) {
79                 return false;
80         }
81
82         return true;
83 }
84
85 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
86 {
87         NTSTATUS status;
88         int ret;
89
90         TALLOC_FREE(sconn->smb1.fde);
91
92         sconn->smb2.event_ctx = smbd_event_context();
93
94         sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
95         if (sconn->smb2.recv_queue == NULL) {
96                 return NT_STATUS_NO_MEMORY;
97         }
98
99         sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
100         if (sconn->smb2.send_queue == NULL) {
101                 return NT_STATUS_NO_MEMORY;
102         }
103
104         sconn->smb2.sessions.idtree = idr_init(sconn);
105         if (sconn->smb2.sessions.idtree == NULL) {
106                 return NT_STATUS_NO_MEMORY;
107         }
108         sconn->smb2.sessions.limit = 0x0000FFFE;
109         sconn->smb2.sessions.list = NULL;
110
111         ret = tstream_bsd_existing_socket(sconn, smbd_server_fd(),
112                                           &sconn->smb2.stream);
113         if (ret == -1) {
114                 status = map_nt_error_from_unix(errno);
115                 return status;
116         }
117
118         /* Ensure child is set to non-blocking mode */
119         set_blocking(smbd_server_fd(),false);
120         return NT_STATUS_OK;
121 }
122
123 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
124 #define _smb2_setlen(_buf,len) do { \
125         uint8_t *buf = (uint8_t *)_buf; \
126         buf[0] = 0; \
127         buf[1] = ((len)&0xFF0000)>>16; \
128         buf[2] = ((len)&0xFF00)>>8; \
129         buf[3] = (len)&0xFF; \
130 } while (0)
131
132 static void smb2_setup_nbt_length(struct iovec *vector, int count)
133 {
134         size_t len = 0;
135         int i;
136
137         for (i=1; i < count; i++) {
138                 len += vector[i].iov_len;
139         }
140
141         _smb2_setlen(vector[0].iov_base, len);
142 }
143
144 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request **req)
145 {
146         if (*req) {
147                 (*req)->parent = NULL;
148                 (*req)->mem_pool = NULL;
149         }
150
151         return 0;
152 }
153
154 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
155 {
156         if (req->out.vector) {
157                 DLIST_REMOVE(req->sconn->smb2.requests, req);
158         }
159
160         if (req->parent) {
161                 *req->parent = NULL;
162                 talloc_free(req->mem_pool);
163         }
164
165         return 0;
166 }
167
168 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
169 {
170         TALLOC_CTX *mem_pool;
171         struct smbd_smb2_request **parent;
172         struct smbd_smb2_request *req;
173
174         mem_pool = talloc_pool(mem_ctx, 8192);
175         if (mem_pool == NULL) {
176                 return NULL;
177         }
178
179         parent = talloc(mem_pool, struct smbd_smb2_request *);
180         if (parent == NULL) {
181                 talloc_free(mem_pool);
182                 return NULL;
183         }
184
185         req = talloc_zero(parent, struct smbd_smb2_request);
186         if (req == NULL) {
187                 talloc_free(mem_pool);
188                 return NULL;
189         }
190         *parent         = req;
191         req->mem_pool   = mem_pool;
192         req->parent     = parent;
193
194         talloc_set_destructor(parent, smbd_smb2_request_parent_destructor);
195         talloc_set_destructor(req, smbd_smb2_request_destructor);
196
197         return req;
198 }
199
200 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
201                                          const uint8_t *inbuf, size_t size,
202                                          struct smbd_smb2_request **_req)
203 {
204         struct smbd_smb2_request *req;
205         uint32_t protocol_version;
206         const uint8_t *inhdr = NULL;
207         off_t ofs = 0;
208         uint16_t cmd;
209         uint32_t next_command_ofs;
210
211         if (size < (4 + SMB2_HDR_BODY + 2)) {
212                 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
213                 return NT_STATUS_INVALID_PARAMETER;
214         }
215
216         inhdr = inbuf + 4;
217
218         protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
219         if (protocol_version != SMB2_MAGIC) {
220                 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
221                          protocol_version));
222                 return NT_STATUS_INVALID_PARAMETER;
223         }
224
225         cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
226         if (cmd != SMB2_OP_NEGPROT) {
227                 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
228                          cmd));
229                 return NT_STATUS_INVALID_PARAMETER;
230         }
231
232         next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
233         if (next_command_ofs != 0) {
234                 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
235                          next_command_ofs));
236                 return NT_STATUS_INVALID_PARAMETER;
237         }
238
239         req = smbd_smb2_request_allocate(sconn);
240         if (req == NULL) {
241                 return NT_STATUS_NO_MEMORY;
242         }
243         req->sconn = sconn;
244
245         talloc_steal(req, inbuf);
246
247         req->in.vector = talloc_array(req, struct iovec, 4);
248         if (req->in.vector == NULL) {
249                 TALLOC_FREE(req);
250                 return NT_STATUS_NO_MEMORY;
251         }
252         req->in.vector_count = 4;
253
254         memcpy(req->in.nbt_hdr, inbuf, 4);
255
256         ofs = 0;
257         req->in.vector[0].iov_base      = (void *)req->in.nbt_hdr;
258         req->in.vector[0].iov_len       = 4;
259         ofs += req->in.vector[0].iov_len;
260
261         req->in.vector[1].iov_base      = (void *)(inbuf + ofs);
262         req->in.vector[1].iov_len       = SMB2_HDR_BODY;
263         ofs += req->in.vector[1].iov_len;
264
265         req->in.vector[2].iov_base      = (void *)(inbuf + ofs);
266         req->in.vector[2].iov_len       = SVAL(inbuf, ofs) & 0xFFFE;
267         ofs += req->in.vector[2].iov_len;
268
269         if (ofs > size) {
270                 return NT_STATUS_INVALID_PARAMETER;
271         }
272
273         req->in.vector[3].iov_base      = (void *)(inbuf + ofs);
274         req->in.vector[3].iov_len       = size - ofs;
275         ofs += req->in.vector[3].iov_len;
276
277         req->current_idx = 1;
278
279         *_req = req;
280         return NT_STATUS_OK;
281 }
282
283 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req,
284                                 uint16_t *p_creds_requested)
285 {
286         int count;
287         int idx;
288         bool compound_related = false;
289
290         *p_creds_requested = 0;
291         count = req->in.vector_count;
292
293         if (count < 4) {
294                 /* It's not a SMB2 request */
295                 return NT_STATUS_INVALID_PARAMETER;
296         }
297
298         for (idx=1; idx < count; idx += 3) {
299                 uint16_t creds_requested = 0;
300                 const uint8_t *inhdr = NULL;
301                 uint32_t flags;
302
303                 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
304                         return NT_STATUS_INVALID_PARAMETER;
305                 }
306
307                 if (req->in.vector[idx+1].iov_len < 2) {
308                         return NT_STATUS_INVALID_PARAMETER;
309                 }
310
311                 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
312
313                 /* setup the SMB2 header */
314                 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
315                         return NT_STATUS_INVALID_PARAMETER;
316                 }
317
318                 creds_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
319                 if (*p_creds_requested + creds_requested < creds_requested) {
320                         *p_creds_requested = 65535;
321                 } else {
322                         *p_creds_requested += creds_requested;
323                 }
324
325                 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
326                 if (idx == 1) {
327                         /*
328                          * the 1st request should never have the
329                          * SMB2_HDR_FLAG_CHAINED flag set
330                          */
331                         if (flags & SMB2_HDR_FLAG_CHAINED) {
332                                 req->next_status = NT_STATUS_INVALID_PARAMETER;
333                                 return NT_STATUS_OK;
334                         }
335                 } else if (idx == 4) {
336                         /*
337                          * the 2nd request triggers related vs. unrelated
338                          * compounded requests
339                          */
340                         if (flags & SMB2_HDR_FLAG_CHAINED) {
341                                 compound_related = true;
342                         }
343                 } else if (idx > 4) {
344 #if 0
345                         /*
346                          * It seems the this tests are wrong
347                          * see the SMB2-COMPOUND test
348                          */
349
350                         /*
351                          * all other requests should match the 2nd one
352                          */
353                         if (flags & SMB2_HDR_FLAG_CHAINED) {
354                                 if (!compound_related) {
355                                         req->next_status =
356                                                 NT_STATUS_INVALID_PARAMETER;
357                                         return NT_STATUS_OK;
358                                 }
359                         } else {
360                                 if (compound_related) {
361                                         req->next_status =
362                                                 NT_STATUS_INVALID_PARAMETER;
363                                         return NT_STATUS_OK;
364                                 }
365                         }
366 #endif
367                 }
368         }
369
370         return NT_STATUS_OK;
371 }
372
373 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req, uint16_t creds)
374 {
375         struct iovec *vector;
376         int count;
377         int idx;
378
379         count = req->in.vector_count;
380         vector = talloc_array(req, struct iovec, count);
381         if (vector == NULL) {
382                 return NT_STATUS_NO_MEMORY;
383         }
384
385         vector[0].iov_base      = req->out.nbt_hdr;
386         vector[0].iov_len       = 4;
387         SIVAL(req->out.nbt_hdr, 0, 0);
388
389         for (idx=1; idx < count; idx += 3) {
390                 const uint8_t *inhdr = NULL;
391                 uint32_t in_flags;
392                 uint8_t *outhdr = NULL;
393                 uint8_t *outbody = NULL;
394                 uint32_t next_command_ofs = 0;
395                 struct iovec *current = &vector[idx];
396
397                 if ((idx + 3) < count) {
398                         /* we have a next command */
399                         next_command_ofs = SMB2_HDR_BODY + 8;
400                 }
401
402                 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
403                 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
404
405                 outhdr = talloc_array(vector, uint8_t,
406                                       SMB2_HDR_BODY + 8);
407                 if (outhdr == NULL) {
408                         return NT_STATUS_NO_MEMORY;
409                 }
410
411                 outbody = outhdr + SMB2_HDR_BODY;
412
413                 current[0].iov_base     = (void *)outhdr;
414                 current[0].iov_len      = SMB2_HDR_BODY;
415
416                 current[1].iov_base     = (void *)outbody;
417                 current[1].iov_len      = 8;
418
419                 current[2].iov_base     = NULL;
420                 current[2].iov_len      = 0;
421
422                 /* setup the SMB2 header */
423                 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID,     SMB2_MAGIC);
424                 SSVAL(outhdr, SMB2_HDR_LENGTH,          SMB2_HDR_BODY);
425                 SSVAL(outhdr, SMB2_HDR_EPOCH,           0);
426                 SIVAL(outhdr, SMB2_HDR_STATUS,
427                       NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
428                 SSVAL(outhdr, SMB2_HDR_OPCODE,
429                       SVAL(inhdr, SMB2_HDR_OPCODE));
430                 SSVAL(outhdr, SMB2_HDR_CREDIT,          creds);
431                 SIVAL(outhdr, SMB2_HDR_FLAGS,
432                       IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
433                 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND,    next_command_ofs);
434                 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
435                       BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
436                 SIVAL(outhdr, SMB2_HDR_PID,
437                       IVAL(inhdr, SMB2_HDR_PID));
438                 SIVAL(outhdr, SMB2_HDR_TID,
439                       IVAL(inhdr, SMB2_HDR_TID));
440                 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
441                       BVAL(inhdr, SMB2_HDR_SESSION_ID));
442                 memset(outhdr + SMB2_HDR_SIGNATURE, 0, 16);
443
444                 /* setup error body header */
445                 SSVAL(outbody, 0x00, 0x08 + 1);
446                 SSVAL(outbody, 0x02, 0);
447                 SIVAL(outbody, 0x04, 0);
448         }
449
450         req->out.vector = vector;
451         req->out.vector_count = count;
452
453         /* setup the length of the NBT packet */
454         smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
455
456         DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
457
458         return NT_STATUS_OK;
459 }
460
461 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
462                                          const char *reason,
463                                          const char *location)
464 {
465         DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
466                   reason, location));
467         exit_server_cleanly(reason);
468 }
469
470 static bool dup_smb2_vec(struct iovec *dstvec,
471                         const struct iovec *srcvec,
472                         int offset)
473 {
474
475         if (srcvec[offset].iov_len &&
476                         srcvec[offset].iov_base) {
477                 dstvec[offset].iov_base = talloc_memdup(dstvec,
478                                         srcvec[offset].iov_base,
479                                         srcvec[offset].iov_len);
480                 if (!dstvec[offset].iov_base) {
481                         return false;
482                 }
483                 dstvec[offset].iov_len = srcvec[offset].iov_len;
484         } else {
485                 dstvec[offset].iov_base = NULL;
486                 dstvec[offset].iov_len = 0;
487         }
488         return true;
489 }
490
491 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
492 {
493         struct smbd_smb2_request *newreq = NULL;
494         struct iovec *outvec = NULL;
495         int count = req->out.vector_count;
496         int i;
497
498         newreq = smbd_smb2_request_allocate(req->sconn);
499         if (!newreq) {
500                 return NULL;
501         }
502
503         newreq->sconn = req->sconn;
504         newreq->do_signing = req->do_signing;
505         newreq->current_idx = req->current_idx;
506         newreq->async = false;
507         newreq->cancelled = false;
508
509         outvec = talloc_array(newreq, struct iovec, count);
510         if (!outvec) {
511                 TALLOC_FREE(newreq);
512                 return NULL;
513         }
514         newreq->out.vector = outvec;
515         newreq->out.vector_count = count;
516
517         /* Setup the outvec's identically to req. */
518         outvec[0].iov_base = newreq->out.nbt_hdr;
519         outvec[0].iov_len = 4;
520         memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
521                 
522         for (i = 1; i < count; i++) {
523                 if (!dup_smb2_vec(outvec,
524                                 req->out.vector,
525                                 i)) {
526                         TALLOC_FREE(newreq);
527                         return NULL;
528                 }
529         }
530
531         smb2_setup_nbt_length(newreq->out.vector,
532                 newreq->out.vector_count);
533
534         return newreq;
535 }
536
537 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
538
539 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
540 {
541         int i = 0;
542         uint8_t *outhdr = NULL;
543         struct smbd_smb2_request *nreq = NULL;
544
545         /* Create a new smb2 request we'll use
546            for the interim return. */
547         nreq = dup_smb2_req(req);
548         if (!nreq) {
549                 return NT_STATUS_NO_MEMORY;
550         }
551
552         /* Lose the last 3 out vectors. They're the
553            ones we'll be using for the async reply. */
554         nreq->out.vector_count -= 3;
555
556         smb2_setup_nbt_length(nreq->out.vector,
557                 nreq->out.vector_count);
558
559         /* Step back to the previous reply. */
560         i = nreq->current_idx - 3;
561         outhdr = nreq->out.vector[i].iov_base;
562         /* And end the chain. */
563         SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
564
565         /* Re-sign if needed. */
566         if (nreq->do_signing) {
567                 NTSTATUS status;
568                 status = smb2_signing_sign_pdu(nreq->session->session_key,
569                                         &nreq->out.vector[i], 3);
570                 if (!NT_STATUS_IS_OK(status)) {
571                         return status;
572                 }
573         }
574         if (DEBUGLEVEL >= 10) {
575                 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
576                         (unsigned int)nreq->current_idx );
577                 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
578                         (unsigned int)nreq->out.vector_count );
579                 print_req_vectors(nreq);
580         }
581         nreq->subreq = tstream_writev_queue_send(nreq,
582                                         nreq->sconn->smb2.event_ctx,
583                                         nreq->sconn->smb2.stream,
584                                         nreq->sconn->smb2.send_queue,
585                                         nreq->out.vector,
586                                         nreq->out.vector_count);
587
588         if (nreq->subreq == NULL) {
589                 return NT_STATUS_NO_MEMORY;
590         }
591
592         tevent_req_set_callback(nreq->subreq,
593                         smbd_smb2_request_writev_done,
594                         nreq);
595
596         return NT_STATUS_OK;
597 }
598
599 struct smbd_smb2_request_pending_state {
600         struct smbd_server_connection *sconn;
601         uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
602         struct iovec vector[3];
603 };
604
605 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
606 {
607         struct smbd_smb2_request_pending_state *state =
608                 tevent_req_callback_data(subreq,
609                         struct smbd_smb2_request_pending_state);
610         struct smbd_server_connection *sconn = state->sconn;
611         int ret;
612         int sys_errno;
613
614         ret = tstream_writev_queue_recv(subreq, &sys_errno);
615         TALLOC_FREE(subreq);
616         if (ret == -1) {
617                 NTSTATUS status = map_nt_error_from_unix(sys_errno);
618                 smbd_server_connection_terminate(sconn, nt_errstr(status));
619                 return;
620         }
621
622         TALLOC_FREE(state);
623 }
624
625 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
626                                          struct tevent_req *subreq)
627 {
628         NTSTATUS status;
629         struct smbd_smb2_request_pending_state *state = NULL;
630         int i = req->current_idx;
631         uint8_t *reqhdr = NULL;
632         uint8_t *hdr = NULL;
633         uint8_t *body = NULL;
634         uint32_t flags = 0;
635         uint64_t message_id = 0;
636         uint64_t async_id = 0;
637         struct iovec *outvec = NULL;
638
639         if (!tevent_req_is_in_progress(subreq)) {
640                 return NT_STATUS_OK;
641         }
642
643         if (req->async) {
644                 /* We're already async. */
645                 return NT_STATUS_OK;
646         }
647
648         if (req->in.vector_count > i + 3) {
649                 /*
650                  * We're trying to go async in a compound
651                  * request chain. This is not allowed.
652                  * Cancel the outstanding request.
653                  */
654                 tevent_req_cancel(subreq);
655                 return smbd_smb2_request_error(req,
656                         NT_STATUS_INSUFFICIENT_RESOURCES);
657         }
658
659         req->subreq = subreq;
660         subreq = NULL;
661
662         if (DEBUGLEVEL >= 10) {
663                 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
664                         (unsigned int)req->current_idx );
665                 print_req_vectors(req);
666         }
667
668         if (req->out.vector_count > 4) {
669                 /* This is a compound reply. We
670                  * must do an interim response
671                  * followed by the async response
672                  * to match W2K8R2.
673                  */
674                 status = smb2_send_async_interim_response(req);
675                 if (!NT_STATUS_IS_OK(status)) {
676                         return status;
677                 }
678         }
679
680         reqhdr = (uint8_t *)req->out.vector[i].iov_base;
681         flags = IVAL(reqhdr, SMB2_HDR_FLAGS);
682         message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
683         async_id = message_id; /* keep it simple for now... */
684
685         /*
686          * What we send is identical to a smbd_smb2_request_error
687          * packet with an error status of STATUS_PENDING. Make use
688          * of this fact sometime when refactoring. JRA.
689          */
690
691         state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
692         if (state == NULL) {
693                 return NT_STATUS_NO_MEMORY;
694         }
695         state->sconn = req->sconn;
696
697         state->vector[0].iov_base = (void *)state->buf;
698         state->vector[0].iov_len = 4;
699
700         state->vector[1].iov_base = state->buf + 4;
701         state->vector[1].iov_len = SMB2_HDR_BODY;
702
703         state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
704         state->vector[2].iov_len = 9;
705
706         smb2_setup_nbt_length(state->vector, 3);
707
708         hdr = state->vector[1].iov_base;
709         body = state->vector[2].iov_base;
710
711         SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
712         SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
713         SSVAL(hdr, SMB2_HDR_EPOCH, 0);
714         SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
715         SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
716         SSVAL(hdr, SMB2_HDR_CREDIT, 5);
717         SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
718         SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
719         SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
720         SBVAL(hdr, SMB2_HDR_PID, async_id);
721         SBVAL(hdr, SMB2_HDR_SESSION_ID,
722                 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
723         memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
724
725         SSVAL(body, 0x00, 0x08 + 1);
726
727         SCVAL(body, 0x02, 0);
728         SCVAL(body, 0x03, 0);
729         SIVAL(body, 0x04, 0);
730         /* Match W2K8R2... */
731         SCVAL(body, 0x08, 0x21);
732
733         if (req->do_signing) {
734                 status = smb2_signing_sign_pdu(req->session->session_key,
735                                         state->vector, 3);
736                 if (!NT_STATUS_IS_OK(status)) {
737                         return status;
738                 }
739         }
740
741         subreq = tstream_writev_queue_send(state,
742                                         req->sconn->smb2.event_ctx,
743                                         req->sconn->smb2.stream,
744                                         req->sconn->smb2.send_queue,
745                                         state->vector,
746                                         3);
747
748         if (subreq == NULL) {
749                 return NT_STATUS_NO_MEMORY;
750         }
751
752         tevent_req_set_callback(subreq,
753                         smbd_smb2_request_pending_writev_done,
754                         state);
755
756         /* Note we're going async with this request. */
757         req->async = true;
758
759         /*
760          * Now manipulate req so that the outstanding async request
761          * is the only one left in the struct smbd_smb2_request.
762          */
763
764         if (req->current_idx == 1) {
765                 /* There was only one. */
766                 goto out;
767         }
768
769         /* Re-arrange the in.vectors. */
770         req->in.vector[1] = req->in.vector[i];
771         req->in.vector[2] = req->in.vector[i+1];
772         req->in.vector[3] = req->in.vector[i+2];
773         req->in.vector_count = 4;
774         /* Reset the new in size. */
775         smb2_setup_nbt_length(req->in.vector, 4);
776
777         /* Now recreate the out.vectors. */
778         outvec = talloc_array(req, struct iovec, 4);
779         if (!outvec) {
780                 return NT_STATUS_NO_MEMORY;
781         }
782         outvec[0].iov_base = req->out.nbt_hdr;
783         outvec[0].iov_len = 4;
784         SIVAL(req->out.nbt_hdr, 0, 0);
785
786         outvec[1].iov_base = talloc_memdup(outvec,
787                                 req->out.vector[i].iov_base,
788                                 SMB2_HDR_BODY + 8);
789         if (!outvec[1].iov_base) {
790                 return NT_STATUS_NO_MEMORY;
791         }
792         outvec[1].iov_len = SMB2_HDR_BODY;
793
794         outvec[2].iov_base = ((uint8_t *)outvec[1].iov_base) +
795                                 SMB2_HDR_BODY;
796         outvec[2].iov_len = 8;
797
798         if (req->out.vector[i+2].iov_base &&
799                         req->out.vector[i+2].iov_len) {
800                 outvec[3].iov_base = talloc_memdup(outvec,
801                                         req->out.vector[i+2].iov_base,
802                                         req->out.vector[i+2].iov_len);
803                 if (!outvec[3].iov_base) {
804                         return NT_STATUS_NO_MEMORY;
805                 }
806                 outvec[3].iov_len = req->out.vector[i+2].iov_len;
807         } else {
808                 outvec[3].iov_base = NULL;
809                 outvec[3].iov_len = 0;
810         }
811
812         TALLOC_FREE(req->out.vector);
813
814         req->out.vector = outvec;
815
816         req->current_idx = 1;
817         req->out.vector_count = 4;
818
819   out:
820
821         smb2_setup_nbt_length(req->out.vector,
822                 req->out.vector_count);
823
824         /* Ensure our final reply matches the interim one. */
825         reqhdr = (uint8_t *)req->out.vector[1].iov_base;
826         SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
827         SBVAL(reqhdr, SMB2_HDR_PID, async_id);
828
829         {
830                 const uint8_t *inhdr =
831                         (const uint8_t *)req->in.vector[1].iov_base;
832                 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
833                         "going async\n",
834                         smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
835                         (unsigned long long)async_id ));
836         }
837         return NT_STATUS_OK;
838 }
839
840 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
841 {
842         struct smbd_server_connection *sconn = req->sconn;
843         struct smbd_smb2_request *cur;
844         const uint8_t *inhdr;
845         int i = req->current_idx;
846         uint32_t flags;
847         uint64_t search_message_id;
848         uint64_t search_async_id;
849         uint64_t found_id;
850
851         inhdr = (const uint8_t *)req->in.vector[i].iov_base;
852
853         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
854         search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
855         search_async_id = BVAL(inhdr, SMB2_HDR_PID);
856
857         /*
858          * we don't need the request anymore
859          * cancel requests never have a response
860          */
861         TALLOC_FREE(req);
862
863         for (cur = sconn->smb2.requests; cur; cur = cur->next) {
864                 const uint8_t *outhdr;
865                 uint64_t message_id;
866                 uint64_t async_id;
867
868                 i = cur->current_idx;
869
870                 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
871
872                 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
873                 async_id = BVAL(outhdr, SMB2_HDR_PID);
874
875                 if (flags & SMB2_HDR_FLAG_ASYNC) {
876                         if (search_async_id == async_id) {
877                                 found_id = async_id;
878                                 break;
879                         }
880                 } else {
881                         if (search_message_id == message_id) {
882                                 found_id = message_id;
883                                 break;
884                         }
885                 }
886         }
887
888         if (cur && cur->subreq) {
889                 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
890                 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
891                         "cancel opcode[%s] mid %llu\n",
892                         smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
893                         (unsigned long long)found_id ));
894                 tevent_req_cancel(cur->subreq);
895         }
896
897         return NT_STATUS_OK;
898 }
899
900 static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
901 {
902         const uint8_t *inhdr;
903         int i = req->current_idx;
904         uint16_t opcode;
905         uint32_t flags;
906         uint64_t mid;
907         NTSTATUS status;
908         NTSTATUS session_status;
909         uint32_t allowed_flags;
910
911         inhdr = (const uint8_t *)req->in.vector[i].iov_base;
912
913         /* TODO: verify more things */
914
915         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
916         opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
917         mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
918         DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
919                 smb2_opcode_name(opcode),
920                 (unsigned long long)mid));
921
922         allowed_flags = SMB2_HDR_FLAG_CHAINED |
923                         SMB2_HDR_FLAG_SIGNED |
924                         SMB2_HDR_FLAG_DFS;
925         if (opcode == SMB2_OP_CANCEL) {
926                 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
927         }
928         if ((flags & ~allowed_flags) != 0) {
929                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
930         }
931
932         session_status = smbd_smb2_request_check_session(req);
933
934         req->do_signing = false;
935         if (flags & SMB2_HDR_FLAG_SIGNED) {
936                 if (!NT_STATUS_IS_OK(session_status)) {
937                         return smbd_smb2_request_error(req, session_status);
938                 }
939
940                 req->do_signing = true;
941                 status = smb2_signing_check_pdu(req->session->session_key,
942                                                 &req->in.vector[i], 3);
943                 if (!NT_STATUS_IS_OK(status)) {
944                         return smbd_smb2_request_error(req, status);
945                 }
946         } else if (req->session && req->session->do_signing) {
947                 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
948         }
949
950         if (flags & SMB2_HDR_FLAG_CHAINED) {
951                 /*
952                  * This check is mostly for giving the correct error code
953                  * for compounded requests.
954                  *
955                  * TODO: we may need to move this after the session
956                  *       and tcon checks.
957                  */
958                 if (!NT_STATUS_IS_OK(req->next_status)) {
959                         return smbd_smb2_request_error(req, req->next_status);
960                 }
961         } else {
962                 req->compat_chain_fsp = NULL;
963         }
964
965         switch (opcode) {
966         case SMB2_OP_NEGPROT:
967                 return smbd_smb2_request_process_negprot(req);
968
969         case SMB2_OP_SESSSETUP:
970                 return smbd_smb2_request_process_sesssetup(req);
971
972         case SMB2_OP_LOGOFF:
973                 if (!NT_STATUS_IS_OK(session_status)) {
974                         return smbd_smb2_request_error(req, session_status);
975                 }
976                 return smbd_smb2_request_process_logoff(req);
977
978         case SMB2_OP_TCON:
979                 if (!NT_STATUS_IS_OK(session_status)) {
980                         return smbd_smb2_request_error(req, session_status);
981                 }
982                 status = smbd_smb2_request_check_session(req);
983                 if (!NT_STATUS_IS_OK(status)) {
984                         return smbd_smb2_request_error(req, status);
985                 }
986                 return smbd_smb2_request_process_tcon(req);
987
988         case SMB2_OP_TDIS:
989                 if (!NT_STATUS_IS_OK(session_status)) {
990                         return smbd_smb2_request_error(req, session_status);
991                 }
992                 status = smbd_smb2_request_check_tcon(req);
993                 if (!NT_STATUS_IS_OK(status)) {
994                         return smbd_smb2_request_error(req, status);
995                 }
996                 return smbd_smb2_request_process_tdis(req);
997
998         case SMB2_OP_CREATE:
999                 if (!NT_STATUS_IS_OK(session_status)) {
1000                         return smbd_smb2_request_error(req, session_status);
1001                 }
1002                 status = smbd_smb2_request_check_tcon(req);
1003                 if (!NT_STATUS_IS_OK(status)) {
1004                         return smbd_smb2_request_error(req, status);
1005                 }
1006                 return smbd_smb2_request_process_create(req);
1007
1008         case SMB2_OP_CLOSE:
1009                 if (!NT_STATUS_IS_OK(session_status)) {
1010                         return smbd_smb2_request_error(req, session_status);
1011                 }
1012                 status = smbd_smb2_request_check_tcon(req);
1013                 if (!NT_STATUS_IS_OK(status)) {
1014                         return smbd_smb2_request_error(req, status);
1015                 }
1016                 return smbd_smb2_request_process_close(req);
1017
1018         case SMB2_OP_FLUSH:
1019                 if (!NT_STATUS_IS_OK(session_status)) {
1020                         return smbd_smb2_request_error(req, session_status);
1021                 }
1022                 status = smbd_smb2_request_check_tcon(req);
1023                 if (!NT_STATUS_IS_OK(status)) {
1024                         return smbd_smb2_request_error(req, status);
1025                 }
1026                 return smbd_smb2_request_process_flush(req);
1027
1028         case SMB2_OP_READ:
1029                 if (!NT_STATUS_IS_OK(session_status)) {
1030                         return smbd_smb2_request_error(req, session_status);
1031                 }
1032                 status = smbd_smb2_request_check_tcon(req);
1033                 if (!NT_STATUS_IS_OK(status)) {
1034                         return smbd_smb2_request_error(req, status);
1035                 }
1036                 return smbd_smb2_request_process_read(req);
1037
1038         case SMB2_OP_WRITE:
1039                 if (!NT_STATUS_IS_OK(session_status)) {
1040                         return smbd_smb2_request_error(req, session_status);
1041                 }
1042                 status = smbd_smb2_request_check_tcon(req);
1043                 if (!NT_STATUS_IS_OK(status)) {
1044                         return smbd_smb2_request_error(req, status);
1045                 }
1046                 return smbd_smb2_request_process_write(req);
1047
1048         case SMB2_OP_LOCK:
1049                 if (!NT_STATUS_IS_OK(session_status)) {
1050                         return smbd_smb2_request_error(req, session_status);
1051                 }
1052                 status = smbd_smb2_request_check_tcon(req);
1053                 if (!NT_STATUS_IS_OK(status)) {
1054                         return smbd_smb2_request_error(req, status);
1055                 }
1056                 return smbd_smb2_request_process_lock(req);
1057
1058         case SMB2_OP_IOCTL:
1059                 if (!NT_STATUS_IS_OK(session_status)) {
1060                         return smbd_smb2_request_error(req, session_status);
1061                 }
1062                 status = smbd_smb2_request_check_tcon(req);
1063                 if (!NT_STATUS_IS_OK(status)) {
1064                         return smbd_smb2_request_error(req, status);
1065                 }
1066                 return smbd_smb2_request_process_ioctl(req);
1067
1068         case SMB2_OP_CANCEL:
1069                 return smbd_smb2_request_process_cancel(req);
1070
1071         case SMB2_OP_KEEPALIVE:
1072                 return smbd_smb2_request_process_keepalive(req);
1073
1074         case SMB2_OP_FIND:
1075                 if (!NT_STATUS_IS_OK(session_status)) {
1076                         return smbd_smb2_request_error(req, session_status);
1077                 }
1078                 status = smbd_smb2_request_check_tcon(req);
1079                 if (!NT_STATUS_IS_OK(status)) {
1080                         return smbd_smb2_request_error(req, status);
1081                 }
1082                 return smbd_smb2_request_process_find(req);
1083
1084         case SMB2_OP_NOTIFY:
1085                 if (!NT_STATUS_IS_OK(session_status)) {
1086                         return smbd_smb2_request_error(req, session_status);
1087                 }
1088                 status = smbd_smb2_request_check_tcon(req);
1089                 if (!NT_STATUS_IS_OK(status)) {
1090                         return smbd_smb2_request_error(req, status);
1091                 }
1092                 return smbd_smb2_request_process_notify(req);
1093
1094         case SMB2_OP_GETINFO:
1095                 if (!NT_STATUS_IS_OK(session_status)) {
1096                         return smbd_smb2_request_error(req, session_status);
1097                 }
1098                 status = smbd_smb2_request_check_tcon(req);
1099                 if (!NT_STATUS_IS_OK(status)) {
1100                         return smbd_smb2_request_error(req, status);
1101                 }
1102                 return smbd_smb2_request_process_getinfo(req);
1103
1104         case SMB2_OP_SETINFO:
1105                 if (!NT_STATUS_IS_OK(session_status)) {
1106                         return smbd_smb2_request_error(req, session_status);
1107                 }
1108                 status = smbd_smb2_request_check_tcon(req);
1109                 if (!NT_STATUS_IS_OK(status)) {
1110                         return smbd_smb2_request_error(req, status);
1111                 }
1112                 return smbd_smb2_request_process_setinfo(req);
1113
1114         case SMB2_OP_BREAK:
1115                 if (!NT_STATUS_IS_OK(session_status)) {
1116                         return smbd_smb2_request_error(req, session_status);
1117                 }
1118                 status = smbd_smb2_request_check_tcon(req);
1119                 if (!NT_STATUS_IS_OK(status)) {
1120                         return smbd_smb2_request_error(req, status);
1121                 }
1122                 return smbd_smb2_request_process_break(req);
1123         }
1124
1125         return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1126 }
1127
1128 static void smbd_smb2_request_dispatch_compound(struct tevent_context *ctx,
1129                                         struct tevent_immediate *im,
1130                                         void *private_data);
1131
1132 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1133 {
1134         struct tevent_req *subreq;
1135
1136         req->subreq = NULL;
1137
1138         smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1139
1140         if (req->do_signing) {
1141                 int i = req->current_idx;
1142                 NTSTATUS status;
1143                 status = smb2_signing_sign_pdu(req->session->session_key,
1144                                                &req->out.vector[i], 3);
1145                 if (!NT_STATUS_IS_OK(status)) {
1146                         return status;
1147                 }
1148         }
1149
1150         req->current_idx += 3;
1151
1152         if (req->current_idx < req->out.vector_count) {
1153                 /*
1154                  * We must process the remaining compound
1155                  * SMB2 requests before any new incoming SMB2
1156                  * requests. This is because incoming SMB2
1157                  * requests may include a cancel for a
1158                  * compound request we haven't processed
1159                  * yet.
1160                  */
1161                 struct tevent_immediate *im = tevent_create_immediate(req);
1162                 if (!im) {
1163                         return NT_STATUS_NO_MEMORY;
1164                 }
1165                 tevent_schedule_immediate(im,
1166                                         req->sconn->smb2.event_ctx,
1167                                         smbd_smb2_request_dispatch_compound,
1168                                         req);
1169                 return NT_STATUS_OK;
1170         }
1171
1172         if (DEBUGLEVEL >= 10) {
1173                 dbgtext("smbd_smb2_request_reply: sending...\n");
1174                 print_req_vectors(req);
1175         }
1176
1177         subreq = tstream_writev_queue_send(req,
1178                                            req->sconn->smb2.event_ctx,
1179                                            req->sconn->smb2.stream,
1180                                            req->sconn->smb2.send_queue,
1181                                            req->out.vector,
1182                                            req->out.vector_count);
1183         if (subreq == NULL) {
1184                 return NT_STATUS_NO_MEMORY;
1185         }
1186         tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1187
1188         return NT_STATUS_OK;
1189 }
1190
1191 static void smbd_smb2_request_dispatch_compound(struct tevent_context *ctx,
1192                                         struct tevent_immediate *im,
1193                                         void *private_data)
1194 {
1195         struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1196                                         struct smbd_smb2_request);
1197         struct smbd_server_connection *sconn = req->sconn;
1198         NTSTATUS status;
1199
1200         TALLOC_FREE(im);
1201
1202         if (DEBUGLEVEL >= 10) {
1203                 DEBUG(10,("smbd_smb2_request_dispatch_compound: idx[%d] of %d vectors\n",
1204                         req->current_idx, req->in.vector_count));
1205                 print_req_vectors(req);
1206         }
1207
1208         status = smbd_smb2_request_dispatch(req);
1209         if (!NT_STATUS_IS_OK(status)) {
1210                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1211                 return;
1212         }
1213 }
1214
1215 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1216 {
1217         struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1218                                         struct smbd_smb2_request);
1219         struct smbd_server_connection *sconn = req->sconn;
1220         int ret;
1221         int sys_errno;
1222
1223         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1224         TALLOC_FREE(subreq);
1225         TALLOC_FREE(req);
1226         if (ret == -1) {
1227                 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1228                 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1229                         nt_errstr(status)));
1230                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1231                 return;
1232         }
1233 }
1234
1235 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
1236                                     NTSTATUS status,
1237                                     DATA_BLOB *info,
1238                                     const char *location)
1239 {
1240         uint8_t *outhdr;
1241         uint8_t *outbody;
1242         int i = req->current_idx;
1243
1244         DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1245                   i, nt_errstr(status), info ? " +info" : "",
1246                   location));
1247
1248         outhdr = (uint8_t *)req->out.vector[i].iov_base;
1249
1250         SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1251
1252         outbody = outhdr + SMB2_HDR_BODY;
1253         SSVAL(outbody, 0, 9);
1254
1255         req->out.vector[i+1].iov_base = (void *)outbody;
1256         req->out.vector[i+1].iov_len = 8;
1257
1258         if (info) {
1259                 SIVAL(outbody, 0x04, info->length);
1260                 req->out.vector[i+2].iov_base   = (void *)info->data;
1261                 req->out.vector[i+2].iov_len    = info->length;
1262         } else {
1263                 req->out.vector[i+2].iov_base = talloc_array(req, uint8_t, 1);
1264                 if (!req->out.vector[i+2].iov_base) {
1265                         return NT_STATUS_NO_MEMORY;
1266                 }
1267                 SCVAL(req->out.vector[i+2].iov_base, 0, 0);
1268                 req->out.vector[i+2].iov_len = 1;
1269         }
1270
1271         /*
1272          * if a request fails, all other remaining
1273          * compounded requests should fail too
1274          */
1275         req->next_status = NT_STATUS_INVALID_PARAMETER;
1276
1277         return smbd_smb2_request_reply(req);
1278 }
1279
1280 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1281                                    NTSTATUS status,
1282                                    DATA_BLOB body, DATA_BLOB *dyn,
1283                                    const char *location)
1284 {
1285         uint8_t *outhdr;
1286         uint8_t *outdyn;
1287         int i = req->current_idx;
1288         uint32_t next_command_ofs;
1289
1290         DEBUG(10,("smbd_smb2_request_done_ex: "
1291                   "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1292                   i, nt_errstr(status), (unsigned int)body.length,
1293                   dyn ? "yes": "no",
1294                   (unsigned int)(dyn ? dyn->length : 0),
1295                   location));
1296
1297         if (body.length < 2) {
1298                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1299         }
1300
1301         if ((body.length % 2) != 0) {
1302                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1303         }
1304
1305         outhdr = (uint8_t *)req->out.vector[i].iov_base;
1306         /* the fallback dynamic buffer */
1307         outdyn = outhdr + SMB2_HDR_BODY + 8;
1308
1309         next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1310         SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1311
1312         req->out.vector[i+1].iov_base = (void *)body.data;
1313         req->out.vector[i+1].iov_len = body.length;
1314
1315         if (dyn) {
1316                 req->out.vector[i+2].iov_base   = (void *)dyn->data;
1317                 req->out.vector[i+2].iov_len    = dyn->length;
1318         } else {
1319                 req->out.vector[i+2].iov_base = NULL;
1320                 req->out.vector[i+2].iov_len = 0;
1321         }
1322
1323         /* see if we need to recalculate the offset to the next response */
1324         if (next_command_ofs > 0) {
1325                 next_command_ofs  = SMB2_HDR_BODY;
1326                 next_command_ofs += req->out.vector[i+1].iov_len;
1327                 next_command_ofs += req->out.vector[i+2].iov_len;
1328         }
1329
1330         if ((next_command_ofs % 8) != 0) {
1331                 size_t pad_size = 8 - (next_command_ofs % 8);
1332                 if (req->out.vector[i+2].iov_len == 0) {
1333                         /*
1334                          * if the dyn buffer is empty
1335                          * we can use it to add padding
1336                          */
1337                         uint8_t *pad;
1338
1339                         pad = talloc_zero_array(req->out.vector,
1340                                                 uint8_t, pad_size);
1341                         if (pad == NULL) {
1342                                 return smbd_smb2_request_error(req,
1343                                                 NT_STATUS_NO_MEMORY);
1344                         }
1345
1346                         req->out.vector[i+2].iov_base = (void *)pad;
1347                         req->out.vector[i+2].iov_len = pad_size;
1348                 } else {
1349                         /*
1350                          * For now we copy the dynamic buffer
1351                          * and add the padding to the new buffer
1352                          */
1353                         size_t old_size;
1354                         uint8_t *old_dyn;
1355                         size_t new_size;
1356                         uint8_t *new_dyn;
1357
1358                         old_size = req->out.vector[i+2].iov_len;
1359                         old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1360
1361                         new_size = old_size + pad_size;
1362                         new_dyn = talloc_array(req->out.vector,
1363                                                uint8_t, new_size);
1364                         if (new_dyn == NULL) {
1365                                 return smbd_smb2_request_error(req,
1366                                                 NT_STATUS_NO_MEMORY);
1367                         }
1368
1369                         memcpy(new_dyn, old_dyn, old_size);
1370                         memset(new_dyn + old_size, 0, pad_size);
1371
1372                         req->out.vector[i+2].iov_base = (void *)new_dyn;
1373                         req->out.vector[i+2].iov_len = new_size;
1374
1375                         TALLOC_FREE(old_dyn);
1376                 }
1377                 next_command_ofs += pad_size;
1378         }
1379
1380         SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1381
1382         return smbd_smb2_request_reply(req);
1383 }
1384
1385 struct smbd_smb2_send_oplock_break_state {
1386         struct smbd_server_connection *sconn;
1387         uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
1388         struct iovec vector;
1389 };
1390
1391 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
1392
1393 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
1394                                      uint64_t file_id_persistent,
1395                                      uint64_t file_id_volatile,
1396                                      uint8_t oplock_level)
1397 {
1398         struct smbd_smb2_send_oplock_break_state *state;
1399         struct tevent_req *subreq;
1400         uint8_t *hdr;
1401         uint8_t *body;
1402
1403         state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
1404         if (state == NULL) {
1405                 return NT_STATUS_NO_MEMORY;
1406         }
1407         state->sconn = sconn;
1408
1409         state->vector.iov_base = (void *)state->buf;
1410         state->vector.iov_len = sizeof(state->buf);
1411
1412         _smb2_setlen(state->buf, sizeof(state->buf) - 4);
1413         hdr = state->buf + 4;
1414         body = hdr + SMB2_HDR_BODY;
1415
1416         SIVAL(hdr, 0,                           SMB2_MAGIC);
1417         SSVAL(hdr, SMB2_HDR_LENGTH,             SMB2_HDR_BODY);
1418         SSVAL(hdr, SMB2_HDR_EPOCH,              0);
1419         SIVAL(hdr, SMB2_HDR_STATUS,             0);
1420         SSVAL(hdr, SMB2_HDR_OPCODE,             SMB2_OP_BREAK);
1421         SSVAL(hdr, SMB2_HDR_CREDIT,             0);
1422         SIVAL(hdr, SMB2_HDR_FLAGS,              SMB2_HDR_FLAG_REDIRECT);
1423         SIVAL(hdr, SMB2_HDR_NEXT_COMMAND,       0);
1424         SBVAL(hdr, SMB2_HDR_MESSAGE_ID,         UINT64_MAX);
1425         SIVAL(hdr, SMB2_HDR_PID,                0);
1426         SIVAL(hdr, SMB2_HDR_TID,                0);
1427         SBVAL(hdr, SMB2_HDR_SESSION_ID,         0);
1428         memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1429
1430         SSVAL(body, 0x00, 0x18);
1431
1432         SCVAL(body, 0x02, oplock_level);
1433         SCVAL(body, 0x03, 0);           /* reserved */
1434         SIVAL(body, 0x04, 0);           /* reserved */
1435         SBVAL(body, 0x08, file_id_persistent);
1436         SBVAL(body, 0x10, file_id_volatile);
1437
1438         subreq = tstream_writev_queue_send(state,
1439                                            sconn->smb2.event_ctx,
1440                                            sconn->smb2.stream,
1441                                            sconn->smb2.send_queue,
1442                                            &state->vector, 1);
1443         if (subreq == NULL) {
1444                 return NT_STATUS_NO_MEMORY;
1445         }
1446         tevent_req_set_callback(subreq,
1447                                 smbd_smb2_oplock_break_writev_done,
1448                                 state);
1449
1450         return NT_STATUS_OK;
1451 }
1452
1453 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
1454 {
1455         struct smbd_smb2_send_oplock_break_state *state =
1456                 tevent_req_callback_data(subreq,
1457                 struct smbd_smb2_send_oplock_break_state);
1458         struct smbd_server_connection *sconn = state->sconn;
1459         int ret;
1460         int sys_errno;
1461
1462         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1463         TALLOC_FREE(subreq);
1464         if (ret == -1) {
1465                 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1466                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1467                 return;
1468         }
1469
1470         TALLOC_FREE(state);
1471 }
1472
1473 struct smbd_smb2_request_read_state {
1474         size_t missing;
1475         bool asked_for_header;
1476         struct smbd_smb2_request *smb2_req;
1477 };
1478
1479 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1480                                          void *private_data,
1481                                          TALLOC_CTX *mem_ctx,
1482                                          struct iovec **_vector,
1483                                          size_t *_count);
1484 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
1485
1486 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
1487                                         struct tevent_context *ev,
1488                                         struct smbd_server_connection *sconn)
1489 {
1490         struct tevent_req *req;
1491         struct smbd_smb2_request_read_state *state;
1492         struct tevent_req *subreq;
1493
1494         req = tevent_req_create(mem_ctx, &state,
1495                                 struct smbd_smb2_request_read_state);
1496         if (req == NULL) {
1497                 return NULL;
1498         }
1499         state->missing = 0;
1500         state->asked_for_header = false;
1501
1502         state->smb2_req = smbd_smb2_request_allocate(state);
1503         if (tevent_req_nomem(state->smb2_req, req)) {
1504                 return tevent_req_post(req, ev);
1505         }
1506         state->smb2_req->sconn = sconn;
1507
1508         subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
1509                                               sconn->smb2.recv_queue,
1510                                               smbd_smb2_request_next_vector,
1511                                               state);
1512         if (tevent_req_nomem(subreq, req)) {
1513                 return tevent_req_post(req, ev);
1514         }
1515         tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
1516
1517         return req;
1518 }
1519
1520 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1521                                          void *private_data,
1522                                          TALLOC_CTX *mem_ctx,
1523                                          struct iovec **_vector,
1524                                          size_t *_count)
1525 {
1526         struct smbd_smb2_request_read_state *state =
1527                 talloc_get_type_abort(private_data,
1528                 struct smbd_smb2_request_read_state);
1529         struct smbd_smb2_request *req = state->smb2_req;
1530         struct iovec *vector;
1531         int idx = req->in.vector_count;
1532         size_t len = 0;
1533         uint8_t *buf = NULL;
1534
1535         if (req->in.vector_count == 0) {
1536                 /*
1537                  * first we need to get the NBT header
1538                  */
1539                 req->in.vector = talloc_array(req, struct iovec,
1540                                               req->in.vector_count + 1);
1541                 if (req->in.vector == NULL) {
1542                         return -1;
1543                 }
1544                 req->in.vector_count += 1;
1545
1546                 req->in.vector[idx].iov_base    = (void *)req->in.nbt_hdr;
1547                 req->in.vector[idx].iov_len     = 4;
1548
1549                 vector = talloc_array(mem_ctx, struct iovec, 1);
1550                 if (vector == NULL) {
1551                         return -1;
1552                 }
1553
1554                 vector[0] = req->in.vector[idx];
1555
1556                 *_vector = vector;
1557                 *_count = 1;
1558                 return 0;
1559         }
1560
1561         if (req->in.vector_count == 1) {
1562                 /*
1563                  * Now we analyze the NBT header
1564                  */
1565                 state->missing = smb2_len(req->in.vector[0].iov_base);
1566
1567                 if (state->missing == 0) {
1568                         /* if there're no remaining bytes, we're done */
1569                         *_vector = NULL;
1570                         *_count = 0;
1571                         return 0;
1572                 }
1573
1574                 req->in.vector = talloc_realloc(req, req->in.vector,
1575                                                 struct iovec,
1576                                                 req->in.vector_count + 1);
1577                 if (req->in.vector == NULL) {
1578                         return -1;
1579                 }
1580                 req->in.vector_count += 1;
1581
1582                 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
1583                         /*
1584                          * it's a special NBT message,
1585                          * so get all remaining bytes
1586                          */
1587                         len = state->missing;
1588                 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
1589                         /*
1590                          * it's an invalid message, just read what we can get
1591                          * and let the caller handle the error
1592                          */
1593                         len = state->missing;
1594                 } else {
1595                         /*
1596                          * We assume it's a SMB2 request,
1597                          * and we first get the header and the
1598                          * first 2 bytes (the struct size) of the body
1599                          */
1600                         len = SMB2_HDR_BODY + 2;
1601
1602                         state->asked_for_header = true;
1603                 }
1604
1605                 state->missing -= len;
1606
1607                 buf = talloc_array(req->in.vector, uint8_t, len);
1608                 if (buf == NULL) {
1609                         return -1;
1610                 }
1611
1612                 req->in.vector[idx].iov_base    = (void *)buf;
1613                 req->in.vector[idx].iov_len     = len;
1614
1615                 vector = talloc_array(mem_ctx, struct iovec, 1);
1616                 if (vector == NULL) {
1617                         return -1;
1618                 }
1619
1620                 vector[0] = req->in.vector[idx];
1621
1622                 *_vector = vector;
1623                 *_count = 1;
1624                 return 0;
1625         }
1626
1627         if (state->missing == 0) {
1628                 /* if there're no remaining bytes, we're done */
1629                 *_vector = NULL;
1630                 *_count = 0;
1631                 return 0;
1632         }
1633
1634         if (state->asked_for_header) {
1635                 const uint8_t *hdr;
1636                 size_t full_size;
1637                 size_t next_command_ofs;
1638                 size_t body_size;
1639                 uint8_t *body;
1640                 size_t dyn_size;
1641                 uint8_t *dyn;
1642                 bool invalid = false;
1643
1644                 state->asked_for_header = false;
1645
1646                 /*
1647                  * We got the SMB2 header and the first 2 bytes
1648                  * of the body. We fix the size to just the header
1649                  * and manually copy the 2 first bytes to the body section
1650                  */
1651                 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
1652                 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
1653
1654                 /* allocate vectors for body and dynamic areas */
1655                 req->in.vector = talloc_realloc(req, req->in.vector,
1656                                                 struct iovec,
1657                                                 req->in.vector_count + 2);
1658                 if (req->in.vector == NULL) {
1659                         return -1;
1660                 }
1661                 req->in.vector_count += 2;
1662
1663                 full_size = state->missing + SMB2_HDR_BODY + 2;
1664                 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
1665                 body_size = SVAL(hdr, SMB2_HDR_BODY);
1666
1667                 if (next_command_ofs != 0) {
1668                         if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
1669                                 /*
1670                                  * this is invalid, just return a zero
1671                                  * body and let the caller deal with the error
1672                                  */
1673                                 invalid = true;
1674                         } else if (next_command_ofs > full_size) {
1675                                 /*
1676                                  * this is invalid, just return a zero
1677                                  * body and let the caller deal with the error
1678                                  */
1679                                 invalid = true;
1680                         } else {
1681                                 full_size = next_command_ofs;
1682                         }
1683                 }
1684
1685                 if (!invalid) {
1686                         if (body_size < 2) {
1687                                 /*
1688                                  * this is invalid, just return a zero
1689                                  * body and let the caller deal with the error
1690                                  */
1691                                 invalid = true;
1692                         }
1693
1694                         if ((body_size % 2) != 0) {
1695                                 body_size -= 1;
1696                         }
1697
1698                         if (body_size > (full_size - SMB2_HDR_BODY)) {
1699                                 /*
1700                                  * this is invalid, just return a zero
1701                                  * body and let the caller deal with the error
1702                                  */
1703                                 invalid = true;
1704                         }
1705                 }
1706
1707                 if (invalid) {
1708                         /* the caller should check this */
1709                         body_size = 2;
1710                 }
1711
1712                 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
1713
1714                 state->missing -= (body_size - 2) + dyn_size;
1715
1716                 body = talloc_array(req->in.vector, uint8_t, body_size);
1717                 if (body == NULL) {
1718                         return -1;
1719                 }
1720
1721                 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
1722                 if (dyn == NULL) {
1723                         return -1;
1724                 }
1725
1726                 req->in.vector[idx].iov_base    = (void *)body;
1727                 req->in.vector[idx].iov_len     = body_size;
1728                 req->in.vector[idx+1].iov_base  = (void *)dyn;
1729                 req->in.vector[idx+1].iov_len   = dyn_size;
1730
1731                 vector = talloc_array(mem_ctx, struct iovec, 2);
1732                 if (vector == NULL) {
1733                         return -1;
1734                 }
1735
1736                 /*
1737                  * the first 2 bytes of the body were already fetched
1738                  * together with the header
1739                  */
1740                 memcpy(body, hdr + SMB2_HDR_BODY, 2);
1741                 vector[0].iov_base = body + 2;
1742                 vector[0].iov_len = body_size - 2;
1743
1744                 vector[1] = req->in.vector[idx+1];
1745
1746                 *_vector = vector;
1747                 *_count = 2;
1748                 return 0;
1749         }
1750
1751         /*
1752          * when we endup here, we're looking for a new SMB2 request
1753          * next. And we ask for its header and the first 2 bytes of
1754          * the body (like we did for the first SMB2 request).
1755          */
1756
1757         req->in.vector = talloc_realloc(req, req->in.vector,
1758                                         struct iovec,
1759                                         req->in.vector_count + 1);
1760         if (req->in.vector == NULL) {
1761                 return -1;
1762         }
1763         req->in.vector_count += 1;
1764
1765         /*
1766          * We assume it's a SMB2 request,
1767          * and we first get the header and the
1768          * first 2 bytes (the struct size) of the body
1769          */
1770         len = SMB2_HDR_BODY + 2;
1771
1772         if (len > state->missing) {
1773                 /* let the caller handle the error */
1774                 len = state->missing;
1775         }
1776
1777         state->missing -= len;
1778         state->asked_for_header = true;
1779
1780         buf = talloc_array(req->in.vector, uint8_t, len);
1781         if (buf == NULL) {
1782                 return -1;
1783         }
1784
1785         req->in.vector[idx].iov_base    = (void *)buf;
1786         req->in.vector[idx].iov_len     = len;
1787
1788         vector = talloc_array(mem_ctx, struct iovec, 1);
1789         if (vector == NULL) {
1790                 return -1;
1791         }
1792
1793         vector[0] = req->in.vector[idx];
1794
1795         *_vector = vector;
1796         *_count = 1;
1797         return 0;
1798 }
1799
1800 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
1801 {
1802         struct tevent_req *req =
1803                 tevent_req_callback_data(subreq,
1804                 struct tevent_req);
1805         int ret;
1806         int sys_errno;
1807         NTSTATUS status;
1808
1809         ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
1810         if (ret == -1) {
1811                 status = map_nt_error_from_unix(sys_errno);
1812                 tevent_req_nterror(req, status);
1813                 return;
1814         }
1815
1816         tevent_req_done(req);
1817 }
1818
1819 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
1820                                             TALLOC_CTX *mem_ctx,
1821                                             struct smbd_smb2_request **_smb2_req)
1822 {
1823         struct smbd_smb2_request_read_state *state =
1824                 tevent_req_data(req,
1825                 struct smbd_smb2_request_read_state);
1826         NTSTATUS status;
1827
1828         if (tevent_req_is_nterror(req, &status)) {
1829                 tevent_req_received(req);
1830                 return status;
1831         }
1832
1833         talloc_steal(mem_ctx, state->smb2_req->mem_pool);
1834         *_smb2_req = state->smb2_req;
1835         tevent_req_received(req);
1836         return NT_STATUS_OK;
1837 }
1838
1839 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
1840
1841 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
1842                              const uint8_t *inbuf, size_t size)
1843 {
1844         NTSTATUS status;
1845         struct smbd_smb2_request *req;
1846         struct tevent_req *subreq;
1847
1848         DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
1849                  (unsigned int)size));
1850
1851         status = smbd_initialize_smb2(sconn);
1852         if (!NT_STATUS_IS_OK(status)) {
1853                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1854                 return;
1855         }
1856
1857         status = smbd_smb2_request_create(sconn, inbuf, size, &req);
1858         if (!NT_STATUS_IS_OK(status)) {
1859                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1860                 return;
1861         }
1862
1863         status = smbd_smb2_request_setup_out(req, (uint16_t)lp_maxmux());
1864         if (!NT_STATUS_IS_OK(status)) {
1865                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1866                 return;
1867         }
1868
1869         status = smbd_smb2_request_dispatch(req);
1870         if (!NT_STATUS_IS_OK(status)) {
1871                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1872                 return;
1873         }
1874
1875         /* ask for the next request */
1876         subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
1877         if (subreq == NULL) {
1878                 smbd_server_connection_terminate(sconn, "no memory for reading");
1879                 return;
1880         }
1881         tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
1882 }
1883
1884 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
1885 {
1886         uint16_t creds_requested = 0;
1887         struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
1888                                                struct smbd_server_connection);
1889         NTSTATUS status;
1890         struct smbd_smb2_request *req = NULL;
1891
1892         status = smbd_smb2_request_read_recv(subreq, sconn, &req);
1893         TALLOC_FREE(subreq);
1894         if (!NT_STATUS_IS_OK(status)) {
1895                 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
1896                         nt_errstr(status)));
1897                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1898                 return;
1899         }
1900
1901         if (req->in.nbt_hdr[0] != 0x00) {
1902                 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
1903                          req->in.nbt_hdr[0]));
1904                 TALLOC_FREE(req);
1905                 goto next;
1906         }
1907
1908         req->current_idx = 1;
1909
1910         DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
1911                  req->current_idx, req->in.vector_count));
1912
1913         status = smbd_smb2_request_validate(req, &creds_requested);
1914         if (!NT_STATUS_IS_OK(status)) {
1915                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1916                 return;
1917         }
1918
1919         status = smbd_smb2_request_setup_out(req, 5);
1920         if (!NT_STATUS_IS_OK(status)) {
1921                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1922                 return;
1923         }
1924
1925         status = smbd_smb2_request_dispatch(req);
1926         if (!NT_STATUS_IS_OK(status)) {
1927                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1928                 return;
1929         }
1930
1931 next:
1932         /* ask for the next request (this constructs the main loop) */
1933         subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
1934         if (subreq == NULL) {
1935                 smbd_server_connection_terminate(sconn, "no memory for reading");
1936                 return;
1937         }
1938         tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
1939 }