Remove an unused auto variable.
[amitay/samba.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 = (uint8_t *)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 = (uint8_t *)state->vector[1].iov_base;
709         body = (uint8_t *)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         int i = req->current_idx;
1287         uint32_t next_command_ofs;
1288
1289         DEBUG(10,("smbd_smb2_request_done_ex: "
1290                   "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1291                   i, nt_errstr(status), (unsigned int)body.length,
1292                   dyn ? "yes": "no",
1293                   (unsigned int)(dyn ? dyn->length : 0),
1294                   location));
1295
1296         if (body.length < 2) {
1297                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1298         }
1299
1300         if ((body.length % 2) != 0) {
1301                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1302         }
1303
1304         outhdr = (uint8_t *)req->out.vector[i].iov_base;
1305
1306         next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1307         SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1308
1309         req->out.vector[i+1].iov_base = (void *)body.data;
1310         req->out.vector[i+1].iov_len = body.length;
1311
1312         if (dyn) {
1313                 req->out.vector[i+2].iov_base   = (void *)dyn->data;
1314                 req->out.vector[i+2].iov_len    = dyn->length;
1315         } else {
1316                 req->out.vector[i+2].iov_base = NULL;
1317                 req->out.vector[i+2].iov_len = 0;
1318         }
1319
1320         /* see if we need to recalculate the offset to the next response */
1321         if (next_command_ofs > 0) {
1322                 next_command_ofs  = SMB2_HDR_BODY;
1323                 next_command_ofs += req->out.vector[i+1].iov_len;
1324                 next_command_ofs += req->out.vector[i+2].iov_len;
1325         }
1326
1327         if ((next_command_ofs % 8) != 0) {
1328                 size_t pad_size = 8 - (next_command_ofs % 8);
1329                 if (req->out.vector[i+2].iov_len == 0) {
1330                         /*
1331                          * if the dyn buffer is empty
1332                          * we can use it to add padding
1333                          */
1334                         uint8_t *pad;
1335
1336                         pad = talloc_zero_array(req->out.vector,
1337                                                 uint8_t, pad_size);
1338                         if (pad == NULL) {
1339                                 return smbd_smb2_request_error(req,
1340                                                 NT_STATUS_NO_MEMORY);
1341                         }
1342
1343                         req->out.vector[i+2].iov_base = (void *)pad;
1344                         req->out.vector[i+2].iov_len = pad_size;
1345                 } else {
1346                         /*
1347                          * For now we copy the dynamic buffer
1348                          * and add the padding to the new buffer
1349                          */
1350                         size_t old_size;
1351                         uint8_t *old_dyn;
1352                         size_t new_size;
1353                         uint8_t *new_dyn;
1354
1355                         old_size = req->out.vector[i+2].iov_len;
1356                         old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1357
1358                         new_size = old_size + pad_size;
1359                         new_dyn = talloc_array(req->out.vector,
1360                                                uint8_t, new_size);
1361                         if (new_dyn == NULL) {
1362                                 return smbd_smb2_request_error(req,
1363                                                 NT_STATUS_NO_MEMORY);
1364                         }
1365
1366                         memcpy(new_dyn, old_dyn, old_size);
1367                         memset(new_dyn + old_size, 0, pad_size);
1368
1369                         req->out.vector[i+2].iov_base = (void *)new_dyn;
1370                         req->out.vector[i+2].iov_len = new_size;
1371
1372                         TALLOC_FREE(old_dyn);
1373                 }
1374                 next_command_ofs += pad_size;
1375         }
1376
1377         SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1378
1379         return smbd_smb2_request_reply(req);
1380 }
1381
1382 struct smbd_smb2_send_oplock_break_state {
1383         struct smbd_server_connection *sconn;
1384         uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
1385         struct iovec vector;
1386 };
1387
1388 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
1389
1390 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
1391                                      uint64_t file_id_persistent,
1392                                      uint64_t file_id_volatile,
1393                                      uint8_t oplock_level)
1394 {
1395         struct smbd_smb2_send_oplock_break_state *state;
1396         struct tevent_req *subreq;
1397         uint8_t *hdr;
1398         uint8_t *body;
1399
1400         state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
1401         if (state == NULL) {
1402                 return NT_STATUS_NO_MEMORY;
1403         }
1404         state->sconn = sconn;
1405
1406         state->vector.iov_base = (void *)state->buf;
1407         state->vector.iov_len = sizeof(state->buf);
1408
1409         _smb2_setlen(state->buf, sizeof(state->buf) - 4);
1410         hdr = state->buf + 4;
1411         body = hdr + SMB2_HDR_BODY;
1412
1413         SIVAL(hdr, 0,                           SMB2_MAGIC);
1414         SSVAL(hdr, SMB2_HDR_LENGTH,             SMB2_HDR_BODY);
1415         SSVAL(hdr, SMB2_HDR_EPOCH,              0);
1416         SIVAL(hdr, SMB2_HDR_STATUS,             0);
1417         SSVAL(hdr, SMB2_HDR_OPCODE,             SMB2_OP_BREAK);
1418         SSVAL(hdr, SMB2_HDR_CREDIT,             0);
1419         SIVAL(hdr, SMB2_HDR_FLAGS,              SMB2_HDR_FLAG_REDIRECT);
1420         SIVAL(hdr, SMB2_HDR_NEXT_COMMAND,       0);
1421         SBVAL(hdr, SMB2_HDR_MESSAGE_ID,         UINT64_MAX);
1422         SIVAL(hdr, SMB2_HDR_PID,                0);
1423         SIVAL(hdr, SMB2_HDR_TID,                0);
1424         SBVAL(hdr, SMB2_HDR_SESSION_ID,         0);
1425         memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1426
1427         SSVAL(body, 0x00, 0x18);
1428
1429         SCVAL(body, 0x02, oplock_level);
1430         SCVAL(body, 0x03, 0);           /* reserved */
1431         SIVAL(body, 0x04, 0);           /* reserved */
1432         SBVAL(body, 0x08, file_id_persistent);
1433         SBVAL(body, 0x10, file_id_volatile);
1434
1435         subreq = tstream_writev_queue_send(state,
1436                                            sconn->smb2.event_ctx,
1437                                            sconn->smb2.stream,
1438                                            sconn->smb2.send_queue,
1439                                            &state->vector, 1);
1440         if (subreq == NULL) {
1441                 return NT_STATUS_NO_MEMORY;
1442         }
1443         tevent_req_set_callback(subreq,
1444                                 smbd_smb2_oplock_break_writev_done,
1445                                 state);
1446
1447         return NT_STATUS_OK;
1448 }
1449
1450 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
1451 {
1452         struct smbd_smb2_send_oplock_break_state *state =
1453                 tevent_req_callback_data(subreq,
1454                 struct smbd_smb2_send_oplock_break_state);
1455         struct smbd_server_connection *sconn = state->sconn;
1456         int ret;
1457         int sys_errno;
1458
1459         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1460         TALLOC_FREE(subreq);
1461         if (ret == -1) {
1462                 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1463                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1464                 return;
1465         }
1466
1467         TALLOC_FREE(state);
1468 }
1469
1470 struct smbd_smb2_request_read_state {
1471         size_t missing;
1472         bool asked_for_header;
1473         struct smbd_smb2_request *smb2_req;
1474 };
1475
1476 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1477                                          void *private_data,
1478                                          TALLOC_CTX *mem_ctx,
1479                                          struct iovec **_vector,
1480                                          size_t *_count);
1481 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
1482
1483 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
1484                                         struct tevent_context *ev,
1485                                         struct smbd_server_connection *sconn)
1486 {
1487         struct tevent_req *req;
1488         struct smbd_smb2_request_read_state *state;
1489         struct tevent_req *subreq;
1490
1491         req = tevent_req_create(mem_ctx, &state,
1492                                 struct smbd_smb2_request_read_state);
1493         if (req == NULL) {
1494                 return NULL;
1495         }
1496         state->missing = 0;
1497         state->asked_for_header = false;
1498
1499         state->smb2_req = smbd_smb2_request_allocate(state);
1500         if (tevent_req_nomem(state->smb2_req, req)) {
1501                 return tevent_req_post(req, ev);
1502         }
1503         state->smb2_req->sconn = sconn;
1504
1505         subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
1506                                               sconn->smb2.recv_queue,
1507                                               smbd_smb2_request_next_vector,
1508                                               state);
1509         if (tevent_req_nomem(subreq, req)) {
1510                 return tevent_req_post(req, ev);
1511         }
1512         tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
1513
1514         return req;
1515 }
1516
1517 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1518                                          void *private_data,
1519                                          TALLOC_CTX *mem_ctx,
1520                                          struct iovec **_vector,
1521                                          size_t *_count)
1522 {
1523         struct smbd_smb2_request_read_state *state =
1524                 talloc_get_type_abort(private_data,
1525                 struct smbd_smb2_request_read_state);
1526         struct smbd_smb2_request *req = state->smb2_req;
1527         struct iovec *vector;
1528         int idx = req->in.vector_count;
1529         size_t len = 0;
1530         uint8_t *buf = NULL;
1531
1532         if (req->in.vector_count == 0) {
1533                 /*
1534                  * first we need to get the NBT header
1535                  */
1536                 req->in.vector = talloc_array(req, struct iovec,
1537                                               req->in.vector_count + 1);
1538                 if (req->in.vector == NULL) {
1539                         return -1;
1540                 }
1541                 req->in.vector_count += 1;
1542
1543                 req->in.vector[idx].iov_base    = (void *)req->in.nbt_hdr;
1544                 req->in.vector[idx].iov_len     = 4;
1545
1546                 vector = talloc_array(mem_ctx, struct iovec, 1);
1547                 if (vector == NULL) {
1548                         return -1;
1549                 }
1550
1551                 vector[0] = req->in.vector[idx];
1552
1553                 *_vector = vector;
1554                 *_count = 1;
1555                 return 0;
1556         }
1557
1558         if (req->in.vector_count == 1) {
1559                 /*
1560                  * Now we analyze the NBT header
1561                  */
1562                 state->missing = smb2_len(req->in.vector[0].iov_base);
1563
1564                 if (state->missing == 0) {
1565                         /* if there're no remaining bytes, we're done */
1566                         *_vector = NULL;
1567                         *_count = 0;
1568                         return 0;
1569                 }
1570
1571                 req->in.vector = talloc_realloc(req, req->in.vector,
1572                                                 struct iovec,
1573                                                 req->in.vector_count + 1);
1574                 if (req->in.vector == NULL) {
1575                         return -1;
1576                 }
1577                 req->in.vector_count += 1;
1578
1579                 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
1580                         /*
1581                          * it's a special NBT message,
1582                          * so get all remaining bytes
1583                          */
1584                         len = state->missing;
1585                 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
1586                         /*
1587                          * it's an invalid message, just read what we can get
1588                          * and let the caller handle the error
1589                          */
1590                         len = state->missing;
1591                 } else {
1592                         /*
1593                          * We assume it's a SMB2 request,
1594                          * and we first get the header and the
1595                          * first 2 bytes (the struct size) of the body
1596                          */
1597                         len = SMB2_HDR_BODY + 2;
1598
1599                         state->asked_for_header = true;
1600                 }
1601
1602                 state->missing -= len;
1603
1604                 buf = talloc_array(req->in.vector, uint8_t, len);
1605                 if (buf == NULL) {
1606                         return -1;
1607                 }
1608
1609                 req->in.vector[idx].iov_base    = (void *)buf;
1610                 req->in.vector[idx].iov_len     = len;
1611
1612                 vector = talloc_array(mem_ctx, struct iovec, 1);
1613                 if (vector == NULL) {
1614                         return -1;
1615                 }
1616
1617                 vector[0] = req->in.vector[idx];
1618
1619                 *_vector = vector;
1620                 *_count = 1;
1621                 return 0;
1622         }
1623
1624         if (state->missing == 0) {
1625                 /* if there're no remaining bytes, we're done */
1626                 *_vector = NULL;
1627                 *_count = 0;
1628                 return 0;
1629         }
1630
1631         if (state->asked_for_header) {
1632                 const uint8_t *hdr;
1633                 size_t full_size;
1634                 size_t next_command_ofs;
1635                 size_t body_size;
1636                 uint8_t *body;
1637                 size_t dyn_size;
1638                 uint8_t *dyn;
1639                 bool invalid = false;
1640
1641                 state->asked_for_header = false;
1642
1643                 /*
1644                  * We got the SMB2 header and the first 2 bytes
1645                  * of the body. We fix the size to just the header
1646                  * and manually copy the 2 first bytes to the body section
1647                  */
1648                 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
1649                 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
1650
1651                 /* allocate vectors for body and dynamic areas */
1652                 req->in.vector = talloc_realloc(req, req->in.vector,
1653                                                 struct iovec,
1654                                                 req->in.vector_count + 2);
1655                 if (req->in.vector == NULL) {
1656                         return -1;
1657                 }
1658                 req->in.vector_count += 2;
1659
1660                 full_size = state->missing + SMB2_HDR_BODY + 2;
1661                 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
1662                 body_size = SVAL(hdr, SMB2_HDR_BODY);
1663
1664                 if (next_command_ofs != 0) {
1665                         if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
1666                                 /*
1667                                  * this is invalid, just return a zero
1668                                  * body and let the caller deal with the error
1669                                  */
1670                                 invalid = true;
1671                         } else if (next_command_ofs > full_size) {
1672                                 /*
1673                                  * this is invalid, just return a zero
1674                                  * body and let the caller deal with the error
1675                                  */
1676                                 invalid = true;
1677                         } else {
1678                                 full_size = next_command_ofs;
1679                         }
1680                 }
1681
1682                 if (!invalid) {
1683                         if (body_size < 2) {
1684                                 /*
1685                                  * this is invalid, just return a zero
1686                                  * body and let the caller deal with the error
1687                                  */
1688                                 invalid = true;
1689                         }
1690
1691                         if ((body_size % 2) != 0) {
1692                                 body_size -= 1;
1693                         }
1694
1695                         if (body_size > (full_size - SMB2_HDR_BODY)) {
1696                                 /*
1697                                  * this is invalid, just return a zero
1698                                  * body and let the caller deal with the error
1699                                  */
1700                                 invalid = true;
1701                         }
1702                 }
1703
1704                 if (invalid) {
1705                         /* the caller should check this */
1706                         body_size = 2;
1707                 }
1708
1709                 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
1710
1711                 state->missing -= (body_size - 2) + dyn_size;
1712
1713                 body = talloc_array(req->in.vector, uint8_t, body_size);
1714                 if (body == NULL) {
1715                         return -1;
1716                 }
1717
1718                 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
1719                 if (dyn == NULL) {
1720                         return -1;
1721                 }
1722
1723                 req->in.vector[idx].iov_base    = (void *)body;
1724                 req->in.vector[idx].iov_len     = body_size;
1725                 req->in.vector[idx+1].iov_base  = (void *)dyn;
1726                 req->in.vector[idx+1].iov_len   = dyn_size;
1727
1728                 vector = talloc_array(mem_ctx, struct iovec, 2);
1729                 if (vector == NULL) {
1730                         return -1;
1731                 }
1732
1733                 /*
1734                  * the first 2 bytes of the body were already fetched
1735                  * together with the header
1736                  */
1737                 memcpy(body, hdr + SMB2_HDR_BODY, 2);
1738                 vector[0].iov_base = body + 2;
1739                 vector[0].iov_len = body_size - 2;
1740
1741                 vector[1] = req->in.vector[idx+1];
1742
1743                 *_vector = vector;
1744                 *_count = 2;
1745                 return 0;
1746         }
1747
1748         /*
1749          * when we endup here, we're looking for a new SMB2 request
1750          * next. And we ask for its header and the first 2 bytes of
1751          * the body (like we did for the first SMB2 request).
1752          */
1753
1754         req->in.vector = talloc_realloc(req, req->in.vector,
1755                                         struct iovec,
1756                                         req->in.vector_count + 1);
1757         if (req->in.vector == NULL) {
1758                 return -1;
1759         }
1760         req->in.vector_count += 1;
1761
1762         /*
1763          * We assume it's a SMB2 request,
1764          * and we first get the header and the
1765          * first 2 bytes (the struct size) of the body
1766          */
1767         len = SMB2_HDR_BODY + 2;
1768
1769         if (len > state->missing) {
1770                 /* let the caller handle the error */
1771                 len = state->missing;
1772         }
1773
1774         state->missing -= len;
1775         state->asked_for_header = true;
1776
1777         buf = talloc_array(req->in.vector, uint8_t, len);
1778         if (buf == NULL) {
1779                 return -1;
1780         }
1781
1782         req->in.vector[idx].iov_base    = (void *)buf;
1783         req->in.vector[idx].iov_len     = len;
1784
1785         vector = talloc_array(mem_ctx, struct iovec, 1);
1786         if (vector == NULL) {
1787                 return -1;
1788         }
1789
1790         vector[0] = req->in.vector[idx];
1791
1792         *_vector = vector;
1793         *_count = 1;
1794         return 0;
1795 }
1796
1797 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
1798 {
1799         struct tevent_req *req =
1800                 tevent_req_callback_data(subreq,
1801                 struct tevent_req);
1802         int ret;
1803         int sys_errno;
1804         NTSTATUS status;
1805
1806         ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
1807         if (ret == -1) {
1808                 status = map_nt_error_from_unix(sys_errno);
1809                 tevent_req_nterror(req, status);
1810                 return;
1811         }
1812
1813         tevent_req_done(req);
1814 }
1815
1816 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
1817                                             TALLOC_CTX *mem_ctx,
1818                                             struct smbd_smb2_request **_smb2_req)
1819 {
1820         struct smbd_smb2_request_read_state *state =
1821                 tevent_req_data(req,
1822                 struct smbd_smb2_request_read_state);
1823         NTSTATUS status;
1824
1825         if (tevent_req_is_nterror(req, &status)) {
1826                 tevent_req_received(req);
1827                 return status;
1828         }
1829
1830         talloc_steal(mem_ctx, state->smb2_req->mem_pool);
1831         *_smb2_req = state->smb2_req;
1832         tevent_req_received(req);
1833         return NT_STATUS_OK;
1834 }
1835
1836 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
1837
1838 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
1839                              const uint8_t *inbuf, size_t size)
1840 {
1841         NTSTATUS status;
1842         struct smbd_smb2_request *req;
1843         struct tevent_req *subreq;
1844
1845         DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
1846                  (unsigned int)size));
1847
1848         status = smbd_initialize_smb2(sconn);
1849         if (!NT_STATUS_IS_OK(status)) {
1850                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1851                 return;
1852         }
1853
1854         status = smbd_smb2_request_create(sconn, inbuf, size, &req);
1855         if (!NT_STATUS_IS_OK(status)) {
1856                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1857                 return;
1858         }
1859
1860         status = smbd_smb2_request_setup_out(req, (uint16_t)lp_maxmux());
1861         if (!NT_STATUS_IS_OK(status)) {
1862                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1863                 return;
1864         }
1865
1866         status = smbd_smb2_request_dispatch(req);
1867         if (!NT_STATUS_IS_OK(status)) {
1868                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1869                 return;
1870         }
1871
1872         /* ask for the next request */
1873         subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
1874         if (subreq == NULL) {
1875                 smbd_server_connection_terminate(sconn, "no memory for reading");
1876                 return;
1877         }
1878         tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
1879 }
1880
1881 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
1882 {
1883         uint16_t creds_requested = 0;
1884         struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
1885                                                struct smbd_server_connection);
1886         NTSTATUS status;
1887         struct smbd_smb2_request *req = NULL;
1888
1889         status = smbd_smb2_request_read_recv(subreq, sconn, &req);
1890         TALLOC_FREE(subreq);
1891         if (!NT_STATUS_IS_OK(status)) {
1892                 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
1893                         nt_errstr(status)));
1894                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1895                 return;
1896         }
1897
1898         if (req->in.nbt_hdr[0] != 0x00) {
1899                 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
1900                          req->in.nbt_hdr[0]));
1901                 TALLOC_FREE(req);
1902                 goto next;
1903         }
1904
1905         req->current_idx = 1;
1906
1907         DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
1908                  req->current_idx, req->in.vector_count));
1909
1910         status = smbd_smb2_request_validate(req, &creds_requested);
1911         if (!NT_STATUS_IS_OK(status)) {
1912                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1913                 return;
1914         }
1915
1916         status = smbd_smb2_request_setup_out(req, 5);
1917         if (!NT_STATUS_IS_OK(status)) {
1918                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1919                 return;
1920         }
1921
1922         status = smbd_smb2_request_dispatch(req);
1923         if (!NT_STATUS_IS_OK(status)) {
1924                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1925                 return;
1926         }
1927
1928 next:
1929         /* ask for the next request (this constructs the main loop) */
1930         subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
1931         if (subreq == NULL) {
1932                 smbd_server_connection_terminate(sconn, "no memory for reading");
1933                 return;
1934         }
1935         tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
1936 }