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

Last change on this file was 746, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated vendor to 3.6.9

File size: 68.8 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 struct iovec *outvec = NULL;
931
932 if (!tevent_req_is_in_progress(subreq)) {
933 return NT_STATUS_OK;
934 }
935
936 req->subreq = subreq;
937 subreq = NULL;
938
939 if (req->async) {
940 /* We're already async. */
941 return NT_STATUS_OK;
942 }
943
944 if (req->in.vector_count > i + 3) {
945 /*
946 * We're trying to go async in a compound
947 * request chain. This is not allowed.
948 * Cancel the outstanding request.
949 */
950 bool ok = tevent_req_cancel(req->subreq);
951 if (ok) {
952 return NT_STATUS_OK;
953 }
954 TALLOC_FREE(req->subreq);
955 return smbd_smb2_request_error(req,
956 NT_STATUS_INTERNAL_ERROR);
957 }
958
959 if (DEBUGLEVEL >= 10) {
960 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
961 (unsigned int)req->current_idx );
962 print_req_vectors(req);
963 }
964
965 if (req->out.vector_count > 4) {
966 /* This is a compound reply. We
967 * must do an interim response
968 * followed by the async response
969 * to match W2K8R2.
970 */
971 status = smb2_send_async_interim_response(req);
972 if (!NT_STATUS_IS_OK(status)) {
973 return status;
974 }
975
976 /*
977 * We're splitting off the last SMB2
978 * request in a compound set, and the
979 * smb2_send_async_interim_response()
980 * call above just sent all the replies
981 * for the previous SMB2 requests in
982 * this compound set. So we're no longer
983 * in the "compound_related_in_progress"
984 * state, and this is no longer a compound
985 * request.
986 */
987 req->compound_related = false;
988 req->sconn->smb2.compound_related_in_progress = false;
989 }
990
991 /* Don't return an intermediate packet on a pipe read/write. */
992 if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
993 goto ipc_out;
994 }
995
996 reqhdr = (uint8_t *)req->out.vector[i].iov_base;
997 flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
998 message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
999 async_id = message_id; /* keep it simple for now... */
1000
1001 /*
1002 * What we send is identical to a smbd_smb2_request_error
1003 * packet with an error status of STATUS_PENDING. Make use
1004 * of this fact sometime when refactoring. JRA.
1005 */
1006
1007 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1008 if (state == NULL) {
1009 return NT_STATUS_NO_MEMORY;
1010 }
1011 state->sconn = req->sconn;
1012
1013 state->vector[0].iov_base = (void *)state->buf;
1014 state->vector[0].iov_len = 4;
1015
1016 state->vector[1].iov_base = state->buf + 4;
1017 state->vector[1].iov_len = SMB2_HDR_BODY;
1018
1019 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1020 state->vector[2].iov_len = 9;
1021
1022 smb2_setup_nbt_length(state->vector, 3);
1023
1024 hdr = (uint8_t *)state->vector[1].iov_base;
1025 body = (uint8_t *)state->vector[2].iov_base;
1026
1027 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1028 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1029 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1030 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1031 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
1032
1033 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1034 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1035 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1036 SBVAL(hdr, SMB2_HDR_PID, async_id);
1037 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1038 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
1039 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1040
1041 SSVAL(body, 0x00, 0x08 + 1);
1042
1043 SCVAL(body, 0x02, 0);
1044 SCVAL(body, 0x03, 0);
1045 SIVAL(body, 0x04, 0);
1046 /* Match W2K8R2... */
1047 SCVAL(body, 0x08, 0x21);
1048
1049 /* Ensure we correctly go through crediting. Grant
1050 the credits now, and zero credits on the final
1051 response. */
1052 smb2_set_operation_credit(req->sconn,
1053 &req->in.vector[i],
1054 &state->vector[1]);
1055
1056 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1057
1058 if (req->do_signing) {
1059 status = smb2_signing_sign_pdu(req->session->session_key,
1060 &state->vector[1], 2);
1061 if (!NT_STATUS_IS_OK(status)) {
1062 return status;
1063 }
1064 }
1065
1066 subreq = tstream_writev_queue_send(state,
1067 req->sconn->smb2.event_ctx,
1068 req->sconn->smb2.stream,
1069 req->sconn->smb2.send_queue,
1070 state->vector,
1071 3);
1072
1073 if (subreq == NULL) {
1074 return NT_STATUS_NO_MEMORY;
1075 }
1076
1077 tevent_req_set_callback(subreq,
1078 smbd_smb2_request_pending_writev_done,
1079 state);
1080
1081 /* Note we're going async with this request. */
1082 req->async = true;
1083
1084 ipc_out:
1085
1086 /*
1087 * Now manipulate req so that the outstanding async request
1088 * is the only one left in the struct smbd_smb2_request.
1089 */
1090
1091 if (req->current_idx == 1) {
1092 /* There was only one. */
1093 goto out;
1094 }
1095
1096 /* Re-arrange the in.vectors. */
1097 req->in.vector[1] = req->in.vector[i];
1098 req->in.vector[2] = req->in.vector[i+1];
1099 req->in.vector[3] = req->in.vector[i+2];
1100 req->in.vector_count = 4;
1101 /* Reset the new in size. */
1102 smb2_setup_nbt_length(req->in.vector, 4);
1103
1104 /* Now recreate the out.vectors. */
1105 outvec = talloc_zero_array(req, struct iovec, 4);
1106 if (!outvec) {
1107 return NT_STATUS_NO_MEMORY;
1108 }
1109
1110 /* 0 is always boilerplate and must
1111 * be of size 4 for the length field. */
1112
1113 outvec[0].iov_base = req->out.nbt_hdr;
1114 outvec[0].iov_len = 4;
1115 SIVAL(req->out.nbt_hdr, 0, 0);
1116
1117 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1118 return NT_STATUS_NO_MEMORY;
1119 }
1120
1121 TALLOC_FREE(req->out.vector);
1122
1123 req->out.vector = outvec;
1124
1125 req->current_idx = 1;
1126 req->out.vector_count = 4;
1127
1128 out:
1129
1130 smb2_setup_nbt_length(req->out.vector,
1131 req->out.vector_count);
1132
1133 if (req->async) {
1134 /* Ensure our final reply matches the interim one. */
1135 reqhdr = (uint8_t *)req->out.vector[1].iov_base;
1136 SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1137 SBVAL(reqhdr, SMB2_HDR_PID, async_id);
1138
1139 {
1140 const uint8_t *inhdr =
1141 (const uint8_t *)req->in.vector[1].iov_base;
1142 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1143 "going async\n",
1144 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1145 (unsigned long long)async_id ));
1146 }
1147 }
1148
1149 return NT_STATUS_OK;
1150}
1151
1152static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1153{
1154 struct smbd_server_connection *sconn = req->sconn;
1155 struct smbd_smb2_request *cur;
1156 const uint8_t *inhdr;
1157 int i = req->current_idx;
1158 uint32_t flags;
1159 uint64_t search_message_id;
1160 uint64_t search_async_id;
1161 uint64_t found_id;
1162
1163 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1164
1165 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1166 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1167 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1168
1169 /*
1170 * we don't need the request anymore
1171 * cancel requests never have a response
1172 */
1173 DLIST_REMOVE(req->sconn->smb2.requests, req);
1174 TALLOC_FREE(req);
1175
1176 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1177 const uint8_t *outhdr;
1178 uint64_t message_id;
1179 uint64_t async_id;
1180
1181 i = cur->current_idx;
1182
1183 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1184
1185 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1186 async_id = BVAL(outhdr, SMB2_HDR_PID);
1187
1188 if (flags & SMB2_HDR_FLAG_ASYNC) {
1189 if (search_async_id == async_id) {
1190 found_id = async_id;
1191 break;
1192 }
1193 } else {
1194 if (search_message_id == message_id) {
1195 found_id = message_id;
1196 break;
1197 }
1198 }
1199 }
1200
1201 if (cur && cur->subreq) {
1202 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1203 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1204 "cancel opcode[%s] mid %llu\n",
1205 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1206 (unsigned long long)found_id ));
1207 tevent_req_cancel(cur->subreq);
1208 }
1209
1210 return NT_STATUS_OK;
1211}
1212
1213NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1214 size_t expected_body_size)
1215{
1216 const uint8_t *inhdr;
1217 uint16_t opcode;
1218 const uint8_t *inbody;
1219 int i = req->current_idx;
1220 size_t body_size;
1221 size_t min_dyn_size = expected_body_size & 0x00000001;
1222
1223 /*
1224 * The following should be checked already.
1225 */
1226 if ((i+2) > req->in.vector_count) {
1227 return NT_STATUS_INTERNAL_ERROR;
1228 }
1229 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1230 return NT_STATUS_INTERNAL_ERROR;
1231 }
1232 if (req->in.vector[i+1].iov_len < 2) {
1233 return NT_STATUS_INTERNAL_ERROR;
1234 }
1235
1236 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1237 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1238
1239 switch (opcode) {
1240 case SMB2_OP_IOCTL:
1241 case SMB2_OP_GETINFO:
1242 min_dyn_size = 0;
1243 break;
1244 }
1245
1246 /*
1247 * Now check the expected body size,
1248 * where the last byte might be in the
1249 * dynnamic section..
1250 */
1251 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1252 return NT_STATUS_INVALID_PARAMETER;
1253 }
1254 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1255 return NT_STATUS_INVALID_PARAMETER;
1256 }
1257
1258 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1259
1260 body_size = SVAL(inbody, 0x00);
1261 if (body_size != expected_body_size) {
1262 return NT_STATUS_INVALID_PARAMETER;
1263 }
1264
1265 return NT_STATUS_OK;
1266}
1267
1268NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1269{
1270 const uint8_t *inhdr;
1271 int i = req->current_idx;
1272 uint16_t opcode;
1273 uint32_t flags;
1274 uint64_t mid;
1275 NTSTATUS status;
1276 NTSTATUS session_status;
1277 uint32_t allowed_flags;
1278 NTSTATUS return_value;
1279
1280 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1281
1282 /* TODO: verify more things */
1283
1284 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1285 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1286 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1287 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1288 smb2_opcode_name(opcode),
1289 (unsigned long long)mid));
1290
1291 if (get_Protocol() >= PROTOCOL_SMB2) {
1292 /*
1293 * once the protocol is negotiated
1294 * SMB2_OP_NEGPROT is not allowed anymore
1295 */
1296 if (opcode == SMB2_OP_NEGPROT) {
1297 /* drop the connection */
1298 return NT_STATUS_INVALID_PARAMETER;
1299 }
1300 } else {
1301 /*
1302 * if the protocol is not negotiated yet
1303 * only SMB2_OP_NEGPROT is allowed.
1304 */
1305 if (opcode != SMB2_OP_NEGPROT) {
1306 /* drop the connection */
1307 return NT_STATUS_INVALID_PARAMETER;
1308 }
1309 }
1310
1311 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1312 SMB2_HDR_FLAG_SIGNED |
1313 SMB2_HDR_FLAG_DFS;
1314 if (opcode == SMB2_OP_CANCEL) {
1315 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1316 }
1317 if ((flags & ~allowed_flags) != 0) {
1318 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1319 }
1320
1321 /*
1322 * Check if the client provided a valid session id,
1323 * if so smbd_smb2_request_check_session() calls
1324 * set_current_user_info().
1325 *
1326 * As some command don't require a valid session id
1327 * we defer the check of the session_status
1328 */
1329 session_status = smbd_smb2_request_check_session(req);
1330
1331 if (flags & SMB2_HDR_FLAG_CHAINED) {
1332 /*
1333 * This check is mostly for giving the correct error code
1334 * for compounded requests.
1335 */
1336 if (!NT_STATUS_IS_OK(session_status)) {
1337 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1338 }
1339 } else {
1340 req->compat_chain_fsp = NULL;
1341 }
1342
1343 req->do_signing = false;
1344 if (flags & SMB2_HDR_FLAG_SIGNED) {
1345 if (!NT_STATUS_IS_OK(session_status)) {
1346 return smbd_smb2_request_error(req, session_status);
1347 }
1348
1349 req->do_signing = true;
1350 status = smb2_signing_check_pdu(req->session->session_key,
1351 &req->in.vector[i], 3);
1352 if (!NT_STATUS_IS_OK(status)) {
1353 return smbd_smb2_request_error(req, status);
1354 }
1355 } else if (opcode == SMB2_OP_CANCEL) {
1356 /* Cancel requests are allowed to skip the signing */
1357 } else if (req->session && req->session->do_signing) {
1358 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1359 }
1360
1361 if (flags & SMB2_HDR_FLAG_CHAINED) {
1362 req->compound_related = true;
1363 req->sconn->smb2.compound_related_in_progress = true;
1364 }
1365
1366 switch (opcode) {
1367 case SMB2_OP_NEGPROT:
1368 /* This call needs to be run as root */
1369 change_to_root_user();
1370
1371 {
1372 START_PROFILE(smb2_negprot);
1373 return_value = smbd_smb2_request_process_negprot(req);
1374 END_PROFILE(smb2_negprot);
1375 }
1376 break;
1377
1378 case SMB2_OP_SESSSETUP:
1379 /* This call needs to be run as root */
1380 change_to_root_user();
1381
1382 {
1383 START_PROFILE(smb2_sesssetup);
1384 return_value = smbd_smb2_request_process_sesssetup(req);
1385 END_PROFILE(smb2_sesssetup);
1386 }
1387 break;
1388
1389 case SMB2_OP_LOGOFF:
1390 if (!NT_STATUS_IS_OK(session_status)) {
1391 return_value = smbd_smb2_request_error(req, session_status);
1392 break;
1393 }
1394
1395 /* This call needs to be run as root */
1396 change_to_root_user();
1397
1398 {
1399 START_PROFILE(smb2_logoff);
1400 return_value = smbd_smb2_request_process_logoff(req);
1401 END_PROFILE(smb2_logoff);
1402 }
1403 break;
1404
1405 case SMB2_OP_TCON:
1406 if (!NT_STATUS_IS_OK(session_status)) {
1407 return_value = smbd_smb2_request_error(req, session_status);
1408 break;
1409 }
1410
1411 /*
1412 * This call needs to be run as root.
1413 *
1414 * smbd_smb2_request_process_tcon()
1415 * calls make_connection_snum(), which will call
1416 * change_to_user(), when needed.
1417 */
1418 change_to_root_user();
1419
1420 {
1421 START_PROFILE(smb2_tcon);
1422 return_value = smbd_smb2_request_process_tcon(req);
1423 END_PROFILE(smb2_tcon);
1424 }
1425 break;
1426
1427 case SMB2_OP_TDIS:
1428 if (!NT_STATUS_IS_OK(session_status)) {
1429 return_value = smbd_smb2_request_error(req, session_status);
1430 break;
1431 }
1432 /*
1433 * This call needs to be run as user.
1434 *
1435 * smbd_smb2_request_check_tcon()
1436 * calls change_to_user() on success.
1437 */
1438 status = smbd_smb2_request_check_tcon(req);
1439 if (!NT_STATUS_IS_OK(status)) {
1440 return_value = smbd_smb2_request_error(req, status);
1441 break;
1442 }
1443 /* This call needs to be run as root */
1444 change_to_root_user();
1445
1446
1447 {
1448 START_PROFILE(smb2_tdis);
1449 return_value = smbd_smb2_request_process_tdis(req);
1450 END_PROFILE(smb2_tdis);
1451 }
1452 break;
1453
1454 case SMB2_OP_CREATE:
1455 if (!NT_STATUS_IS_OK(session_status)) {
1456 return_value = smbd_smb2_request_error(req, session_status);
1457 break;
1458 }
1459 /*
1460 * This call needs to be run as user.
1461 *
1462 * smbd_smb2_request_check_tcon()
1463 * calls change_to_user() on success.
1464 */
1465 status = smbd_smb2_request_check_tcon(req);
1466 if (!NT_STATUS_IS_OK(status)) {
1467 return_value = smbd_smb2_request_error(req, status);
1468 break;
1469 }
1470
1471 {
1472 START_PROFILE(smb2_create);
1473 return_value = smbd_smb2_request_process_create(req);
1474 END_PROFILE(smb2_create);
1475 }
1476 break;
1477
1478 case SMB2_OP_CLOSE:
1479 if (!NT_STATUS_IS_OK(session_status)) {
1480 return_value = smbd_smb2_request_error(req, session_status);
1481 break;
1482 }
1483 /*
1484 * This call needs to be run as user.
1485 *
1486 * smbd_smb2_request_check_tcon()
1487 * calls change_to_user() on success.
1488 */
1489 status = smbd_smb2_request_check_tcon(req);
1490 if (!NT_STATUS_IS_OK(status)) {
1491 return_value = smbd_smb2_request_error(req, status);
1492 break;
1493 }
1494
1495 {
1496 START_PROFILE(smb2_close);
1497 return_value = smbd_smb2_request_process_close(req);
1498 END_PROFILE(smb2_close);
1499 }
1500 break;
1501
1502 case SMB2_OP_FLUSH:
1503 if (!NT_STATUS_IS_OK(session_status)) {
1504 return_value = smbd_smb2_request_error(req, session_status);
1505 break;
1506 }
1507 /*
1508 * This call needs to be run as user.
1509 *
1510 * smbd_smb2_request_check_tcon()
1511 * calls change_to_user() on success.
1512 */
1513 status = smbd_smb2_request_check_tcon(req);
1514 if (!NT_STATUS_IS_OK(status)) {
1515 return_value = smbd_smb2_request_error(req, status);
1516 break;
1517 }
1518
1519 {
1520 START_PROFILE(smb2_flush);
1521 return_value = smbd_smb2_request_process_flush(req);
1522 END_PROFILE(smb2_flush);
1523 }
1524 break;
1525
1526 case SMB2_OP_READ:
1527 if (!NT_STATUS_IS_OK(session_status)) {
1528 return_value = smbd_smb2_request_error(req, session_status);
1529 break;
1530 }
1531 /*
1532 * This call needs to be run as user.
1533 *
1534 * smbd_smb2_request_check_tcon()
1535 * calls change_to_user() on success.
1536 */
1537 status = smbd_smb2_request_check_tcon(req);
1538 if (!NT_STATUS_IS_OK(status)) {
1539 return_value = smbd_smb2_request_error(req, status);
1540 break;
1541 }
1542
1543 {
1544 START_PROFILE(smb2_read);
1545 return_value = smbd_smb2_request_process_read(req);
1546 END_PROFILE(smb2_read);
1547 }
1548 break;
1549
1550 case SMB2_OP_WRITE:
1551 if (!NT_STATUS_IS_OK(session_status)) {
1552 return_value = smbd_smb2_request_error(req, session_status);
1553 break;
1554 }
1555 /*
1556 * This call needs to be run as user.
1557 *
1558 * smbd_smb2_request_check_tcon()
1559 * calls change_to_user() on success.
1560 */
1561 status = smbd_smb2_request_check_tcon(req);
1562 if (!NT_STATUS_IS_OK(status)) {
1563 return_value = smbd_smb2_request_error(req, status);
1564 break;
1565 }
1566
1567 {
1568 START_PROFILE(smb2_write);
1569 return_value = smbd_smb2_request_process_write(req);
1570 END_PROFILE(smb2_write);
1571 }
1572 break;
1573
1574 case SMB2_OP_LOCK:
1575 if (!NT_STATUS_IS_OK(session_status)) {
1576 /* Too ugly to live ? JRA. */
1577 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1578 session_status = NT_STATUS_FILE_CLOSED;
1579 }
1580 return_value = smbd_smb2_request_error(req, session_status);
1581 break;
1582 }
1583 /*
1584 * This call needs to be run as user.
1585 *
1586 * smbd_smb2_request_check_tcon()
1587 * calls change_to_user() on success.
1588 */
1589 status = smbd_smb2_request_check_tcon(req);
1590 if (!NT_STATUS_IS_OK(status)) {
1591 /* Too ugly to live ? JRA. */
1592 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1593 status = NT_STATUS_FILE_CLOSED;
1594 }
1595 return_value = smbd_smb2_request_error(req, status);
1596 break;
1597 }
1598
1599 {
1600 START_PROFILE(smb2_lock);
1601 return_value = smbd_smb2_request_process_lock(req);
1602 END_PROFILE(smb2_lock);
1603 }
1604 break;
1605
1606 case SMB2_OP_IOCTL:
1607 if (!NT_STATUS_IS_OK(session_status)) {
1608 return_value = smbd_smb2_request_error(req, session_status);
1609 break;
1610 }
1611 /*
1612 * This call needs to be run as user.
1613 *
1614 * smbd_smb2_request_check_tcon()
1615 * calls change_to_user() on success.
1616 */
1617 status = smbd_smb2_request_check_tcon(req);
1618 if (!NT_STATUS_IS_OK(status)) {
1619 return_value = smbd_smb2_request_error(req, status);
1620 break;
1621 }
1622
1623 {
1624 START_PROFILE(smb2_ioctl);
1625 return_value = smbd_smb2_request_process_ioctl(req);
1626 END_PROFILE(smb2_ioctl);
1627 }
1628 break;
1629
1630 case SMB2_OP_CANCEL:
1631 /*
1632 * This call needs to be run as root
1633 *
1634 * That is what we also do in the SMB1 case.
1635 */
1636 change_to_root_user();
1637
1638 {
1639 START_PROFILE(smb2_cancel);
1640 return_value = smbd_smb2_request_process_cancel(req);
1641 END_PROFILE(smb2_cancel);
1642 }
1643 break;
1644
1645 case SMB2_OP_KEEPALIVE:
1646 /* This call needs to be run as root */
1647 change_to_root_user();
1648
1649 {
1650 START_PROFILE(smb2_keepalive);
1651 return_value = smbd_smb2_request_process_keepalive(req);
1652 END_PROFILE(smb2_keepalive);
1653 }
1654 break;
1655
1656 case SMB2_OP_FIND:
1657 if (!NT_STATUS_IS_OK(session_status)) {
1658 return_value = smbd_smb2_request_error(req, session_status);
1659 break;
1660 }
1661 /*
1662 * This call needs to be run as user.
1663 *
1664 * smbd_smb2_request_check_tcon()
1665 * calls change_to_user() on success.
1666 */
1667 status = smbd_smb2_request_check_tcon(req);
1668 if (!NT_STATUS_IS_OK(status)) {
1669 return_value = smbd_smb2_request_error(req, status);
1670 break;
1671 }
1672
1673 {
1674 START_PROFILE(smb2_find);
1675 return_value = smbd_smb2_request_process_find(req);
1676 END_PROFILE(smb2_find);
1677 }
1678 break;
1679
1680 case SMB2_OP_NOTIFY:
1681 if (!NT_STATUS_IS_OK(session_status)) {
1682 return_value = smbd_smb2_request_error(req, session_status);
1683 break;
1684 }
1685 /*
1686 * This call needs to be run as user.
1687 *
1688 * smbd_smb2_request_check_tcon()
1689 * calls change_to_user() on success.
1690 */
1691 status = smbd_smb2_request_check_tcon(req);
1692 if (!NT_STATUS_IS_OK(status)) {
1693 return_value = smbd_smb2_request_error(req, status);
1694 break;
1695 }
1696
1697 {
1698 START_PROFILE(smb2_notify);
1699 return_value = smbd_smb2_request_process_notify(req);
1700 END_PROFILE(smb2_notify);
1701 }
1702 break;
1703
1704 case SMB2_OP_GETINFO:
1705 if (!NT_STATUS_IS_OK(session_status)) {
1706 return_value = smbd_smb2_request_error(req, session_status);
1707 break;
1708 }
1709 /*
1710 * This call needs to be run as user.
1711 *
1712 * smbd_smb2_request_check_tcon()
1713 * calls change_to_user() on success.
1714 */
1715 status = smbd_smb2_request_check_tcon(req);
1716 if (!NT_STATUS_IS_OK(status)) {
1717 return_value = smbd_smb2_request_error(req, status);
1718 break;
1719 }
1720
1721 {
1722 START_PROFILE(smb2_getinfo);
1723 return_value = smbd_smb2_request_process_getinfo(req);
1724 END_PROFILE(smb2_getinfo);
1725 }
1726 break;
1727
1728 case SMB2_OP_SETINFO:
1729 if (!NT_STATUS_IS_OK(session_status)) {
1730 return_value = smbd_smb2_request_error(req, session_status);
1731 break;
1732 }
1733 /*
1734 * This call needs to be run as user.
1735 *
1736 * smbd_smb2_request_check_tcon()
1737 * calls change_to_user() on success.
1738 */
1739 status = smbd_smb2_request_check_tcon(req);
1740 if (!NT_STATUS_IS_OK(status)) {
1741 return_value = smbd_smb2_request_error(req, status);
1742 break;
1743 }
1744
1745 {
1746 START_PROFILE(smb2_setinfo);
1747 return_value = smbd_smb2_request_process_setinfo(req);
1748 END_PROFILE(smb2_setinfo);
1749 }
1750 break;
1751
1752 case SMB2_OP_BREAK:
1753 if (!NT_STATUS_IS_OK(session_status)) {
1754 return_value = smbd_smb2_request_error(req, session_status);
1755 break;
1756 }
1757 /*
1758 * This call needs to be run as user.
1759 *
1760 * smbd_smb2_request_check_tcon()
1761 * calls change_to_user() on success.
1762 */
1763 status = smbd_smb2_request_check_tcon(req);
1764 if (!NT_STATUS_IS_OK(status)) {
1765 return_value = smbd_smb2_request_error(req, status);
1766 break;
1767 }
1768
1769 {
1770 START_PROFILE(smb2_break);
1771 return_value = smbd_smb2_request_process_break(req);
1772 END_PROFILE(smb2_break);
1773 }
1774 break;
1775
1776 default:
1777 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1778 break;
1779 }
1780 return return_value;
1781}
1782
1783static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1784{
1785 struct tevent_req *subreq;
1786 int i = req->current_idx;
1787
1788 req->subreq = NULL;
1789
1790 req->current_idx += 3;
1791
1792 if (req->current_idx < req->out.vector_count) {
1793 /*
1794 * We must process the remaining compound
1795 * SMB2 requests before any new incoming SMB2
1796 * requests. This is because incoming SMB2
1797 * requests may include a cancel for a
1798 * compound request we haven't processed
1799 * yet.
1800 */
1801 struct tevent_immediate *im = tevent_create_immediate(req);
1802 if (!im) {
1803 return NT_STATUS_NO_MEMORY;
1804 }
1805 tevent_schedule_immediate(im,
1806 req->sconn->smb2.event_ctx,
1807 smbd_smb2_request_dispatch_immediate,
1808 req);
1809 return NT_STATUS_OK;
1810 }
1811
1812 if (req->compound_related) {
1813 req->compound_related = false;
1814 req->sconn->smb2.compound_related_in_progress = false;
1815 }
1816
1817 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1818
1819 /* Set credit for these operations (zero credits if this
1820 is a final reply for an async operation). */
1821 smb2_calculate_credits(req, req);
1822
1823 if (req->do_signing) {
1824 NTSTATUS status;
1825 status = smb2_signing_sign_pdu(req->session->session_key,
1826 &req->out.vector[i], 3);
1827 if (!NT_STATUS_IS_OK(status)) {
1828 return status;
1829 }
1830 }
1831
1832 if (DEBUGLEVEL >= 10) {
1833 dbgtext("smbd_smb2_request_reply: sending...\n");
1834 print_req_vectors(req);
1835 }
1836
1837 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1838 if (req->out.vector_count == 4 &&
1839 req->out.vector[3].iov_base == NULL &&
1840 req->out.vector[3].iov_len != 0) {
1841 /* Dynamic part is NULL. Chop it off,
1842 We're going to send it via sendfile. */
1843 req->out.vector_count -= 1;
1844 }
1845
1846 subreq = tstream_writev_queue_send(req,
1847 req->sconn->smb2.event_ctx,
1848 req->sconn->smb2.stream,
1849 req->sconn->smb2.send_queue,
1850 req->out.vector,
1851 req->out.vector_count);
1852 if (subreq == NULL) {
1853 return NT_STATUS_NO_MEMORY;
1854 }
1855 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1856 /*
1857 * We're done with this request -
1858 * move it off the "being processed" queue.
1859 */
1860 DLIST_REMOVE(req->sconn->smb2.requests, req);
1861
1862 return NT_STATUS_OK;
1863}
1864
1865static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1866
1867void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1868 struct tevent_immediate *im,
1869 void *private_data)
1870{
1871 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1872 struct smbd_smb2_request);
1873 struct smbd_server_connection *sconn = req->sconn;
1874 NTSTATUS status;
1875
1876 TALLOC_FREE(im);
1877
1878 if (DEBUGLEVEL >= 10) {
1879 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1880 req->current_idx, req->in.vector_count));
1881 print_req_vectors(req);
1882 }
1883
1884 status = smbd_smb2_request_dispatch(req);
1885 if (!NT_STATUS_IS_OK(status)) {
1886 smbd_server_connection_terminate(sconn, nt_errstr(status));
1887 return;
1888 }
1889
1890 status = smbd_smb2_request_next_incoming(sconn);
1891 if (!NT_STATUS_IS_OK(status)) {
1892 smbd_server_connection_terminate(sconn, nt_errstr(status));
1893 return;
1894 }
1895}
1896
1897static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1898{
1899 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1900 struct smbd_smb2_request);
1901 struct smbd_server_connection *sconn = req->sconn;
1902 int ret;
1903 int sys_errno;
1904 NTSTATUS status;
1905
1906 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1907 TALLOC_FREE(subreq);
1908 TALLOC_FREE(req);
1909 if (ret == -1) {
1910 status = map_nt_error_from_unix(sys_errno);
1911 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1912 nt_errstr(status)));
1913 smbd_server_connection_terminate(sconn, nt_errstr(status));
1914 return;
1915 }
1916
1917 status = smbd_smb2_request_next_incoming(sconn);
1918 if (!NT_STATUS_IS_OK(status)) {
1919 smbd_server_connection_terminate(sconn, nt_errstr(status));
1920 return;
1921 }
1922}
1923
1924NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1925 NTSTATUS status,
1926 DATA_BLOB body, DATA_BLOB *dyn,
1927 const char *location)
1928{
1929 uint8_t *outhdr;
1930 int i = req->current_idx;
1931 uint32_t next_command_ofs;
1932
1933 DEBUG(10,("smbd_smb2_request_done_ex: "
1934 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1935 i, nt_errstr(status), (unsigned int)body.length,
1936 dyn ? "yes": "no",
1937 (unsigned int)(dyn ? dyn->length : 0),
1938 location));
1939
1940 if (body.length < 2) {
1941 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1942 }
1943
1944 if ((body.length % 2) != 0) {
1945 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1946 }
1947
1948 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1949
1950 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1951 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1952
1953 req->out.vector[i+1].iov_base = (void *)body.data;
1954 req->out.vector[i+1].iov_len = body.length;
1955
1956 if (dyn) {
1957 req->out.vector[i+2].iov_base = (void *)dyn->data;
1958 req->out.vector[i+2].iov_len = dyn->length;
1959 } else {
1960 req->out.vector[i+2].iov_base = NULL;
1961 req->out.vector[i+2].iov_len = 0;
1962 }
1963
1964 /* see if we need to recalculate the offset to the next response */
1965 if (next_command_ofs > 0) {
1966 next_command_ofs = SMB2_HDR_BODY;
1967 next_command_ofs += req->out.vector[i+1].iov_len;
1968 next_command_ofs += req->out.vector[i+2].iov_len;
1969 }
1970
1971 if ((next_command_ofs % 8) != 0) {
1972 size_t pad_size = 8 - (next_command_ofs % 8);
1973 if (req->out.vector[i+2].iov_len == 0) {
1974 /*
1975 * if the dyn buffer is empty
1976 * we can use it to add padding
1977 */
1978 uint8_t *pad;
1979
1980 pad = talloc_zero_array(req->out.vector,
1981 uint8_t, pad_size);
1982 if (pad == NULL) {
1983 return smbd_smb2_request_error(req,
1984 NT_STATUS_NO_MEMORY);
1985 }
1986
1987 req->out.vector[i+2].iov_base = (void *)pad;
1988 req->out.vector[i+2].iov_len = pad_size;
1989 } else {
1990 /*
1991 * For now we copy the dynamic buffer
1992 * and add the padding to the new buffer
1993 */
1994 size_t old_size;
1995 uint8_t *old_dyn;
1996 size_t new_size;
1997 uint8_t *new_dyn;
1998
1999 old_size = req->out.vector[i+2].iov_len;
2000 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2001
2002 new_size = old_size + pad_size;
2003 new_dyn = talloc_zero_array(req->out.vector,
2004 uint8_t, new_size);
2005 if (new_dyn == NULL) {
2006 return smbd_smb2_request_error(req,
2007 NT_STATUS_NO_MEMORY);
2008 }
2009
2010 memcpy(new_dyn, old_dyn, old_size);
2011 memset(new_dyn + old_size, 0, pad_size);
2012
2013 req->out.vector[i+2].iov_base = (void *)new_dyn;
2014 req->out.vector[i+2].iov_len = new_size;
2015 }
2016 next_command_ofs += pad_size;
2017 }
2018
2019 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2020
2021 return smbd_smb2_request_reply(req);
2022}
2023
2024NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2025 NTSTATUS status,
2026 DATA_BLOB *info,
2027 const char *location)
2028{
2029 DATA_BLOB body;
2030 int i = req->current_idx;
2031 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
2032
2033 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2034 i, nt_errstr(status), info ? " +info" : "",
2035 location));
2036
2037 body.data = outhdr + SMB2_HDR_BODY;
2038 body.length = 8;
2039 SSVAL(body.data, 0, 9);
2040
2041 if (info) {
2042 SIVAL(body.data, 0x04, info->length);
2043 } else {
2044 /* Allocated size of req->out.vector[i].iov_base
2045 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2046 * 1 byte without having to do an alloc.
2047 */
2048 info = talloc_zero_array(req->out.vector,
2049 DATA_BLOB,
2050 1);
2051 if (!info) {
2052 return NT_STATUS_NO_MEMORY;
2053 }
2054 info->data = ((uint8_t *)outhdr) +
2055 OUTVEC_ALLOC_SIZE - 1;
2056 info->length = 1;
2057 SCVAL(info->data, 0, 0);
2058 }
2059
2060 /*
2061 * Note: Even if there is an error, continue to process the request.
2062 * per MS-SMB2.
2063 */
2064
2065 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2066}
2067
2068
2069struct smbd_smb2_send_oplock_break_state {
2070 struct smbd_server_connection *sconn;
2071 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2072 struct iovec vector;
2073};
2074
2075static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2076
2077NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2078 uint64_t file_id_persistent,
2079 uint64_t file_id_volatile,
2080 uint8_t oplock_level)
2081{
2082 struct smbd_smb2_send_oplock_break_state *state;
2083 struct tevent_req *subreq;
2084 uint8_t *hdr;
2085 uint8_t *body;
2086
2087 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2088 if (state == NULL) {
2089 return NT_STATUS_NO_MEMORY;
2090 }
2091 state->sconn = sconn;
2092
2093 state->vector.iov_base = (void *)state->buf;
2094 state->vector.iov_len = sizeof(state->buf);
2095
2096 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2097 hdr = state->buf + 4;
2098 body = hdr + SMB2_HDR_BODY;
2099
2100 SIVAL(hdr, 0, SMB2_MAGIC);
2101 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2102 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2103 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2104 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2105 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2106 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2107 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2108 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2109 SIVAL(hdr, SMB2_HDR_PID, 0);
2110 SIVAL(hdr, SMB2_HDR_TID, 0);
2111 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2112 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2113
2114 SSVAL(body, 0x00, 0x18);
2115
2116 SCVAL(body, 0x02, oplock_level);
2117 SCVAL(body, 0x03, 0); /* reserved */
2118 SIVAL(body, 0x04, 0); /* reserved */
2119 SBVAL(body, 0x08, file_id_persistent);
2120 SBVAL(body, 0x10, file_id_volatile);
2121
2122 subreq = tstream_writev_queue_send(state,
2123 sconn->smb2.event_ctx,
2124 sconn->smb2.stream,
2125 sconn->smb2.send_queue,
2126 &state->vector, 1);
2127 if (subreq == NULL) {
2128 return NT_STATUS_NO_MEMORY;
2129 }
2130 tevent_req_set_callback(subreq,
2131 smbd_smb2_oplock_break_writev_done,
2132 state);
2133
2134 return NT_STATUS_OK;
2135}
2136
2137static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2138{
2139 struct smbd_smb2_send_oplock_break_state *state =
2140 tevent_req_callback_data(subreq,
2141 struct smbd_smb2_send_oplock_break_state);
2142 struct smbd_server_connection *sconn = state->sconn;
2143 int ret;
2144 int sys_errno;
2145
2146 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2147 TALLOC_FREE(subreq);
2148 if (ret == -1) {
2149 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2150 smbd_server_connection_terminate(sconn, nt_errstr(status));
2151 return;
2152 }
2153
2154 TALLOC_FREE(state);
2155}
2156
2157struct smbd_smb2_request_read_state {
2158 size_t missing;
2159 bool asked_for_header;
2160 struct smbd_smb2_request *smb2_req;
2161};
2162
2163static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2164 void *private_data,
2165 TALLOC_CTX *mem_ctx,
2166 struct iovec **_vector,
2167 size_t *_count);
2168static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2169
2170static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2171 struct tevent_context *ev,
2172 struct smbd_server_connection *sconn)
2173{
2174 struct tevent_req *req;
2175 struct smbd_smb2_request_read_state *state;
2176 struct tevent_req *subreq;
2177
2178 req = tevent_req_create(mem_ctx, &state,
2179 struct smbd_smb2_request_read_state);
2180 if (req == NULL) {
2181 return NULL;
2182 }
2183 state->missing = 0;
2184 state->asked_for_header = false;
2185
2186 state->smb2_req = smbd_smb2_request_allocate(state);
2187 if (tevent_req_nomem(state->smb2_req, req)) {
2188 return tevent_req_post(req, ev);
2189 }
2190 state->smb2_req->sconn = sconn;
2191
2192 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2193 sconn->smb2.recv_queue,
2194 smbd_smb2_request_next_vector,
2195 state);
2196 if (tevent_req_nomem(subreq, req)) {
2197 return tevent_req_post(req, ev);
2198 }
2199 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2200
2201 return req;
2202}
2203
2204static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2205 void *private_data,
2206 TALLOC_CTX *mem_ctx,
2207 struct iovec **_vector,
2208 size_t *_count)
2209{
2210 struct smbd_smb2_request_read_state *state =
2211 talloc_get_type_abort(private_data,
2212 struct smbd_smb2_request_read_state);
2213 struct smbd_smb2_request *req = state->smb2_req;
2214 struct iovec *vector;
2215 int idx = req->in.vector_count;
2216 size_t len = 0;
2217 uint8_t *buf = NULL;
2218
2219 if (req->in.vector_count == 0) {
2220 /*
2221 * first we need to get the NBT header
2222 */
2223 req->in.vector = talloc_array(req, struct iovec,
2224 req->in.vector_count + 1);
2225 if (req->in.vector == NULL) {
2226 return -1;
2227 }
2228 req->in.vector_count += 1;
2229
2230 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2231 req->in.vector[idx].iov_len = 4;
2232
2233 vector = talloc_array(mem_ctx, struct iovec, 1);
2234 if (vector == NULL) {
2235 return -1;
2236 }
2237
2238 vector[0] = req->in.vector[idx];
2239
2240 *_vector = vector;
2241 *_count = 1;
2242 return 0;
2243 }
2244
2245 if (req->in.vector_count == 1) {
2246 /*
2247 * Now we analyze the NBT header
2248 */
2249 state->missing = smb2_len(req->in.vector[0].iov_base);
2250
2251 if (state->missing == 0) {
2252 /* if there're no remaining bytes, we're done */
2253 *_vector = NULL;
2254 *_count = 0;
2255 return 0;
2256 }
2257
2258 req->in.vector = talloc_realloc(req, req->in.vector,
2259 struct iovec,
2260 req->in.vector_count + 1);
2261 if (req->in.vector == NULL) {
2262 return -1;
2263 }
2264 req->in.vector_count += 1;
2265
2266 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2267 /*
2268 * it's a special NBT message,
2269 * so get all remaining bytes
2270 */
2271 len = state->missing;
2272 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2273 /*
2274 * it's an invalid message, just read what we can get
2275 * and let the caller handle the error
2276 */
2277 len = state->missing;
2278 } else {
2279 /*
2280 * We assume it's a SMB2 request,
2281 * and we first get the header and the
2282 * first 2 bytes (the struct size) of the body
2283 */
2284 len = SMB2_HDR_BODY + 2;
2285
2286 state->asked_for_header = true;
2287 }
2288
2289 state->missing -= len;
2290
2291 buf = talloc_array(req->in.vector, uint8_t, len);
2292 if (buf == NULL) {
2293 return -1;
2294 }
2295
2296 req->in.vector[idx].iov_base = (void *)buf;
2297 req->in.vector[idx].iov_len = len;
2298
2299 vector = talloc_array(mem_ctx, struct iovec, 1);
2300 if (vector == NULL) {
2301 return -1;
2302 }
2303
2304 vector[0] = req->in.vector[idx];
2305
2306 *_vector = vector;
2307 *_count = 1;
2308 return 0;
2309 }
2310
2311 if (state->missing == 0) {
2312 /* if there're no remaining bytes, we're done */
2313 *_vector = NULL;
2314 *_count = 0;
2315 return 0;
2316 }
2317
2318 if (state->asked_for_header) {
2319 const uint8_t *hdr;
2320 size_t full_size;
2321 size_t next_command_ofs;
2322 size_t body_size;
2323 uint8_t *body;
2324 size_t dyn_size;
2325 uint8_t *dyn;
2326 bool invalid = false;
2327
2328 state->asked_for_header = false;
2329
2330 /*
2331 * We got the SMB2 header and the first 2 bytes
2332 * of the body. We fix the size to just the header
2333 * and manually copy the 2 first bytes to the body section
2334 */
2335 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2336 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2337
2338 /* allocate vectors for body and dynamic areas */
2339 req->in.vector = talloc_realloc(req, req->in.vector,
2340 struct iovec,
2341 req->in.vector_count + 2);
2342 if (req->in.vector == NULL) {
2343 return -1;
2344 }
2345 req->in.vector_count += 2;
2346
2347 full_size = state->missing + SMB2_HDR_BODY + 2;
2348 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2349 body_size = SVAL(hdr, SMB2_HDR_BODY);
2350
2351 if (next_command_ofs != 0) {
2352 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2353 /*
2354 * this is invalid, just return a zero
2355 * body and let the caller deal with the error
2356 */
2357 invalid = true;
2358 } else if (next_command_ofs > full_size) {
2359 /*
2360 * this is invalid, just return a zero
2361 * body and let the caller deal with the error
2362 */
2363 invalid = true;
2364 } else {
2365 full_size = next_command_ofs;
2366 }
2367 }
2368
2369 if (!invalid) {
2370 if (body_size < 2) {
2371 /*
2372 * this is invalid, just return a zero
2373 * body and let the caller deal with the error
2374 */
2375 invalid = true;
2376 }
2377
2378 if ((body_size % 2) != 0) {
2379 body_size -= 1;
2380 }
2381
2382 if (body_size > (full_size - SMB2_HDR_BODY)) {
2383 /*
2384 * this is invalid, just return a zero
2385 * body and let the caller deal with the error
2386 */
2387 invalid = true;
2388 }
2389 }
2390
2391 if (invalid) {
2392 /* the caller should check this */
2393 body_size = 2;
2394 }
2395
2396 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2397
2398 state->missing -= (body_size - 2) + dyn_size;
2399
2400 body = talloc_array(req->in.vector, uint8_t, body_size);
2401 if (body == NULL) {
2402 return -1;
2403 }
2404
2405 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2406 if (dyn == NULL) {
2407 return -1;
2408 }
2409
2410 req->in.vector[idx].iov_base = (void *)body;
2411 req->in.vector[idx].iov_len = body_size;
2412 req->in.vector[idx+1].iov_base = (void *)dyn;
2413 req->in.vector[idx+1].iov_len = dyn_size;
2414
2415 vector = talloc_array(mem_ctx, struct iovec, 2);
2416 if (vector == NULL) {
2417 return -1;
2418 }
2419
2420 /*
2421 * the first 2 bytes of the body were already fetched
2422 * together with the header
2423 */
2424 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2425 vector[0].iov_base = body + 2;
2426 vector[0].iov_len = body_size - 2;
2427
2428 vector[1] = req->in.vector[idx+1];
2429
2430 *_vector = vector;
2431 *_count = 2;
2432 return 0;
2433 }
2434
2435 /*
2436 * when we endup here, we're looking for a new SMB2 request
2437 * next. And we ask for its header and the first 2 bytes of
2438 * the body (like we did for the first SMB2 request).
2439 */
2440
2441 req->in.vector = talloc_realloc(req, req->in.vector,
2442 struct iovec,
2443 req->in.vector_count + 1);
2444 if (req->in.vector == NULL) {
2445 return -1;
2446 }
2447 req->in.vector_count += 1;
2448
2449 /*
2450 * We assume it's a SMB2 request,
2451 * and we first get the header and the
2452 * first 2 bytes (the struct size) of the body
2453 */
2454 len = SMB2_HDR_BODY + 2;
2455
2456 if (len > state->missing) {
2457 /* let the caller handle the error */
2458 len = state->missing;
2459 }
2460
2461 state->missing -= len;
2462 state->asked_for_header = true;
2463
2464 buf = talloc_array(req->in.vector, uint8_t, len);
2465 if (buf == NULL) {
2466 return -1;
2467 }
2468
2469 req->in.vector[idx].iov_base = (void *)buf;
2470 req->in.vector[idx].iov_len = len;
2471
2472 vector = talloc_array(mem_ctx, struct iovec, 1);
2473 if (vector == NULL) {
2474 return -1;
2475 }
2476
2477 vector[0] = req->in.vector[idx];
2478
2479 *_vector = vector;
2480 *_count = 1;
2481 return 0;
2482}
2483
2484static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2485{
2486 struct tevent_req *req =
2487 tevent_req_callback_data(subreq,
2488 struct tevent_req);
2489 int ret;
2490 int sys_errno;
2491 NTSTATUS status;
2492
2493 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2494 if (ret == -1) {
2495 status = map_nt_error_from_unix(sys_errno);
2496 tevent_req_nterror(req, status);
2497 return;
2498 }
2499
2500 tevent_req_done(req);
2501}
2502
2503static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2504 TALLOC_CTX *mem_ctx,
2505 struct smbd_smb2_request **_smb2_req)
2506{
2507 struct smbd_smb2_request_read_state *state =
2508 tevent_req_data(req,
2509 struct smbd_smb2_request_read_state);
2510 NTSTATUS status;
2511
2512 if (tevent_req_is_nterror(req, &status)) {
2513 tevent_req_received(req);
2514 return status;
2515 }
2516
2517 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2518 *_smb2_req = state->smb2_req;
2519 tevent_req_received(req);
2520 return NT_STATUS_OK;
2521}
2522
2523static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2524
2525static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2526{
2527 size_t max_send_queue_len;
2528 size_t cur_send_queue_len;
2529 struct tevent_req *subreq;
2530
2531 if (sconn->smb2.compound_related_in_progress) {
2532 /*
2533 * Can't read another until the related
2534 * compound is done.
2535 */
2536 return NT_STATUS_OK;
2537 }
2538
2539 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2540 /*
2541 * if there is already a smbd_smb2_request_read
2542 * pending, we are done.
2543 */
2544 return NT_STATUS_OK;
2545 }
2546
2547 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2548 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2549
2550 if (cur_send_queue_len > max_send_queue_len) {
2551 /*
2552 * if we have a lot of requests to send,
2553 * we wait until they are on the wire until we
2554 * ask for the next request.
2555 */
2556 return NT_STATUS_OK;
2557 }
2558
2559 /* ask for the next request */
2560 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2561 if (subreq == NULL) {
2562 return NT_STATUS_NO_MEMORY;
2563 }
2564 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2565
2566 return NT_STATUS_OK;
2567}
2568
2569void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2570 const uint8_t *inbuf, size_t size)
2571{
2572 NTSTATUS status;
2573 struct smbd_smb2_request *req = NULL;
2574
2575 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2576 (unsigned int)size));
2577
2578 status = smbd_initialize_smb2(sconn);
2579 if (!NT_STATUS_IS_OK(status)) {
2580 smbd_server_connection_terminate(sconn, nt_errstr(status));
2581 return;
2582 }
2583
2584 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2585 if (!NT_STATUS_IS_OK(status)) {
2586 smbd_server_connection_terminate(sconn, nt_errstr(status));
2587 return;
2588 }
2589
2590 status = smbd_smb2_request_validate(req);
2591 if (!NT_STATUS_IS_OK(status)) {
2592 smbd_server_connection_terminate(sconn, nt_errstr(status));
2593 return;
2594 }
2595
2596 status = smbd_smb2_request_setup_out(req);
2597 if (!NT_STATUS_IS_OK(status)) {
2598 smbd_server_connection_terminate(sconn, nt_errstr(status));
2599 return;
2600 }
2601
2602 status = smbd_smb2_request_dispatch(req);
2603 if (!NT_STATUS_IS_OK(status)) {
2604 smbd_server_connection_terminate(sconn, nt_errstr(status));
2605 return;
2606 }
2607
2608 status = smbd_smb2_request_next_incoming(sconn);
2609 if (!NT_STATUS_IS_OK(status)) {
2610 smbd_server_connection_terminate(sconn, nt_errstr(status));
2611 return;
2612 }
2613
2614 sconn->num_requests++;
2615}
2616
2617static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2618{
2619 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2620 struct smbd_server_connection);
2621 NTSTATUS status;
2622 struct smbd_smb2_request *req = NULL;
2623
2624 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2625 TALLOC_FREE(subreq);
2626 if (!NT_STATUS_IS_OK(status)) {
2627 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2628 nt_errstr(status)));
2629 smbd_server_connection_terminate(sconn, nt_errstr(status));
2630 return;
2631 }
2632
2633 if (req->in.nbt_hdr[0] != 0x00) {
2634 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2635 req->in.nbt_hdr[0]));
2636 TALLOC_FREE(req);
2637 goto next;
2638 }
2639
2640 req->current_idx = 1;
2641
2642 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2643 req->current_idx, req->in.vector_count));
2644
2645 status = smbd_smb2_request_validate(req);
2646 if (!NT_STATUS_IS_OK(status)) {
2647 smbd_server_connection_terminate(sconn, nt_errstr(status));
2648 return;
2649 }
2650
2651 status = smbd_smb2_request_setup_out(req);
2652 if (!NT_STATUS_IS_OK(status)) {
2653 smbd_server_connection_terminate(sconn, nt_errstr(status));
2654 return;
2655 }
2656
2657 status = smbd_smb2_request_dispatch(req);
2658 if (!NT_STATUS_IS_OK(status)) {
2659 smbd_server_connection_terminate(sconn, nt_errstr(status));
2660 return;
2661 }
2662
2663next:
2664 status = smbd_smb2_request_next_incoming(sconn);
2665 if (!NT_STATUS_IS_OK(status)) {
2666 smbd_server_connection_terminate(sconn, nt_errstr(status));
2667 return;
2668 }
2669
2670 sconn->num_requests++;
2671
2672 /* The timeout_processing function isn't run nearly
2673 often enough to implement 'max log size' without
2674 overrunning the size of the file by many megabytes.
2675 This is especially true if we are running at debug
2676 level 10. Checking every 50 SMB2s is a nice
2677 tradeoff of performance vs log file size overrun. */
2678
2679 if ((sconn->num_requests % 50) == 0 &&
2680 need_to_check_log_size()) {
2681 change_to_root_user();
2682 check_log_size();
2683 }
2684}
Note: See TracBrowser for help on using the repository browser.