source: vendor/3.6.23/source3/smbd/smb2_server.c

Last change on this file was 860, checked in by Silvan Scherrer, 11 years ago

Samba 3.6: updated vendor to latest version

File size: 66.3 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 Core SMB2 server
4
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#include "includes.h"
23#include "smbd/smbd.h"
24#include "smbd/globals.h"
25#include "../libcli/smb/smb_common.h"
26#include "../lib/tsocket/tsocket.h"
27#include "../lib/util/tevent_ntstatus.h"
28#include "smbprofile.h"
29
30#define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
31
32static const char *smb2_names[] = {
33 "SMB2_NEGPROT",
34 "SMB2_SESSSETUP",
35 "SMB2_LOGOFF",
36 "SMB2_TCON",
37 "SMB2_TDIS",
38 "SMB2_CREATE",
39 "SMB2_CLOSE",
40 "SMB2_FLUSH",
41 "SMB2_READ",
42 "SMB2_WRITE",
43 "SMB2_LOCK",
44 "SMB2_IOCTL",
45 "SMB2_CANCEL",
46 "SMB2_KEEPALIVE",
47 "SMB2_FIND",
48 "SMB2_NOTIFY",
49 "SMB2_GETINFO",
50 "SMB2_SETINFO",
51 "SMB2_BREAK"
52};
53
54const char *smb2_opcode_name(uint16_t opcode)
55{
56 if (opcode > 0x12) {
57 return "Bad SMB2 opcode";
58 }
59 return smb2_names[opcode];
60}
61
62static void print_req_vectors(struct smbd_smb2_request *req)
63{
64 int i;
65
66 for (i = 0; i < req->in.vector_count; i++) {
67 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
68 (unsigned int)i,
69 (unsigned int)req->in.vector[i].iov_len);
70 }
71 for (i = 0; i < req->out.vector_count; i++) {
72 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
73 (unsigned int)i,
74 (unsigned int)req->out.vector[i].iov_len);
75 }
76}
77
78bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
79{
80 if (size < (4 + SMB2_HDR_BODY)) {
81 return false;
82 }
83
84 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
85 return false;
86 }
87
88 return true;
89}
90
91static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
92{
93 NTSTATUS status;
94 int ret;
95
96 TALLOC_FREE(sconn->smb1.fde);
97
98 sconn->smb2.event_ctx = smbd_event_context();
99
100 sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
101 if (sconn->smb2.recv_queue == NULL) {
102 return NT_STATUS_NO_MEMORY;
103 }
104
105 sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
106 if (sconn->smb2.send_queue == NULL) {
107 return NT_STATUS_NO_MEMORY;
108 }
109
110 sconn->smb2.sessions.idtree = idr_init(sconn);
111 if (sconn->smb2.sessions.idtree == NULL) {
112 return NT_STATUS_NO_MEMORY;
113 }
114 sconn->smb2.sessions.limit = 0x0000FFFE;
115 sconn->smb2.sessions.list = NULL;
116 sconn->smb2.seqnum_low = 0;
117 sconn->smb2.seqnum_range = 1;
118 sconn->smb2.credits_granted = 1;
119 sconn->smb2.max_credits = lp_smb2_max_credits();
120 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
121 sconn->smb2.max_credits);
122 if (sconn->smb2.credits_bitmap == NULL) {
123 return NT_STATUS_NO_MEMORY;
124 }
125
126 ret = tstream_bsd_existing_socket(sconn, sconn->sock,
127 &sconn->smb2.stream);
128 if (ret == -1) {
129 status = map_nt_error_from_unix(errno);
130 return status;
131 }
132
133 /* Ensure child is set to non-blocking mode */
134 set_blocking(sconn->sock, false);
135 return NT_STATUS_OK;
136}
137
138#define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
139#define _smb2_setlen(_buf,len) do { \
140 uint8_t *buf = (uint8_t *)_buf; \
141 buf[0] = 0; \
142 buf[1] = ((len)&0xFF0000)>>16; \
143 buf[2] = ((len)&0xFF00)>>8; \
144 buf[3] = (len)&0xFF; \
145} while (0)
146
147static void smb2_setup_nbt_length(struct iovec *vector, int count)
148{
149 size_t len = 0;
150 int i;
151
152 for (i=1; i < count; i++) {
153 len += vector[i].iov_len;
154 }
155
156 _smb2_setlen(vector[0].iov_base, len);
157}
158
159static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request **req)
160{
161 if (*req) {
162 (*req)->parent = NULL;
163 (*req)->mem_pool = NULL;
164 }
165
166 return 0;
167}
168
169static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
170{
171 if (req->parent) {
172 *req->parent = NULL;
173 talloc_free(req->mem_pool);
174 }
175
176 return 0;
177}
178
179static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
180{
181 TALLOC_CTX *mem_pool;
182 struct smbd_smb2_request **parent;
183 struct smbd_smb2_request *req;
184
185#if 0
186 /* Enable this to find subtle valgrind errors. */
187 mem_pool = talloc_init("smbd_smb2_request_allocate");
188#else
189 mem_pool = talloc_pool(mem_ctx, 8192);
190#endif
191 if (mem_pool == NULL) {
192 return NULL;
193 }
194
195 parent = talloc(mem_pool, struct smbd_smb2_request *);
196 if (parent == NULL) {
197 talloc_free(mem_pool);
198 return NULL;
199 }
200
201 req = talloc_zero(parent, struct smbd_smb2_request);
202 if (req == NULL) {
203 talloc_free(mem_pool);
204 return NULL;
205 }
206 *parent = req;
207 req->mem_pool = mem_pool;
208 req->parent = parent;
209
210 req->last_session_id = UINT64_MAX;
211 req->last_tid = UINT32_MAX;
212
213 talloc_set_destructor(parent, smbd_smb2_request_parent_destructor);
214 talloc_set_destructor(req, smbd_smb2_request_destructor);
215
216 return req;
217}
218
219static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
220 const uint8_t *inbuf, size_t size,
221 struct smbd_smb2_request **_req)
222{
223 struct smbd_smb2_request *req;
224 uint32_t protocol_version;
225 const uint8_t *inhdr = NULL;
226 off_t ofs = 0;
227 uint16_t cmd;
228 uint32_t next_command_ofs;
229
230 if (size < (4 + SMB2_HDR_BODY + 2)) {
231 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
232 return NT_STATUS_INVALID_PARAMETER;
233 }
234
235 inhdr = inbuf + 4;
236
237 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
238 if (protocol_version != SMB2_MAGIC) {
239 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
240 protocol_version));
241 return NT_STATUS_INVALID_PARAMETER;
242 }
243
244 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
245 if (cmd != SMB2_OP_NEGPROT) {
246 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
247 cmd));
248 return NT_STATUS_INVALID_PARAMETER;
249 }
250
251 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
252 if (next_command_ofs != 0) {
253 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
254 next_command_ofs));
255 return NT_STATUS_INVALID_PARAMETER;
256 }
257
258 req = smbd_smb2_request_allocate(sconn);
259 if (req == NULL) {
260 return NT_STATUS_NO_MEMORY;
261 }
262 req->sconn = sconn;
263
264 talloc_steal(req, inbuf);
265
266 req->in.vector = talloc_array(req, struct iovec, 4);
267 if (req->in.vector == NULL) {
268 TALLOC_FREE(req);
269 return NT_STATUS_NO_MEMORY;
270 }
271 req->in.vector_count = 4;
272
273 memcpy(req->in.nbt_hdr, inbuf, 4);
274
275 ofs = 0;
276 req->in.vector[0].iov_base = (void *)req->in.nbt_hdr;
277 req->in.vector[0].iov_len = 4;
278 ofs += req->in.vector[0].iov_len;
279
280 req->in.vector[1].iov_base = (void *)(inbuf + ofs);
281 req->in.vector[1].iov_len = SMB2_HDR_BODY;
282 ofs += req->in.vector[1].iov_len;
283
284 req->in.vector[2].iov_base = (void *)(inbuf + ofs);
285 req->in.vector[2].iov_len = SVAL(inbuf, ofs) & 0xFFFE;
286 ofs += req->in.vector[2].iov_len;
287
288 if (ofs > size) {
289 return NT_STATUS_INVALID_PARAMETER;
290 }
291
292 req->in.vector[3].iov_base = (void *)(inbuf + ofs);
293 req->in.vector[3].iov_len = size - ofs;
294 ofs += req->in.vector[3].iov_len;
295
296 req->current_idx = 1;
297
298 *_req = req;
299 return NT_STATUS_OK;
300}
301
302static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
303 uint64_t message_id, uint64_t seq_id)
304{
305 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
306 unsigned int offset;
307
308 if (seq_id < sconn->smb2.seqnum_low) {
309 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
310 "%llu (sequence id %llu) "
311 "(granted = %u, low = %llu, range = %u)\n",
312 (unsigned long long)message_id,
313 (unsigned long long)seq_id,
314 (unsigned int)sconn->smb2.credits_granted,
315 (unsigned long long)sconn->smb2.seqnum_low,
316 (unsigned int)sconn->smb2.seqnum_range));
317 return false;
318 }
319
320 if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) {
321 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
322 "%llu (sequence id %llu) "
323 "(granted = %u, low = %llu, range = %u)\n",
324 (unsigned long long)message_id,
325 (unsigned long long)seq_id,
326 (unsigned int)sconn->smb2.credits_granted,
327 (unsigned long long)sconn->smb2.seqnum_low,
328 (unsigned int)sconn->smb2.seqnum_range));
329 return false;
330 }
331
332 offset = seq_id % sconn->smb2.max_credits;
333
334 if (bitmap_query(credits_bm, offset)) {
335 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
336 "%llu (sequence id %llu) "
337 "(granted = %u, low = %llu, range = %u) "
338 "(bm offset %u)\n",
339 (unsigned long long)message_id,
340 (unsigned long long)seq_id,
341 (unsigned int)sconn->smb2.credits_granted,
342 (unsigned long long)sconn->smb2.seqnum_low,
343 (unsigned int)sconn->smb2.seqnum_range,
344 offset));
345 return false;
346 }
347
348 /* Mark the message_ids as seen in the bitmap. */
349 bitmap_set(credits_bm, offset);
350
351 if (seq_id != sconn->smb2.seqnum_low) {
352 return true;
353 }
354
355 /*
356 * Move the window forward by all the message_id's
357 * already seen.
358 */
359 while (bitmap_query(credits_bm, offset)) {
360 DEBUG(10,("smb2_validate_sequence_number: clearing "
361 "id %llu (position %u) from bitmap\n",
362 (unsigned long long)(sconn->smb2.seqnum_low),
363 offset));
364 bitmap_clear(credits_bm, offset);
365
366 sconn->smb2.seqnum_low += 1;
367 sconn->smb2.seqnum_range -= 1;
368 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
369 }
370
371 return true;
372}
373
374static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
375 const uint8_t *inhdr)
376{
377 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
378 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
379 bool ok;
380
381 if (opcode == SMB2_OP_CANCEL) {
382 /* SMB2_CANCEL requests by definition resend messageids. */
383 return true;
384 }
385
386 DEBUG(11, ("smb2_validate_message_id: mid %llu, credits_granted %llu, "
387 "seqnum low/range: %llu/%llu\n",
388 (unsigned long long) message_id,
389 (unsigned long long) sconn->smb2.credits_granted,
390 (unsigned long long) sconn->smb2.seqnum_low,
391 (unsigned long long) sconn->smb2.seqnum_range));
392
393 if (sconn->smb2.credits_granted < 1) {
394 DEBUG(0, ("smb2_validate_message_id: client used more "
395 "credits than granted, mid %llu, credits_granted %llu, "
396 "seqnum low/range: %llu/%llu\n",
397 (unsigned long long) message_id,
398 (unsigned long long) sconn->smb2.credits_granted,
399 (unsigned long long) sconn->smb2.seqnum_low,
400 (unsigned long long) sconn->smb2.seqnum_range));
401 return false;
402 }
403
404 ok = smb2_validate_sequence_number(sconn, message_id, message_id);
405 if (!ok) {
406 return false;
407 }
408
409 /* substract used credits */
410 sconn->smb2.credits_granted -= 1;
411
412 return true;
413}
414
415static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
416{
417 int count;
418 int idx;
419
420 count = req->in.vector_count;
421
422 if (count < 4) {
423 /* It's not a SMB2 request */
424 return NT_STATUS_INVALID_PARAMETER;
425 }
426
427 for (idx=1; idx < count; idx += 3) {
428 const uint8_t *inhdr = NULL;
429
430 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
431 return NT_STATUS_INVALID_PARAMETER;
432 }
433
434 if (req->in.vector[idx+1].iov_len < 2) {
435 return NT_STATUS_INVALID_PARAMETER;
436 }
437
438 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
439
440 /* Check the SMB2 header */
441 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
442 return NT_STATUS_INVALID_PARAMETER;
443 }
444
445 if (!smb2_validate_message_id(req->sconn, inhdr)) {
446 return NT_STATUS_INVALID_PARAMETER;
447 }
448 }
449
450 return NT_STATUS_OK;
451}
452
453static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
454 const struct iovec *in_vector,
455 struct iovec *out_vector)
456{
457 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
458 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
459 uint16_t credits_requested;
460 uint32_t out_flags;
461 uint16_t cmd;
462 NTSTATUS out_status;
463 uint16_t credits_granted = 0;
464 uint64_t credits_possible;
465 uint16_t current_max_credits;
466
467 /*
468 * first we grant only 1/16th of the max range.
469 *
470 * Windows also starts with the 1/16th and then grants
471 * more later. I was only able to trigger higher
472 * values, when using a verify high credit charge.
473 *
474 * TODO: scale up depending one load, free memory
475 * or other stuff.
476 * Maybe also on the relationship between number
477 * of requests and the used sequence number.
478 * Which means we would grant more credits
479 * for client which use multi credit requests.
480 */
481 current_max_credits = sconn->smb2.max_credits / 16;
482 current_max_credits = MAX(current_max_credits, 1);
483
484 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
485 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
486 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
487 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
488
489 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
490
491 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
492 /*
493 * In case we already send an async interim
494 * response, we should not grant
495 * credits on the final response.
496 */
497 credits_granted = 0;
498 } else if (credits_requested > 0) {
499 uint16_t additional_max = 0;
500 uint16_t additional_credits = credits_requested - 1;
501
502 switch (cmd) {
503 case SMB2_OP_NEGPROT:
504 break;
505 case SMB2_OP_SESSSETUP:
506 /*
507 * Windows 2012 RC1 starts to grant
508 * additional credits
509 * with a successful session setup
510 */
511 if (NT_STATUS_IS_OK(out_status)) {
512 additional_max = 32;
513 }
514 break;
515 default:
516 /*
517 * We match windows and only grant additional credits
518 * in chunks of 32.
519 */
520 additional_max = 32;
521 break;
522 }
523
524 additional_credits = MIN(additional_credits, additional_max);
525
526 credits_granted = 1 + additional_credits;
527 } else if (sconn->smb2.credits_granted == 0) {
528 /*
529 * Make sure the client has always at least one credit
530 */
531 credits_granted = 1;
532 }
533
534 /*
535 * sequence numbers should not wrap
536 *
537 * 1. calculate the possible credits until
538 * the sequence numbers start to wrap on 64-bit.
539 *
540 * 2. UINT64_MAX is used for Break Notifications.
541 *
542 * 2. truncate the possible credits to the maximum
543 * credits we want to grant to the client in total.
544 *
545 * 3. remove the range we'll already granted to the client
546 * this makes sure the client consumes the lowest sequence
547 * number, before we can grant additional credits.
548 */
549 credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
550 if (credits_possible > 0) {
551 /* remove UINT64_MAX */
552 credits_possible -= 1;
553 }
554 credits_possible = MIN(credits_possible, current_max_credits);
555 credits_possible -= sconn->smb2.seqnum_range;
556
557 credits_granted = MIN(credits_granted, credits_possible);
558
559 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
560 sconn->smb2.credits_granted += credits_granted;
561 sconn->smb2.seqnum_range += credits_granted;
562
563 DEBUG(10,("smb2_set_operation_credit: requested %u, "
564 "granted %u, current possible/max %u/%u, "
565 "total granted/max/low/range %u/%u/%llu/%u\n",
566 (unsigned int)credits_requested,
567 (unsigned int)credits_granted,
568 (unsigned int)credits_possible,
569 (unsigned int)current_max_credits,
570 (unsigned int)sconn->smb2.credits_granted,
571 (unsigned int)sconn->smb2.max_credits,
572 (unsigned long long)sconn->smb2.seqnum_low,
573 (unsigned int)sconn->smb2.seqnum_range));
574}
575
576static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
577 struct smbd_smb2_request *outreq)
578{
579 int count, idx;
580 uint16_t total_credits = 0;
581
582 count = outreq->out.vector_count;
583
584 for (idx=1; idx < count; idx += 3) {
585 uint8_t *outhdr = (uint8_t *)outreq->out.vector[idx].iov_base;
586 smb2_set_operation_credit(outreq->sconn,
587 &inreq->in.vector[idx],
588 &outreq->out.vector[idx]);
589 /* To match Windows, count up what we
590 just granted. */
591 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
592 /* Set to zero in all but the last reply. */
593 if (idx + 3 < count) {
594 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
595 } else {
596 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
597 }
598 }
599}
600
601static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
602{
603 struct iovec *vector;
604 int count;
605 int idx;
606
607 count = req->in.vector_count;
608 vector = talloc_zero_array(req, struct iovec, count);
609 if (vector == NULL) {
610 return NT_STATUS_NO_MEMORY;
611 }
612
613 vector[0].iov_base = req->out.nbt_hdr;
614 vector[0].iov_len = 4;
615 SIVAL(req->out.nbt_hdr, 0, 0);
616
617 for (idx=1; idx < count; idx += 3) {
618 const uint8_t *inhdr = NULL;
619 uint32_t in_flags;
620 uint8_t *outhdr = NULL;
621 uint8_t *outbody = NULL;
622 uint32_t next_command_ofs = 0;
623 struct iovec *current = &vector[idx];
624
625 if ((idx + 3) < count) {
626 /* we have a next command -
627 * setup for the error case. */
628 next_command_ofs = SMB2_HDR_BODY + 9;
629 }
630
631 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
632 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
633
634 outhdr = talloc_zero_array(vector, uint8_t,
635 OUTVEC_ALLOC_SIZE);
636 if (outhdr == NULL) {
637 return NT_STATUS_NO_MEMORY;
638 }
639
640 outbody = outhdr + SMB2_HDR_BODY;
641
642 current[0].iov_base = (void *)outhdr;
643 current[0].iov_len = SMB2_HDR_BODY;
644
645 current[1].iov_base = (void *)outbody;
646 current[1].iov_len = 8;
647
648 current[2].iov_base = NULL;
649 current[2].iov_len = 0;
650
651 /* setup the SMB2 header */
652 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
653 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
654 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
655 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
656 SIVAL(outhdr, SMB2_HDR_STATUS,
657 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
658 SSVAL(outhdr, SMB2_HDR_OPCODE,
659 SVAL(inhdr, SMB2_HDR_OPCODE));
660 SIVAL(outhdr, SMB2_HDR_FLAGS,
661 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
662 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
663 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
664 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
665 SIVAL(outhdr, SMB2_HDR_PID,
666 IVAL(inhdr, SMB2_HDR_PID));
667 SIVAL(outhdr, SMB2_HDR_TID,
668 IVAL(inhdr, SMB2_HDR_TID));
669 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
670 BVAL(inhdr, SMB2_HDR_SESSION_ID));
671 memcpy(outhdr + SMB2_HDR_SIGNATURE,
672 inhdr + SMB2_HDR_SIGNATURE, 16);
673
674 /* setup error body header */
675 SSVAL(outbody, 0x00, 0x08 + 1);
676 SSVAL(outbody, 0x02, 0);
677 SIVAL(outbody, 0x04, 0);
678 }
679
680 req->out.vector = vector;
681 req->out.vector_count = count;
682
683 /* setup the length of the NBT packet */
684 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
685
686 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
687
688 return NT_STATUS_OK;
689}
690
691void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
692 const char *reason,
693 const char *location)
694{
695 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
696 reason, location));
697 exit_server_cleanly(reason);
698}
699
700static bool dup_smb2_vec3(TALLOC_CTX *ctx,
701 struct iovec *outvec,
702 const struct iovec *srcvec)
703{
704 /* vec[0] is always boilerplate and must
705 * be allocated with size OUTVEC_ALLOC_SIZE. */
706
707 outvec[0].iov_base = talloc_memdup(ctx,
708 srcvec[0].iov_base,
709 OUTVEC_ALLOC_SIZE);
710 if (!outvec[0].iov_base) {
711 return false;
712 }
713 outvec[0].iov_len = SMB2_HDR_BODY;
714
715 /*
716 * If this is a "standard" vec[1] of length 8,
717 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
718 * then duplicate this. Else use talloc_memdup().
719 */
720
721 if (srcvec[1].iov_len == 8 &&
722 srcvec[1].iov_base ==
723 ((uint8_t *)srcvec[0].iov_base) +
724 SMB2_HDR_BODY) {
725 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
726 SMB2_HDR_BODY;
727 outvec[1].iov_len = 8;
728 } else {
729 outvec[1].iov_base = talloc_memdup(ctx,
730 srcvec[1].iov_base,
731 srcvec[1].iov_len);
732 if (!outvec[1].iov_base) {
733 return false;
734 }
735 outvec[1].iov_len = srcvec[1].iov_len;
736 }
737
738 /*
739 * If this is a "standard" vec[2] of length 1,
740 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
741 * then duplicate this. Else use talloc_memdup().
742 */
743
744 if (srcvec[2].iov_base &&
745 srcvec[2].iov_len) {
746 if (srcvec[2].iov_base ==
747 ((uint8_t *)srcvec[0].iov_base) +
748 (OUTVEC_ALLOC_SIZE - 1) &&
749 srcvec[2].iov_len == 1) {
750 /* Common SMB2 error packet case. */
751 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
752 (OUTVEC_ALLOC_SIZE - 1);
753 } else {
754 outvec[2].iov_base = talloc_memdup(ctx,
755 srcvec[2].iov_base,
756 srcvec[2].iov_len);
757 if (!outvec[2].iov_base) {
758 return false;
759 }
760 }
761 outvec[2].iov_len = srcvec[2].iov_len;
762 } else {
763 outvec[2].iov_base = NULL;
764 outvec[2].iov_len = 0;
765 }
766 return true;
767}
768
769static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
770{
771 struct smbd_smb2_request *newreq = NULL;
772 struct iovec *outvec = NULL;
773 int count = req->out.vector_count;
774 int i;
775
776 newreq = smbd_smb2_request_allocate(req->sconn);
777 if (!newreq) {
778 return NULL;
779 }
780
781 newreq->sconn = req->sconn;
782 newreq->session = req->session;
783 newreq->do_signing = req->do_signing;
784 newreq->current_idx = req->current_idx;
785 newreq->async = false;
786 newreq->cancelled = false;
787 /* Note we are leaving:
788 ->tcon
789 ->smb1req
790 ->compat_chain_fsp
791 uninitialized as NULL here as
792 they're not used in the interim
793 response code. JRA. */
794
795 outvec = talloc_zero_array(newreq, struct iovec, count);
796 if (!outvec) {
797 TALLOC_FREE(newreq);
798 return NULL;
799 }
800 newreq->out.vector = outvec;
801 newreq->out.vector_count = count;
802
803 /* Setup the outvec's identically to req. */
804 outvec[0].iov_base = newreq->out.nbt_hdr;
805 outvec[0].iov_len = 4;
806 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
807
808 /* Setup the vectors identically to the ones in req. */
809 for (i = 1; i < count; i += 3) {
810 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
811 break;
812 }
813 }
814
815 if (i < count) {
816 /* Alloc failed. */
817 TALLOC_FREE(newreq);
818 return NULL;
819 }
820
821 smb2_setup_nbt_length(newreq->out.vector,
822 newreq->out.vector_count);
823
824 return newreq;
825}
826
827static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
828
829static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
830{
831 int i = 0;
832 uint8_t *outhdr = NULL;
833 struct smbd_smb2_request *nreq = NULL;
834
835 /* Create a new smb2 request we'll use
836 for the interim return. */
837 nreq = dup_smb2_req(req);
838 if (!nreq) {
839 return NT_STATUS_NO_MEMORY;
840 }
841
842 /* Lose the last 3 out vectors. They're the
843 ones we'll be using for the async reply. */
844 nreq->out.vector_count -= 3;
845
846 smb2_setup_nbt_length(nreq->out.vector,
847 nreq->out.vector_count);
848
849 /* Step back to the previous reply. */
850 i = nreq->current_idx - 3;
851 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
852 /* And end the chain. */
853 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
854
855 /* Calculate outgoing credits */
856 smb2_calculate_credits(req, nreq);
857
858 /* Re-sign if needed. */
859 if (nreq->do_signing) {
860 NTSTATUS status;
861 status = smb2_signing_sign_pdu(nreq->session->session_key,
862 &nreq->out.vector[i], 3);
863 if (!NT_STATUS_IS_OK(status)) {
864 return status;
865 }
866 }
867 if (DEBUGLEVEL >= 10) {
868 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
869 (unsigned int)nreq->current_idx );
870 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
871 (unsigned int)nreq->out.vector_count );
872 print_req_vectors(nreq);
873 }
874 nreq->subreq = tstream_writev_queue_send(nreq,
875 nreq->sconn->smb2.event_ctx,
876 nreq->sconn->smb2.stream,
877 nreq->sconn->smb2.send_queue,
878 nreq->out.vector,
879 nreq->out.vector_count);
880
881 if (nreq->subreq == NULL) {
882 return NT_STATUS_NO_MEMORY;
883 }
884
885 tevent_req_set_callback(nreq->subreq,
886 smbd_smb2_request_writev_done,
887 nreq);
888
889 return NT_STATUS_OK;
890}
891
892struct smbd_smb2_request_pending_state {
893 struct smbd_server_connection *sconn;
894 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
895 struct iovec vector[3];
896};
897
898static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
899{
900 struct smbd_smb2_request_pending_state *state =
901 tevent_req_callback_data(subreq,
902 struct smbd_smb2_request_pending_state);
903 struct smbd_server_connection *sconn = state->sconn;
904 int ret;
905 int sys_errno;
906
907 ret = tstream_writev_queue_recv(subreq, &sys_errno);
908 TALLOC_FREE(subreq);
909 if (ret == -1) {
910 NTSTATUS status = map_nt_error_from_unix(sys_errno);
911 smbd_server_connection_terminate(sconn, nt_errstr(status));
912 return;
913 }
914
915 TALLOC_FREE(state);
916}
917
918NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
919 struct tevent_req *subreq)
920{
921 NTSTATUS status;
922 struct smbd_smb2_request_pending_state *state = NULL;
923 int i = req->current_idx;
924 uint8_t *reqhdr = NULL;
925 uint8_t *hdr = NULL;
926 uint8_t *body = NULL;
927 uint32_t flags = 0;
928 uint64_t message_id = 0;
929 uint64_t async_id = 0;
930
931 if (!tevent_req_is_in_progress(subreq)) {
932 return NT_STATUS_OK;
933 }
934
935 req->subreq = subreq;
936 subreq = NULL;
937
938 if (req->async) {
939 /* We're already async. */
940 return NT_STATUS_OK;
941 }
942
943 if (req->in.vector_count > i + 3) {
944 /*
945 * We're trying to go async in a compound
946 * request chain.
947 * This is only allowed for opens that
948 * cause an oplock break, otherwise it
949 * is not allowed. See [MS-SMB2].pdf
950 * note <194> on Section 3.3.5.2.7.
951 */
952 const uint8_t *inhdr =
953 (const uint8_t *)req->in.vector[i].iov_base;
954
955 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
956 /*
957 * Cancel the outstanding request.
958 */
959 bool ok = tevent_req_cancel(req->subreq);
960 if (ok) {
961 return NT_STATUS_OK;
962 }
963 TALLOC_FREE(req->subreq);
964 return smbd_smb2_request_error(req,
965 NT_STATUS_INTERNAL_ERROR);
966 }
967 }
968
969 if (DEBUGLEVEL >= 10) {
970 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
971 (unsigned int)req->current_idx );
972 print_req_vectors(req);
973 }
974
975 if (i > 1) {
976 /*
977 * We're going async in a compound
978 * chain after the first request has
979 * already been processed. Send an
980 * interim response containing the
981 * set of replies already generated.
982 */
983 status = smb2_send_async_interim_response(req);
984 if (!NT_STATUS_IS_OK(status)) {
985 return status;
986 }
987
988 req->current_idx = 1;
989
990 /*
991 * Re-arrange the in.vectors to remove what
992 * we just sent.
993 */
994 memmove(&req->in.vector[1],
995 &req->in.vector[i],
996 sizeof(req->in.vector[0])*(req->in.vector_count - i));
997 req->in.vector_count = 1 + (req->in.vector_count - i);
998
999 smb2_setup_nbt_length(req->in.vector, req->in.vector_count);
1000
1001 /* Re-arrange the out.vectors to match. */
1002 memmove(&req->out.vector[1],
1003 &req->out.vector[i],
1004 sizeof(req->out.vector[0])*(req->out.vector_count - i));
1005 req->out.vector_count = 1 + (req->out.vector_count - i);
1006
1007 if (req->in.vector_count == 4) {
1008 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
1009 /*
1010 * We only have one remaining request as
1011 * we've processed everything else.
1012 * This is no longer a compound request.
1013 */
1014 req->compound_related = false;
1015 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1016 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1017 }
1018 }
1019
1020 /* Don't return an intermediate packet on a pipe read/write. */
1021 if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
1022 goto out;
1023 }
1024
1025 reqhdr = (uint8_t *)req->out.vector[i].iov_base;
1026 flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1027 message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
1028 async_id = message_id; /* keep it simple for now... */
1029
1030 /*
1031 * What we send is identical to a smbd_smb2_request_error
1032 * packet with an error status of STATUS_PENDING. Make use
1033 * of this fact sometime when refactoring. JRA.
1034 */
1035
1036 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1037 if (state == NULL) {
1038 return NT_STATUS_NO_MEMORY;
1039 }
1040 state->sconn = req->sconn;
1041
1042 state->vector[0].iov_base = (void *)state->buf;
1043 state->vector[0].iov_len = 4;
1044
1045 state->vector[1].iov_base = state->buf + 4;
1046 state->vector[1].iov_len = SMB2_HDR_BODY;
1047
1048 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1049 state->vector[2].iov_len = 9;
1050
1051 smb2_setup_nbt_length(state->vector, 3);
1052
1053 hdr = (uint8_t *)state->vector[1].iov_base;
1054 body = (uint8_t *)state->vector[2].iov_base;
1055
1056 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1057 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1058 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1059 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1060 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
1061
1062 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1063 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1064 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1065 SBVAL(hdr, SMB2_HDR_PID, async_id);
1066 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1067 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
1068 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1069
1070 SSVAL(body, 0x00, 0x08 + 1);
1071
1072 SCVAL(body, 0x02, 0);
1073 SCVAL(body, 0x03, 0);
1074 SIVAL(body, 0x04, 0);
1075 /* Match W2K8R2... */
1076 SCVAL(body, 0x08, 0x21);
1077
1078 /* Ensure we correctly go through crediting. Grant
1079 the credits now, and zero credits on the final
1080 response. */
1081 smb2_set_operation_credit(req->sconn,
1082 &req->in.vector[i],
1083 &state->vector[1]);
1084
1085 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1086
1087 if (req->do_signing) {
1088 status = smb2_signing_sign_pdu(req->session->session_key,
1089 &state->vector[1], 2);
1090 if (!NT_STATUS_IS_OK(status)) {
1091 return status;
1092 }
1093 }
1094
1095 subreq = tstream_writev_queue_send(state,
1096 req->sconn->smb2.event_ctx,
1097 req->sconn->smb2.stream,
1098 req->sconn->smb2.send_queue,
1099 state->vector,
1100 3);
1101
1102 if (subreq == NULL) {
1103 return NT_STATUS_NO_MEMORY;
1104 }
1105
1106 tevent_req_set_callback(subreq,
1107 smbd_smb2_request_pending_writev_done,
1108 state);
1109
1110 /* Note we're going async with this request. */
1111 req->async = true;
1112
1113 out:
1114
1115 smb2_setup_nbt_length(req->out.vector,
1116 req->out.vector_count);
1117
1118 if (req->async) {
1119 /* Ensure our final reply matches the interim one. */
1120 reqhdr = (uint8_t *)req->out.vector[1].iov_base;
1121 SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1122 SBVAL(reqhdr, SMB2_HDR_PID, async_id);
1123
1124 {
1125 const uint8_t *inhdr =
1126 (const uint8_t *)req->in.vector[1].iov_base;
1127 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1128 "going async\n",
1129 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1130 (unsigned long long)async_id ));
1131 }
1132 }
1133
1134 return NT_STATUS_OK;
1135}
1136
1137static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1138{
1139 struct smbd_server_connection *sconn = req->sconn;
1140 struct smbd_smb2_request *cur;
1141 const uint8_t *inhdr;
1142 int i = req->current_idx;
1143 uint32_t flags;
1144 uint64_t search_message_id;
1145 uint64_t search_async_id;
1146 uint64_t found_id;
1147
1148 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1149
1150 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1151 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1152 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1153
1154 /*
1155 * we don't need the request anymore
1156 * cancel requests never have a response
1157 */
1158 DLIST_REMOVE(req->sconn->smb2.requests, req);
1159 TALLOC_FREE(req);
1160
1161 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1162 const uint8_t *outhdr;
1163 uint64_t message_id;
1164 uint64_t async_id;
1165
1166 if (cur->compound_related) {
1167 /*
1168 * Never cancel anything in a compound request.
1169 * Way too hard to deal with the result.
1170 */
1171 continue;
1172 }
1173
1174 i = cur->current_idx;
1175
1176 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1177
1178 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1179 async_id = BVAL(outhdr, SMB2_HDR_PID);
1180
1181 if (flags & SMB2_HDR_FLAG_ASYNC) {
1182 if (search_async_id == async_id) {
1183 found_id = async_id;
1184 break;
1185 }
1186 } else {
1187 if (search_message_id == message_id) {
1188 found_id = message_id;
1189 break;
1190 }
1191 }
1192 }
1193
1194 if (cur && cur->subreq) {
1195 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1196 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1197 "cancel opcode[%s] mid %llu\n",
1198 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1199 (unsigned long long)found_id ));
1200 tevent_req_cancel(cur->subreq);
1201 }
1202
1203 return NT_STATUS_OK;
1204}
1205
1206NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1207 size_t expected_body_size)
1208{
1209 const uint8_t *inhdr;
1210 uint16_t opcode;
1211 const uint8_t *inbody;
1212 int i = req->current_idx;
1213 size_t body_size;
1214 size_t min_dyn_size = expected_body_size & 0x00000001;
1215
1216 /*
1217 * The following should be checked already.
1218 */
1219 if ((i+2) > req->in.vector_count) {
1220 return NT_STATUS_INTERNAL_ERROR;
1221 }
1222 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1223 return NT_STATUS_INTERNAL_ERROR;
1224 }
1225 if (req->in.vector[i+1].iov_len < 2) {
1226 return NT_STATUS_INTERNAL_ERROR;
1227 }
1228
1229 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1230 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1231
1232 switch (opcode) {
1233 case SMB2_OP_IOCTL:
1234 case SMB2_OP_GETINFO:
1235 min_dyn_size = 0;
1236 break;
1237 }
1238
1239 /*
1240 * Now check the expected body size,
1241 * where the last byte might be in the
1242 * dynnamic section..
1243 */
1244 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1245 return NT_STATUS_INVALID_PARAMETER;
1246 }
1247 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1248 return NT_STATUS_INVALID_PARAMETER;
1249 }
1250
1251 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1252
1253 body_size = SVAL(inbody, 0x00);
1254 if (body_size != expected_body_size) {
1255 return NT_STATUS_INVALID_PARAMETER;
1256 }
1257
1258 return NT_STATUS_OK;
1259}
1260
1261NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1262{
1263 const uint8_t *inhdr;
1264 int i = req->current_idx;
1265 uint16_t opcode;
1266 uint32_t flags;
1267 uint64_t mid;
1268 NTSTATUS status;
1269 NTSTATUS session_status;
1270 uint32_t allowed_flags;
1271 NTSTATUS return_value;
1272
1273 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1274
1275 /* TODO: verify more things */
1276
1277 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1278 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1279 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1280 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1281 smb2_opcode_name(opcode),
1282 (unsigned long long)mid));
1283
1284 if (get_Protocol() >= PROTOCOL_SMB2) {
1285 /*
1286 * once the protocol is negotiated
1287 * SMB2_OP_NEGPROT is not allowed anymore
1288 */
1289 if (opcode == SMB2_OP_NEGPROT) {
1290 /* drop the connection */
1291 return NT_STATUS_INVALID_PARAMETER;
1292 }
1293 } else {
1294 /*
1295 * if the protocol is not negotiated yet
1296 * only SMB2_OP_NEGPROT is allowed.
1297 */
1298 if (opcode != SMB2_OP_NEGPROT) {
1299 /* drop the connection */
1300 return NT_STATUS_INVALID_PARAMETER;
1301 }
1302 }
1303
1304 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1305 SMB2_HDR_FLAG_SIGNED |
1306 SMB2_HDR_FLAG_DFS;
1307 if (opcode == SMB2_OP_CANCEL) {
1308 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1309 }
1310 if ((flags & ~allowed_flags) != 0) {
1311 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1312 }
1313
1314 /*
1315 * Check if the client provided a valid session id,
1316 * if so smbd_smb2_request_check_session() calls
1317 * set_current_user_info().
1318 *
1319 * As some command don't require a valid session id
1320 * we defer the check of the session_status
1321 */
1322 session_status = smbd_smb2_request_check_session(req);
1323
1324 if (flags & SMB2_HDR_FLAG_CHAINED) {
1325 /*
1326 * This check is mostly for giving the correct error code
1327 * for compounded requests.
1328 */
1329 if (!NT_STATUS_IS_OK(session_status)) {
1330 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1331 }
1332 } else {
1333 req->compat_chain_fsp = NULL;
1334 }
1335
1336 req->do_signing = false;
1337 if (flags & SMB2_HDR_FLAG_SIGNED) {
1338 if (!NT_STATUS_IS_OK(session_status)) {
1339 return smbd_smb2_request_error(req, session_status);
1340 }
1341
1342 req->do_signing = true;
1343 status = smb2_signing_check_pdu(req->session->session_key,
1344 &req->in.vector[i], 3);
1345 if (!NT_STATUS_IS_OK(status)) {
1346 return smbd_smb2_request_error(req, status);
1347 }
1348 } else if (opcode == SMB2_OP_CANCEL) {
1349 /* Cancel requests are allowed to skip the signing */
1350 } else if (req->session && req->session->do_signing) {
1351 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1352 }
1353
1354 if (flags & SMB2_HDR_FLAG_CHAINED) {
1355 req->compound_related = true;
1356 }
1357
1358 switch (opcode) {
1359 case SMB2_OP_NEGPROT:
1360 /* This call needs to be run as root */
1361 change_to_root_user();
1362
1363 {
1364 START_PROFILE(smb2_negprot);
1365 return_value = smbd_smb2_request_process_negprot(req);
1366 END_PROFILE(smb2_negprot);
1367 }
1368 break;
1369
1370 case SMB2_OP_SESSSETUP:
1371 /* This call needs to be run as root */
1372 change_to_root_user();
1373
1374 {
1375 START_PROFILE(smb2_sesssetup);
1376 return_value = smbd_smb2_request_process_sesssetup(req);
1377 END_PROFILE(smb2_sesssetup);
1378 }
1379 break;
1380
1381 case SMB2_OP_LOGOFF:
1382 if (!NT_STATUS_IS_OK(session_status)) {
1383 return_value = smbd_smb2_request_error(req, session_status);
1384 break;
1385 }
1386
1387 /* This call needs to be run as root */
1388 change_to_root_user();
1389
1390 {
1391 START_PROFILE(smb2_logoff);
1392 return_value = smbd_smb2_request_process_logoff(req);
1393 END_PROFILE(smb2_logoff);
1394 }
1395 break;
1396
1397 case SMB2_OP_TCON:
1398 if (!NT_STATUS_IS_OK(session_status)) {
1399 return_value = smbd_smb2_request_error(req, session_status);
1400 break;
1401 }
1402
1403 /*
1404 * This call needs to be run as root.
1405 *
1406 * smbd_smb2_request_process_tcon()
1407 * calls make_connection_snum(), which will call
1408 * change_to_user(), when needed.
1409 */
1410 change_to_root_user();
1411
1412 {
1413 START_PROFILE(smb2_tcon);
1414 return_value = smbd_smb2_request_process_tcon(req);
1415 END_PROFILE(smb2_tcon);
1416 }
1417 break;
1418
1419 case SMB2_OP_TDIS:
1420 if (!NT_STATUS_IS_OK(session_status)) {
1421 return_value = smbd_smb2_request_error(req, session_status);
1422 break;
1423 }
1424 /*
1425 * This call needs to be run as user.
1426 *
1427 * smbd_smb2_request_check_tcon()
1428 * calls change_to_user() on success.
1429 */
1430 status = smbd_smb2_request_check_tcon(req);
1431 if (!NT_STATUS_IS_OK(status)) {
1432 return_value = smbd_smb2_request_error(req, status);
1433 break;
1434 }
1435 /* This call needs to be run as root */
1436 change_to_root_user();
1437
1438
1439 {
1440 START_PROFILE(smb2_tdis);
1441 return_value = smbd_smb2_request_process_tdis(req);
1442 END_PROFILE(smb2_tdis);
1443 }
1444 break;
1445
1446 case SMB2_OP_CREATE:
1447 if (!NT_STATUS_IS_OK(session_status)) {
1448 return_value = smbd_smb2_request_error(req, session_status);
1449 break;
1450 }
1451 /*
1452 * This call needs to be run as user.
1453 *
1454 * smbd_smb2_request_check_tcon()
1455 * calls change_to_user() on success.
1456 */
1457 status = smbd_smb2_request_check_tcon(req);
1458 if (!NT_STATUS_IS_OK(status)) {
1459 return_value = smbd_smb2_request_error(req, status);
1460 break;
1461 }
1462
1463 {
1464 START_PROFILE(smb2_create);
1465 return_value = smbd_smb2_request_process_create(req);
1466 END_PROFILE(smb2_create);
1467 }
1468 break;
1469
1470 case SMB2_OP_CLOSE:
1471 if (!NT_STATUS_IS_OK(session_status)) {
1472 return_value = smbd_smb2_request_error(req, session_status);
1473 break;
1474 }
1475 /*
1476 * This call needs to be run as user.
1477 *
1478 * smbd_smb2_request_check_tcon()
1479 * calls change_to_user() on success.
1480 */
1481 status = smbd_smb2_request_check_tcon(req);
1482 if (!NT_STATUS_IS_OK(status)) {
1483 return_value = smbd_smb2_request_error(req, status);
1484 break;
1485 }
1486
1487 {
1488 START_PROFILE(smb2_close);
1489 return_value = smbd_smb2_request_process_close(req);
1490 END_PROFILE(smb2_close);
1491 }
1492 break;
1493
1494 case SMB2_OP_FLUSH:
1495 if (!NT_STATUS_IS_OK(session_status)) {
1496 return_value = smbd_smb2_request_error(req, session_status);
1497 break;
1498 }
1499 /*
1500 * This call needs to be run as user.
1501 *
1502 * smbd_smb2_request_check_tcon()
1503 * calls change_to_user() on success.
1504 */
1505 status = smbd_smb2_request_check_tcon(req);
1506 if (!NT_STATUS_IS_OK(status)) {
1507 return_value = smbd_smb2_request_error(req, status);
1508 break;
1509 }
1510
1511 {
1512 START_PROFILE(smb2_flush);
1513 return_value = smbd_smb2_request_process_flush(req);
1514 END_PROFILE(smb2_flush);
1515 }
1516 break;
1517
1518 case SMB2_OP_READ:
1519 if (!NT_STATUS_IS_OK(session_status)) {
1520 return_value = smbd_smb2_request_error(req, session_status);
1521 break;
1522 }
1523 /*
1524 * This call needs to be run as user.
1525 *
1526 * smbd_smb2_request_check_tcon()
1527 * calls change_to_user() on success.
1528 */
1529 status = smbd_smb2_request_check_tcon(req);
1530 if (!NT_STATUS_IS_OK(status)) {
1531 return_value = smbd_smb2_request_error(req, status);
1532 break;
1533 }
1534
1535 {
1536 START_PROFILE(smb2_read);
1537 return_value = smbd_smb2_request_process_read(req);
1538 END_PROFILE(smb2_read);
1539 }
1540 break;
1541
1542 case SMB2_OP_WRITE:
1543 if (!NT_STATUS_IS_OK(session_status)) {
1544 return_value = smbd_smb2_request_error(req, session_status);
1545 break;
1546 }
1547 /*
1548 * This call needs to be run as user.
1549 *
1550 * smbd_smb2_request_check_tcon()
1551 * calls change_to_user() on success.
1552 */
1553 status = smbd_smb2_request_check_tcon(req);
1554 if (!NT_STATUS_IS_OK(status)) {
1555 return_value = smbd_smb2_request_error(req, status);
1556 break;
1557 }
1558
1559 {
1560 START_PROFILE(smb2_write);
1561 return_value = smbd_smb2_request_process_write(req);
1562 END_PROFILE(smb2_write);
1563 }
1564 break;
1565
1566 case SMB2_OP_LOCK:
1567 if (!NT_STATUS_IS_OK(session_status)) {
1568 /* Too ugly to live ? JRA. */
1569 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1570 session_status = NT_STATUS_FILE_CLOSED;
1571 }
1572 return_value = smbd_smb2_request_error(req, session_status);
1573 break;
1574 }
1575 /*
1576 * This call needs to be run as user.
1577 *
1578 * smbd_smb2_request_check_tcon()
1579 * calls change_to_user() on success.
1580 */
1581 status = smbd_smb2_request_check_tcon(req);
1582 if (!NT_STATUS_IS_OK(status)) {
1583 /* Too ugly to live ? JRA. */
1584 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1585 status = NT_STATUS_FILE_CLOSED;
1586 }
1587 return_value = smbd_smb2_request_error(req, status);
1588 break;
1589 }
1590
1591 {
1592 START_PROFILE(smb2_lock);
1593 return_value = smbd_smb2_request_process_lock(req);
1594 END_PROFILE(smb2_lock);
1595 }
1596 break;
1597
1598 case SMB2_OP_IOCTL:
1599 if (!NT_STATUS_IS_OK(session_status)) {
1600 return_value = smbd_smb2_request_error(req, session_status);
1601 break;
1602 }
1603 /*
1604 * This call needs to be run as user.
1605 *
1606 * smbd_smb2_request_check_tcon()
1607 * calls change_to_user() on success.
1608 */
1609 status = smbd_smb2_request_check_tcon(req);
1610 if (!NT_STATUS_IS_OK(status)) {
1611 return_value = smbd_smb2_request_error(req, status);
1612 break;
1613 }
1614
1615 {
1616 START_PROFILE(smb2_ioctl);
1617 return_value = smbd_smb2_request_process_ioctl(req);
1618 END_PROFILE(smb2_ioctl);
1619 }
1620 break;
1621
1622 case SMB2_OP_CANCEL:
1623 /*
1624 * This call needs to be run as root
1625 *
1626 * That is what we also do in the SMB1 case.
1627 */
1628 change_to_root_user();
1629
1630 {
1631 START_PROFILE(smb2_cancel);
1632 return_value = smbd_smb2_request_process_cancel(req);
1633 END_PROFILE(smb2_cancel);
1634 }
1635 break;
1636
1637 case SMB2_OP_KEEPALIVE:
1638 /* This call needs to be run as root */
1639 change_to_root_user();
1640
1641 {
1642 START_PROFILE(smb2_keepalive);
1643 return_value = smbd_smb2_request_process_keepalive(req);
1644 END_PROFILE(smb2_keepalive);
1645 }
1646 break;
1647
1648 case SMB2_OP_FIND:
1649 if (!NT_STATUS_IS_OK(session_status)) {
1650 return_value = smbd_smb2_request_error(req, session_status);
1651 break;
1652 }
1653 /*
1654 * This call needs to be run as user.
1655 *
1656 * smbd_smb2_request_check_tcon()
1657 * calls change_to_user() on success.
1658 */
1659 status = smbd_smb2_request_check_tcon(req);
1660 if (!NT_STATUS_IS_OK(status)) {
1661 return_value = smbd_smb2_request_error(req, status);
1662 break;
1663 }
1664
1665 {
1666 START_PROFILE(smb2_find);
1667 return_value = smbd_smb2_request_process_find(req);
1668 END_PROFILE(smb2_find);
1669 }
1670 break;
1671
1672 case SMB2_OP_NOTIFY:
1673 if (!NT_STATUS_IS_OK(session_status)) {
1674 return_value = smbd_smb2_request_error(req, session_status);
1675 break;
1676 }
1677 /*
1678 * This call needs to be run as user.
1679 *
1680 * smbd_smb2_request_check_tcon()
1681 * calls change_to_user() on success.
1682 */
1683 status = smbd_smb2_request_check_tcon(req);
1684 if (!NT_STATUS_IS_OK(status)) {
1685 return_value = smbd_smb2_request_error(req, status);
1686 break;
1687 }
1688
1689 {
1690 START_PROFILE(smb2_notify);
1691 return_value = smbd_smb2_request_process_notify(req);
1692 END_PROFILE(smb2_notify);
1693 }
1694 break;
1695
1696 case SMB2_OP_GETINFO:
1697 if (!NT_STATUS_IS_OK(session_status)) {
1698 return_value = smbd_smb2_request_error(req, session_status);
1699 break;
1700 }
1701 /*
1702 * This call needs to be run as user.
1703 *
1704 * smbd_smb2_request_check_tcon()
1705 * calls change_to_user() on success.
1706 */
1707 status = smbd_smb2_request_check_tcon(req);
1708 if (!NT_STATUS_IS_OK(status)) {
1709 return_value = smbd_smb2_request_error(req, status);
1710 break;
1711 }
1712
1713 {
1714 START_PROFILE(smb2_getinfo);
1715 return_value = smbd_smb2_request_process_getinfo(req);
1716 END_PROFILE(smb2_getinfo);
1717 }
1718 break;
1719
1720 case SMB2_OP_SETINFO:
1721 if (!NT_STATUS_IS_OK(session_status)) {
1722 return_value = smbd_smb2_request_error(req, session_status);
1723 break;
1724 }
1725 /*
1726 * This call needs to be run as user.
1727 *
1728 * smbd_smb2_request_check_tcon()
1729 * calls change_to_user() on success.
1730 */
1731 status = smbd_smb2_request_check_tcon(req);
1732 if (!NT_STATUS_IS_OK(status)) {
1733 return_value = smbd_smb2_request_error(req, status);
1734 break;
1735 }
1736
1737 {
1738 START_PROFILE(smb2_setinfo);
1739 return_value = smbd_smb2_request_process_setinfo(req);
1740 END_PROFILE(smb2_setinfo);
1741 }
1742 break;
1743
1744 case SMB2_OP_BREAK:
1745 if (!NT_STATUS_IS_OK(session_status)) {
1746 return_value = smbd_smb2_request_error(req, session_status);
1747 break;
1748 }
1749 /*
1750 * This call needs to be run as user.
1751 *
1752 * smbd_smb2_request_check_tcon()
1753 * calls change_to_user() on success.
1754 */
1755 status = smbd_smb2_request_check_tcon(req);
1756 if (!NT_STATUS_IS_OK(status)) {
1757 return_value = smbd_smb2_request_error(req, status);
1758 break;
1759 }
1760
1761 {
1762 START_PROFILE(smb2_break);
1763 return_value = smbd_smb2_request_process_break(req);
1764 END_PROFILE(smb2_break);
1765 }
1766 break;
1767
1768 default:
1769 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1770 break;
1771 }
1772 return return_value;
1773}
1774
1775static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1776{
1777 struct tevent_req *subreq;
1778 int i = req->current_idx;
1779
1780 req->subreq = NULL;
1781
1782 req->current_idx += 3;
1783
1784 if (req->current_idx < req->out.vector_count) {
1785 /*
1786 * We must process the remaining compound
1787 * SMB2 requests before any new incoming SMB2
1788 * requests. This is because incoming SMB2
1789 * requests may include a cancel for a
1790 * compound request we haven't processed
1791 * yet.
1792 */
1793 struct tevent_immediate *im = tevent_create_immediate(req);
1794 if (!im) {
1795 return NT_STATUS_NO_MEMORY;
1796 }
1797
1798 if (req->do_signing) {
1799 /*
1800 * We sign each reply as we go along.
1801 * We can do this as smb2_calculate_credits()
1802 * grants zero credits on every part of a
1803 * compound reply except the last one,
1804 * which is signed just before calling
1805 * tstream_writev_queue_send().
1806 */
1807 NTSTATUS status;
1808 status = smb2_signing_sign_pdu(req->session->session_key,
1809 &req->out.vector[i], 3);
1810 if (!NT_STATUS_IS_OK(status)) {
1811 TALLOC_FREE(im);
1812 return status;
1813 }
1814 }
1815
1816 tevent_schedule_immediate(im,
1817 req->sconn->smb2.event_ctx,
1818 smbd_smb2_request_dispatch_immediate,
1819 req);
1820 return NT_STATUS_OK;
1821 }
1822
1823 if (req->compound_related) {
1824 req->compound_related = false;
1825 }
1826
1827 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1828
1829 /* Set credit for these operations (zero credits if this
1830 is a final reply for an async operation). */
1831 smb2_calculate_credits(req, req);
1832
1833 if (req->do_signing) {
1834 NTSTATUS status;
1835 status = smb2_signing_sign_pdu(req->session->session_key,
1836 &req->out.vector[i], 3);
1837 if (!NT_STATUS_IS_OK(status)) {
1838 return status;
1839 }
1840 }
1841
1842 if (DEBUGLEVEL >= 10) {
1843 dbgtext("smbd_smb2_request_reply: sending...\n");
1844 print_req_vectors(req);
1845 }
1846
1847 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1848 if (req->out.vector_count == 4 &&
1849 req->out.vector[3].iov_base == NULL &&
1850 req->out.vector[3].iov_len != 0) {
1851 /* Dynamic part is NULL. Chop it off,
1852 We're going to send it via sendfile. */
1853 req->out.vector_count -= 1;
1854 }
1855
1856 subreq = tstream_writev_queue_send(req,
1857 req->sconn->smb2.event_ctx,
1858 req->sconn->smb2.stream,
1859 req->sconn->smb2.send_queue,
1860 req->out.vector,
1861 req->out.vector_count);
1862 if (subreq == NULL) {
1863 return NT_STATUS_NO_MEMORY;
1864 }
1865 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1866 /*
1867 * We're done with this request -
1868 * move it off the "being processed" queue.
1869 */
1870 DLIST_REMOVE(req->sconn->smb2.requests, req);
1871
1872 return NT_STATUS_OK;
1873}
1874
1875static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1876
1877void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1878 struct tevent_immediate *im,
1879 void *private_data)
1880{
1881 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1882 struct smbd_smb2_request);
1883 struct smbd_server_connection *sconn = req->sconn;
1884 NTSTATUS status;
1885
1886 TALLOC_FREE(im);
1887
1888 if (DEBUGLEVEL >= 10) {
1889 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1890 req->current_idx, req->in.vector_count));
1891 print_req_vectors(req);
1892 }
1893
1894 status = smbd_smb2_request_dispatch(req);
1895 if (!NT_STATUS_IS_OK(status)) {
1896 smbd_server_connection_terminate(sconn, nt_errstr(status));
1897 return;
1898 }
1899
1900 status = smbd_smb2_request_next_incoming(sconn);
1901 if (!NT_STATUS_IS_OK(status)) {
1902 smbd_server_connection_terminate(sconn, nt_errstr(status));
1903 return;
1904 }
1905}
1906
1907static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1908{
1909 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1910 struct smbd_smb2_request);
1911 struct smbd_server_connection *sconn = req->sconn;
1912 int ret;
1913 int sys_errno;
1914 NTSTATUS status;
1915
1916 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1917 TALLOC_FREE(subreq);
1918 TALLOC_FREE(req);
1919 if (ret == -1) {
1920 status = map_nt_error_from_unix(sys_errno);
1921 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1922 nt_errstr(status)));
1923 smbd_server_connection_terminate(sconn, nt_errstr(status));
1924 return;
1925 }
1926
1927 status = smbd_smb2_request_next_incoming(sconn);
1928 if (!NT_STATUS_IS_OK(status)) {
1929 smbd_server_connection_terminate(sconn, nt_errstr(status));
1930 return;
1931 }
1932}
1933
1934NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1935 NTSTATUS status,
1936 DATA_BLOB body, DATA_BLOB *dyn,
1937 const char *location)
1938{
1939 uint8_t *outhdr;
1940 int i = req->current_idx;
1941 uint32_t next_command_ofs;
1942
1943 DEBUG(10,("smbd_smb2_request_done_ex: "
1944 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1945 i, nt_errstr(status), (unsigned int)body.length,
1946 dyn ? "yes": "no",
1947 (unsigned int)(dyn ? dyn->length : 0),
1948 location));
1949
1950 if (body.length < 2) {
1951 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1952 }
1953
1954 if ((body.length % 2) != 0) {
1955 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1956 }
1957
1958 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1959
1960 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1961 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1962
1963 req->out.vector[i+1].iov_base = (void *)body.data;
1964 req->out.vector[i+1].iov_len = body.length;
1965
1966 if (dyn) {
1967 req->out.vector[i+2].iov_base = (void *)dyn->data;
1968 req->out.vector[i+2].iov_len = dyn->length;
1969 } else {
1970 req->out.vector[i+2].iov_base = NULL;
1971 req->out.vector[i+2].iov_len = 0;
1972 }
1973
1974 /* see if we need to recalculate the offset to the next response */
1975 if (next_command_ofs > 0) {
1976 next_command_ofs = SMB2_HDR_BODY;
1977 next_command_ofs += req->out.vector[i+1].iov_len;
1978 next_command_ofs += req->out.vector[i+2].iov_len;
1979 }
1980
1981 if ((next_command_ofs % 8) != 0) {
1982 size_t pad_size = 8 - (next_command_ofs % 8);
1983 if (req->out.vector[i+2].iov_len == 0) {
1984 /*
1985 * if the dyn buffer is empty
1986 * we can use it to add padding
1987 */
1988 uint8_t *pad;
1989
1990 pad = talloc_zero_array(req->out.vector,
1991 uint8_t, pad_size);
1992 if (pad == NULL) {
1993 return smbd_smb2_request_error(req,
1994 NT_STATUS_NO_MEMORY);
1995 }
1996
1997 req->out.vector[i+2].iov_base = (void *)pad;
1998 req->out.vector[i+2].iov_len = pad_size;
1999 } else {
2000 /*
2001 * For now we copy the dynamic buffer
2002 * and add the padding to the new buffer
2003 */
2004 size_t old_size;
2005 uint8_t *old_dyn;
2006 size_t new_size;
2007 uint8_t *new_dyn;
2008
2009 old_size = req->out.vector[i+2].iov_len;
2010 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2011
2012 new_size = old_size + pad_size;
2013 new_dyn = talloc_zero_array(req->out.vector,
2014 uint8_t, new_size);
2015 if (new_dyn == NULL) {
2016 return smbd_smb2_request_error(req,
2017 NT_STATUS_NO_MEMORY);
2018 }
2019
2020 memcpy(new_dyn, old_dyn, old_size);
2021 memset(new_dyn + old_size, 0, pad_size);
2022
2023 req->out.vector[i+2].iov_base = (void *)new_dyn;
2024 req->out.vector[i+2].iov_len = new_size;
2025 }
2026 next_command_ofs += pad_size;
2027 }
2028
2029 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2030
2031 return smbd_smb2_request_reply(req);
2032}
2033
2034NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2035 NTSTATUS status,
2036 DATA_BLOB *info,
2037 const char *location)
2038{
2039 DATA_BLOB body;
2040 int i = req->current_idx;
2041 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
2042
2043 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2044 i, nt_errstr(status), info ? " +info" : "",
2045 location));
2046
2047 body.data = outhdr + SMB2_HDR_BODY;
2048 body.length = 8;
2049 SSVAL(body.data, 0, 9);
2050
2051 if (info) {
2052 SIVAL(body.data, 0x04, info->length);
2053 } else {
2054 /* Allocated size of req->out.vector[i].iov_base
2055 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2056 * 1 byte without having to do an alloc.
2057 */
2058 info = talloc_zero_array(req->out.vector,
2059 DATA_BLOB,
2060 1);
2061 if (!info) {
2062 return NT_STATUS_NO_MEMORY;
2063 }
2064 info->data = ((uint8_t *)outhdr) +
2065 OUTVEC_ALLOC_SIZE - 1;
2066 info->length = 1;
2067 SCVAL(info->data, 0, 0);
2068 }
2069
2070 /*
2071 * Note: Even if there is an error, continue to process the request.
2072 * per MS-SMB2.
2073 */
2074
2075 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2076}
2077
2078
2079struct smbd_smb2_send_oplock_break_state {
2080 struct smbd_server_connection *sconn;
2081 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2082 struct iovec vector;
2083};
2084
2085static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2086
2087NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2088 uint64_t file_id_persistent,
2089 uint64_t file_id_volatile,
2090 uint8_t oplock_level)
2091{
2092 struct smbd_smb2_send_oplock_break_state *state;
2093 struct tevent_req *subreq;
2094 uint8_t *hdr;
2095 uint8_t *body;
2096
2097 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2098 if (state == NULL) {
2099 return NT_STATUS_NO_MEMORY;
2100 }
2101 state->sconn = sconn;
2102
2103 state->vector.iov_base = (void *)state->buf;
2104 state->vector.iov_len = sizeof(state->buf);
2105
2106 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2107 hdr = state->buf + 4;
2108 body = hdr + SMB2_HDR_BODY;
2109
2110 SIVAL(hdr, 0, SMB2_MAGIC);
2111 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2112 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2113 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2114 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2115 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2116 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2117 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2118 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2119 SIVAL(hdr, SMB2_HDR_PID, 0);
2120 SIVAL(hdr, SMB2_HDR_TID, 0);
2121 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2122 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2123
2124 SSVAL(body, 0x00, 0x18);
2125
2126 SCVAL(body, 0x02, oplock_level);
2127 SCVAL(body, 0x03, 0); /* reserved */
2128 SIVAL(body, 0x04, 0); /* reserved */
2129 SBVAL(body, 0x08, file_id_persistent);
2130 SBVAL(body, 0x10, file_id_volatile);
2131
2132 subreq = tstream_writev_queue_send(state,
2133 sconn->smb2.event_ctx,
2134 sconn->smb2.stream,
2135 sconn->smb2.send_queue,
2136 &state->vector, 1);
2137 if (subreq == NULL) {
2138 return NT_STATUS_NO_MEMORY;
2139 }
2140 tevent_req_set_callback(subreq,
2141 smbd_smb2_oplock_break_writev_done,
2142 state);
2143
2144 return NT_STATUS_OK;
2145}
2146
2147static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2148{
2149 struct smbd_smb2_send_oplock_break_state *state =
2150 tevent_req_callback_data(subreq,
2151 struct smbd_smb2_send_oplock_break_state);
2152 struct smbd_server_connection *sconn = state->sconn;
2153 int ret;
2154 int sys_errno;
2155
2156 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2157 TALLOC_FREE(subreq);
2158 if (ret == -1) {
2159 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2160 smbd_server_connection_terminate(sconn, nt_errstr(status));
2161 return;
2162 }
2163
2164 TALLOC_FREE(state);
2165}
2166
2167struct smbd_smb2_request_read_state {
2168 size_t missing;
2169 bool asked_for_header;
2170 struct smbd_smb2_request *smb2_req;
2171};
2172
2173static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2174 void *private_data,
2175 TALLOC_CTX *mem_ctx,
2176 struct iovec **_vector,
2177 size_t *_count);
2178static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2179
2180static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2181 struct tevent_context *ev,
2182 struct smbd_server_connection *sconn)
2183{
2184 struct tevent_req *req;
2185 struct smbd_smb2_request_read_state *state;
2186 struct tevent_req *subreq;
2187
2188 req = tevent_req_create(mem_ctx, &state,
2189 struct smbd_smb2_request_read_state);
2190 if (req == NULL) {
2191 return NULL;
2192 }
2193 state->missing = 0;
2194 state->asked_for_header = false;
2195
2196 state->smb2_req = smbd_smb2_request_allocate(state);
2197 if (tevent_req_nomem(state->smb2_req, req)) {
2198 return tevent_req_post(req, ev);
2199 }
2200 state->smb2_req->sconn = sconn;
2201
2202 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2203 sconn->smb2.recv_queue,
2204 smbd_smb2_request_next_vector,
2205 state);
2206 if (tevent_req_nomem(subreq, req)) {
2207 return tevent_req_post(req, ev);
2208 }
2209 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2210
2211 return req;
2212}
2213
2214static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2215 void *private_data,
2216 TALLOC_CTX *mem_ctx,
2217 struct iovec **_vector,
2218 size_t *_count)
2219{
2220 struct smbd_smb2_request_read_state *state =
2221 talloc_get_type_abort(private_data,
2222 struct smbd_smb2_request_read_state);
2223 struct smbd_smb2_request *req = state->smb2_req;
2224 struct iovec *vector;
2225 int idx = req->in.vector_count;
2226 size_t len = 0;
2227 uint8_t *buf = NULL;
2228
2229 if (req->in.vector_count == 0) {
2230 /*
2231 * first we need to get the NBT header
2232 */
2233 req->in.vector = talloc_array(req, struct iovec,
2234 req->in.vector_count + 1);
2235 if (req->in.vector == NULL) {
2236 return -1;
2237 }
2238 req->in.vector_count += 1;
2239
2240 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2241 req->in.vector[idx].iov_len = 4;
2242
2243 vector = talloc_array(mem_ctx, struct iovec, 1);
2244 if (vector == NULL) {
2245 return -1;
2246 }
2247
2248 vector[0] = req->in.vector[idx];
2249
2250 *_vector = vector;
2251 *_count = 1;
2252 return 0;
2253 }
2254
2255 if (req->in.vector_count == 1) {
2256 /*
2257 * Now we analyze the NBT header
2258 */
2259 state->missing = smb2_len(req->in.vector[0].iov_base);
2260
2261 if (state->missing == 0) {
2262 /* if there're no remaining bytes, we're done */
2263 *_vector = NULL;
2264 *_count = 0;
2265 return 0;
2266 }
2267
2268 req->in.vector = talloc_realloc(req, req->in.vector,
2269 struct iovec,
2270 req->in.vector_count + 1);
2271 if (req->in.vector == NULL) {
2272 return -1;
2273 }
2274 req->in.vector_count += 1;
2275
2276 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2277 /*
2278 * it's a special NBT message,
2279 * so get all remaining bytes
2280 */
2281 len = state->missing;
2282 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2283 /*
2284 * it's an invalid message, just read what we can get
2285 * and let the caller handle the error
2286 */
2287 len = state->missing;
2288 } else {
2289 /*
2290 * We assume it's a SMB2 request,
2291 * and we first get the header and the
2292 * first 2 bytes (the struct size) of the body
2293 */
2294 len = SMB2_HDR_BODY + 2;
2295
2296 state->asked_for_header = true;
2297 }
2298
2299 state->missing -= len;
2300
2301 buf = talloc_array(req->in.vector, uint8_t, len);
2302 if (buf == NULL) {
2303 return -1;
2304 }
2305
2306 req->in.vector[idx].iov_base = (void *)buf;
2307 req->in.vector[idx].iov_len = len;
2308
2309 vector = talloc_array(mem_ctx, struct iovec, 1);
2310 if (vector == NULL) {
2311 return -1;
2312 }
2313
2314 vector[0] = req->in.vector[idx];
2315
2316 *_vector = vector;
2317 *_count = 1;
2318 return 0;
2319 }
2320
2321 if (state->missing == 0) {
2322 /* if there're no remaining bytes, we're done */
2323 *_vector = NULL;
2324 *_count = 0;
2325 return 0;
2326 }
2327
2328 if (state->asked_for_header) {
2329 const uint8_t *hdr;
2330 size_t full_size;
2331 size_t next_command_ofs;
2332 size_t body_size;
2333 uint8_t *body;
2334 size_t dyn_size;
2335 uint8_t *dyn;
2336 bool invalid = false;
2337
2338 state->asked_for_header = false;
2339
2340 /*
2341 * We got the SMB2 header and the first 2 bytes
2342 * of the body. We fix the size to just the header
2343 * and manually copy the 2 first bytes to the body section
2344 */
2345 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2346 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2347
2348 /* allocate vectors for body and dynamic areas */
2349 req->in.vector = talloc_realloc(req, req->in.vector,
2350 struct iovec,
2351 req->in.vector_count + 2);
2352 if (req->in.vector == NULL) {
2353 return -1;
2354 }
2355 req->in.vector_count += 2;
2356
2357 full_size = state->missing + SMB2_HDR_BODY + 2;
2358 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2359 body_size = SVAL(hdr, SMB2_HDR_BODY);
2360
2361 if (next_command_ofs != 0) {
2362 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2363 /*
2364 * this is invalid, just return a zero
2365 * body and let the caller deal with the error
2366 */
2367 invalid = true;
2368 } else if (next_command_ofs > full_size) {
2369 /*
2370 * this is invalid, just return a zero
2371 * body and let the caller deal with the error
2372 */
2373 invalid = true;
2374 } else {
2375 full_size = next_command_ofs;
2376 }
2377 }
2378
2379 if (!invalid) {
2380 if (body_size < 2) {
2381 /*
2382 * this is invalid, just return a zero
2383 * body and let the caller deal with the error
2384 */
2385 invalid = true;
2386 }
2387
2388 if ((body_size % 2) != 0) {
2389 body_size -= 1;
2390 }
2391
2392 if (body_size > (full_size - SMB2_HDR_BODY)) {
2393 /*
2394 * this is invalid, just return a zero
2395 * body and let the caller deal with the error
2396 */
2397 invalid = true;
2398 }
2399 }
2400
2401 if (invalid) {
2402 /* the caller should check this */
2403 body_size = 2;
2404 }
2405
2406 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2407
2408 state->missing -= (body_size - 2) + dyn_size;
2409
2410 body = talloc_array(req->in.vector, uint8_t, body_size);
2411 if (body == NULL) {
2412 return -1;
2413 }
2414
2415 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2416 if (dyn == NULL) {
2417 return -1;
2418 }
2419
2420 req->in.vector[idx].iov_base = (void *)body;
2421 req->in.vector[idx].iov_len = body_size;
2422 req->in.vector[idx+1].iov_base = (void *)dyn;
2423 req->in.vector[idx+1].iov_len = dyn_size;
2424
2425 vector = talloc_array(mem_ctx, struct iovec, 2);
2426 if (vector == NULL) {
2427 return -1;
2428 }
2429
2430 /*
2431 * the first 2 bytes of the body were already fetched
2432 * together with the header
2433 */
2434 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2435 vector[0].iov_base = body + 2;
2436 vector[0].iov_len = body_size - 2;
2437
2438 vector[1] = req->in.vector[idx+1];
2439
2440 *_vector = vector;
2441 *_count = 2;
2442 return 0;
2443 }
2444
2445 /*
2446 * when we endup here, we're looking for a new SMB2 request
2447 * next. And we ask for its header and the first 2 bytes of
2448 * the body (like we did for the first SMB2 request).
2449 */
2450
2451 req->in.vector = talloc_realloc(req, req->in.vector,
2452 struct iovec,
2453 req->in.vector_count + 1);
2454 if (req->in.vector == NULL) {
2455 return -1;
2456 }
2457 req->in.vector_count += 1;
2458
2459 /*
2460 * We assume it's a SMB2 request,
2461 * and we first get the header and the
2462 * first 2 bytes (the struct size) of the body
2463 */
2464 len = SMB2_HDR_BODY + 2;
2465
2466 if (len > state->missing) {
2467 /* let the caller handle the error */
2468 len = state->missing;
2469 }
2470
2471 state->missing -= len;
2472 state->asked_for_header = true;
2473
2474 buf = talloc_array(req->in.vector, uint8_t, len);
2475 if (buf == NULL) {
2476 return -1;
2477 }
2478
2479 req->in.vector[idx].iov_base = (void *)buf;
2480 req->in.vector[idx].iov_len = len;
2481
2482 vector = talloc_array(mem_ctx, struct iovec, 1);
2483 if (vector == NULL) {
2484 return -1;
2485 }
2486
2487 vector[0] = req->in.vector[idx];
2488
2489 *_vector = vector;
2490 *_count = 1;
2491 return 0;
2492}
2493
2494static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2495{
2496 struct tevent_req *req =
2497 tevent_req_callback_data(subreq,
2498 struct tevent_req);
2499 int ret;
2500 int sys_errno;
2501 NTSTATUS status;
2502
2503 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2504 if (ret == -1) {
2505 status = map_nt_error_from_unix(sys_errno);
2506 tevent_req_nterror(req, status);
2507 return;
2508 }
2509
2510 tevent_req_done(req);
2511}
2512
2513static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2514 TALLOC_CTX *mem_ctx,
2515 struct smbd_smb2_request **_smb2_req)
2516{
2517 struct smbd_smb2_request_read_state *state =
2518 tevent_req_data(req,
2519 struct smbd_smb2_request_read_state);
2520 NTSTATUS status;
2521
2522 if (tevent_req_is_nterror(req, &status)) {
2523 tevent_req_received(req);
2524 return status;
2525 }
2526
2527 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2528 *_smb2_req = state->smb2_req;
2529 tevent_req_received(req);
2530 return NT_STATUS_OK;
2531}
2532
2533static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2534
2535static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2536{
2537 size_t max_send_queue_len;
2538 size_t cur_send_queue_len;
2539 struct tevent_req *subreq;
2540
2541 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2542 /*
2543 * if there is already a smbd_smb2_request_read
2544 * pending, we are done.
2545 */
2546 return NT_STATUS_OK;
2547 }
2548
2549 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2550 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2551
2552 if (cur_send_queue_len > max_send_queue_len) {
2553 /*
2554 * if we have a lot of requests to send,
2555 * we wait until they are on the wire until we
2556 * ask for the next request.
2557 */
2558 return NT_STATUS_OK;
2559 }
2560
2561 /* ask for the next request */
2562 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2563 if (subreq == NULL) {
2564 return NT_STATUS_NO_MEMORY;
2565 }
2566 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2567
2568 return NT_STATUS_OK;
2569}
2570
2571void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2572 const uint8_t *inbuf, size_t size)
2573{
2574 NTSTATUS status;
2575 struct smbd_smb2_request *req = NULL;
2576
2577 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2578 (unsigned int)size));
2579
2580 status = smbd_initialize_smb2(sconn);
2581 if (!NT_STATUS_IS_OK(status)) {
2582 smbd_server_connection_terminate(sconn, nt_errstr(status));
2583 return;
2584 }
2585
2586 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2587 if (!NT_STATUS_IS_OK(status)) {
2588 smbd_server_connection_terminate(sconn, nt_errstr(status));
2589 return;
2590 }
2591
2592 status = smbd_smb2_request_validate(req);
2593 if (!NT_STATUS_IS_OK(status)) {
2594 smbd_server_connection_terminate(sconn, nt_errstr(status));
2595 return;
2596 }
2597
2598 status = smbd_smb2_request_setup_out(req);
2599 if (!NT_STATUS_IS_OK(status)) {
2600 smbd_server_connection_terminate(sconn, nt_errstr(status));
2601 return;
2602 }
2603
2604 status = smbd_smb2_request_dispatch(req);
2605 if (!NT_STATUS_IS_OK(status)) {
2606 smbd_server_connection_terminate(sconn, nt_errstr(status));
2607 return;
2608 }
2609
2610 status = smbd_smb2_request_next_incoming(sconn);
2611 if (!NT_STATUS_IS_OK(status)) {
2612 smbd_server_connection_terminate(sconn, nt_errstr(status));
2613 return;
2614 }
2615
2616 sconn->num_requests++;
2617}
2618
2619static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2620{
2621 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2622 struct smbd_server_connection);
2623 NTSTATUS status;
2624 struct smbd_smb2_request *req = NULL;
2625
2626 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2627 TALLOC_FREE(subreq);
2628 if (!NT_STATUS_IS_OK(status)) {
2629 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2630 nt_errstr(status)));
2631 smbd_server_connection_terminate(sconn, nt_errstr(status));
2632 return;
2633 }
2634
2635 if (req->in.nbt_hdr[0] != 0x00) {
2636 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2637 req->in.nbt_hdr[0]));
2638 TALLOC_FREE(req);
2639 goto next;
2640 }
2641
2642 req->current_idx = 1;
2643
2644 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2645 req->current_idx, req->in.vector_count));
2646
2647 status = smbd_smb2_request_validate(req);
2648 if (!NT_STATUS_IS_OK(status)) {
2649 smbd_server_connection_terminate(sconn, nt_errstr(status));
2650 return;
2651 }
2652
2653 status = smbd_smb2_request_setup_out(req);
2654 if (!NT_STATUS_IS_OK(status)) {
2655 smbd_server_connection_terminate(sconn, nt_errstr(status));
2656 return;
2657 }
2658
2659 status = smbd_smb2_request_dispatch(req);
2660 if (!NT_STATUS_IS_OK(status)) {
2661 smbd_server_connection_terminate(sconn, nt_errstr(status));
2662 return;
2663 }
2664
2665next:
2666 status = smbd_smb2_request_next_incoming(sconn);
2667 if (!NT_STATUS_IS_OK(status)) {
2668 smbd_server_connection_terminate(sconn, nt_errstr(status));
2669 return;
2670 }
2671
2672 sconn->num_requests++;
2673
2674 /* The timeout_processing function isn't run nearly
2675 often enough to implement 'max log size' without
2676 overrunning the size of the file by many megabytes.
2677 This is especially true if we are running at debug
2678 level 10. Checking every 50 SMB2s is a nice
2679 tradeoff of performance vs log file size overrun. */
2680
2681 if ((sconn->num_requests % 50) == 0 &&
2682 need_to_check_log_size()) {
2683 change_to_root_user();
2684 check_log_size();
2685 }
2686}
Note: See TracBrowser for help on using the repository browser.