source: trunk/server/source3/smbd/smb2_server.c

Last change on this file was 920, checked in by Silvan Scherrer, 9 years ago

Samba Server: apply latest security patches to trunk

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