Fix for bug 7501 - SMB2: CREATE request replies getting mangled.
[Samba/gebeck_regimport.git] / source3 / smbd / smb2_server.c
blob009cc77e9f2e743823f4fe88745d430b2a8204dc
1 /*
2 Unix SMB/CIFS implementation.
3 Core SMB2 server
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "smbd/globals.h"
24 #include "../libcli/smb/smb_common.h"
25 #include "../lib/tsocket/tsocket.h"
27 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
29 static const char *smb2_names[] = {
30 "SMB2_NEGPROT",
31 "SMB2_SESSSETUP",
32 "SMB2_LOGOFF",
33 "SMB2_TCON",
34 "SMB2_TDIS",
35 "SMB2_CREATE",
36 "SMB2_CLOSE",
37 "SMB2_FLUSH",
38 "SMB2_READ",
39 "SMB2_WRITE",
40 "SMB2_LOCK",
41 "SMB2_IOCTL",
42 "SMB2_CANCEL",
43 "SMB2_KEEPALIVE",
44 "SMB2_FIND",
45 "SMB2_NOTIFY",
46 "SMB2_GETINFO",
47 "SMB2_SETINFO",
48 "SMB2_BREAK"
51 const char *smb2_opcode_name(uint16_t opcode)
53 if (opcode > 0x12) {
54 return "Bad SMB2 opcode";
56 return smb2_names[opcode];
59 static void print_req_vectors(struct smbd_smb2_request *req)
61 int i;
63 for (i = 0; i < req->in.vector_count; i++) {
64 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
65 (unsigned int)i,
66 (unsigned int)req->in.vector[i].iov_len);
68 for (i = 0; i < req->out.vector_count; i++) {
69 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
70 (unsigned int)i,
71 (unsigned int)req->out.vector[i].iov_len);
75 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
77 if (size < (4 + SMB2_HDR_BODY)) {
78 return false;
81 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
82 return false;
85 return true;
88 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
90 NTSTATUS status;
91 int ret;
93 TALLOC_FREE(sconn->smb1.fde);
95 sconn->smb2.event_ctx = smbd_event_context();
97 sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
98 if (sconn->smb2.recv_queue == NULL) {
99 return NT_STATUS_NO_MEMORY;
102 sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
103 if (sconn->smb2.send_queue == NULL) {
104 return NT_STATUS_NO_MEMORY;
107 sconn->smb2.sessions.idtree = idr_init(sconn);
108 if (sconn->smb2.sessions.idtree == NULL) {
109 return NT_STATUS_NO_MEMORY;
111 sconn->smb2.sessions.limit = 0x0000FFFE;
112 sconn->smb2.sessions.list = NULL;
114 ret = tstream_bsd_existing_socket(sconn, smbd_server_fd(),
115 &sconn->smb2.stream);
116 if (ret == -1) {
117 status = map_nt_error_from_unix(errno);
118 return status;
121 /* Ensure child is set to non-blocking mode */
122 set_blocking(smbd_server_fd(),false);
123 return NT_STATUS_OK;
126 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
127 #define _smb2_setlen(_buf,len) do { \
128 uint8_t *buf = (uint8_t *)_buf; \
129 buf[0] = 0; \
130 buf[1] = ((len)&0xFF0000)>>16; \
131 buf[2] = ((len)&0xFF00)>>8; \
132 buf[3] = (len)&0xFF; \
133 } while (0)
135 static void smb2_setup_nbt_length(struct iovec *vector, int count)
137 size_t len = 0;
138 int i;
140 for (i=1; i < count; i++) {
141 len += vector[i].iov_len;
144 _smb2_setlen(vector[0].iov_base, len);
147 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request **req)
149 if (*req) {
150 (*req)->parent = NULL;
151 (*req)->mem_pool = NULL;
154 return 0;
157 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
159 if (req->parent) {
160 *req->parent = NULL;
161 talloc_free(req->mem_pool);
164 return 0;
167 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
169 TALLOC_CTX *mem_pool;
170 struct smbd_smb2_request **parent;
171 struct smbd_smb2_request *req;
173 #if 0
174 /* Enable this to find subtle valgrind errors. */
175 mem_pool = talloc_init("smbd_smb2_request_allocate");
176 #else
177 mem_pool = talloc_pool(mem_ctx, 8192);
178 #endif
179 if (mem_pool == NULL) {
180 return NULL;
183 parent = talloc(mem_pool, struct smbd_smb2_request *);
184 if (parent == NULL) {
185 talloc_free(mem_pool);
186 return NULL;
189 req = talloc_zero(parent, struct smbd_smb2_request);
190 if (req == NULL) {
191 talloc_free(mem_pool);
192 return NULL;
194 *parent = req;
195 req->mem_pool = mem_pool;
196 req->parent = parent;
198 talloc_set_destructor(parent, smbd_smb2_request_parent_destructor);
199 talloc_set_destructor(req, smbd_smb2_request_destructor);
201 return req;
204 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
205 const uint8_t *inbuf, size_t size,
206 struct smbd_smb2_request **_req)
208 struct smbd_smb2_request *req;
209 uint32_t protocol_version;
210 const uint8_t *inhdr = NULL;
211 off_t ofs = 0;
212 uint16_t cmd;
213 uint32_t next_command_ofs;
215 if (size < (4 + SMB2_HDR_BODY + 2)) {
216 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
217 return NT_STATUS_INVALID_PARAMETER;
220 inhdr = inbuf + 4;
222 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
223 if (protocol_version != SMB2_MAGIC) {
224 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
225 protocol_version));
226 return NT_STATUS_INVALID_PARAMETER;
229 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
230 if (cmd != SMB2_OP_NEGPROT) {
231 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
232 cmd));
233 return NT_STATUS_INVALID_PARAMETER;
236 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
237 if (next_command_ofs != 0) {
238 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
239 next_command_ofs));
240 return NT_STATUS_INVALID_PARAMETER;
243 req = smbd_smb2_request_allocate(sconn);
244 if (req == NULL) {
245 return NT_STATUS_NO_MEMORY;
247 req->sconn = sconn;
249 talloc_steal(req, inbuf);
251 req->in.vector = talloc_array(req, struct iovec, 4);
252 if (req->in.vector == NULL) {
253 TALLOC_FREE(req);
254 return NT_STATUS_NO_MEMORY;
256 req->in.vector_count = 4;
258 memcpy(req->in.nbt_hdr, inbuf, 4);
260 ofs = 0;
261 req->in.vector[0].iov_base = (void *)req->in.nbt_hdr;
262 req->in.vector[0].iov_len = 4;
263 ofs += req->in.vector[0].iov_len;
265 req->in.vector[1].iov_base = (void *)(inbuf + ofs);
266 req->in.vector[1].iov_len = SMB2_HDR_BODY;
267 ofs += req->in.vector[1].iov_len;
269 req->in.vector[2].iov_base = (void *)(inbuf + ofs);
270 req->in.vector[2].iov_len = SVAL(inbuf, ofs) & 0xFFFE;
271 ofs += req->in.vector[2].iov_len;
273 if (ofs > size) {
274 return NT_STATUS_INVALID_PARAMETER;
277 req->in.vector[3].iov_base = (void *)(inbuf + ofs);
278 req->in.vector[3].iov_len = size - ofs;
279 ofs += req->in.vector[3].iov_len;
281 req->current_idx = 1;
283 *_req = req;
284 return NT_STATUS_OK;
287 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req,
288 uint16_t *p_creds_requested)
290 int count;
291 int idx;
292 bool compound_related = false;
294 *p_creds_requested = 0;
295 count = req->in.vector_count;
297 if (count < 4) {
298 /* It's not a SMB2 request */
299 return NT_STATUS_INVALID_PARAMETER;
302 for (idx=1; idx < count; idx += 3) {
303 uint16_t creds_requested = 0;
304 const uint8_t *inhdr = NULL;
305 uint32_t flags;
307 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
308 return NT_STATUS_INVALID_PARAMETER;
311 if (req->in.vector[idx+1].iov_len < 2) {
312 return NT_STATUS_INVALID_PARAMETER;
315 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
317 /* setup the SMB2 header */
318 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
319 return NT_STATUS_INVALID_PARAMETER;
322 creds_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
323 if (*p_creds_requested + creds_requested < creds_requested) {
324 *p_creds_requested = 65535;
325 } else {
326 *p_creds_requested += creds_requested;
329 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
330 if (idx == 1) {
332 * the 1st request should never have the
333 * SMB2_HDR_FLAG_CHAINED flag set
335 if (flags & SMB2_HDR_FLAG_CHAINED) {
336 req->next_status = NT_STATUS_INVALID_PARAMETER;
337 return NT_STATUS_OK;
339 } else if (idx == 4) {
341 * the 2nd request triggers related vs. unrelated
342 * compounded requests
344 if (flags & SMB2_HDR_FLAG_CHAINED) {
345 compound_related = true;
347 } else if (idx > 4) {
348 #if 0
350 * It seems the this tests are wrong
351 * see the SMB2-COMPOUND test
355 * all other requests should match the 2nd one
357 if (flags & SMB2_HDR_FLAG_CHAINED) {
358 if (!compound_related) {
359 req->next_status =
360 NT_STATUS_INVALID_PARAMETER;
361 return NT_STATUS_OK;
363 } else {
364 if (compound_related) {
365 req->next_status =
366 NT_STATUS_INVALID_PARAMETER;
367 return NT_STATUS_OK;
370 #endif
374 return NT_STATUS_OK;
377 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req, uint16_t creds)
379 struct iovec *vector;
380 int count;
381 int idx;
383 count = req->in.vector_count;
384 vector = talloc_zero_array(req, struct iovec, count);
385 if (vector == NULL) {
386 return NT_STATUS_NO_MEMORY;
389 vector[0].iov_base = req->out.nbt_hdr;
390 vector[0].iov_len = 4;
391 SIVAL(req->out.nbt_hdr, 0, 0);
393 for (idx=1; idx < count; idx += 3) {
394 const uint8_t *inhdr = NULL;
395 uint32_t in_flags;
396 uint8_t *outhdr = NULL;
397 uint8_t *outbody = NULL;
398 uint32_t next_command_ofs = 0;
399 struct iovec *current = &vector[idx];
401 if ((idx + 3) < count) {
402 /* we have a next command -
403 * setup for the error case. */
404 next_command_ofs = SMB2_HDR_BODY + 9;
407 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
408 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
410 outhdr = talloc_zero_array(vector, uint8_t,
411 OUTVEC_ALLOC_SIZE);
412 if (outhdr == NULL) {
413 return NT_STATUS_NO_MEMORY;
416 outbody = outhdr + SMB2_HDR_BODY;
418 current[0].iov_base = (void *)outhdr;
419 current[0].iov_len = SMB2_HDR_BODY;
421 current[1].iov_base = (void *)outbody;
422 current[1].iov_len = 8;
424 current[2].iov_base = NULL;
425 current[2].iov_len = 0;
427 /* setup the SMB2 header */
428 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
429 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
430 SSVAL(outhdr, SMB2_HDR_EPOCH, 0);
431 SIVAL(outhdr, SMB2_HDR_STATUS,
432 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
433 SSVAL(outhdr, SMB2_HDR_OPCODE,
434 SVAL(inhdr, SMB2_HDR_OPCODE));
435 SSVAL(outhdr, SMB2_HDR_CREDIT, creds);
437 /* Remember what we gave out. */
438 req->sconn->smb2.credits_granted += creds;
440 SIVAL(outhdr, SMB2_HDR_FLAGS,
441 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
442 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
443 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
444 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
445 SIVAL(outhdr, SMB2_HDR_PID,
446 IVAL(inhdr, SMB2_HDR_PID));
447 SIVAL(outhdr, SMB2_HDR_TID,
448 IVAL(inhdr, SMB2_HDR_TID));
449 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
450 BVAL(inhdr, SMB2_HDR_SESSION_ID));
451 memset(outhdr + SMB2_HDR_SIGNATURE, 0, 16);
453 /* setup error body header */
454 SSVAL(outbody, 0x00, 0x08 + 1);
455 SSVAL(outbody, 0x02, 0);
456 SIVAL(outbody, 0x04, 0);
459 req->out.vector = vector;
460 req->out.vector_count = count;
462 /* setup the length of the NBT packet */
463 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
465 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
467 return NT_STATUS_OK;
470 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
471 const char *reason,
472 const char *location)
474 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
475 reason, location));
476 exit_server_cleanly(reason);
479 static bool dup_smb2_vec(struct iovec *dstvec,
480 const struct iovec *srcvec,
481 int offset)
484 if (srcvec[offset].iov_len &&
485 srcvec[offset].iov_base) {
486 dstvec[offset].iov_base = talloc_memdup(dstvec,
487 srcvec[offset].iov_base,
488 srcvec[offset].iov_len);
489 if (!dstvec[offset].iov_base) {
490 return false;
492 dstvec[offset].iov_len = srcvec[offset].iov_len;
493 } else {
494 dstvec[offset].iov_base = NULL;
495 dstvec[offset].iov_len = 0;
497 return true;
500 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
502 struct smbd_smb2_request *newreq = NULL;
503 struct iovec *outvec = NULL;
504 int count = req->out.vector_count;
505 int i;
507 newreq = smbd_smb2_request_allocate(req->sconn);
508 if (!newreq) {
509 return NULL;
512 newreq->sconn = req->sconn;
513 newreq->do_signing = req->do_signing;
514 newreq->current_idx = req->current_idx;
515 newreq->async = false;
516 newreq->cancelled = false;
518 outvec = talloc_zero_array(newreq, struct iovec, count);
519 if (!outvec) {
520 TALLOC_FREE(newreq);
521 return NULL;
523 newreq->out.vector = outvec;
524 newreq->out.vector_count = count;
526 /* Setup the outvec's identically to req. */
527 outvec[0].iov_base = newreq->out.nbt_hdr;
528 outvec[0].iov_len = 4;
529 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
531 for (i = 1; i < count; i += 3) {
532 /* i + 0 and i + 1 are always
533 * boilerplate. */
534 outvec[i].iov_base = talloc_memdup(outvec,
535 req->out.vector[i].iov_base,
536 OUTVEC_ALLOC_SIZE);
537 if (!outvec[i].iov_base) {
538 break;
540 outvec[i].iov_len = SMB2_HDR_BODY;
542 outvec[i+1].iov_base = ((uint8_t *)outvec[i].iov_base) +
543 SMB2_HDR_BODY;
544 outvec[i+1].iov_len = 8;
546 if (req->out.vector[i+2].iov_base ==
547 ((uint8_t *)req->out.vector[i].iov_base) +
548 (OUTVEC_ALLOC_SIZE - 1) &&
549 req->out.vector[i+2].iov_len == 1) {
550 /* Common SMB2 error packet case. */
551 outvec[i+2].iov_base = ((uint8_t *)outvec[i].iov_base) +
552 (OUTVEC_ALLOC_SIZE - 1);
553 outvec[i+2].iov_len = 1;
554 } else if (!dup_smb2_vec(outvec, req->out.vector, i+2)) {
555 break;
559 if (i < count) {
560 /* Alloc failed. */
561 TALLOC_FREE(newreq);
562 return NULL;
565 smb2_setup_nbt_length(newreq->out.vector,
566 newreq->out.vector_count);
568 return newreq;
571 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
573 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
575 int i = 0;
576 uint8_t *outhdr = NULL;
577 struct smbd_smb2_request *nreq = NULL;
579 /* Create a new smb2 request we'll use
580 for the interim return. */
581 nreq = dup_smb2_req(req);
582 if (!nreq) {
583 return NT_STATUS_NO_MEMORY;
586 /* Lose the last 3 out vectors. They're the
587 ones we'll be using for the async reply. */
588 nreq->out.vector_count -= 3;
590 smb2_setup_nbt_length(nreq->out.vector,
591 nreq->out.vector_count);
593 /* Step back to the previous reply. */
594 i = nreq->current_idx - 3;
595 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
596 /* And end the chain. */
597 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
599 /* Re-sign if needed. */
600 if (nreq->do_signing) {
601 NTSTATUS status;
602 status = smb2_signing_sign_pdu(nreq->session->session_key,
603 &nreq->out.vector[i], 3);
604 if (!NT_STATUS_IS_OK(status)) {
605 return status;
608 if (DEBUGLEVEL >= 10) {
609 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
610 (unsigned int)nreq->current_idx );
611 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
612 (unsigned int)nreq->out.vector_count );
613 print_req_vectors(nreq);
615 nreq->subreq = tstream_writev_queue_send(nreq,
616 nreq->sconn->smb2.event_ctx,
617 nreq->sconn->smb2.stream,
618 nreq->sconn->smb2.send_queue,
619 nreq->out.vector,
620 nreq->out.vector_count);
622 if (nreq->subreq == NULL) {
623 return NT_STATUS_NO_MEMORY;
626 tevent_req_set_callback(nreq->subreq,
627 smbd_smb2_request_writev_done,
628 nreq);
630 return NT_STATUS_OK;
633 struct smbd_smb2_request_pending_state {
634 struct smbd_server_connection *sconn;
635 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
636 struct iovec vector[3];
639 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
641 struct smbd_smb2_request_pending_state *state =
642 tevent_req_callback_data(subreq,
643 struct smbd_smb2_request_pending_state);
644 struct smbd_server_connection *sconn = state->sconn;
645 int ret;
646 int sys_errno;
648 ret = tstream_writev_queue_recv(subreq, &sys_errno);
649 TALLOC_FREE(subreq);
650 if (ret == -1) {
651 NTSTATUS status = map_nt_error_from_unix(sys_errno);
652 smbd_server_connection_terminate(sconn, nt_errstr(status));
653 return;
656 TALLOC_FREE(state);
659 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
660 struct tevent_req *subreq)
662 NTSTATUS status;
663 struct smbd_smb2_request_pending_state *state = NULL;
664 int i = req->current_idx;
665 uint8_t *reqhdr = NULL;
666 uint8_t *hdr = NULL;
667 uint8_t *body = NULL;
668 uint32_t flags = 0;
669 uint64_t message_id = 0;
670 uint64_t async_id = 0;
671 struct iovec *outvec = NULL;
673 if (!tevent_req_is_in_progress(subreq)) {
674 return NT_STATUS_OK;
677 if (req->async) {
678 /* We're already async. */
679 return NT_STATUS_OK;
682 if (req->in.vector_count > i + 3) {
684 * We're trying to go async in a compound
685 * request chain. This is not allowed.
686 * Cancel the outstanding request.
688 tevent_req_cancel(subreq);
689 return smbd_smb2_request_error(req,
690 NT_STATUS_INSUFFICIENT_RESOURCES);
693 req->subreq = subreq;
694 subreq = NULL;
696 if (DEBUGLEVEL >= 10) {
697 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
698 (unsigned int)req->current_idx );
699 print_req_vectors(req);
702 if (req->out.vector_count > 4) {
703 /* This is a compound reply. We
704 * must do an interim response
705 * followed by the async response
706 * to match W2K8R2.
708 status = smb2_send_async_interim_response(req);
709 if (!NT_STATUS_IS_OK(status)) {
710 return status;
714 /* Don't return an intermediate packet on a pipe read/write. */
715 if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
716 return NT_STATUS_OK;
719 reqhdr = (uint8_t *)req->out.vector[i].iov_base;
720 flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
721 message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
722 async_id = message_id; /* keep it simple for now... */
725 * What we send is identical to a smbd_smb2_request_error
726 * packet with an error status of STATUS_PENDING. Make use
727 * of this fact sometime when refactoring. JRA.
730 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
731 if (state == NULL) {
732 return NT_STATUS_NO_MEMORY;
734 state->sconn = req->sconn;
736 state->vector[0].iov_base = (void *)state->buf;
737 state->vector[0].iov_len = 4;
739 state->vector[1].iov_base = state->buf + 4;
740 state->vector[1].iov_len = SMB2_HDR_BODY;
742 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
743 state->vector[2].iov_len = 9;
745 smb2_setup_nbt_length(state->vector, 3);
747 hdr = (uint8_t *)state->vector[1].iov_base;
748 body = (uint8_t *)state->vector[2].iov_base;
750 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
751 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
752 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
753 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
754 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
755 SSVAL(hdr, SMB2_HDR_CREDIT, 5);
757 req->sconn->smb2.credits_granted += 5;
759 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
760 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
761 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
762 SBVAL(hdr, SMB2_HDR_PID, async_id);
763 SBVAL(hdr, SMB2_HDR_SESSION_ID,
764 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
765 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
767 SSVAL(body, 0x00, 0x08 + 1);
769 SCVAL(body, 0x02, 0);
770 SCVAL(body, 0x03, 0);
771 SIVAL(body, 0x04, 0);
772 /* Match W2K8R2... */
773 SCVAL(body, 0x08, 0x21);
775 if (req->do_signing) {
776 status = smb2_signing_sign_pdu(req->session->session_key,
777 state->vector, 3);
778 if (!NT_STATUS_IS_OK(status)) {
779 return status;
783 subreq = tstream_writev_queue_send(state,
784 req->sconn->smb2.event_ctx,
785 req->sconn->smb2.stream,
786 req->sconn->smb2.send_queue,
787 state->vector,
790 if (subreq == NULL) {
791 return NT_STATUS_NO_MEMORY;
794 tevent_req_set_callback(subreq,
795 smbd_smb2_request_pending_writev_done,
796 state);
798 /* Note we're going async with this request. */
799 req->async = true;
802 * Now manipulate req so that the outstanding async request
803 * is the only one left in the struct smbd_smb2_request.
806 if (req->current_idx == 1) {
807 /* There was only one. */
808 goto out;
811 /* Re-arrange the in.vectors. */
812 req->in.vector[1] = req->in.vector[i];
813 req->in.vector[2] = req->in.vector[i+1];
814 req->in.vector[3] = req->in.vector[i+2];
815 req->in.vector_count = 4;
816 /* Reset the new in size. */
817 smb2_setup_nbt_length(req->in.vector, 4);
819 /* Now recreate the out.vectors. */
820 outvec = talloc_zero_array(req, struct iovec, 4);
821 if (!outvec) {
822 return NT_STATUS_NO_MEMORY;
824 outvec[0].iov_base = req->out.nbt_hdr;
825 outvec[0].iov_len = 4;
826 SIVAL(req->out.nbt_hdr, 0, 0);
828 outvec[1].iov_base = talloc_memdup(outvec,
829 req->out.vector[i].iov_base,
830 OUTVEC_ALLOC_SIZE);
831 if (!outvec[1].iov_base) {
832 return NT_STATUS_NO_MEMORY;
834 outvec[1].iov_len = SMB2_HDR_BODY;
836 outvec[2].iov_base = ((uint8_t *)outvec[1].iov_base) +
837 SMB2_HDR_BODY;
838 outvec[2].iov_len = 8;
840 if (req->out.vector[i+2].iov_base &&
841 req->out.vector[i+2].iov_len) {
842 if (req->out.vector[i+2].iov_base ==
843 ((uint8_t *)req->out.vector[i].iov_base) +
844 (OUTVEC_ALLOC_SIZE - 1) &&
845 req->out.vector[i].iov_len == 1) {
846 /* Common SMB2 error packet case. */
847 outvec[3].iov_base = ((uint8_t *)outvec[1].iov_base) +
848 (OUTVEC_ALLOC_SIZE - 1);
849 } else {
850 outvec[3].iov_base = talloc_memdup(outvec,
851 req->out.vector[i+2].iov_base,
852 req->out.vector[i+2].iov_len);
853 if (!outvec[3].iov_base) {
854 return NT_STATUS_NO_MEMORY;
857 outvec[3].iov_len = req->out.vector[i+2].iov_len;
858 } else {
859 outvec[3].iov_base = NULL;
860 outvec[3].iov_len = 0;
863 TALLOC_FREE(req->out.vector);
865 req->out.vector = outvec;
867 req->current_idx = 1;
868 req->out.vector_count = 4;
870 out:
872 smb2_setup_nbt_length(req->out.vector,
873 req->out.vector_count);
875 /* Ensure our final reply matches the interim one. */
876 reqhdr = (uint8_t *)req->out.vector[1].iov_base;
877 SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
878 SBVAL(reqhdr, SMB2_HDR_PID, async_id);
881 const uint8_t *inhdr =
882 (const uint8_t *)req->in.vector[1].iov_base;
883 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
884 "going async\n",
885 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
886 (unsigned long long)async_id ));
888 return NT_STATUS_OK;
891 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
893 struct smbd_server_connection *sconn = req->sconn;
894 struct smbd_smb2_request *cur;
895 const uint8_t *inhdr;
896 int i = req->current_idx;
897 uint32_t flags;
898 uint64_t search_message_id;
899 uint64_t search_async_id;
900 uint64_t found_id;
902 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
904 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
905 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
906 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
909 * we don't need the request anymore
910 * cancel requests never have a response
912 DLIST_REMOVE(req->sconn->smb2.requests, req);
913 TALLOC_FREE(req);
915 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
916 const uint8_t *outhdr;
917 uint64_t message_id;
918 uint64_t async_id;
920 i = cur->current_idx;
922 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
924 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
925 async_id = BVAL(outhdr, SMB2_HDR_PID);
927 if (flags & SMB2_HDR_FLAG_ASYNC) {
928 if (search_async_id == async_id) {
929 found_id = async_id;
930 break;
932 } else {
933 if (search_message_id == message_id) {
934 found_id = message_id;
935 break;
940 if (cur && cur->subreq) {
941 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
942 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
943 "cancel opcode[%s] mid %llu\n",
944 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
945 (unsigned long long)found_id ));
946 tevent_req_cancel(cur->subreq);
949 return NT_STATUS_OK;
952 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
954 const uint8_t *inhdr;
955 int i = req->current_idx;
956 uint16_t opcode;
957 uint32_t flags;
958 uint64_t mid;
959 NTSTATUS status;
960 NTSTATUS session_status;
961 uint32_t allowed_flags;
963 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
965 /* TODO: verify more things */
967 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
968 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
969 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
970 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
971 smb2_opcode_name(opcode),
972 (unsigned long long)mid));
974 allowed_flags = SMB2_HDR_FLAG_CHAINED |
975 SMB2_HDR_FLAG_SIGNED |
976 SMB2_HDR_FLAG_DFS;
977 if (opcode == SMB2_OP_CANCEL) {
978 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
980 if ((flags & ~allowed_flags) != 0) {
981 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
984 session_status = smbd_smb2_request_check_session(req);
986 req->do_signing = false;
987 if (flags & SMB2_HDR_FLAG_SIGNED) {
988 if (!NT_STATUS_IS_OK(session_status)) {
989 return smbd_smb2_request_error(req, session_status);
992 req->do_signing = true;
993 status = smb2_signing_check_pdu(req->session->session_key,
994 &req->in.vector[i], 3);
995 if (!NT_STATUS_IS_OK(status)) {
996 return smbd_smb2_request_error(req, status);
998 } else if (req->session && req->session->do_signing) {
999 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1002 if (flags & SMB2_HDR_FLAG_CHAINED) {
1004 * This check is mostly for giving the correct error code
1005 * for compounded requests.
1007 * TODO: we may need to move this after the session
1008 * and tcon checks.
1010 if (!NT_STATUS_IS_OK(req->next_status)) {
1011 return smbd_smb2_request_error(req, req->next_status);
1013 } else {
1014 req->compat_chain_fsp = NULL;
1017 switch (opcode) {
1018 case SMB2_OP_NEGPROT:
1019 return smbd_smb2_request_process_negprot(req);
1021 case SMB2_OP_SESSSETUP:
1022 return smbd_smb2_request_process_sesssetup(req);
1024 case SMB2_OP_LOGOFF:
1025 if (!NT_STATUS_IS_OK(session_status)) {
1026 return smbd_smb2_request_error(req, session_status);
1028 return smbd_smb2_request_process_logoff(req);
1030 case SMB2_OP_TCON:
1031 if (!NT_STATUS_IS_OK(session_status)) {
1032 return smbd_smb2_request_error(req, session_status);
1034 status = smbd_smb2_request_check_session(req);
1035 if (!NT_STATUS_IS_OK(status)) {
1036 return smbd_smb2_request_error(req, status);
1038 return smbd_smb2_request_process_tcon(req);
1040 case SMB2_OP_TDIS:
1041 if (!NT_STATUS_IS_OK(session_status)) {
1042 return smbd_smb2_request_error(req, session_status);
1044 status = smbd_smb2_request_check_tcon(req);
1045 if (!NT_STATUS_IS_OK(status)) {
1046 return smbd_smb2_request_error(req, status);
1048 return smbd_smb2_request_process_tdis(req);
1050 case SMB2_OP_CREATE:
1051 if (!NT_STATUS_IS_OK(session_status)) {
1052 return smbd_smb2_request_error(req, session_status);
1054 status = smbd_smb2_request_check_tcon(req);
1055 if (!NT_STATUS_IS_OK(status)) {
1056 return smbd_smb2_request_error(req, status);
1058 return smbd_smb2_request_process_create(req);
1060 case SMB2_OP_CLOSE:
1061 if (!NT_STATUS_IS_OK(session_status)) {
1062 return smbd_smb2_request_error(req, session_status);
1064 status = smbd_smb2_request_check_tcon(req);
1065 if (!NT_STATUS_IS_OK(status)) {
1066 return smbd_smb2_request_error(req, status);
1068 return smbd_smb2_request_process_close(req);
1070 case SMB2_OP_FLUSH:
1071 if (!NT_STATUS_IS_OK(session_status)) {
1072 return smbd_smb2_request_error(req, session_status);
1074 status = smbd_smb2_request_check_tcon(req);
1075 if (!NT_STATUS_IS_OK(status)) {
1076 return smbd_smb2_request_error(req, status);
1078 return smbd_smb2_request_process_flush(req);
1080 case SMB2_OP_READ:
1081 if (!NT_STATUS_IS_OK(session_status)) {
1082 return smbd_smb2_request_error(req, session_status);
1084 status = smbd_smb2_request_check_tcon(req);
1085 if (!NT_STATUS_IS_OK(status)) {
1086 return smbd_smb2_request_error(req, status);
1088 return smbd_smb2_request_process_read(req);
1090 case SMB2_OP_WRITE:
1091 if (!NT_STATUS_IS_OK(session_status)) {
1092 return smbd_smb2_request_error(req, session_status);
1094 status = smbd_smb2_request_check_tcon(req);
1095 if (!NT_STATUS_IS_OK(status)) {
1096 return smbd_smb2_request_error(req, status);
1098 return smbd_smb2_request_process_write(req);
1100 case SMB2_OP_LOCK:
1101 if (!NT_STATUS_IS_OK(session_status)) {
1102 /* Too ugly to live ? JRA. */
1103 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1104 session_status = NT_STATUS_FILE_CLOSED;
1106 return smbd_smb2_request_error(req, session_status);
1108 status = smbd_smb2_request_check_tcon(req);
1109 if (!NT_STATUS_IS_OK(status)) {
1110 /* Too ugly to live ? JRA. */
1111 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1112 status = NT_STATUS_FILE_CLOSED;
1114 return smbd_smb2_request_error(req, status);
1116 return smbd_smb2_request_process_lock(req);
1118 case SMB2_OP_IOCTL:
1119 if (!NT_STATUS_IS_OK(session_status)) {
1120 return smbd_smb2_request_error(req, session_status);
1122 status = smbd_smb2_request_check_tcon(req);
1123 if (!NT_STATUS_IS_OK(status)) {
1124 return smbd_smb2_request_error(req, status);
1126 return smbd_smb2_request_process_ioctl(req);
1128 case SMB2_OP_CANCEL:
1129 return smbd_smb2_request_process_cancel(req);
1131 case SMB2_OP_KEEPALIVE:
1132 return smbd_smb2_request_process_keepalive(req);
1134 case SMB2_OP_FIND:
1135 if (!NT_STATUS_IS_OK(session_status)) {
1136 return smbd_smb2_request_error(req, session_status);
1138 status = smbd_smb2_request_check_tcon(req);
1139 if (!NT_STATUS_IS_OK(status)) {
1140 return smbd_smb2_request_error(req, status);
1142 return smbd_smb2_request_process_find(req);
1144 case SMB2_OP_NOTIFY:
1145 if (!NT_STATUS_IS_OK(session_status)) {
1146 return smbd_smb2_request_error(req, session_status);
1148 status = smbd_smb2_request_check_tcon(req);
1149 if (!NT_STATUS_IS_OK(status)) {
1150 return smbd_smb2_request_error(req, status);
1152 return smbd_smb2_request_process_notify(req);
1154 case SMB2_OP_GETINFO:
1155 if (!NT_STATUS_IS_OK(session_status)) {
1156 return smbd_smb2_request_error(req, session_status);
1158 status = smbd_smb2_request_check_tcon(req);
1159 if (!NT_STATUS_IS_OK(status)) {
1160 return smbd_smb2_request_error(req, status);
1162 return smbd_smb2_request_process_getinfo(req);
1164 case SMB2_OP_SETINFO:
1165 if (!NT_STATUS_IS_OK(session_status)) {
1166 return smbd_smb2_request_error(req, session_status);
1168 status = smbd_smb2_request_check_tcon(req);
1169 if (!NT_STATUS_IS_OK(status)) {
1170 return smbd_smb2_request_error(req, status);
1172 return smbd_smb2_request_process_setinfo(req);
1174 case SMB2_OP_BREAK:
1175 if (!NT_STATUS_IS_OK(session_status)) {
1176 return smbd_smb2_request_error(req, session_status);
1178 status = smbd_smb2_request_check_tcon(req);
1179 if (!NT_STATUS_IS_OK(status)) {
1180 return smbd_smb2_request_error(req, status);
1182 return smbd_smb2_request_process_break(req);
1185 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1188 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1190 struct tevent_req *subreq;
1192 req->subreq = NULL;
1194 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1196 if (req->do_signing) {
1197 int i = req->current_idx;
1198 NTSTATUS status;
1199 status = smb2_signing_sign_pdu(req->session->session_key,
1200 &req->out.vector[i], 3);
1201 if (!NT_STATUS_IS_OK(status)) {
1202 return status;
1206 req->current_idx += 3;
1208 if (req->current_idx < req->out.vector_count) {
1210 * We must process the remaining compound
1211 * SMB2 requests before any new incoming SMB2
1212 * requests. This is because incoming SMB2
1213 * requests may include a cancel for a
1214 * compound request we haven't processed
1215 * yet.
1217 struct tevent_immediate *im = tevent_create_immediate(req);
1218 if (!im) {
1219 return NT_STATUS_NO_MEMORY;
1221 tevent_schedule_immediate(im,
1222 req->sconn->smb2.event_ctx,
1223 smbd_smb2_request_dispatch_immediate,
1224 req);
1225 return NT_STATUS_OK;
1228 if (DEBUGLEVEL >= 10) {
1229 dbgtext("smbd_smb2_request_reply: sending...\n");
1230 print_req_vectors(req);
1233 subreq = tstream_writev_queue_send(req,
1234 req->sconn->smb2.event_ctx,
1235 req->sconn->smb2.stream,
1236 req->sconn->smb2.send_queue,
1237 req->out.vector,
1238 req->out.vector_count);
1239 if (subreq == NULL) {
1240 return NT_STATUS_NO_MEMORY;
1242 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1244 * We're done with this request -
1245 * move it off the "being processed" queue.
1247 DLIST_REMOVE(req->sconn->smb2.requests, req);
1249 return NT_STATUS_OK;
1252 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1253 struct tevent_immediate *im,
1254 void *private_data)
1256 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1257 struct smbd_smb2_request);
1258 struct smbd_server_connection *sconn = req->sconn;
1259 NTSTATUS status;
1261 TALLOC_FREE(im);
1263 if (DEBUGLEVEL >= 10) {
1264 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1265 req->current_idx, req->in.vector_count));
1266 print_req_vectors(req);
1269 status = smbd_smb2_request_dispatch(req);
1270 if (!NT_STATUS_IS_OK(status)) {
1271 smbd_server_connection_terminate(sconn, nt_errstr(status));
1272 return;
1276 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1278 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1279 struct smbd_smb2_request);
1280 struct smbd_server_connection *sconn = req->sconn;
1281 int ret;
1282 int sys_errno;
1284 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1285 TALLOC_FREE(subreq);
1286 TALLOC_FREE(req);
1287 if (ret == -1) {
1288 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1289 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1290 nt_errstr(status)));
1291 smbd_server_connection_terminate(sconn, nt_errstr(status));
1292 return;
1296 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1297 NTSTATUS status,
1298 DATA_BLOB body, DATA_BLOB *dyn,
1299 const char *location)
1301 uint8_t *outhdr;
1302 int i = req->current_idx;
1303 uint32_t next_command_ofs;
1305 DEBUG(10,("smbd_smb2_request_done_ex: "
1306 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1307 i, nt_errstr(status), (unsigned int)body.length,
1308 dyn ? "yes": "no",
1309 (unsigned int)(dyn ? dyn->length : 0),
1310 location));
1312 if (body.length < 2) {
1313 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1316 if ((body.length % 2) != 0) {
1317 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1320 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1322 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1323 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1325 req->out.vector[i+1].iov_base = (void *)body.data;
1326 req->out.vector[i+1].iov_len = body.length;
1328 if (dyn) {
1329 req->out.vector[i+2].iov_base = (void *)dyn->data;
1330 req->out.vector[i+2].iov_len = dyn->length;
1331 } else {
1332 req->out.vector[i+2].iov_base = NULL;
1333 req->out.vector[i+2].iov_len = 0;
1336 /* see if we need to recalculate the offset to the next response */
1337 if (next_command_ofs > 0) {
1338 next_command_ofs = SMB2_HDR_BODY;
1339 next_command_ofs += req->out.vector[i+1].iov_len;
1340 next_command_ofs += req->out.vector[i+2].iov_len;
1343 if ((next_command_ofs % 8) != 0) {
1344 size_t pad_size = 8 - (next_command_ofs % 8);
1345 if (req->out.vector[i+2].iov_len == 0) {
1347 * if the dyn buffer is empty
1348 * we can use it to add padding
1350 uint8_t *pad;
1352 pad = talloc_zero_array(req->out.vector,
1353 uint8_t, pad_size);
1354 if (pad == NULL) {
1355 return smbd_smb2_request_error(req,
1356 NT_STATUS_NO_MEMORY);
1359 req->out.vector[i+2].iov_base = (void *)pad;
1360 req->out.vector[i+2].iov_len = pad_size;
1361 } else {
1363 * For now we copy the dynamic buffer
1364 * and add the padding to the new buffer
1366 size_t old_size;
1367 uint8_t *old_dyn;
1368 size_t new_size;
1369 uint8_t *new_dyn;
1371 old_size = req->out.vector[i+2].iov_len;
1372 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1374 new_size = old_size + pad_size;
1375 new_dyn = talloc_zero_array(req->out.vector,
1376 uint8_t, new_size);
1377 if (new_dyn == NULL) {
1378 return smbd_smb2_request_error(req,
1379 NT_STATUS_NO_MEMORY);
1382 memcpy(new_dyn, old_dyn, old_size);
1383 memset(new_dyn + old_size, 0, pad_size);
1385 req->out.vector[i+2].iov_base = (void *)new_dyn;
1386 req->out.vector[i+2].iov_len = new_size;
1388 next_command_ofs += pad_size;
1391 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1393 return smbd_smb2_request_reply(req);
1396 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
1397 NTSTATUS status,
1398 DATA_BLOB *info,
1399 const char *location)
1401 DATA_BLOB body;
1402 int i = req->current_idx;
1403 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
1405 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1406 i, nt_errstr(status), info ? " +info" : "",
1407 location));
1409 body.data = outhdr + SMB2_HDR_BODY;
1410 body.length = 8;
1411 SSVAL(body.data, 0, 9);
1413 if (info) {
1414 SIVAL(body.data, 0x04, info->length);
1415 } else {
1416 /* Allocated size of req->out.vector[i].iov_base
1417 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1418 * 1 byte without having to do an alloc.
1420 info = talloc_zero_array(req->out.vector,
1421 DATA_BLOB,
1423 if (!info) {
1424 return NT_STATUS_NO_MEMORY;
1426 info->data = ((uint8_t *)outhdr) +
1427 OUTVEC_ALLOC_SIZE - 1;
1428 info->length = 1;
1429 SCVAL(info->data, 0, 0);
1433 * if a request fails, all other remaining
1434 * compounded requests should fail too
1436 req->next_status = NT_STATUS_INVALID_PARAMETER;
1438 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
1442 struct smbd_smb2_send_oplock_break_state {
1443 struct smbd_server_connection *sconn;
1444 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
1445 struct iovec vector;
1448 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
1450 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
1451 uint64_t file_id_persistent,
1452 uint64_t file_id_volatile,
1453 uint8_t oplock_level)
1455 struct smbd_smb2_send_oplock_break_state *state;
1456 struct tevent_req *subreq;
1457 uint8_t *hdr;
1458 uint8_t *body;
1460 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
1461 if (state == NULL) {
1462 return NT_STATUS_NO_MEMORY;
1464 state->sconn = sconn;
1466 state->vector.iov_base = (void *)state->buf;
1467 state->vector.iov_len = sizeof(state->buf);
1469 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
1470 hdr = state->buf + 4;
1471 body = hdr + SMB2_HDR_BODY;
1473 SIVAL(hdr, 0, SMB2_MAGIC);
1474 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1475 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1476 SIVAL(hdr, SMB2_HDR_STATUS, 0);
1477 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
1478 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
1479 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
1480 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1481 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
1482 SIVAL(hdr, SMB2_HDR_PID, 0);
1483 SIVAL(hdr, SMB2_HDR_TID, 0);
1484 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
1485 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1487 SSVAL(body, 0x00, 0x18);
1489 SCVAL(body, 0x02, oplock_level);
1490 SCVAL(body, 0x03, 0); /* reserved */
1491 SIVAL(body, 0x04, 0); /* reserved */
1492 SBVAL(body, 0x08, file_id_persistent);
1493 SBVAL(body, 0x10, file_id_volatile);
1495 subreq = tstream_writev_queue_send(state,
1496 sconn->smb2.event_ctx,
1497 sconn->smb2.stream,
1498 sconn->smb2.send_queue,
1499 &state->vector, 1);
1500 if (subreq == NULL) {
1501 return NT_STATUS_NO_MEMORY;
1503 tevent_req_set_callback(subreq,
1504 smbd_smb2_oplock_break_writev_done,
1505 state);
1507 return NT_STATUS_OK;
1510 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
1512 struct smbd_smb2_send_oplock_break_state *state =
1513 tevent_req_callback_data(subreq,
1514 struct smbd_smb2_send_oplock_break_state);
1515 struct smbd_server_connection *sconn = state->sconn;
1516 int ret;
1517 int sys_errno;
1519 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1520 TALLOC_FREE(subreq);
1521 if (ret == -1) {
1522 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1523 smbd_server_connection_terminate(sconn, nt_errstr(status));
1524 return;
1527 TALLOC_FREE(state);
1530 struct smbd_smb2_request_read_state {
1531 size_t missing;
1532 bool asked_for_header;
1533 struct smbd_smb2_request *smb2_req;
1536 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1537 void *private_data,
1538 TALLOC_CTX *mem_ctx,
1539 struct iovec **_vector,
1540 size_t *_count);
1541 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
1543 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
1544 struct tevent_context *ev,
1545 struct smbd_server_connection *sconn)
1547 struct tevent_req *req;
1548 struct smbd_smb2_request_read_state *state;
1549 struct tevent_req *subreq;
1551 req = tevent_req_create(mem_ctx, &state,
1552 struct smbd_smb2_request_read_state);
1553 if (req == NULL) {
1554 return NULL;
1556 state->missing = 0;
1557 state->asked_for_header = false;
1559 state->smb2_req = smbd_smb2_request_allocate(state);
1560 if (tevent_req_nomem(state->smb2_req, req)) {
1561 return tevent_req_post(req, ev);
1563 state->smb2_req->sconn = sconn;
1565 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
1566 sconn->smb2.recv_queue,
1567 smbd_smb2_request_next_vector,
1568 state);
1569 if (tevent_req_nomem(subreq, req)) {
1570 return tevent_req_post(req, ev);
1572 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
1574 return req;
1577 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1578 void *private_data,
1579 TALLOC_CTX *mem_ctx,
1580 struct iovec **_vector,
1581 size_t *_count)
1583 struct smbd_smb2_request_read_state *state =
1584 talloc_get_type_abort(private_data,
1585 struct smbd_smb2_request_read_state);
1586 struct smbd_smb2_request *req = state->smb2_req;
1587 struct iovec *vector;
1588 int idx = req->in.vector_count;
1589 size_t len = 0;
1590 uint8_t *buf = NULL;
1592 if (req->in.vector_count == 0) {
1594 * first we need to get the NBT header
1596 req->in.vector = talloc_array(req, struct iovec,
1597 req->in.vector_count + 1);
1598 if (req->in.vector == NULL) {
1599 return -1;
1601 req->in.vector_count += 1;
1603 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
1604 req->in.vector[idx].iov_len = 4;
1606 vector = talloc_array(mem_ctx, struct iovec, 1);
1607 if (vector == NULL) {
1608 return -1;
1611 vector[0] = req->in.vector[idx];
1613 *_vector = vector;
1614 *_count = 1;
1615 return 0;
1618 if (req->in.vector_count == 1) {
1620 * Now we analyze the NBT header
1622 state->missing = smb2_len(req->in.vector[0].iov_base);
1624 if (state->missing == 0) {
1625 /* if there're no remaining bytes, we're done */
1626 *_vector = NULL;
1627 *_count = 0;
1628 return 0;
1631 req->in.vector = talloc_realloc(req, req->in.vector,
1632 struct iovec,
1633 req->in.vector_count + 1);
1634 if (req->in.vector == NULL) {
1635 return -1;
1637 req->in.vector_count += 1;
1639 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
1641 * it's a special NBT message,
1642 * so get all remaining bytes
1644 len = state->missing;
1645 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
1647 * it's an invalid message, just read what we can get
1648 * and let the caller handle the error
1650 len = state->missing;
1651 } else {
1653 * We assume it's a SMB2 request,
1654 * and we first get the header and the
1655 * first 2 bytes (the struct size) of the body
1657 len = SMB2_HDR_BODY + 2;
1659 state->asked_for_header = true;
1662 state->missing -= len;
1664 buf = talloc_array(req->in.vector, uint8_t, len);
1665 if (buf == NULL) {
1666 return -1;
1669 req->in.vector[idx].iov_base = (void *)buf;
1670 req->in.vector[idx].iov_len = len;
1672 vector = talloc_array(mem_ctx, struct iovec, 1);
1673 if (vector == NULL) {
1674 return -1;
1677 vector[0] = req->in.vector[idx];
1679 *_vector = vector;
1680 *_count = 1;
1681 return 0;
1684 if (state->missing == 0) {
1685 /* if there're no remaining bytes, we're done */
1686 *_vector = NULL;
1687 *_count = 0;
1688 return 0;
1691 if (state->asked_for_header) {
1692 const uint8_t *hdr;
1693 size_t full_size;
1694 size_t next_command_ofs;
1695 size_t body_size;
1696 uint8_t *body;
1697 size_t dyn_size;
1698 uint8_t *dyn;
1699 bool invalid = false;
1701 state->asked_for_header = false;
1704 * We got the SMB2 header and the first 2 bytes
1705 * of the body. We fix the size to just the header
1706 * and manually copy the 2 first bytes to the body section
1708 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
1709 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
1711 /* allocate vectors for body and dynamic areas */
1712 req->in.vector = talloc_realloc(req, req->in.vector,
1713 struct iovec,
1714 req->in.vector_count + 2);
1715 if (req->in.vector == NULL) {
1716 return -1;
1718 req->in.vector_count += 2;
1720 full_size = state->missing + SMB2_HDR_BODY + 2;
1721 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
1722 body_size = SVAL(hdr, SMB2_HDR_BODY);
1724 if (next_command_ofs != 0) {
1725 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
1727 * this is invalid, just return a zero
1728 * body and let the caller deal with the error
1730 invalid = true;
1731 } else if (next_command_ofs > full_size) {
1733 * this is invalid, just return a zero
1734 * body and let the caller deal with the error
1736 invalid = true;
1737 } else {
1738 full_size = next_command_ofs;
1742 if (!invalid) {
1743 if (body_size < 2) {
1745 * this is invalid, just return a zero
1746 * body and let the caller deal with the error
1748 invalid = true;
1751 if ((body_size % 2) != 0) {
1752 body_size -= 1;
1755 if (body_size > (full_size - SMB2_HDR_BODY)) {
1757 * this is invalid, just return a zero
1758 * body and let the caller deal with the error
1760 invalid = true;
1764 if (invalid) {
1765 /* the caller should check this */
1766 body_size = 2;
1769 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
1771 state->missing -= (body_size - 2) + dyn_size;
1773 body = talloc_array(req->in.vector, uint8_t, body_size);
1774 if (body == NULL) {
1775 return -1;
1778 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
1779 if (dyn == NULL) {
1780 return -1;
1783 req->in.vector[idx].iov_base = (void *)body;
1784 req->in.vector[idx].iov_len = body_size;
1785 req->in.vector[idx+1].iov_base = (void *)dyn;
1786 req->in.vector[idx+1].iov_len = dyn_size;
1788 vector = talloc_array(mem_ctx, struct iovec, 2);
1789 if (vector == NULL) {
1790 return -1;
1794 * the first 2 bytes of the body were already fetched
1795 * together with the header
1797 memcpy(body, hdr + SMB2_HDR_BODY, 2);
1798 vector[0].iov_base = body + 2;
1799 vector[0].iov_len = body_size - 2;
1801 vector[1] = req->in.vector[idx+1];
1803 *_vector = vector;
1804 *_count = 2;
1805 return 0;
1809 * when we endup here, we're looking for a new SMB2 request
1810 * next. And we ask for its header and the first 2 bytes of
1811 * the body (like we did for the first SMB2 request).
1814 req->in.vector = talloc_realloc(req, req->in.vector,
1815 struct iovec,
1816 req->in.vector_count + 1);
1817 if (req->in.vector == NULL) {
1818 return -1;
1820 req->in.vector_count += 1;
1823 * We assume it's a SMB2 request,
1824 * and we first get the header and the
1825 * first 2 bytes (the struct size) of the body
1827 len = SMB2_HDR_BODY + 2;
1829 if (len > state->missing) {
1830 /* let the caller handle the error */
1831 len = state->missing;
1834 state->missing -= len;
1835 state->asked_for_header = true;
1837 buf = talloc_array(req->in.vector, uint8_t, len);
1838 if (buf == NULL) {
1839 return -1;
1842 req->in.vector[idx].iov_base = (void *)buf;
1843 req->in.vector[idx].iov_len = len;
1845 vector = talloc_array(mem_ctx, struct iovec, 1);
1846 if (vector == NULL) {
1847 return -1;
1850 vector[0] = req->in.vector[idx];
1852 *_vector = vector;
1853 *_count = 1;
1854 return 0;
1857 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
1859 struct tevent_req *req =
1860 tevent_req_callback_data(subreq,
1861 struct tevent_req);
1862 int ret;
1863 int sys_errno;
1864 NTSTATUS status;
1866 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
1867 if (ret == -1) {
1868 status = map_nt_error_from_unix(sys_errno);
1869 tevent_req_nterror(req, status);
1870 return;
1873 tevent_req_done(req);
1876 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
1877 TALLOC_CTX *mem_ctx,
1878 struct smbd_smb2_request **_smb2_req)
1880 struct smbd_smb2_request_read_state *state =
1881 tevent_req_data(req,
1882 struct smbd_smb2_request_read_state);
1883 NTSTATUS status;
1885 if (tevent_req_is_nterror(req, &status)) {
1886 tevent_req_received(req);
1887 return status;
1890 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
1891 *_smb2_req = state->smb2_req;
1892 tevent_req_received(req);
1893 return NT_STATUS_OK;
1896 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
1898 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
1899 const uint8_t *inbuf, size_t size)
1901 NTSTATUS status;
1902 struct smbd_smb2_request *req;
1903 struct tevent_req *subreq;
1905 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
1906 (unsigned int)size));
1908 status = smbd_initialize_smb2(sconn);
1909 if (!NT_STATUS_IS_OK(status)) {
1910 smbd_server_connection_terminate(sconn, nt_errstr(status));
1911 return;
1914 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
1915 if (!NT_STATUS_IS_OK(status)) {
1916 smbd_server_connection_terminate(sconn, nt_errstr(status));
1917 return;
1920 status = smbd_smb2_request_setup_out(req, 1);
1921 if (!NT_STATUS_IS_OK(status)) {
1922 smbd_server_connection_terminate(sconn, nt_errstr(status));
1923 return;
1926 status = smbd_smb2_request_dispatch(req);
1927 if (!NT_STATUS_IS_OK(status)) {
1928 smbd_server_connection_terminate(sconn, nt_errstr(status));
1929 return;
1932 /* ask for the next request */
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;
1938 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
1941 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
1943 uint16_t creds_requested = 0;
1944 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
1945 struct smbd_server_connection);
1946 NTSTATUS status;
1947 struct smbd_smb2_request *req = NULL;
1949 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
1950 TALLOC_FREE(subreq);
1951 if (!NT_STATUS_IS_OK(status)) {
1952 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
1953 nt_errstr(status)));
1954 smbd_server_connection_terminate(sconn, nt_errstr(status));
1955 return;
1958 if (req->in.nbt_hdr[0] != 0x00) {
1959 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
1960 req->in.nbt_hdr[0]));
1961 TALLOC_FREE(req);
1962 goto next;
1965 req->current_idx = 1;
1967 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
1968 req->current_idx, req->in.vector_count));
1970 status = smbd_smb2_request_validate(req, &creds_requested);
1971 if (!NT_STATUS_IS_OK(status)) {
1972 smbd_server_connection_terminate(sconn, nt_errstr(status));
1973 return;
1976 status = smbd_smb2_request_setup_out(req, 5);
1977 if (!NT_STATUS_IS_OK(status)) {
1978 smbd_server_connection_terminate(sconn, nt_errstr(status));
1979 return;
1982 status = smbd_smb2_request_dispatch(req);
1983 if (!NT_STATUS_IS_OK(status)) {
1984 smbd_server_connection_terminate(sconn, nt_errstr(status));
1985 return;
1988 next:
1989 /* ask for the next request (this constructs the main loop) */
1990 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
1991 if (subreq == NULL) {
1992 smbd_server_connection_terminate(sconn, "no memory for reading");
1993 return;
1995 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);