Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Infrastructure for async SMB client requests
4 : Copyright (C) Volker Lendecke 2008
5 : Copyright (C) Stefan Metzmacher 2011
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "includes.h"
22 : #include "system/network.h"
23 : #include "../lib/async_req/async_sock.h"
24 : #include "../lib/util/tevent_ntstatus.h"
25 : #include "../lib/util/tevent_unix.h"
26 : #include "lib/util/util_net.h"
27 : #include "lib/util/dlinklist.h"
28 : #include "lib/util/iov_buf.h"
29 : #include "../libcli/smb/smb_common.h"
30 : #include "../libcli/smb/smb_seal.h"
31 : #include "../libcli/smb/smb_signing.h"
32 : #include "../libcli/smb/read_smb.h"
33 : #include "smbXcli_base.h"
34 : #include "librpc/ndr/libndr.h"
35 : #include "libcli/smb/smb2_negotiate_context.h"
36 : #include "libcli/smb/smb2_signing.h"
37 :
38 : #include "lib/crypto/gnutls_helpers.h"
39 : #include <gnutls/gnutls.h>
40 : #include <gnutls/crypto.h>
41 :
42 : struct smbXcli_conn;
43 : struct smbXcli_req;
44 : struct smbXcli_session;
45 : struct smbXcli_tcon;
46 :
47 : struct smbXcli_conn {
48 : int sock_fd;
49 : struct sockaddr_storage local_ss;
50 : struct sockaddr_storage remote_ss;
51 : const char *remote_name;
52 :
53 : struct tevent_queue *outgoing;
54 : struct tevent_req **pending;
55 : struct tevent_req *read_smb_req;
56 : struct tevent_req *suicide_req;
57 :
58 : enum protocol_types min_protocol;
59 : enum protocol_types max_protocol;
60 : enum protocol_types protocol;
61 : bool allow_signing;
62 : bool desire_signing;
63 : bool mandatory_signing;
64 :
65 : /*
66 : * The incoming dispatch function should return:
67 : * - NT_STATUS_RETRY, if more incoming PDUs are expected.
68 : * - NT_STATUS_OK, if no more processing is desired, e.g.
69 : * the dispatch function called
70 : * tevent_req_done().
71 : * - All other return values disconnect the connection.
72 : */
73 : NTSTATUS (*dispatch_incoming)(struct smbXcli_conn *conn,
74 : TALLOC_CTX *tmp_mem,
75 : uint8_t *inbuf);
76 :
77 : struct {
78 : struct {
79 : uint32_t capabilities;
80 : uint32_t max_xmit;
81 : } client;
82 :
83 : struct {
84 : uint32_t capabilities;
85 : uint32_t max_xmit;
86 : uint16_t max_mux;
87 : uint16_t security_mode;
88 : bool readbraw;
89 : bool writebraw;
90 : bool lockread;
91 : bool writeunlock;
92 : uint32_t session_key;
93 : struct GUID guid;
94 : DATA_BLOB gss_blob;
95 : uint8_t challenge[8];
96 : const char *workgroup;
97 : const char *name;
98 : int time_zone;
99 : NTTIME system_time;
100 : } server;
101 :
102 : uint32_t capabilities;
103 : uint32_t max_xmit;
104 :
105 : uint16_t mid;
106 :
107 : struct smb_signing_state *signing;
108 : struct smb_trans_enc_state *trans_enc;
109 :
110 : struct tevent_req *read_braw_req;
111 : } smb1;
112 :
113 : struct {
114 : struct {
115 : uint32_t capabilities;
116 : uint16_t security_mode;
117 : struct GUID guid;
118 : struct smb311_capabilities smb3_capabilities;
119 : } client;
120 :
121 : struct {
122 : uint32_t capabilities;
123 : uint16_t security_mode;
124 : struct GUID guid;
125 : uint32_t max_trans_size;
126 : uint32_t max_read_size;
127 : uint32_t max_write_size;
128 : NTTIME system_time;
129 : NTTIME start_time;
130 : DATA_BLOB gss_blob;
131 : uint16_t sign_algo;
132 : uint16_t cipher;
133 : } server;
134 :
135 : uint64_t mid;
136 : uint16_t cur_credits;
137 : uint16_t max_credits;
138 :
139 : uint32_t cc_chunk_len;
140 : uint32_t cc_max_chunks;
141 :
142 : uint8_t io_priority;
143 :
144 : bool force_channel_sequence;
145 :
146 : uint8_t preauth_sha512[64];
147 : } smb2;
148 :
149 : struct smbXcli_session *sessions;
150 : };
151 :
152 : struct smb2cli_session {
153 : uint64_t session_id;
154 : uint16_t session_flags;
155 : struct smb2_signing_key *application_key;
156 : struct smb2_signing_key *signing_key;
157 : bool should_sign;
158 : bool should_encrypt;
159 : struct smb2_signing_key *encryption_key;
160 : struct smb2_signing_key *decryption_key;
161 : uint64_t nonce_high_random;
162 : uint64_t nonce_high_max;
163 : uint64_t nonce_high;
164 : uint64_t nonce_low;
165 : uint16_t channel_sequence;
166 : bool replay_active;
167 : bool require_signed_response;
168 : };
169 :
170 : struct smbXcli_session {
171 : struct smbXcli_session *prev, *next;
172 : struct smbXcli_conn *conn;
173 :
174 : struct {
175 : uint16_t session_id;
176 : uint16_t action;
177 : DATA_BLOB application_key;
178 : bool protected_key;
179 : } smb1;
180 :
181 : struct smb2cli_session *smb2;
182 :
183 : struct {
184 : struct smb2_signing_key *signing_key;
185 : uint8_t preauth_sha512[64];
186 : } smb2_channel;
187 :
188 : /*
189 : * this should be a short term hack
190 : * until the upper layers have implemented
191 : * re-authentication.
192 : */
193 : bool disconnect_expired;
194 : };
195 :
196 : struct smbXcli_tcon {
197 : bool is_smb1;
198 : uint32_t fs_attributes;
199 :
200 : struct {
201 : uint16_t tcon_id;
202 : uint16_t optional_support;
203 : uint32_t maximal_access;
204 : uint32_t guest_maximal_access;
205 : char *service;
206 : char *fs_type;
207 : } smb1;
208 :
209 : struct {
210 : uint32_t tcon_id;
211 : uint8_t type;
212 : uint32_t flags;
213 : uint32_t capabilities;
214 : uint32_t maximal_access;
215 : bool should_sign;
216 : bool should_encrypt;
217 : } smb2;
218 : };
219 :
220 : struct smbXcli_req_state {
221 : struct tevent_context *ev;
222 : struct smbXcli_conn *conn;
223 : struct smbXcli_session *session; /* maybe NULL */
224 : struct smbXcli_tcon *tcon; /* maybe NULL */
225 :
226 : uint8_t length_hdr[4];
227 :
228 : bool one_way;
229 :
230 : uint8_t *inbuf;
231 :
232 : struct tevent_req *write_req;
233 :
234 : struct timeval endtime;
235 :
236 : struct {
237 : /* Space for the header including the wct */
238 : uint8_t hdr[HDR_VWV];
239 :
240 : /*
241 : * For normal requests, smb1cli_req_send chooses a mid.
242 : * SecondaryV trans requests need to use the mid of the primary
243 : * request, so we need a place to store it.
244 : * Assume it is set if != 0.
245 : */
246 : uint16_t mid;
247 :
248 : uint16_t *vwv;
249 : uint8_t bytecount_buf[2];
250 :
251 : #define MAX_SMB_IOV 10
252 : /* length_hdr, hdr, words, byte_count, buffers */
253 : struct iovec iov[1 + 3 + MAX_SMB_IOV];
254 : int iov_count;
255 :
256 : bool one_way_seqnum;
257 : uint32_t seqnum;
258 : struct tevent_req **chained_requests;
259 :
260 : uint8_t recv_cmd;
261 : NTSTATUS recv_status;
262 : /* always an array of 3 talloc elements */
263 : struct iovec *recv_iov;
264 : } smb1;
265 :
266 : struct {
267 : const uint8_t *fixed;
268 : uint16_t fixed_len;
269 : const uint8_t *dyn;
270 : uint32_t dyn_len;
271 :
272 : uint8_t transform[SMB2_TF_HDR_SIZE];
273 : uint8_t hdr[SMB2_HDR_BODY];
274 : uint8_t pad[7]; /* padding space for compounding */
275 :
276 : /*
277 : * always an array of 3 talloc elements
278 : * (without a SMB2_TRANSFORM header!)
279 : *
280 : * HDR, BODY, DYN
281 : */
282 : struct iovec *recv_iov;
283 :
284 : /*
285 : * the expected max for the response dyn_len
286 : */
287 : uint32_t max_dyn_len;
288 :
289 : uint16_t credit_charge;
290 :
291 : bool should_sign;
292 : bool should_encrypt;
293 : uint64_t encryption_session_id;
294 :
295 : bool signing_skipped;
296 : bool require_signed_response;
297 : bool notify_async;
298 : bool got_async;
299 : uint16_t cancel_flags;
300 : uint64_t cancel_mid;
301 : uint64_t cancel_aid;
302 : } smb2;
303 : };
304 :
305 26550 : static int smbXcli_conn_destructor(struct smbXcli_conn *conn)
306 : {
307 : /*
308 : * NT_STATUS_OK, means we do not notify the callers
309 : */
310 26550 : smbXcli_conn_disconnect(conn, NT_STATUS_OK);
311 :
312 49663 : while (conn->sessions) {
313 506 : conn->sessions->conn = NULL;
314 506 : DLIST_REMOVE(conn->sessions, conn->sessions);
315 : }
316 :
317 26550 : if (conn->smb1.trans_enc) {
318 254 : TALLOC_FREE(conn->smb1.trans_enc);
319 : }
320 :
321 26550 : return 0;
322 : }
323 :
324 29651 : struct smbXcli_conn *smbXcli_conn_create(TALLOC_CTX *mem_ctx,
325 : int fd,
326 : const char *remote_name,
327 : enum smb_signing_setting signing_state,
328 : uint32_t smb1_capabilities,
329 : struct GUID *client_guid,
330 : uint32_t smb2_capabilities,
331 : const struct smb311_capabilities *smb3_capabilities)
332 : {
333 29651 : struct smbXcli_conn *conn = NULL;
334 29651 : void *ss = NULL;
335 29651 : struct sockaddr *sa = NULL;
336 : socklen_t sa_length;
337 : int ret;
338 :
339 29651 : if (smb3_capabilities != NULL) {
340 26795 : const struct smb3_signing_capabilities *sign_algos =
341 : &smb3_capabilities->signing;
342 26795 : const struct smb3_encryption_capabilities *ciphers =
343 : &smb3_capabilities->encryption;
344 :
345 26795 : SMB_ASSERT(sign_algos->num_algos <= SMB3_SIGNING_CAPABILITIES_MAX_ALGOS);
346 26795 : SMB_ASSERT(ciphers->num_algos <= SMB3_ENCRYTION_CAPABILITIES_MAX_ALGOS);
347 : }
348 :
349 29651 : conn = talloc_zero(mem_ctx, struct smbXcli_conn);
350 29651 : if (!conn) {
351 0 : return NULL;
352 : }
353 :
354 29651 : ret = set_blocking(fd, false);
355 29651 : if (ret < 0) {
356 0 : goto error;
357 : }
358 29651 : conn->sock_fd = fd;
359 :
360 29651 : conn->remote_name = talloc_strdup(conn, remote_name);
361 29651 : if (conn->remote_name == NULL) {
362 0 : goto error;
363 : }
364 :
365 29651 : ss = (void *)&conn->local_ss;
366 29651 : sa = (struct sockaddr *)ss;
367 29651 : sa_length = sizeof(conn->local_ss);
368 29651 : ret = getsockname(fd, sa, &sa_length);
369 29651 : if (ret == -1) {
370 0 : goto error;
371 : }
372 29651 : ss = (void *)&conn->remote_ss;
373 29651 : sa = (struct sockaddr *)ss;
374 29651 : sa_length = sizeof(conn->remote_ss);
375 29651 : ret = getpeername(fd, sa, &sa_length);
376 29651 : if (ret == -1) {
377 0 : goto error;
378 : }
379 :
380 29651 : conn->outgoing = tevent_queue_create(conn, "smbXcli_outgoing");
381 29651 : if (conn->outgoing == NULL) {
382 0 : goto error;
383 : }
384 29651 : conn->pending = NULL;
385 :
386 29651 : conn->min_protocol = PROTOCOL_NONE;
387 29651 : conn->max_protocol = PROTOCOL_NONE;
388 29651 : conn->protocol = PROTOCOL_NONE;
389 :
390 29651 : switch (signing_state) {
391 30 : case SMB_SIGNING_OFF:
392 : /* never */
393 30 : conn->allow_signing = false;
394 30 : conn->desire_signing = false;
395 30 : conn->mandatory_signing = false;
396 30 : break;
397 19182 : case SMB_SIGNING_DEFAULT:
398 : case SMB_SIGNING_IF_REQUIRED:
399 : /* if the server requires it */
400 19182 : conn->allow_signing = true;
401 19182 : conn->desire_signing = false;
402 19182 : conn->mandatory_signing = false;
403 19182 : break;
404 6 : case SMB_SIGNING_DESIRED:
405 : /* if the server desires it */
406 6 : conn->allow_signing = true;
407 6 : conn->desire_signing = true;
408 6 : conn->mandatory_signing = false;
409 6 : break;
410 10433 : case SMB_SIGNING_IPC_DEFAULT:
411 : case SMB_SIGNING_REQUIRED:
412 : /* always */
413 10433 : conn->allow_signing = true;
414 10433 : conn->desire_signing = true;
415 10433 : conn->mandatory_signing = true;
416 10433 : break;
417 : }
418 :
419 29651 : conn->smb1.client.capabilities = smb1_capabilities;
420 29651 : conn->smb1.client.max_xmit = UINT16_MAX;
421 :
422 29651 : conn->smb1.capabilities = conn->smb1.client.capabilities;
423 29651 : conn->smb1.max_xmit = 1024;
424 :
425 29651 : conn->smb1.mid = 1;
426 :
427 : /* initialise signing */
428 84966 : conn->smb1.signing = smb_signing_init(conn,
429 29651 : conn->allow_signing,
430 29651 : conn->desire_signing,
431 29651 : conn->mandatory_signing);
432 29651 : if (!conn->smb1.signing) {
433 0 : goto error;
434 : }
435 :
436 29651 : conn->smb2.client.security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED;
437 29651 : if (conn->mandatory_signing) {
438 10433 : conn->smb2.client.security_mode |= SMB2_NEGOTIATE_SIGNING_REQUIRED;
439 : }
440 29651 : if (client_guid) {
441 26795 : conn->smb2.client.guid = *client_guid;
442 : }
443 29651 : conn->smb2.client.capabilities = smb2_capabilities;
444 29651 : if (smb3_capabilities != NULL) {
445 26795 : conn->smb2.client.smb3_capabilities = *smb3_capabilities;
446 : }
447 :
448 29651 : conn->smb2.cur_credits = 1;
449 29651 : conn->smb2.max_credits = 0;
450 29651 : conn->smb2.io_priority = 1;
451 :
452 : /*
453 : * Samba and Windows servers accept a maximum of 16 MiB with a maximum
454 : * chunk length of 1 MiB.
455 : */
456 29651 : conn->smb2.cc_chunk_len = 1024 * 1024;
457 29651 : conn->smb2.cc_max_chunks = 16;
458 :
459 29651 : talloc_set_destructor(conn, smbXcli_conn_destructor);
460 29651 : return conn;
461 :
462 0 : error:
463 0 : TALLOC_FREE(conn);
464 0 : return NULL;
465 : }
466 :
467 8665110 : bool smbXcli_conn_is_connected(struct smbXcli_conn *conn)
468 : {
469 8665110 : if (conn == NULL) {
470 13438 : return false;
471 : }
472 :
473 8650554 : if (conn->sock_fd == -1) {
474 69 : return false;
475 : }
476 :
477 8650485 : return true;
478 : }
479 :
480 4295442 : enum protocol_types smbXcli_conn_protocol(struct smbXcli_conn *conn)
481 : {
482 4295442 : return conn->protocol;
483 : }
484 :
485 141542 : bool smbXcli_conn_use_unicode(struct smbXcli_conn *conn)
486 : {
487 141542 : if (conn->protocol >= PROTOCOL_SMB2_02) {
488 6847 : return true;
489 : }
490 :
491 134695 : if (conn->smb1.capabilities & CAP_UNICODE) {
492 133338 : return true;
493 : }
494 :
495 116 : return false;
496 : }
497 :
498 341 : bool smbXcli_conn_signing_mandatory(struct smbXcli_conn *conn)
499 : {
500 341 : return conn->mandatory_signing;
501 : }
502 :
503 : /*
504 : * [MS-SMB] 2.2.2.3.5 - SMB1 support for passing through
505 : * query/set commands to the file system
506 : */
507 0 : bool smbXcli_conn_support_passthrough(struct smbXcli_conn *conn)
508 : {
509 0 : if (conn->protocol >= PROTOCOL_SMB2_02) {
510 0 : return true;
511 : }
512 :
513 0 : if (conn->smb1.capabilities & CAP_W2K_SMBS) {
514 0 : return true;
515 : }
516 :
517 0 : return false;
518 : }
519 :
520 370 : void smbXcli_conn_set_sockopt(struct smbXcli_conn *conn, const char *options)
521 : {
522 370 : set_socket_options(conn->sock_fd, options);
523 370 : }
524 :
525 857 : const struct sockaddr_storage *smbXcli_conn_local_sockaddr(struct smbXcli_conn *conn)
526 : {
527 857 : return &conn->local_ss;
528 : }
529 :
530 52 : const struct sockaddr_storage *smbXcli_conn_remote_sockaddr(struct smbXcli_conn *conn)
531 : {
532 52 : return &conn->remote_ss;
533 : }
534 :
535 115853 : const char *smbXcli_conn_remote_name(struct smbXcli_conn *conn)
536 : {
537 115853 : return conn->remote_name;
538 : }
539 :
540 8745 : uint16_t smbXcli_conn_max_requests(struct smbXcli_conn *conn)
541 : {
542 8745 : if (conn->protocol >= PROTOCOL_SMB2_02) {
543 : /*
544 : * TODO...
545 : */
546 0 : return 1;
547 : }
548 :
549 8745 : return conn->smb1.server.max_mux;
550 : }
551 :
552 2786 : NTTIME smbXcli_conn_server_system_time(struct smbXcli_conn *conn)
553 : {
554 2786 : if (conn->protocol >= PROTOCOL_SMB2_02) {
555 6 : return conn->smb2.server.system_time;
556 : }
557 :
558 2780 : return conn->smb1.server.system_time;
559 : }
560 :
561 32359 : const DATA_BLOB *smbXcli_conn_server_gss_blob(struct smbXcli_conn *conn)
562 : {
563 32359 : if (conn->protocol >= PROTOCOL_SMB2_02) {
564 26265 : return &conn->smb2.server.gss_blob;
565 : }
566 :
567 6094 : return &conn->smb1.server.gss_blob;
568 : }
569 :
570 0 : const struct GUID *smbXcli_conn_server_guid(struct smbXcli_conn *conn)
571 : {
572 0 : if (conn->protocol >= PROTOCOL_SMB2_02) {
573 0 : return &conn->smb2.server.guid;
574 : }
575 :
576 0 : return &conn->smb1.server.guid;
577 : }
578 :
579 0 : bool smbXcli_conn_get_force_channel_sequence(struct smbXcli_conn *conn)
580 : {
581 0 : return conn->smb2.force_channel_sequence;
582 : }
583 :
584 8 : void smbXcli_conn_set_force_channel_sequence(struct smbXcli_conn *conn,
585 : bool v)
586 : {
587 8 : conn->smb2.force_channel_sequence = v;
588 8 : }
589 :
590 : struct smbXcli_conn_samba_suicide_state {
591 : struct smbXcli_conn *conn;
592 : struct iovec iov;
593 : uint8_t buf[9];
594 : struct tevent_req *write_req;
595 : };
596 :
597 : static void smbXcli_conn_samba_suicide_cleanup(struct tevent_req *req,
598 : enum tevent_req_state req_state);
599 : static void smbXcli_conn_samba_suicide_done(struct tevent_req *subreq);
600 :
601 17 : struct tevent_req *smbXcli_conn_samba_suicide_send(TALLOC_CTX *mem_ctx,
602 : struct tevent_context *ev,
603 : struct smbXcli_conn *conn,
604 : uint8_t exitcode)
605 : {
606 : struct tevent_req *req, *subreq;
607 : struct smbXcli_conn_samba_suicide_state *state;
608 :
609 17 : req = tevent_req_create(mem_ctx, &state,
610 : struct smbXcli_conn_samba_suicide_state);
611 17 : if (req == NULL) {
612 0 : return NULL;
613 : }
614 17 : state->conn = conn;
615 17 : SIVAL(state->buf, 4, SMB_SUICIDE_PACKET);
616 17 : SCVAL(state->buf, 8, exitcode);
617 17 : _smb_setlen_nbt(state->buf, sizeof(state->buf)-4);
618 :
619 17 : if (conn->suicide_req != NULL) {
620 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
621 0 : return tevent_req_post(req, ev);
622 : }
623 :
624 17 : state->iov.iov_base = state->buf;
625 17 : state->iov.iov_len = sizeof(state->buf);
626 :
627 17 : subreq = writev_send(state, ev, conn->outgoing, conn->sock_fd,
628 17 : false, &state->iov, 1);
629 17 : if (tevent_req_nomem(subreq, req)) {
630 0 : return tevent_req_post(req, ev);
631 : }
632 17 : tevent_req_set_callback(subreq, smbXcli_conn_samba_suicide_done, req);
633 17 : state->write_req = subreq;
634 :
635 17 : tevent_req_set_cleanup_fn(req, smbXcli_conn_samba_suicide_cleanup);
636 :
637 : /*
638 : * We need to use tevent_req_defer_callback()
639 : * in order to allow smbXcli_conn_disconnect()
640 : * to do a safe cleanup.
641 : */
642 17 : tevent_req_defer_callback(req, ev);
643 17 : conn->suicide_req = req;
644 :
645 17 : return req;
646 : }
647 :
648 34 : static void smbXcli_conn_samba_suicide_cleanup(struct tevent_req *req,
649 : enum tevent_req_state req_state)
650 : {
651 34 : struct smbXcli_conn_samba_suicide_state *state = tevent_req_data(
652 : req, struct smbXcli_conn_samba_suicide_state);
653 :
654 34 : TALLOC_FREE(state->write_req);
655 :
656 34 : if (state->conn == NULL) {
657 17 : return;
658 : }
659 :
660 17 : if (state->conn->suicide_req == req) {
661 17 : state->conn->suicide_req = NULL;
662 : }
663 17 : state->conn = NULL;
664 : }
665 :
666 17 : static void smbXcli_conn_samba_suicide_done(struct tevent_req *subreq)
667 : {
668 17 : struct tevent_req *req = tevent_req_callback_data(
669 : subreq, struct tevent_req);
670 17 : struct smbXcli_conn_samba_suicide_state *state = tevent_req_data(
671 : req, struct smbXcli_conn_samba_suicide_state);
672 : ssize_t nwritten;
673 : int err;
674 :
675 17 : state->write_req = NULL;
676 :
677 17 : nwritten = writev_recv(subreq, &err);
678 17 : TALLOC_FREE(subreq);
679 17 : if (nwritten == -1) {
680 : /* here, we need to notify all pending requests */
681 0 : NTSTATUS status = map_nt_error_from_unix_common(err);
682 0 : smbXcli_conn_disconnect(state->conn, status);
683 0 : return;
684 : }
685 17 : tevent_req_done(req);
686 : }
687 :
688 17 : NTSTATUS smbXcli_conn_samba_suicide_recv(struct tevent_req *req)
689 : {
690 17 : return tevent_req_simple_recv_ntstatus(req);
691 : }
692 :
693 17 : NTSTATUS smbXcli_conn_samba_suicide(struct smbXcli_conn *conn,
694 : uint8_t exitcode)
695 : {
696 17 : TALLOC_CTX *frame = talloc_stackframe();
697 : struct tevent_context *ev;
698 : struct tevent_req *req;
699 17 : NTSTATUS status = NT_STATUS_NO_MEMORY;
700 : bool ok;
701 :
702 17 : if (smbXcli_conn_has_async_calls(conn)) {
703 : /*
704 : * Can't use sync call while an async call is in flight
705 : */
706 0 : status = NT_STATUS_INVALID_PARAMETER_MIX;
707 0 : goto fail;
708 : }
709 17 : ev = samba_tevent_context_init(frame);
710 17 : if (ev == NULL) {
711 0 : goto fail;
712 : }
713 17 : req = smbXcli_conn_samba_suicide_send(frame, ev, conn, exitcode);
714 17 : if (req == NULL) {
715 0 : goto fail;
716 : }
717 17 : ok = tevent_req_poll_ntstatus(req, ev, &status);
718 17 : if (!ok) {
719 0 : goto fail;
720 : }
721 17 : status = smbXcli_conn_samba_suicide_recv(req);
722 17 : fail:
723 17 : TALLOC_FREE(frame);
724 17 : return status;
725 : }
726 :
727 937616 : uint32_t smb1cli_conn_capabilities(struct smbXcli_conn *conn)
728 : {
729 937616 : return conn->smb1.capabilities;
730 : }
731 :
732 112099 : uint32_t smb1cli_conn_max_xmit(struct smbXcli_conn *conn)
733 : {
734 112099 : return conn->smb1.max_xmit;
735 : }
736 :
737 13881 : bool smb1cli_conn_req_possible(struct smbXcli_conn *conn)
738 : {
739 13881 : size_t pending = talloc_array_length(conn->pending);
740 13881 : uint16_t possible = conn->smb1.server.max_mux;
741 :
742 13881 : if (pending >= possible) {
743 3296 : return false;
744 : }
745 :
746 10585 : return true;
747 : }
748 :
749 8765 : uint32_t smb1cli_conn_server_session_key(struct smbXcli_conn *conn)
750 : {
751 8765 : return conn->smb1.server.session_key;
752 : }
753 :
754 77 : const uint8_t *smb1cli_conn_server_challenge(struct smbXcli_conn *conn)
755 : {
756 77 : return conn->smb1.server.challenge;
757 : }
758 :
759 23034 : uint16_t smb1cli_conn_server_security_mode(struct smbXcli_conn *conn)
760 : {
761 23034 : return conn->smb1.server.security_mode;
762 : }
763 :
764 2774 : bool smb1cli_conn_server_readbraw(struct smbXcli_conn *conn)
765 : {
766 2774 : return conn->smb1.server.readbraw;
767 : }
768 :
769 2774 : bool smb1cli_conn_server_writebraw(struct smbXcli_conn *conn)
770 : {
771 2774 : return conn->smb1.server.writebraw;
772 : }
773 :
774 2774 : bool smb1cli_conn_server_lockread(struct smbXcli_conn *conn)
775 : {
776 2774 : return conn->smb1.server.lockread;
777 : }
778 :
779 0 : bool smb1cli_conn_server_writeunlock(struct smbXcli_conn *conn)
780 : {
781 0 : return conn->smb1.server.writeunlock;
782 : }
783 :
784 5219 : int smb1cli_conn_server_time_zone(struct smbXcli_conn *conn)
785 : {
786 5219 : return conn->smb1.server.time_zone;
787 : }
788 :
789 5737 : bool smb1cli_conn_activate_signing(struct smbXcli_conn *conn,
790 : const DATA_BLOB user_session_key,
791 : const DATA_BLOB response)
792 : {
793 5737 : return smb_signing_activate(conn->smb1.signing,
794 : user_session_key,
795 : response);
796 : }
797 :
798 3047 : bool smb1cli_conn_check_signing(struct smbXcli_conn *conn,
799 : const uint8_t *buf, uint32_t seqnum)
800 : {
801 3047 : const uint8_t *hdr = buf + NBT_HDR_SIZE;
802 3047 : size_t len = smb_len_nbt(buf);
803 :
804 3047 : return smb_signing_check_pdu(conn->smb1.signing, hdr, len, seqnum);
805 : }
806 :
807 21177 : bool smb1cli_conn_signing_is_active(struct smbXcli_conn *conn)
808 : {
809 21177 : return smb_signing_is_active(conn->smb1.signing);
810 : }
811 :
812 392 : void smb1cli_conn_set_encryption(struct smbXcli_conn *conn,
813 : struct smb_trans_enc_state *es)
814 : {
815 : /* Replace the old state, if any. */
816 392 : if (conn->smb1.trans_enc) {
817 91 : TALLOC_FREE(conn->smb1.trans_enc);
818 : }
819 392 : conn->smb1.trans_enc = es;
820 392 : }
821 :
822 7562 : bool smb1cli_conn_encryption_on(struct smbXcli_conn *conn)
823 : {
824 7562 : return common_encryption_on(conn->smb1.trans_enc);
825 : }
826 :
827 :
828 1801304 : static NTSTATUS smb1cli_pull_raw_error(const uint8_t *hdr)
829 : {
830 1801304 : uint32_t flags2 = SVAL(hdr, HDR_FLG2);
831 1801304 : NTSTATUS status = NT_STATUS(IVAL(hdr, HDR_RCLS));
832 :
833 1801304 : if (NT_STATUS_IS_OK(status)) {
834 878750 : return NT_STATUS_OK;
835 : }
836 :
837 922554 : if (flags2 & FLAGS2_32_BIT_ERROR_CODES) {
838 266710 : return status;
839 : }
840 :
841 655844 : return NT_STATUS_DOS(CVAL(hdr, HDR_RCLS), SVAL(hdr, HDR_ERR));
842 : }
843 :
844 : /**
845 : * Is the SMB command able to hold an AND_X successor
846 : * @param[in] cmd The SMB command in question
847 : * @retval Can we add a chained request after "cmd"?
848 : */
849 1699341 : bool smb1cli_is_andx_req(uint8_t cmd)
850 : {
851 1699341 : switch (cmd) {
852 604694 : case SMBtconX:
853 : case SMBlockingX:
854 : case SMBopenX:
855 : case SMBreadX:
856 : case SMBwriteX:
857 : case SMBsesssetupX:
858 : case SMBulogoffX:
859 : case SMBntcreateX:
860 604694 : return true;
861 : break;
862 1078444 : default:
863 1078444 : break;
864 : }
865 :
866 1092479 : return false;
867 : }
868 :
869 917481 : static uint16_t smb1cli_alloc_mid(struct smbXcli_conn *conn)
870 : {
871 917481 : size_t num_pending = talloc_array_length(conn->pending);
872 : uint16_t result;
873 :
874 917481 : if (conn->protocol == PROTOCOL_NONE) {
875 : /*
876 : * This is what windows sends on the SMB1 Negprot request
877 : * and some vendors reuse the SMB1 MID as SMB2 sequence number.
878 : */
879 22285 : return 0;
880 : }
881 :
882 10 : while (true) {
883 : size_t i;
884 :
885 894676 : result = conn->smb1.mid++;
886 894676 : if ((result == 0) || (result == 0xffff)) {
887 10 : continue;
888 : }
889 :
890 1248013 : for (i=0; i<num_pending; i++) {
891 361025 : if (result == smb1cli_req_mid(conn->pending[i])) {
892 0 : break;
893 : }
894 : }
895 :
896 894666 : if (i == num_pending) {
897 886988 : return result;
898 : }
899 : }
900 : }
901 :
902 2884318 : static NTSTATUS smbXcli_req_cancel_write_req(struct tevent_req *req)
903 : {
904 2627044 : struct smbXcli_req_state *state =
905 2884318 : tevent_req_data(req,
906 : struct smbXcli_req_state);
907 2884318 : struct smbXcli_conn *conn = state->conn;
908 2884318 : size_t num_pending = talloc_array_length(conn->pending);
909 : ssize_t ret;
910 : int err;
911 : bool ok;
912 :
913 2884318 : if (state->write_req == NULL) {
914 2877528 : return NT_STATUS_OK;
915 : }
916 :
917 : /*
918 : * Check if it's possible to cancel the request.
919 : * If the result is true it's not too late.
920 : * See writev_cancel().
921 : */
922 6790 : ok = tevent_req_cancel(state->write_req);
923 6790 : if (ok) {
924 521 : TALLOC_FREE(state->write_req);
925 :
926 521 : if (conn->protocol >= PROTOCOL_SMB2_02) {
927 : /*
928 : * SMB2 has a sane signing state.
929 : */
930 519 : return NT_STATUS_OK;
931 : }
932 :
933 2 : if (num_pending > 1) {
934 : /*
935 : * We have more pending requests following us. This
936 : * means the signing state will be broken for them.
937 : *
938 : * As a solution we could add the requests directly to
939 : * our outgoing queue and do the signing in the trigger
940 : * function and then use writev_send() without passing a
941 : * queue. That way we'll only sign packets we're most
942 : * likely send to the wire.
943 : */
944 2 : return NT_STATUS_REQUEST_OUT_OF_SEQUENCE;
945 : }
946 :
947 : /*
948 : * If we're the only request that's
949 : * pending, we're able to recover the signing
950 : * state.
951 : */
952 0 : smb_signing_cancel_reply(conn->smb1.signing,
953 0 : state->smb1.one_way_seqnum);
954 0 : return NT_STATUS_OK;
955 : }
956 :
957 6269 : ret = writev_recv(state->write_req, &err);
958 6269 : TALLOC_FREE(state->write_req);
959 6269 : if (ret == -1) {
960 0 : return map_nt_error_from_unix_common(err);
961 : }
962 :
963 6269 : return NT_STATUS_OK;
964 : }
965 :
966 2793575 : void smbXcli_req_unset_pending(struct tevent_req *req)
967 : {
968 2540923 : struct smbXcli_req_state *state =
969 2793575 : tevent_req_data(req,
970 : struct smbXcli_req_state);
971 2793575 : struct smbXcli_conn *conn = state->conn;
972 2793575 : size_t num_pending = talloc_array_length(conn->pending);
973 : size_t i;
974 : NTSTATUS cancel_status;
975 :
976 2793575 : cancel_status = smbXcli_req_cancel_write_req(req);
977 :
978 2793575 : if (state->smb1.mid != 0) {
979 : /*
980 : * This is a [nt]trans[2] request which waits
981 : * for more than one reply.
982 : */
983 89062 : if (!NT_STATUS_IS_OK(cancel_status)) {
984 : /*
985 : * If the write_req cancel didn't work
986 : * we can't use the connection anymore.
987 : */
988 0 : smbXcli_conn_disconnect(conn, cancel_status);
989 0 : return;
990 : }
991 87821 : return;
992 : }
993 :
994 2704513 : tevent_req_set_cleanup_fn(req, NULL);
995 :
996 2704513 : if (num_pending == 1) {
997 : /*
998 : * The pending read_smb tevent_req is a child of
999 : * conn->pending. So if nothing is pending anymore, we need to
1000 : * delete the socket read fde.
1001 : */
1002 : /* TODO: smbXcli_conn_cancel_read_req */
1003 2607563 : TALLOC_FREE(conn->pending);
1004 2607563 : conn->read_smb_req = NULL;
1005 :
1006 2607563 : if (!NT_STATUS_IS_OK(cancel_status)) {
1007 : /*
1008 : * If the write_req cancel didn't work
1009 : * we can't use the connection anymore.
1010 : */
1011 0 : smbXcli_conn_disconnect(conn, cancel_status);
1012 0 : return;
1013 : }
1014 2590466 : return;
1015 : }
1016 :
1017 180029 : for (i=0; i<num_pending; i++) {
1018 180134 : if (req == conn->pending[i]) {
1019 96736 : break;
1020 : }
1021 : }
1022 96950 : if (i == num_pending) {
1023 : /*
1024 : * Something's seriously broken. Just returning here is the
1025 : * right thing nevertheless, the point of this routine is to
1026 : * remove ourselves from conn->pending.
1027 : */
1028 :
1029 56 : if (!NT_STATUS_IS_OK(cancel_status)) {
1030 : /*
1031 : * If the write_req cancel didn't work
1032 : * we can't use the connection anymore.
1033 : */
1034 0 : smbXcli_conn_disconnect(conn, cancel_status);
1035 0 : return;
1036 : }
1037 53 : return;
1038 : }
1039 :
1040 : /*
1041 : * Remove ourselves from the conn->pending array
1042 : */
1043 419657 : for (; i < (num_pending - 1); i++) {
1044 322921 : conn->pending[i] = conn->pending[i+1];
1045 : }
1046 :
1047 : /*
1048 : * No NULL check here, we're shrinking by sizeof(void *), and
1049 : * talloc_realloc just adjusts the size for this.
1050 : */
1051 96894 : conn->pending = talloc_realloc(NULL, conn->pending, struct tevent_req *,
1052 : num_pending - 1);
1053 :
1054 96894 : if (!NT_STATUS_IS_OK(cancel_status)) {
1055 : /*
1056 : * If the write_req cancel didn't work
1057 : * we can't use the connection anymore.
1058 : */
1059 2 : smbXcli_conn_disconnect(conn, cancel_status);
1060 2 : return;
1061 : }
1062 96734 : return;
1063 : }
1064 :
1065 101034 : static void smbXcli_req_cleanup(struct tevent_req *req,
1066 : enum tevent_req_state req_state)
1067 : {
1068 94771 : struct smbXcli_req_state *state =
1069 101034 : tevent_req_data(req,
1070 : struct smbXcli_req_state);
1071 101034 : struct smbXcli_conn *conn = state->conn;
1072 : NTSTATUS cancel_status;
1073 :
1074 101034 : switch (req_state) {
1075 10291 : case TEVENT_REQ_RECEIVED:
1076 : /*
1077 : * Make sure we really remove it from
1078 : * the pending array on destruction.
1079 : *
1080 : * smbXcli_req_unset_pending() calls
1081 : * smbXcli_req_cancel_write_req() internal
1082 : */
1083 10291 : state->smb1.mid = 0;
1084 10291 : smbXcli_req_unset_pending(req);
1085 10291 : return;
1086 90743 : default:
1087 90743 : cancel_status = smbXcli_req_cancel_write_req(req);
1088 90743 : if (!NT_STATUS_IS_OK(cancel_status)) {
1089 : /*
1090 : * If the write_req cancel didn't work
1091 : * we can't use the connection anymore.
1092 : */
1093 0 : smbXcli_conn_disconnect(conn, cancel_status);
1094 0 : return;
1095 : }
1096 89502 : return;
1097 : }
1098 : }
1099 :
1100 : static bool smb1cli_req_cancel(struct tevent_req *req);
1101 : static bool smb2cli_req_cancel(struct tevent_req *req);
1102 :
1103 3159 : static bool smbXcli_req_cancel(struct tevent_req *req)
1104 : {
1105 3132 : struct smbXcli_req_state *state =
1106 3159 : tevent_req_data(req,
1107 : struct smbXcli_req_state);
1108 :
1109 3159 : if (!smbXcli_conn_is_connected(state->conn)) {
1110 0 : return false;
1111 : }
1112 :
1113 3159 : if (state->conn->protocol == PROTOCOL_NONE) {
1114 0 : return false;
1115 : }
1116 :
1117 3159 : if (state->conn->protocol >= PROTOCOL_SMB2_02) {
1118 1604 : return smb2cli_req_cancel(req);
1119 : }
1120 :
1121 1555 : return smb1cli_req_cancel(req);
1122 : }
1123 :
1124 : static bool smbXcli_conn_receive_next(struct smbXcli_conn *conn);
1125 :
1126 2704469 : bool smbXcli_req_set_pending(struct tevent_req *req)
1127 : {
1128 2456443 : struct smbXcli_req_state *state =
1129 2704469 : tevent_req_data(req,
1130 : struct smbXcli_req_state);
1131 : struct smbXcli_conn *conn;
1132 : struct tevent_req **pending;
1133 : size_t num_pending;
1134 :
1135 2704469 : conn = state->conn;
1136 :
1137 2704469 : if (!smbXcli_conn_is_connected(conn)) {
1138 8 : return false;
1139 : }
1140 :
1141 2704461 : num_pending = talloc_array_length(conn->pending);
1142 :
1143 2704461 : pending = talloc_realloc(conn, conn->pending, struct tevent_req *,
1144 : num_pending+1);
1145 2704461 : if (pending == NULL) {
1146 0 : return false;
1147 : }
1148 2704461 : pending[num_pending] = req;
1149 2704461 : conn->pending = pending;
1150 2704461 : tevent_req_set_cleanup_fn(req, smbXcli_req_cleanup);
1151 2704461 : tevent_req_set_cancel_fn(req, smbXcli_req_cancel);
1152 :
1153 2704461 : if (!smbXcli_conn_receive_next(conn)) {
1154 : /*
1155 : * the caller should notify the current request
1156 : *
1157 : * And all other pending requests get notified
1158 : * by smbXcli_conn_disconnect().
1159 : */
1160 0 : smbXcli_req_unset_pending(req);
1161 0 : smbXcli_conn_disconnect(conn, NT_STATUS_NO_MEMORY);
1162 0 : return false;
1163 : }
1164 :
1165 2687206 : return true;
1166 : }
1167 :
1168 : static void smbXcli_conn_received(struct tevent_req *subreq);
1169 :
1170 4773669 : static bool smbXcli_conn_receive_next(struct smbXcli_conn *conn)
1171 : {
1172 4773669 : size_t num_pending = talloc_array_length(conn->pending);
1173 : struct tevent_req *req;
1174 : struct smbXcli_req_state *state;
1175 :
1176 4773669 : if (conn->read_smb_req != NULL) {
1177 96736 : return true;
1178 : }
1179 :
1180 4676775 : if (num_pending == 0) {
1181 1778893 : if (conn->smb2.mid < UINT64_MAX) {
1182 : /* no more pending requests, so we are done for now */
1183 1769976 : return true;
1184 : }
1185 :
1186 : /*
1187 : * If there are no more SMB2 requests possible,
1188 : * because we are out of message ids,
1189 : * we need to disconnect.
1190 : */
1191 0 : smbXcli_conn_disconnect(conn, NT_STATUS_CONNECTION_ABORTED);
1192 0 : return true;
1193 : }
1194 :
1195 2897882 : req = conn->pending[0];
1196 2897882 : state = tevent_req_data(req, struct smbXcli_req_state);
1197 :
1198 : /*
1199 : * We're the first ones, add the read_smb request that waits for the
1200 : * answer from the server
1201 : */
1202 2897882 : conn->read_smb_req = read_smb_send(conn->pending,
1203 : state->ev,
1204 : conn->sock_fd);
1205 2897882 : if (conn->read_smb_req == NULL) {
1206 0 : return false;
1207 : }
1208 2897882 : tevent_req_set_callback(conn->read_smb_req, smbXcli_conn_received, conn);
1209 2897882 : return true;
1210 : }
1211 :
1212 54262 : void smbXcli_conn_disconnect(struct smbXcli_conn *conn, NTSTATUS status)
1213 : {
1214 : struct smbXcli_session *session;
1215 54262 : int sock_fd = conn->sock_fd;
1216 :
1217 54262 : tevent_queue_stop(conn->outgoing);
1218 :
1219 54262 : conn->sock_fd = -1;
1220 :
1221 54262 : session = conn->sessions;
1222 54262 : if (talloc_array_length(conn->pending) == 0) {
1223 : /*
1224 : * if we do not have pending requests
1225 : * there is no need to update the channel_sequence
1226 : */
1227 52586 : session = NULL;
1228 : }
1229 54122 : for (; session; session = session->next) {
1230 911 : smb2cli_session_increment_channel_sequence(session);
1231 : }
1232 :
1233 54262 : if (conn->suicide_req != NULL) {
1234 : /*
1235 : * smbXcli_conn_samba_suicide_send()
1236 : * used tevent_req_defer_callback() already.
1237 : */
1238 0 : if (!NT_STATUS_IS_OK(status)) {
1239 0 : tevent_req_nterror(conn->suicide_req, status);
1240 : }
1241 0 : conn->suicide_req = NULL;
1242 : }
1243 :
1244 : /*
1245 : * Cancel all pending requests. We do not do a for-loop walking
1246 : * conn->pending because that array changes in
1247 : * smbXcli_req_unset_pending.
1248 : */
1249 104263 : while (conn->pending != NULL &&
1250 2391 : talloc_array_length(conn->pending) > 0) {
1251 : struct tevent_req *req;
1252 : struct smbXcli_req_state *state;
1253 : struct tevent_req **chain;
1254 : size_t num_chained;
1255 : size_t i;
1256 :
1257 2391 : req = conn->pending[0];
1258 2391 : state = tevent_req_data(req, struct smbXcli_req_state);
1259 :
1260 2391 : if (state->smb1.chained_requests == NULL) {
1261 : bool in_progress;
1262 :
1263 : /*
1264 : * We're dead. No point waiting for trans2
1265 : * replies.
1266 : */
1267 2391 : state->smb1.mid = 0;
1268 :
1269 2391 : smbXcli_req_unset_pending(req);
1270 :
1271 2391 : if (NT_STATUS_IS_OK(status)) {
1272 : /* do not notify the callers */
1273 0 : continue;
1274 : }
1275 :
1276 2391 : in_progress = tevent_req_is_in_progress(req);
1277 2391 : if (!in_progress) {
1278 : /*
1279 : * already finished
1280 : */
1281 0 : continue;
1282 : }
1283 :
1284 : /*
1285 : * we need to defer the callback, because we may notify
1286 : * more then one caller.
1287 : */
1288 2391 : tevent_req_defer_callback(req, state->ev);
1289 2391 : tevent_req_nterror(req, status);
1290 2391 : continue;
1291 : }
1292 :
1293 0 : chain = talloc_move(conn, &state->smb1.chained_requests);
1294 0 : num_chained = talloc_array_length(chain);
1295 :
1296 0 : for (i=0; i<num_chained; i++) {
1297 : bool in_progress;
1298 :
1299 0 : req = chain[i];
1300 0 : state = tevent_req_data(req, struct smbXcli_req_state);
1301 :
1302 : /*
1303 : * We're dead. No point waiting for trans2
1304 : * replies.
1305 : */
1306 0 : state->smb1.mid = 0;
1307 :
1308 0 : smbXcli_req_unset_pending(req);
1309 :
1310 0 : if (NT_STATUS_IS_OK(status)) {
1311 : /* do not notify the callers */
1312 0 : continue;
1313 : }
1314 :
1315 0 : in_progress = tevent_req_is_in_progress(req);
1316 0 : if (!in_progress) {
1317 : /*
1318 : * already finished
1319 : */
1320 0 : continue;
1321 : }
1322 :
1323 : /*
1324 : * we need to defer the callback, because we may notify
1325 : * more than one caller.
1326 : */
1327 0 : tevent_req_defer_callback(req, state->ev);
1328 0 : tevent_req_nterror(req, status);
1329 : }
1330 0 : TALLOC_FREE(chain);
1331 : }
1332 :
1333 54262 : if (sock_fd != -1) {
1334 26561 : close(sock_fd);
1335 : }
1336 54262 : }
1337 :
1338 : /*
1339 : * Fetch a smb request's mid. Only valid after the request has been sent by
1340 : * smb1cli_req_send().
1341 : */
1342 1422232 : uint16_t smb1cli_req_mid(struct tevent_req *req)
1343 : {
1344 1366156 : struct smbXcli_req_state *state =
1345 1422232 : tevent_req_data(req,
1346 : struct smbXcli_req_state);
1347 :
1348 1422232 : if (state->smb1.mid != 0) {
1349 273058 : return state->smb1.mid;
1350 : }
1351 :
1352 1147885 : return SVAL(state->smb1.hdr, HDR_MID);
1353 : }
1354 :
1355 181381 : void smb1cli_req_set_mid(struct tevent_req *req, uint16_t mid)
1356 : {
1357 172137 : struct smbXcli_req_state *state =
1358 181381 : tevent_req_data(req,
1359 : struct smbXcli_req_state);
1360 :
1361 181381 : state->smb1.mid = mid;
1362 181381 : }
1363 :
1364 0 : uint32_t smb1cli_req_seqnum(struct tevent_req *req)
1365 : {
1366 0 : struct smbXcli_req_state *state =
1367 0 : tevent_req_data(req,
1368 : struct smbXcli_req_state);
1369 :
1370 0 : return state->smb1.seqnum;
1371 : }
1372 :
1373 0 : void smb1cli_req_set_seqnum(struct tevent_req *req, uint32_t seqnum)
1374 : {
1375 0 : struct smbXcli_req_state *state =
1376 0 : tevent_req_data(req,
1377 : struct smbXcli_req_state);
1378 :
1379 0 : state->smb1.seqnum = seqnum;
1380 0 : }
1381 :
1382 125 : static size_t smbXcli_iov_len(const struct iovec *iov, int count)
1383 : {
1384 134 : ssize_t ret = iov_buflen(iov, count);
1385 :
1386 : /* Ignore the overflow case for now ... */
1387 134 : return ret;
1388 : }
1389 :
1390 941895 : static void smb1cli_req_flags(enum protocol_types protocol,
1391 : uint32_t smb1_capabilities,
1392 : uint8_t smb_command,
1393 : uint8_t additional_flags,
1394 : uint8_t clear_flags,
1395 : uint8_t *_flags,
1396 : uint16_t additional_flags2,
1397 : uint16_t clear_flags2,
1398 : uint16_t *_flags2)
1399 : {
1400 942425 : uint8_t flags = 0;
1401 942425 : uint16_t flags2 = 0;
1402 :
1403 942425 : if (protocol >= PROTOCOL_LANMAN1) {
1404 919608 : flags |= FLAG_CASELESS_PATHNAMES;
1405 919608 : flags |= FLAG_CANONICAL_PATHNAMES;
1406 : }
1407 :
1408 942425 : if (protocol >= PROTOCOL_LANMAN2) {
1409 919596 : flags2 |= FLAGS2_LONG_PATH_COMPONENTS;
1410 919596 : flags2 |= FLAGS2_EXTENDED_ATTRIBUTES;
1411 : }
1412 :
1413 942425 : if (protocol >= PROTOCOL_NT1) {
1414 919498 : flags2 |= FLAGS2_IS_LONG_NAME;
1415 :
1416 919498 : if (smb1_capabilities & CAP_UNICODE) {
1417 919498 : flags2 |= FLAGS2_UNICODE_STRINGS;
1418 : }
1419 919498 : if (smb1_capabilities & CAP_STATUS32) {
1420 919330 : flags2 |= FLAGS2_32_BIT_ERROR_CODES;
1421 : }
1422 919498 : if (smb1_capabilities & CAP_EXTENDED_SECURITY) {
1423 918581 : flags2 |= FLAGS2_EXTENDED_SECURITY;
1424 : }
1425 : }
1426 :
1427 942425 : flags |= additional_flags;
1428 942425 : flags &= ~clear_flags;
1429 942425 : flags2 |= additional_flags2;
1430 942425 : flags2 &= ~clear_flags2;
1431 :
1432 942425 : *_flags = flags;
1433 942425 : *_flags2 = flags2;
1434 941895 : }
1435 :
1436 : static void smb1cli_req_cancel_done(struct tevent_req *subreq);
1437 :
1438 1555 : static bool smb1cli_req_cancel(struct tevent_req *req)
1439 : {
1440 1555 : struct smbXcli_req_state *state =
1441 1555 : tevent_req_data(req,
1442 : struct smbXcli_req_state);
1443 : uint8_t flags;
1444 : uint16_t flags2;
1445 : uint32_t pid;
1446 : uint16_t mid;
1447 : struct tevent_req *subreq;
1448 : NTSTATUS status;
1449 :
1450 1555 : flags = CVAL(state->smb1.hdr, HDR_FLG);
1451 1555 : flags2 = SVAL(state->smb1.hdr, HDR_FLG2);
1452 1555 : pid = SVAL(state->smb1.hdr, HDR_PID);
1453 1555 : pid |= SVAL(state->smb1.hdr, HDR_PIDHIGH)<<16;
1454 1555 : mid = SVAL(state->smb1.hdr, HDR_MID);
1455 :
1456 1555 : subreq = smb1cli_req_create(state, state->ev,
1457 : state->conn,
1458 : SMBntcancel,
1459 : flags, 0,
1460 : flags2, 0,
1461 : 0, /* timeout */
1462 : pid,
1463 : state->tcon,
1464 : state->session,
1465 : 0, NULL, /* vwv */
1466 : 0, NULL); /* bytes */
1467 1555 : if (subreq == NULL) {
1468 0 : return false;
1469 : }
1470 1555 : smb1cli_req_set_mid(subreq, mid);
1471 :
1472 1555 : status = smb1cli_req_chain_submit(&subreq, 1);
1473 1555 : if (!NT_STATUS_IS_OK(status)) {
1474 0 : TALLOC_FREE(subreq);
1475 0 : return false;
1476 : }
1477 1555 : smb1cli_req_set_mid(subreq, 0);
1478 :
1479 1555 : tevent_req_set_callback(subreq, smb1cli_req_cancel_done, NULL);
1480 :
1481 1555 : return true;
1482 : }
1483 :
1484 1555 : static void smb1cli_req_cancel_done(struct tevent_req *subreq)
1485 : {
1486 : /* we do not care about the result */
1487 1555 : TALLOC_FREE(subreq);
1488 1555 : }
1489 :
1490 919694 : struct tevent_req *smb1cli_req_create(TALLOC_CTX *mem_ctx,
1491 : struct tevent_context *ev,
1492 : struct smbXcli_conn *conn,
1493 : uint8_t smb_command,
1494 : uint8_t additional_flags,
1495 : uint8_t clear_flags,
1496 : uint16_t additional_flags2,
1497 : uint16_t clear_flags2,
1498 : uint32_t timeout_msec,
1499 : uint32_t pid,
1500 : struct smbXcli_tcon *tcon,
1501 : struct smbXcli_session *session,
1502 : uint8_t wct, uint16_t *vwv,
1503 : int iov_count,
1504 : struct iovec *bytes_iov)
1505 : {
1506 : struct tevent_req *req;
1507 : struct smbXcli_req_state *state;
1508 919694 : uint8_t flags = 0;
1509 919694 : uint16_t flags2 = 0;
1510 919694 : uint16_t uid = 0;
1511 919694 : uint16_t tid = 0;
1512 : ssize_t num_bytes;
1513 :
1514 919694 : if (iov_count > MAX_SMB_IOV) {
1515 : /*
1516 : * Should not happen :-)
1517 : */
1518 0 : return NULL;
1519 : }
1520 :
1521 919694 : req = tevent_req_create(mem_ctx, &state,
1522 : struct smbXcli_req_state);
1523 919694 : if (req == NULL) {
1524 0 : return NULL;
1525 : }
1526 919694 : state->ev = ev;
1527 919694 : state->conn = conn;
1528 919694 : state->session = session;
1529 919694 : state->tcon = tcon;
1530 :
1531 919694 : if (session) {
1532 896426 : uid = session->smb1.session_id;
1533 : }
1534 :
1535 919694 : if (tcon) {
1536 882140 : tid = tcon->smb1.tcon_id;
1537 :
1538 882140 : if (tcon->fs_attributes & FILE_CASE_SENSITIVE_SEARCH) {
1539 850 : clear_flags |= FLAG_CASELESS_PATHNAMES;
1540 : } else {
1541 : /* Default setting, case insensitive. */
1542 881290 : additional_flags |= FLAG_CASELESS_PATHNAMES;
1543 : }
1544 :
1545 1763797 : if (smbXcli_conn_dfs_supported(conn) &&
1546 881657 : smbXcli_tcon_is_dfs_share(tcon))
1547 : {
1548 190 : additional_flags2 |= FLAGS2_DFS_PATHNAMES;
1549 : }
1550 : }
1551 :
1552 919694 : state->smb1.recv_cmd = 0xFF;
1553 919694 : state->smb1.recv_status = NT_STATUS_INTERNAL_ERROR;
1554 919694 : state->smb1.recv_iov = talloc_zero_array(state, struct iovec, 3);
1555 919694 : if (state->smb1.recv_iov == NULL) {
1556 0 : TALLOC_FREE(req);
1557 0 : return NULL;
1558 : }
1559 :
1560 919694 : smb1cli_req_flags(conn->protocol,
1561 : conn->smb1.capabilities,
1562 : smb_command,
1563 : additional_flags,
1564 : clear_flags,
1565 : &flags,
1566 : additional_flags2,
1567 : clear_flags2,
1568 : &flags2);
1569 :
1570 919694 : SIVAL(state->smb1.hdr, 0, SMB_MAGIC);
1571 919694 : SCVAL(state->smb1.hdr, HDR_COM, smb_command);
1572 919694 : SIVAL(state->smb1.hdr, HDR_RCLS, NT_STATUS_V(NT_STATUS_OK));
1573 919694 : SCVAL(state->smb1.hdr, HDR_FLG, flags);
1574 919694 : SSVAL(state->smb1.hdr, HDR_FLG2, flags2);
1575 919694 : SSVAL(state->smb1.hdr, HDR_PIDHIGH, pid >> 16);
1576 919694 : SSVAL(state->smb1.hdr, HDR_TID, tid);
1577 919694 : SSVAL(state->smb1.hdr, HDR_PID, pid);
1578 919694 : SSVAL(state->smb1.hdr, HDR_UID, uid);
1579 919694 : SSVAL(state->smb1.hdr, HDR_MID, 0); /* this comes later */
1580 919694 : SCVAL(state->smb1.hdr, HDR_WCT, wct);
1581 :
1582 919694 : state->smb1.vwv = vwv;
1583 :
1584 919694 : num_bytes = iov_buflen(bytes_iov, iov_count);
1585 919694 : if (num_bytes == -1) {
1586 : /*
1587 : * I'd love to add a check for num_bytes<=UINT16_MAX here, but
1588 : * the smbclient->samba connections can lie and transfer more.
1589 : */
1590 0 : TALLOC_FREE(req);
1591 0 : return NULL;
1592 : }
1593 :
1594 919694 : SSVAL(state->smb1.bytecount_buf, 0, num_bytes);
1595 :
1596 919694 : state->smb1.iov[0].iov_base = (void *)state->length_hdr;
1597 919694 : state->smb1.iov[0].iov_len = sizeof(state->length_hdr);
1598 919694 : state->smb1.iov[1].iov_base = (void *)state->smb1.hdr;
1599 919694 : state->smb1.iov[1].iov_len = sizeof(state->smb1.hdr);
1600 919694 : state->smb1.iov[2].iov_base = (void *)state->smb1.vwv;
1601 919694 : state->smb1.iov[2].iov_len = wct * sizeof(uint16_t);
1602 919694 : state->smb1.iov[3].iov_base = (void *)state->smb1.bytecount_buf;
1603 919694 : state->smb1.iov[3].iov_len = sizeof(uint16_t);
1604 :
1605 919694 : if (iov_count != 0) {
1606 906897 : memcpy(&state->smb1.iov[4], bytes_iov,
1607 : iov_count * sizeof(*bytes_iov));
1608 : }
1609 919694 : state->smb1.iov_count = iov_count + 4;
1610 :
1611 919694 : if (timeout_msec > 0) {
1612 917626 : state->endtime = timeval_current_ofs_msec(timeout_msec);
1613 917626 : if (!tevent_req_set_endtime(req, ev, state->endtime)) {
1614 0 : return req;
1615 : }
1616 : }
1617 :
1618 919694 : switch (smb_command) {
1619 0 : case SMBtranss:
1620 : case SMBtranss2:
1621 : case SMBnttranss:
1622 0 : state->one_way = true;
1623 0 : break;
1624 1555 : case SMBntcancel:
1625 1555 : state->one_way = true;
1626 1555 : state->smb1.one_way_seqnum = true;
1627 1555 : break;
1628 6916 : case SMBlockingX:
1629 13794 : if ((wct == 8) &&
1630 6916 : (CVAL(vwv+3, 0) == LOCKING_ANDX_OPLOCK_RELEASE)) {
1631 144 : state->one_way = true;
1632 : }
1633 6901 : break;
1634 : }
1635 :
1636 911481 : return req;
1637 : }
1638 :
1639 919036 : static NTSTATUS smb1cli_conn_signv(struct smbXcli_conn *conn,
1640 : struct iovec *iov, int iov_count,
1641 : uint32_t *seqnum,
1642 : bool one_way_seqnum)
1643 : {
1644 919036 : TALLOC_CTX *frame = NULL;
1645 : NTSTATUS status;
1646 : uint8_t *buf;
1647 :
1648 : /*
1649 : * Obvious optimization: Make cli_calculate_sign_mac work with struct
1650 : * iovec directly. MD5Update would do that just fine.
1651 : */
1652 :
1653 919036 : if (iov_count < 4) {
1654 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
1655 : }
1656 919036 : if (iov[0].iov_len != NBT_HDR_SIZE) {
1657 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
1658 : }
1659 919036 : if (iov[1].iov_len != (MIN_SMB_SIZE-sizeof(uint16_t))) {
1660 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
1661 : }
1662 919036 : if (iov[2].iov_len > (0xFF * sizeof(uint16_t))) {
1663 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
1664 : }
1665 919036 : if (iov[3].iov_len != sizeof(uint16_t)) {
1666 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
1667 : }
1668 :
1669 919036 : frame = talloc_stackframe();
1670 :
1671 919036 : buf = iov_concat(frame, &iov[1], iov_count - 1);
1672 919036 : if (buf == NULL) {
1673 0 : return NT_STATUS_NO_MEMORY;
1674 : }
1675 :
1676 919036 : *seqnum = smb_signing_next_seqnum(conn->smb1.signing,
1677 : one_way_seqnum);
1678 919036 : status = smb_signing_sign_pdu(conn->smb1.signing,
1679 : buf,
1680 : talloc_get_size(buf),
1681 : *seqnum);
1682 919036 : if (!NT_STATUS_IS_OK(status)) {
1683 0 : return status;
1684 : }
1685 927244 : memcpy(iov[1].iov_base, buf, iov[1].iov_len);
1686 :
1687 919036 : TALLOC_FREE(frame);
1688 919036 : return NT_STATUS_OK;
1689 : }
1690 :
1691 : static void smb1cli_req_writev_done(struct tevent_req *subreq);
1692 : static NTSTATUS smb1cli_conn_dispatch_incoming(struct smbXcli_conn *conn,
1693 : TALLOC_CTX *tmp_mem,
1694 : uint8_t *inbuf);
1695 :
1696 919128 : static NTSTATUS smb1cli_req_writev_submit(struct tevent_req *req,
1697 : struct smbXcli_req_state *state,
1698 : struct iovec *iov, int iov_count)
1699 : {
1700 : struct tevent_req *subreq;
1701 : NTSTATUS status;
1702 : uint8_t cmd;
1703 : uint16_t mid;
1704 : ssize_t nbtlen;
1705 :
1706 919128 : if (!smbXcli_conn_is_connected(state->conn)) {
1707 0 : return NT_STATUS_CONNECTION_DISCONNECTED;
1708 : }
1709 :
1710 919128 : if (state->conn->protocol > PROTOCOL_NT1) {
1711 92 : DBG_ERR("called for dialect[%s] server[%s]\n",
1712 : smb_protocol_types_string(state->conn->protocol),
1713 : smbXcli_conn_remote_name(state->conn));
1714 92 : return NT_STATUS_REVISION_MISMATCH;
1715 : }
1716 :
1717 919036 : if (iov_count < 4) {
1718 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
1719 : }
1720 919036 : if (iov[0].iov_len != NBT_HDR_SIZE) {
1721 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
1722 : }
1723 919036 : if (iov[1].iov_len != (MIN_SMB_SIZE-sizeof(uint16_t))) {
1724 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
1725 : }
1726 919036 : if (iov[2].iov_len > (0xFF * sizeof(uint16_t))) {
1727 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
1728 : }
1729 919036 : if (iov[3].iov_len != sizeof(uint16_t)) {
1730 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
1731 : }
1732 :
1733 919036 : cmd = CVAL(iov[1].iov_base, HDR_COM);
1734 919036 : if (cmd == SMBreadBraw) {
1735 60 : if (smbXcli_conn_has_async_calls(state->conn)) {
1736 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
1737 : }
1738 60 : state->conn->smb1.read_braw_req = req;
1739 : }
1740 :
1741 919036 : if (state->smb1.mid != 0) {
1742 1555 : mid = state->smb1.mid;
1743 : } else {
1744 917481 : mid = smb1cli_alloc_mid(state->conn);
1745 : }
1746 919036 : SSVAL(iov[1].iov_base, HDR_MID, mid);
1747 :
1748 919036 : nbtlen = iov_buflen(&iov[1], iov_count-1);
1749 919036 : if ((nbtlen == -1) || (nbtlen > 0x1FFFF)) {
1750 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
1751 : }
1752 :
1753 919036 : _smb_setlen_nbt(iov[0].iov_base, nbtlen);
1754 :
1755 919036 : status = smb1cli_conn_signv(state->conn, iov, iov_count,
1756 : &state->smb1.seqnum,
1757 919036 : state->smb1.one_way_seqnum);
1758 :
1759 919036 : if (!NT_STATUS_IS_OK(status)) {
1760 0 : return status;
1761 : }
1762 :
1763 : /*
1764 : * If we supported multiple encrytion contexts
1765 : * here we'd look up based on tid.
1766 : */
1767 919036 : if (common_encryption_on(state->conn->smb1.trans_enc)) {
1768 : char *buf, *enc_buf;
1769 :
1770 148326 : buf = (char *)iov_concat(talloc_tos(), iov, iov_count);
1771 148326 : if (buf == NULL) {
1772 0 : return NT_STATUS_NO_MEMORY;
1773 : }
1774 148326 : status = common_encrypt_buffer(state->conn->smb1.trans_enc,
1775 : (char *)buf, &enc_buf);
1776 148326 : TALLOC_FREE(buf);
1777 148326 : if (!NT_STATUS_IS_OK(status)) {
1778 0 : DEBUG(0, ("Error in encrypting client message: %s\n",
1779 : nt_errstr(status)));
1780 0 : return status;
1781 : }
1782 148326 : buf = (char *)talloc_memdup(state, enc_buf,
1783 : smb_len_nbt(enc_buf)+4);
1784 148326 : SAFE_FREE(enc_buf);
1785 148326 : if (buf == NULL) {
1786 0 : return NT_STATUS_NO_MEMORY;
1787 : }
1788 148326 : iov[0].iov_base = (void *)buf;
1789 148326 : iov[0].iov_len = talloc_get_size(buf);
1790 148326 : iov_count = 1;
1791 : }
1792 :
1793 919036 : if (state->conn->dispatch_incoming == NULL) {
1794 28 : state->conn->dispatch_incoming = smb1cli_conn_dispatch_incoming;
1795 : }
1796 :
1797 919036 : if (!smbXcli_req_set_pending(req)) {
1798 0 : return NT_STATUS_NO_MEMORY;
1799 : }
1800 :
1801 919036 : tevent_req_set_cancel_fn(req, smbXcli_req_cancel);
1802 :
1803 919036 : subreq = writev_send(state, state->ev, state->conn->outgoing,
1804 919036 : state->conn->sock_fd, false, iov, iov_count);
1805 919036 : if (subreq == NULL) {
1806 0 : return NT_STATUS_NO_MEMORY;
1807 : }
1808 919036 : tevent_req_set_callback(subreq, smb1cli_req_writev_done, req);
1809 919036 : state->write_req = subreq;
1810 :
1811 919036 : return NT_STATUS_OK;
1812 : }
1813 :
1814 370766 : struct tevent_req *smb1cli_req_send(TALLOC_CTX *mem_ctx,
1815 : struct tevent_context *ev,
1816 : struct smbXcli_conn *conn,
1817 : uint8_t smb_command,
1818 : uint8_t additional_flags,
1819 : uint8_t clear_flags,
1820 : uint16_t additional_flags2,
1821 : uint16_t clear_flags2,
1822 : uint32_t timeout_msec,
1823 : uint32_t pid,
1824 : struct smbXcli_tcon *tcon,
1825 : struct smbXcli_session *session,
1826 : uint8_t wct, uint16_t *vwv,
1827 : uint32_t num_bytes,
1828 : const uint8_t *bytes)
1829 : {
1830 : struct tevent_req *req;
1831 : struct iovec iov;
1832 : NTSTATUS status;
1833 :
1834 370766 : iov.iov_base = discard_const_p(void, bytes);
1835 370766 : iov.iov_len = num_bytes;
1836 :
1837 370766 : req = smb1cli_req_create(mem_ctx, ev, conn, smb_command,
1838 : additional_flags, clear_flags,
1839 : additional_flags2, clear_flags2,
1840 : timeout_msec,
1841 : pid, tcon, session,
1842 : wct, vwv, 1, &iov);
1843 370766 : if (req == NULL) {
1844 0 : return NULL;
1845 : }
1846 370766 : if (!tevent_req_is_in_progress(req)) {
1847 0 : return tevent_req_post(req, ev);
1848 : }
1849 370766 : status = smb1cli_req_chain_submit(&req, 1);
1850 370766 : if (tevent_req_nterror(req, status)) {
1851 0 : return tevent_req_post(req, ev);
1852 : }
1853 370766 : return req;
1854 : }
1855 :
1856 918942 : static void smb1cli_req_writev_done(struct tevent_req *subreq)
1857 : {
1858 888915 : struct tevent_req *req =
1859 918942 : tevent_req_callback_data(subreq,
1860 : struct tevent_req);
1861 888915 : struct smbXcli_req_state *state =
1862 918942 : tevent_req_data(req,
1863 : struct smbXcli_req_state);
1864 : ssize_t nwritten;
1865 : int err;
1866 :
1867 918942 : state->write_req = NULL;
1868 :
1869 918942 : nwritten = writev_recv(subreq, &err);
1870 918942 : TALLOC_FREE(subreq);
1871 918942 : if (nwritten == -1) {
1872 : /* here, we need to notify all pending requests */
1873 0 : NTSTATUS status = map_nt_error_from_unix_common(err);
1874 0 : smbXcli_conn_disconnect(state->conn, status);
1875 0 : return;
1876 : }
1877 :
1878 918942 : if (state->one_way) {
1879 1699 : state->inbuf = NULL;
1880 1699 : tevent_req_done(req);
1881 1699 : return;
1882 : }
1883 : }
1884 :
1885 2808642 : static void smbXcli_conn_received(struct tevent_req *subreq)
1886 : {
1887 2538368 : struct smbXcli_conn *conn =
1888 2808642 : tevent_req_callback_data(subreq,
1889 : struct smbXcli_conn);
1890 2808642 : TALLOC_CTX *frame = talloc_stackframe();
1891 : NTSTATUS status;
1892 : uint8_t *inbuf;
1893 : ssize_t received;
1894 : int err;
1895 :
1896 2808642 : if (subreq != conn->read_smb_req) {
1897 0 : DEBUG(1, ("Internal error: cli_smb_received called with "
1898 : "unexpected subreq\n"));
1899 0 : smbXcli_conn_disconnect(conn, NT_STATUS_INTERNAL_ERROR);
1900 0 : TALLOC_FREE(frame);
1901 716487 : return;
1902 : }
1903 2808642 : conn->read_smb_req = NULL;
1904 :
1905 2808642 : received = read_smb_recv(subreq, frame, &inbuf, &err);
1906 2808642 : TALLOC_FREE(subreq);
1907 2808642 : if (received == -1) {
1908 216 : status = map_nt_error_from_unix_common(err);
1909 216 : smbXcli_conn_disconnect(conn, status);
1910 216 : TALLOC_FREE(frame);
1911 216 : return;
1912 : }
1913 :
1914 2808426 : status = conn->dispatch_incoming(conn, frame, inbuf);
1915 2808426 : TALLOC_FREE(frame);
1916 2808426 : if (NT_STATUS_IS_OK(status)) {
1917 : /*
1918 : * We should not do any more processing
1919 : * as the dispatch function called
1920 : * tevent_req_done().
1921 : */
1922 732648 : return;
1923 : }
1924 :
1925 2069216 : if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
1926 : /*
1927 : * We got an error, so notify all pending requests
1928 : */
1929 8 : smbXcli_conn_disconnect(conn, status);
1930 8 : return;
1931 : }
1932 :
1933 : /*
1934 : * We got NT_STATUS_RETRY, so we may ask for a
1935 : * next incoming pdu.
1936 : */
1937 2069208 : if (!smbXcli_conn_receive_next(conn)) {
1938 0 : smbXcli_conn_disconnect(conn, NT_STATUS_NO_MEMORY);
1939 : }
1940 : }
1941 :
1942 900652 : static NTSTATUS smb1cli_inbuf_parse_chain(uint8_t *buf, TALLOC_CTX *mem_ctx,
1943 : struct iovec **piov, int *pnum_iov)
1944 : {
1945 : struct iovec *iov;
1946 : size_t num_iov;
1947 : size_t buflen;
1948 : size_t taken;
1949 : size_t remaining;
1950 : uint8_t *hdr;
1951 : uint8_t cmd;
1952 : uint32_t wct_ofs;
1953 : NTSTATUS status;
1954 900652 : size_t min_size = MIN_SMB_SIZE;
1955 :
1956 900652 : buflen = smb_len_tcp(buf);
1957 900652 : taken = 0;
1958 :
1959 900652 : hdr = buf + NBT_HDR_SIZE;
1960 :
1961 900652 : status = smb1cli_pull_raw_error(hdr);
1962 900652 : if (NT_STATUS_IS_ERR(status)) {
1963 : /*
1964 : * This is an ugly hack to support OS/2
1965 : * which skips the byte_count in the DATA block
1966 : * on some error responses.
1967 : *
1968 : * See bug #9096
1969 : */
1970 461016 : min_size -= sizeof(uint16_t);
1971 : }
1972 :
1973 900652 : if (buflen < min_size) {
1974 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
1975 : }
1976 :
1977 : /*
1978 : * This returns iovec elements in the following order:
1979 : *
1980 : * - SMB header
1981 : *
1982 : * - Parameter Block
1983 : * - Data Block
1984 : *
1985 : * - Parameter Block
1986 : * - Data Block
1987 : *
1988 : * - Parameter Block
1989 : * - Data Block
1990 : */
1991 900652 : num_iov = 1;
1992 :
1993 900652 : iov = talloc_array(mem_ctx, struct iovec, num_iov);
1994 900652 : if (iov == NULL) {
1995 0 : return NT_STATUS_NO_MEMORY;
1996 : }
1997 900652 : iov[0].iov_base = hdr;
1998 900652 : iov[0].iov_len = HDR_WCT;
1999 900652 : taken += HDR_WCT;
2000 :
2001 900652 : cmd = CVAL(hdr, HDR_COM);
2002 900652 : wct_ofs = HDR_WCT;
2003 :
2004 36 : while (true) {
2005 900690 : size_t len = buflen - taken;
2006 : struct iovec *cur;
2007 : struct iovec *iov_tmp;
2008 : uint8_t wct;
2009 : uint32_t bcc_ofs;
2010 : uint16_t bcc;
2011 : size_t needed;
2012 :
2013 : /*
2014 : * we need at least WCT
2015 : */
2016 900690 : needed = sizeof(uint8_t);
2017 900690 : if (len < needed) {
2018 0 : DEBUG(10, ("%s: %d bytes left, expected at least %d\n",
2019 : __location__, (int)len, (int)needed));
2020 0 : goto inval;
2021 : }
2022 :
2023 : /*
2024 : * Now we check if the specified words are there
2025 : */
2026 900690 : wct = CVAL(hdr, wct_ofs);
2027 900690 : needed += wct * sizeof(uint16_t);
2028 900690 : if (len < needed) {
2029 0 : DEBUG(10, ("%s: %d bytes left, expected at least %d\n",
2030 : __location__, (int)len, (int)needed));
2031 0 : goto inval;
2032 : }
2033 :
2034 908510 : if ((num_iov == 1) &&
2035 7820 : (len == needed) &&
2036 0 : NT_STATUS_IS_ERR(status))
2037 : {
2038 : /*
2039 : * This is an ugly hack to support OS/2
2040 : * which skips the byte_count in the DATA block
2041 : * on some error responses.
2042 : *
2043 : * See bug #9096
2044 : */
2045 0 : iov_tmp = talloc_realloc(mem_ctx, iov, struct iovec,
2046 : num_iov + 2);
2047 0 : if (iov_tmp == NULL) {
2048 0 : TALLOC_FREE(iov);
2049 0 : return NT_STATUS_NO_MEMORY;
2050 : }
2051 0 : iov = iov_tmp;
2052 0 : cur = &iov[num_iov];
2053 0 : num_iov += 2;
2054 :
2055 0 : cur[0].iov_len = 0;
2056 0 : cur[0].iov_base = hdr + (wct_ofs + sizeof(uint8_t));
2057 0 : cur[1].iov_len = 0;
2058 0 : cur[1].iov_base = cur[0].iov_base;
2059 :
2060 0 : taken += needed;
2061 0 : break;
2062 : }
2063 :
2064 : /*
2065 : * we need at least BCC
2066 : */
2067 900690 : needed += sizeof(uint16_t);
2068 900690 : if (len < needed) {
2069 0 : DEBUG(10, ("%s: %d bytes left, expected at least %d\n",
2070 : __location__, (int)len, (int)needed));
2071 0 : goto inval;
2072 : }
2073 :
2074 : /*
2075 : * Now we check if the specified bytes are there
2076 : */
2077 900690 : bcc_ofs = wct_ofs + sizeof(uint8_t) + wct * sizeof(uint16_t);
2078 900690 : bcc = SVAL(hdr, bcc_ofs);
2079 900690 : needed += bcc * sizeof(uint8_t);
2080 900690 : if (len < needed) {
2081 0 : DEBUG(10, ("%s: %d bytes left, expected at least %d\n",
2082 : __location__, (int)len, (int)needed));
2083 0 : goto inval;
2084 : }
2085 :
2086 : /*
2087 : * we allocate 2 iovec structures for words and bytes
2088 : */
2089 900690 : iov_tmp = talloc_realloc(mem_ctx, iov, struct iovec,
2090 : num_iov + 2);
2091 900690 : if (iov_tmp == NULL) {
2092 0 : TALLOC_FREE(iov);
2093 0 : return NT_STATUS_NO_MEMORY;
2094 : }
2095 900690 : iov = iov_tmp;
2096 900690 : cur = &iov[num_iov];
2097 900690 : num_iov += 2;
2098 :
2099 900690 : cur[0].iov_len = wct * sizeof(uint16_t);
2100 900690 : cur[0].iov_base = hdr + (wct_ofs + sizeof(uint8_t));
2101 900690 : cur[1].iov_len = bcc * sizeof(uint8_t);
2102 900690 : cur[1].iov_base = hdr + (bcc_ofs + sizeof(uint16_t));
2103 :
2104 900690 : taken += needed;
2105 :
2106 900690 : if (!smb1cli_is_andx_req(cmd)) {
2107 : /*
2108 : * If the current command does not have AndX chanining
2109 : * we are done.
2110 : */
2111 648913 : break;
2112 : }
2113 :
2114 244960 : if (wct == 0 && bcc == 0) {
2115 : /*
2116 : * An empty response also ends the chain,
2117 : * most likely with an error.
2118 : */
2119 46364 : break;
2120 : }
2121 :
2122 198229 : if (wct < 2) {
2123 0 : DEBUG(10, ("%s: wct[%d] < 2 for cmd[0x%02X]\n",
2124 : __location__, (int)wct, (int)cmd));
2125 0 : goto inval;
2126 : }
2127 198229 : cmd = CVAL(cur[0].iov_base, 0);
2128 198229 : if (cmd == 0xFF) {
2129 : /*
2130 : * If it is the end of the chain we are also done.
2131 : */
2132 197557 : break;
2133 : }
2134 38 : wct_ofs = SVAL(cur[0].iov_base, 2);
2135 :
2136 38 : if (wct_ofs < taken) {
2137 0 : goto inval;
2138 : }
2139 38 : if (wct_ofs > buflen) {
2140 0 : goto inval;
2141 : }
2142 :
2143 : /*
2144 : * we consumed everything up to the start of the next
2145 : * parameter block.
2146 : */
2147 36 : taken = wct_ofs;
2148 : }
2149 :
2150 900652 : remaining = buflen - taken;
2151 :
2152 900652 : if (remaining > 0 && num_iov >= 3) {
2153 : /*
2154 : * The last DATA block gets the remaining
2155 : * bytes, this is needed to support
2156 : * CAP_LARGE_WRITEX and CAP_LARGE_READX.
2157 : */
2158 962 : iov[num_iov-1].iov_len += remaining;
2159 : }
2160 :
2161 900652 : *piov = iov;
2162 900652 : *pnum_iov = num_iov;
2163 900652 : return NT_STATUS_OK;
2164 :
2165 0 : inval:
2166 0 : TALLOC_FREE(iov);
2167 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
2168 : }
2169 :
2170 900728 : static NTSTATUS smb1cli_conn_dispatch_incoming(struct smbXcli_conn *conn,
2171 : TALLOC_CTX *tmp_mem,
2172 : uint8_t *inbuf)
2173 : {
2174 : struct tevent_req *req;
2175 : struct smbXcli_req_state *state;
2176 : NTSTATUS status;
2177 : size_t num_pending;
2178 : size_t i;
2179 : uint8_t cmd;
2180 : uint16_t mid;
2181 : bool oplock_break;
2182 900728 : uint8_t *inhdr = inbuf + NBT_HDR_SIZE;
2183 900728 : size_t len = smb_len_tcp(inbuf);
2184 900728 : struct iovec *iov = NULL;
2185 900728 : int num_iov = 0;
2186 900728 : struct tevent_req **chain = NULL;
2187 900728 : size_t num_chained = 0;
2188 900728 : size_t num_responses = 0;
2189 :
2190 900728 : if (conn->smb1.read_braw_req != NULL) {
2191 60 : req = conn->smb1.read_braw_req;
2192 60 : conn->smb1.read_braw_req = NULL;
2193 60 : state = tevent_req_data(req, struct smbXcli_req_state);
2194 :
2195 60 : smbXcli_req_unset_pending(req);
2196 :
2197 60 : if (state->smb1.recv_iov == NULL) {
2198 : /*
2199 : * For requests with more than
2200 : * one response, we have to readd the
2201 : * recv_iov array.
2202 : */
2203 0 : state->smb1.recv_iov = talloc_zero_array(state,
2204 : struct iovec,
2205 : 3);
2206 0 : if (tevent_req_nomem(state->smb1.recv_iov, req)) {
2207 0 : return NT_STATUS_OK;
2208 : }
2209 : }
2210 :
2211 60 : state->smb1.recv_iov[0].iov_base = (void *)(inhdr);
2212 60 : state->smb1.recv_iov[0].iov_len = len;
2213 60 : ZERO_STRUCT(state->smb1.recv_iov[1]);
2214 60 : ZERO_STRUCT(state->smb1.recv_iov[2]);
2215 :
2216 60 : state->smb1.recv_cmd = SMBreadBraw;
2217 60 : state->smb1.recv_status = NT_STATUS_OK;
2218 60 : state->inbuf = talloc_move(state->smb1.recv_iov, &inbuf);
2219 :
2220 60 : tevent_req_done(req);
2221 60 : return NT_STATUS_OK;
2222 : }
2223 :
2224 900668 : if ((IVAL(inhdr, 0) != SMB_MAGIC) /* 0xFF"SMB" */
2225 148330 : && (SVAL(inhdr, 0) != 0x45ff)) /* 0xFF"E" */ {
2226 0 : DEBUG(10, ("Got non-SMB PDU\n"));
2227 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
2228 : }
2229 :
2230 : /*
2231 : * If we supported multiple encrytion contexts
2232 : * here we'd look up based on tid.
2233 : */
2234 900668 : if (common_encryption_on(conn->smb1.trans_enc)
2235 148330 : && (CVAL(inbuf, 0) == 0)) {
2236 : uint16_t enc_ctx_num;
2237 :
2238 148330 : status = get_enc_ctx_num(inbuf, &enc_ctx_num);
2239 148330 : if (!NT_STATUS_IS_OK(status)) {
2240 0 : DEBUG(10, ("get_enc_ctx_num returned %s\n",
2241 : nt_errstr(status)));
2242 0 : return status;
2243 : }
2244 :
2245 148330 : if (enc_ctx_num != conn->smb1.trans_enc->enc_ctx_num) {
2246 0 : DEBUG(10, ("wrong enc_ctx %d, expected %d\n",
2247 : enc_ctx_num,
2248 : conn->smb1.trans_enc->enc_ctx_num));
2249 0 : return NT_STATUS_INVALID_HANDLE;
2250 : }
2251 :
2252 148330 : status = common_decrypt_buffer(conn->smb1.trans_enc,
2253 : (char *)inbuf);
2254 148330 : if (!NT_STATUS_IS_OK(status)) {
2255 0 : DEBUG(10, ("common_decrypt_buffer returned %s\n",
2256 : nt_errstr(status)));
2257 0 : return status;
2258 : }
2259 148330 : inhdr = inbuf + NBT_HDR_SIZE;
2260 148330 : len = smb_len_nbt(inbuf);
2261 : }
2262 :
2263 900668 : mid = SVAL(inhdr, HDR_MID);
2264 900668 : num_pending = talloc_array_length(conn->pending);
2265 :
2266 972342 : for (i=0; i<num_pending; i++) {
2267 972328 : if (mid == smb1cli_req_mid(conn->pending[i])) {
2268 892836 : break;
2269 : }
2270 : }
2271 900668 : if (i == num_pending) {
2272 : /* Dump unexpected reply */
2273 14 : return NT_STATUS_RETRY;
2274 : }
2275 :
2276 900654 : oplock_break = false;
2277 :
2278 900654 : if (mid == 0xffff) {
2279 : /*
2280 : * Paranoia checks that this is really an oplock break request.
2281 : */
2282 168 : oplock_break = (len == 51); /* hdr + 8 words */
2283 168 : oplock_break &= ((CVAL(inhdr, HDR_FLG) & FLAG_REPLY) == 0);
2284 168 : oplock_break &= (CVAL(inhdr, HDR_COM) == SMBlockingX);
2285 168 : oplock_break &= (SVAL(inhdr, HDR_VWV+VWV(6)) == 0);
2286 168 : oplock_break &= (SVAL(inhdr, HDR_VWV+VWV(7)) == 0);
2287 :
2288 168 : if (!oplock_break) {
2289 : /* Dump unexpected reply */
2290 0 : return NT_STATUS_RETRY;
2291 : }
2292 : }
2293 :
2294 900654 : req = conn->pending[i];
2295 900654 : state = tevent_req_data(req, struct smbXcli_req_state);
2296 :
2297 900654 : if (!oplock_break /* oplock breaks are not signed */
2298 900486 : && !smb_signing_check_pdu(conn->smb1.signing,
2299 900486 : inhdr, len, state->smb1.seqnum+1)) {
2300 2 : DEBUG(10, ("cli_check_sign_mac failed\n"));
2301 2 : return NT_STATUS_ACCESS_DENIED;
2302 : }
2303 :
2304 900652 : status = smb1cli_inbuf_parse_chain(inbuf, tmp_mem,
2305 : &iov, &num_iov);
2306 900652 : if (!NT_STATUS_IS_OK(status)) {
2307 0 : DEBUG(10,("smb1cli_inbuf_parse_chain - %s\n",
2308 : nt_errstr(status)));
2309 0 : return status;
2310 : }
2311 :
2312 900652 : cmd = CVAL(inhdr, HDR_COM);
2313 900652 : status = smb1cli_pull_raw_error(inhdr);
2314 :
2315 900654 : if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED) &&
2316 6 : (state->session != NULL) && state->session->disconnect_expired)
2317 : {
2318 : /*
2319 : * this should be a short term hack
2320 : * until the upper layers have implemented
2321 : * re-authentication.
2322 : */
2323 0 : return status;
2324 : }
2325 :
2326 900652 : if (state->smb1.chained_requests == NULL) {
2327 900609 : if (num_iov != 3) {
2328 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
2329 : }
2330 :
2331 900609 : smbXcli_req_unset_pending(req);
2332 :
2333 900609 : if (state->smb1.recv_iov == NULL) {
2334 : /*
2335 : * For requests with more than
2336 : * one response, we have to readd the
2337 : * recv_iov array.
2338 : */
2339 18 : state->smb1.recv_iov = talloc_zero_array(state,
2340 : struct iovec,
2341 : 3);
2342 18 : if (tevent_req_nomem(state->smb1.recv_iov, req)) {
2343 0 : return NT_STATUS_OK;
2344 : }
2345 : }
2346 :
2347 900609 : state->smb1.recv_cmd = cmd;
2348 900609 : state->smb1.recv_status = status;
2349 900609 : state->inbuf = talloc_move(state->smb1.recv_iov, &inbuf);
2350 :
2351 900609 : state->smb1.recv_iov[0] = iov[0];
2352 900609 : state->smb1.recv_iov[1] = iov[1];
2353 900609 : state->smb1.recv_iov[2] = iov[2];
2354 :
2355 900609 : if (talloc_array_length(conn->pending) == 0) {
2356 739150 : tevent_req_done(req);
2357 739150 : return NT_STATUS_OK;
2358 : }
2359 :
2360 161459 : tevent_req_defer_callback(req, state->ev);
2361 161459 : tevent_req_done(req);
2362 161459 : return NT_STATUS_RETRY;
2363 : }
2364 :
2365 43 : chain = talloc_move(tmp_mem, &state->smb1.chained_requests);
2366 43 : num_chained = talloc_array_length(chain);
2367 43 : num_responses = (num_iov - 1)/2;
2368 :
2369 43 : if (num_responses > num_chained) {
2370 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
2371 : }
2372 :
2373 136 : for (i=0; i<num_chained; i++) {
2374 96 : size_t iov_idx = 1 + (i*2);
2375 96 : struct iovec *cur = &iov[iov_idx];
2376 : uint8_t *inbuf_ref;
2377 :
2378 96 : req = chain[i];
2379 96 : state = tevent_req_data(req, struct smbXcli_req_state);
2380 :
2381 96 : smbXcli_req_unset_pending(req);
2382 :
2383 : /*
2384 : * as we finish multiple requests here
2385 : * we need to defer the callbacks as
2386 : * they could destroy our current stack state.
2387 : */
2388 96 : tevent_req_defer_callback(req, state->ev);
2389 :
2390 96 : if (i >= num_responses) {
2391 15 : tevent_req_nterror(req, NT_STATUS_REQUEST_ABORTED);
2392 15 : continue;
2393 : }
2394 :
2395 81 : if (state->smb1.recv_iov == NULL) {
2396 : /*
2397 : * For requests with more than
2398 : * one response, we have to readd the
2399 : * recv_iov array.
2400 : */
2401 0 : state->smb1.recv_iov = talloc_zero_array(state,
2402 : struct iovec,
2403 : 3);
2404 0 : if (tevent_req_nomem(state->smb1.recv_iov, req)) {
2405 0 : continue;
2406 : }
2407 : }
2408 :
2409 81 : state->smb1.recv_cmd = cmd;
2410 :
2411 81 : if (i == (num_responses - 1)) {
2412 : /*
2413 : * The last request in the chain gets the status
2414 : */
2415 43 : state->smb1.recv_status = status;
2416 : } else {
2417 38 : cmd = CVAL(cur[0].iov_base, 0);
2418 38 : state->smb1.recv_status = NT_STATUS_OK;
2419 : }
2420 :
2421 81 : state->inbuf = inbuf;
2422 :
2423 : /*
2424 : * Note: here we use talloc_reference() in a way
2425 : * that does not expose it to the caller.
2426 : */
2427 81 : inbuf_ref = talloc_reference(state->smb1.recv_iov, inbuf);
2428 81 : if (tevent_req_nomem(inbuf_ref, req)) {
2429 0 : continue;
2430 : }
2431 :
2432 : /* copy the related buffers */
2433 81 : state->smb1.recv_iov[0] = iov[0];
2434 81 : state->smb1.recv_iov[1] = cur[0];
2435 81 : state->smb1.recv_iov[2] = cur[1];
2436 :
2437 81 : tevent_req_done(req);
2438 : }
2439 :
2440 43 : return NT_STATUS_RETRY;
2441 : }
2442 :
2443 901502 : NTSTATUS smb1cli_req_recv(struct tevent_req *req,
2444 : TALLOC_CTX *mem_ctx,
2445 : struct iovec **piov,
2446 : uint8_t **phdr,
2447 : uint8_t *pwct,
2448 : uint16_t **pvwv,
2449 : uint32_t *pvwv_offset,
2450 : uint32_t *pnum_bytes,
2451 : uint8_t **pbytes,
2452 : uint32_t *pbytes_offset,
2453 : uint8_t **pinbuf,
2454 : const struct smb1cli_req_expected_response *expected,
2455 : size_t num_expected)
2456 : {
2457 873413 : struct smbXcli_req_state *state =
2458 901502 : tevent_req_data(req,
2459 : struct smbXcli_req_state);
2460 901502 : NTSTATUS status = NT_STATUS_OK;
2461 901502 : struct iovec *recv_iov = NULL;
2462 901502 : uint8_t *hdr = NULL;
2463 901502 : uint8_t wct = 0;
2464 901502 : uint32_t vwv_offset = 0;
2465 901502 : uint16_t *vwv = NULL;
2466 901502 : uint32_t num_bytes = 0;
2467 901502 : uint32_t bytes_offset = 0;
2468 901502 : uint8_t *bytes = NULL;
2469 : size_t i;
2470 901502 : bool found_status = false;
2471 901502 : bool found_size = false;
2472 :
2473 901502 : if (piov != NULL) {
2474 901271 : *piov = NULL;
2475 : }
2476 901502 : if (phdr != NULL) {
2477 526403 : *phdr = 0;
2478 : }
2479 901502 : if (pwct != NULL) {
2480 901100 : *pwct = 0;
2481 : }
2482 901502 : if (pvwv != NULL) {
2483 901254 : *pvwv = NULL;
2484 : }
2485 901502 : if (pvwv_offset != NULL) {
2486 88897 : *pvwv_offset = 0;
2487 : }
2488 901502 : if (pnum_bytes != NULL) {
2489 900740 : *pnum_bytes = 0;
2490 : }
2491 901502 : if (pbytes != NULL) {
2492 900740 : *pbytes = NULL;
2493 : }
2494 901502 : if (pbytes_offset != NULL) {
2495 88925 : *pbytes_offset = 0;
2496 : }
2497 901502 : if (pinbuf != NULL) {
2498 804948 : *pinbuf = NULL;
2499 : }
2500 :
2501 901502 : if (state->inbuf != NULL) {
2502 900750 : recv_iov = state->smb1.recv_iov;
2503 900750 : state->smb1.recv_iov = NULL;
2504 900750 : if (state->smb1.recv_cmd != SMBreadBraw) {
2505 900690 : hdr = (uint8_t *)recv_iov[0].iov_base;
2506 900690 : wct = recv_iov[1].iov_len/2;
2507 900690 : vwv = (uint16_t *)recv_iov[1].iov_base;
2508 900690 : vwv_offset = PTR_DIFF(vwv, hdr);
2509 900690 : num_bytes = recv_iov[2].iov_len;
2510 900690 : bytes = (uint8_t *)recv_iov[2].iov_base;
2511 900690 : bytes_offset = PTR_DIFF(bytes, hdr);
2512 : }
2513 : }
2514 :
2515 901502 : if (tevent_req_is_nterror(req, &status)) {
2516 2390 : for (i=0; i < num_expected; i++) {
2517 1782 : if (NT_STATUS_EQUAL(status, expected[i].status)) {
2518 0 : found_status = true;
2519 0 : break;
2520 : }
2521 : }
2522 :
2523 608 : if (found_status) {
2524 0 : return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2525 : }
2526 :
2527 608 : return status;
2528 : }
2529 :
2530 900894 : if (num_expected == 0) {
2531 887896 : found_status = true;
2532 887896 : found_size = true;
2533 : }
2534 :
2535 900894 : status = state->smb1.recv_status;
2536 :
2537 904816 : for (i=0; i < num_expected; i++) {
2538 16864 : if (!NT_STATUS_EQUAL(status, expected[i].status)) {
2539 3028 : continue;
2540 : }
2541 :
2542 13836 : found_status = true;
2543 13836 : if (expected[i].wct == 0) {
2544 212 : found_size = true;
2545 212 : break;
2546 : }
2547 :
2548 13624 : if (expected[i].wct == wct) {
2549 12590 : found_size = true;
2550 12590 : break;
2551 : }
2552 : }
2553 :
2554 900894 : if (!found_status) {
2555 56 : return status;
2556 : }
2557 :
2558 900838 : if (!found_size) {
2559 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
2560 : }
2561 :
2562 900838 : if (piov != NULL) {
2563 900626 : *piov = talloc_move(mem_ctx, &recv_iov);
2564 : }
2565 :
2566 900838 : if (phdr != NULL) {
2567 525767 : *phdr = hdr;
2568 : }
2569 900838 : if (pwct != NULL) {
2570 900455 : *pwct = wct;
2571 : }
2572 900838 : if (pvwv != NULL) {
2573 900609 : *pvwv = vwv;
2574 : }
2575 900838 : if (pvwv_offset != NULL) {
2576 88894 : *pvwv_offset = vwv_offset;
2577 : }
2578 900838 : if (pnum_bytes != NULL) {
2579 900095 : *pnum_bytes = num_bytes;
2580 : }
2581 900838 : if (pbytes != NULL) {
2582 900095 : *pbytes = bytes;
2583 : }
2584 900838 : if (pbytes_offset != NULL) {
2585 88922 : *pbytes_offset = bytes_offset;
2586 : }
2587 900838 : if (pinbuf != NULL) {
2588 804900 : *pinbuf = state->inbuf;
2589 : }
2590 :
2591 900838 : return status;
2592 : }
2593 :
2594 22700 : size_t smb1cli_req_wct_ofs(struct tevent_req **reqs, int num_reqs)
2595 : {
2596 : size_t wct_ofs;
2597 : int i;
2598 :
2599 22700 : wct_ofs = HDR_WCT;
2600 :
2601 22738 : for (i=0; i<num_reqs; i++) {
2602 : struct smbXcli_req_state *state;
2603 38 : state = tevent_req_data(reqs[i], struct smbXcli_req_state);
2604 44 : wct_ofs += smbXcli_iov_len(state->smb1.iov+2,
2605 38 : state->smb1.iov_count-2);
2606 38 : wct_ofs = (wct_ofs + 3) & ~3;
2607 : }
2608 22700 : return wct_ofs;
2609 : }
2610 :
2611 919128 : NTSTATUS smb1cli_req_chain_submit(struct tevent_req **reqs, int num_reqs)
2612 : {
2613 889076 : struct smbXcli_req_state *first_state =
2614 919128 : tevent_req_data(reqs[0],
2615 : struct smbXcli_req_state);
2616 : struct smbXcli_req_state *state;
2617 : size_t wct_offset;
2618 919128 : size_t chain_padding = 0;
2619 : int i, iovlen;
2620 919128 : struct iovec *iov = NULL;
2621 : struct iovec *this_iov;
2622 : NTSTATUS status;
2623 : ssize_t nbt_len;
2624 :
2625 919128 : if (num_reqs == 1) {
2626 1808121 : return smb1cli_req_writev_submit(reqs[0], first_state,
2627 919085 : first_state->smb1.iov,
2628 : first_state->smb1.iov_count);
2629 : }
2630 :
2631 40 : iovlen = 0;
2632 136 : for (i=0; i<num_reqs; i++) {
2633 96 : if (!tevent_req_is_in_progress(reqs[i])) {
2634 0 : return NT_STATUS_INTERNAL_ERROR;
2635 : }
2636 :
2637 96 : state = tevent_req_data(reqs[i], struct smbXcli_req_state);
2638 :
2639 96 : if (state->smb1.iov_count < 4) {
2640 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
2641 : }
2642 :
2643 96 : if (i == 0) {
2644 : /*
2645 : * The NBT and SMB header
2646 : */
2647 43 : iovlen += 2;
2648 : } else {
2649 : /*
2650 : * Chain padding
2651 : */
2652 53 : iovlen += 1;
2653 : }
2654 :
2655 : /*
2656 : * words and bytes
2657 : */
2658 96 : iovlen += state->smb1.iov_count - 2;
2659 : }
2660 :
2661 43 : iov = talloc_zero_array(first_state, struct iovec, iovlen);
2662 43 : if (iov == NULL) {
2663 0 : return NT_STATUS_NO_MEMORY;
2664 : }
2665 :
2666 43 : first_state->smb1.chained_requests = (struct tevent_req **)talloc_memdup(
2667 : first_state, reqs, sizeof(*reqs) * num_reqs);
2668 43 : if (first_state->smb1.chained_requests == NULL) {
2669 0 : TALLOC_FREE(iov);
2670 0 : return NT_STATUS_NO_MEMORY;
2671 : }
2672 :
2673 40 : wct_offset = HDR_WCT;
2674 40 : this_iov = iov;
2675 :
2676 136 : for (i=0; i<num_reqs; i++) {
2677 96 : size_t next_padding = 0;
2678 : uint16_t *vwv;
2679 :
2680 96 : state = tevent_req_data(reqs[i], struct smbXcli_req_state);
2681 :
2682 96 : if (i < num_reqs-1) {
2683 53 : if (!smb1cli_is_andx_req(CVAL(state->smb1.hdr, HDR_COM))
2684 53 : || CVAL(state->smb1.hdr, HDR_WCT) < 2) {
2685 0 : TALLOC_FREE(iov);
2686 0 : TALLOC_FREE(first_state->smb1.chained_requests);
2687 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
2688 : }
2689 : }
2690 :
2691 198 : wct_offset += smbXcli_iov_len(state->smb1.iov+2,
2692 186 : state->smb1.iov_count-2) + 1;
2693 96 : if ((wct_offset % 4) != 0) {
2694 75 : next_padding = 4 - (wct_offset % 4);
2695 : }
2696 96 : wct_offset += next_padding;
2697 96 : vwv = state->smb1.vwv;
2698 :
2699 96 : if (i < num_reqs-1) {
2700 50 : struct smbXcli_req_state *next_state =
2701 53 : tevent_req_data(reqs[i+1],
2702 : struct smbXcli_req_state);
2703 53 : SCVAL(vwv+0, 0, CVAL(next_state->smb1.hdr, HDR_COM));
2704 53 : SCVAL(vwv+0, 1, 0);
2705 53 : SSVAL(vwv+1, 0, wct_offset);
2706 43 : } else if (smb1cli_is_andx_req(CVAL(state->smb1.hdr, HDR_COM))) {
2707 : /* properly end the chain */
2708 33 : SCVAL(vwv+0, 0, 0xff);
2709 33 : SCVAL(vwv+0, 1, 0xff);
2710 33 : SSVAL(vwv+1, 0, 0);
2711 : }
2712 :
2713 96 : if (i == 0) {
2714 : /*
2715 : * The NBT and SMB header
2716 : */
2717 43 : this_iov[0] = state->smb1.iov[0];
2718 43 : this_iov[1] = state->smb1.iov[1];
2719 43 : this_iov += 2;
2720 : } else {
2721 : /*
2722 : * This one is a bit subtle. We have to add
2723 : * chain_padding bytes between the requests, and we
2724 : * have to also include the wct field of the
2725 : * subsequent requests. We use the subsequent header
2726 : * for the padding, it contains the wct field in its
2727 : * last byte.
2728 : */
2729 53 : this_iov[0].iov_len = chain_padding+1;
2730 53 : this_iov[0].iov_base = (void *)&state->smb1.hdr[
2731 53 : sizeof(state->smb1.hdr) - this_iov[0].iov_len];
2732 56 : memset(this_iov[0].iov_base, 0, this_iov[0].iov_len-1);
2733 53 : this_iov += 1;
2734 : }
2735 :
2736 : /*
2737 : * copy the words and bytes
2738 : */
2739 102 : memcpy(this_iov, state->smb1.iov+2,
2740 96 : sizeof(struct iovec) * (state->smb1.iov_count-2));
2741 96 : this_iov += state->smb1.iov_count - 2;
2742 96 : chain_padding = next_padding;
2743 : }
2744 :
2745 43 : nbt_len = iov_buflen(&iov[1], iovlen-1);
2746 43 : if ((nbt_len == -1) || (nbt_len > first_state->conn->smb1.max_xmit)) {
2747 0 : TALLOC_FREE(iov);
2748 0 : TALLOC_FREE(first_state->smb1.chained_requests);
2749 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
2750 : }
2751 :
2752 43 : status = smb1cli_req_writev_submit(reqs[0], first_state, iov, iovlen);
2753 43 : if (!NT_STATUS_IS_OK(status)) {
2754 0 : TALLOC_FREE(iov);
2755 0 : TALLOC_FREE(first_state->smb1.chained_requests);
2756 0 : return status;
2757 : }
2758 :
2759 43 : return NT_STATUS_OK;
2760 : }
2761 :
2762 42 : struct tevent_queue *smbXcli_conn_send_queue(struct smbXcli_conn *conn)
2763 : {
2764 42 : return conn->outgoing;
2765 : }
2766 :
2767 531629 : bool smbXcli_conn_has_async_calls(struct smbXcli_conn *conn)
2768 : {
2769 531629 : return ((tevent_queue_length(conn->outgoing) != 0)
2770 531629 : || (talloc_array_length(conn->pending) != 0));
2771 : }
2772 :
2773 950345 : bool smbXcli_conn_dfs_supported(struct smbXcli_conn *conn)
2774 : {
2775 950345 : if (conn->protocol >= PROTOCOL_SMB2_02) {
2776 65792 : return (smb2cli_conn_server_capabilities(conn) & SMB2_CAP_DFS);
2777 : }
2778 :
2779 884553 : return (smb1cli_conn_capabilities(conn) & CAP_DFS);
2780 : }
2781 :
2782 16194 : bool smb2cli_conn_req_possible(struct smbXcli_conn *conn, uint32_t *max_dyn_len)
2783 : {
2784 16194 : uint16_t credits = 1;
2785 :
2786 16194 : if (conn->smb2.cur_credits == 0) {
2787 0 : if (max_dyn_len != NULL) {
2788 0 : *max_dyn_len = 0;
2789 : }
2790 0 : return false;
2791 : }
2792 :
2793 16194 : if (conn->smb2.server.capabilities & SMB2_CAP_LARGE_MTU) {
2794 14990 : credits = conn->smb2.cur_credits;
2795 : }
2796 :
2797 16194 : if (max_dyn_len != NULL) {
2798 16194 : *max_dyn_len = credits * 65536;
2799 : }
2800 :
2801 16194 : return true;
2802 : }
2803 :
2804 66369 : uint32_t smb2cli_conn_server_capabilities(struct smbXcli_conn *conn)
2805 : {
2806 66369 : return conn->smb2.server.capabilities;
2807 : }
2808 :
2809 0 : uint16_t smb2cli_conn_server_security_mode(struct smbXcli_conn *conn)
2810 : {
2811 0 : return conn->smb2.server.security_mode;
2812 : }
2813 :
2814 336 : uint16_t smb2cli_conn_server_signing_algo(struct smbXcli_conn *conn)
2815 : {
2816 336 : return conn->smb2.server.sign_algo;
2817 : }
2818 :
2819 0 : uint16_t smb2cli_conn_server_encryption_algo(struct smbXcli_conn *conn)
2820 : {
2821 0 : return conn->smb2.server.cipher;
2822 : }
2823 :
2824 11373 : uint32_t smb2cli_conn_max_trans_size(struct smbXcli_conn *conn)
2825 : {
2826 11373 : return conn->smb2.server.max_trans_size;
2827 : }
2828 :
2829 1907 : uint32_t smb2cli_conn_max_read_size(struct smbXcli_conn *conn)
2830 : {
2831 1907 : return conn->smb2.server.max_read_size;
2832 : }
2833 :
2834 2205 : uint32_t smb2cli_conn_max_write_size(struct smbXcli_conn *conn)
2835 : {
2836 2205 : return conn->smb2.server.max_write_size;
2837 : }
2838 :
2839 11619 : void smb2cli_conn_set_max_credits(struct smbXcli_conn *conn,
2840 : uint16_t max_credits)
2841 : {
2842 11619 : conn->smb2.max_credits = max_credits;
2843 11619 : }
2844 :
2845 20 : uint16_t smb2cli_conn_get_cur_credits(struct smbXcli_conn *conn)
2846 : {
2847 20 : return conn->smb2.cur_credits;
2848 : }
2849 :
2850 0 : uint8_t smb2cli_conn_get_io_priority(struct smbXcli_conn *conn)
2851 : {
2852 0 : if (conn->protocol < PROTOCOL_SMB3_11) {
2853 0 : return 0;
2854 : }
2855 :
2856 0 : return conn->smb2.io_priority;
2857 : }
2858 :
2859 0 : void smb2cli_conn_set_io_priority(struct smbXcli_conn *conn,
2860 : uint8_t io_priority)
2861 : {
2862 0 : conn->smb2.io_priority = io_priority;
2863 0 : }
2864 :
2865 0 : uint32_t smb2cli_conn_cc_chunk_len(struct smbXcli_conn *conn)
2866 : {
2867 0 : return conn->smb2.cc_chunk_len;
2868 : }
2869 :
2870 0 : void smb2cli_conn_set_cc_chunk_len(struct smbXcli_conn *conn,
2871 : uint32_t chunk_len)
2872 : {
2873 0 : conn->smb2.cc_chunk_len = chunk_len;
2874 0 : }
2875 :
2876 0 : uint32_t smb2cli_conn_cc_max_chunks(struct smbXcli_conn *conn)
2877 : {
2878 0 : return conn->smb2.cc_max_chunks;
2879 : }
2880 :
2881 0 : void smb2cli_conn_set_cc_max_chunks(struct smbXcli_conn *conn,
2882 : uint32_t max_chunks)
2883 : {
2884 0 : conn->smb2.cc_max_chunks = max_chunks;
2885 0 : }
2886 :
2887 : static void smb2cli_req_cancel_done(struct tevent_req *subreq);
2888 :
2889 1604 : static bool smb2cli_req_cancel(struct tevent_req *req)
2890 : {
2891 1577 : struct smbXcli_req_state *state =
2892 1604 : tevent_req_data(req,
2893 : struct smbXcli_req_state);
2894 1604 : struct smbXcli_tcon *tcon = state->tcon;
2895 1604 : struct smbXcli_session *session = state->session;
2896 1604 : uint8_t *fixed = state->smb2.pad;
2897 1604 : uint16_t fixed_len = 4;
2898 : struct tevent_req *subreq;
2899 : struct smbXcli_req_state *substate;
2900 : NTSTATUS status;
2901 :
2902 1604 : if (state->smb2.cancel_mid == UINT64_MAX) {
2903 : /*
2904 : * We already send a cancel,
2905 : * make sure we don't do it
2906 : * twice, otherwise we may
2907 : * expose the same NONCE for
2908 : * AES-128-GMAC signing
2909 : */
2910 0 : return true;
2911 : }
2912 :
2913 1604 : SSVAL(fixed, 0, 0x04);
2914 1604 : SSVAL(fixed, 2, 0);
2915 :
2916 1604 : subreq = smb2cli_req_create(state, state->ev,
2917 : state->conn,
2918 : SMB2_OP_CANCEL,
2919 : 0, 0, /* flags */
2920 : 0, /* timeout */
2921 : tcon, session,
2922 : fixed, fixed_len,
2923 : NULL, 0, 0);
2924 1604 : if (subreq == NULL) {
2925 0 : return false;
2926 : }
2927 1604 : substate = tevent_req_data(subreq, struct smbXcli_req_state);
2928 :
2929 1604 : substate->smb2.cancel_mid = BVAL(state->smb2.hdr, SMB2_HDR_MESSAGE_ID);
2930 :
2931 1604 : SIVAL(substate->smb2.hdr, SMB2_HDR_FLAGS, state->smb2.cancel_flags);
2932 1604 : SBVAL(substate->smb2.hdr, SMB2_HDR_MESSAGE_ID, state->smb2.cancel_mid);
2933 1604 : SBVAL(substate->smb2.hdr, SMB2_HDR_ASYNC_ID, state->smb2.cancel_aid);
2934 :
2935 : /*
2936 : * remember that we don't send a cancel again
2937 : */
2938 1604 : state->smb2.cancel_mid = UINT64_MAX;
2939 :
2940 1604 : status = smb2cli_req_compound_submit(&subreq, 1);
2941 1604 : if (!NT_STATUS_IS_OK(status)) {
2942 0 : TALLOC_FREE(subreq);
2943 0 : return false;
2944 : }
2945 :
2946 1604 : tevent_req_set_callback(subreq, smb2cli_req_cancel_done, NULL);
2947 :
2948 1604 : return true;
2949 : }
2950 :
2951 0 : static void smb2cli_req_cancel_done(struct tevent_req *subreq)
2952 : {
2953 : /* we do not care about the result */
2954 0 : TALLOC_FREE(subreq);
2955 0 : }
2956 :
2957 1622 : struct timeval smbXcli_req_endtime(struct tevent_req *req)
2958 : {
2959 1622 : struct smbXcli_req_state *state = tevent_req_data(
2960 : req, struct smbXcli_req_state);
2961 :
2962 1622 : return state->endtime;
2963 : }
2964 :
2965 1784958 : struct tevent_req *smb2cli_req_create(TALLOC_CTX *mem_ctx,
2966 : struct tevent_context *ev,
2967 : struct smbXcli_conn *conn,
2968 : uint16_t cmd,
2969 : uint32_t additional_flags,
2970 : uint32_t clear_flags,
2971 : uint32_t timeout_msec,
2972 : struct smbXcli_tcon *tcon,
2973 : struct smbXcli_session *session,
2974 : const uint8_t *fixed,
2975 : uint16_t fixed_len,
2976 : const uint8_t *dyn,
2977 : uint32_t dyn_len,
2978 : uint32_t max_dyn_len)
2979 : {
2980 : struct tevent_req *req;
2981 : struct smbXcli_req_state *state;
2982 1784958 : uint32_t flags = 0;
2983 1784958 : uint32_t tid = 0;
2984 1784958 : uint64_t uid = 0;
2985 1784958 : bool use_channel_sequence = conn->smb2.force_channel_sequence;
2986 1784958 : uint16_t channel_sequence = 0;
2987 1784958 : bool use_replay_flag = false;
2988 :
2989 1784958 : req = tevent_req_create(mem_ctx, &state,
2990 : struct smbXcli_req_state);
2991 1784958 : if (req == NULL) {
2992 0 : return NULL;
2993 : }
2994 :
2995 1784958 : state->ev = ev;
2996 1784958 : state->conn = conn;
2997 1784958 : state->session = session;
2998 1784958 : state->tcon = tcon;
2999 :
3000 1784958 : if (conn->smb2.server.capabilities & SMB2_CAP_PERSISTENT_HANDLES) {
3001 0 : use_channel_sequence = true;
3002 1784958 : } else if (conn->smb2.server.capabilities & SMB2_CAP_MULTI_CHANNEL) {
3003 1291452 : use_channel_sequence = true;
3004 : }
3005 :
3006 1784958 : if (smbXcli_conn_protocol(conn) >= PROTOCOL_SMB3_00) {
3007 1291448 : use_replay_flag = true;
3008 : }
3009 :
3010 1784958 : if (smbXcli_conn_protocol(conn) >= PROTOCOL_SMB3_11) {
3011 1290898 : flags |= SMB2_PRIORITY_VALUE_TO_MASK(conn->smb2.io_priority);
3012 : }
3013 :
3014 1784958 : if (session) {
3015 1759706 : uid = session->smb2->session_id;
3016 :
3017 1759706 : if (use_channel_sequence) {
3018 1288342 : channel_sequence = session->smb2->channel_sequence;
3019 : }
3020 :
3021 1759706 : if (use_replay_flag && session->smb2->replay_active) {
3022 722 : additional_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
3023 : }
3024 :
3025 1759706 : state->smb2.should_sign = session->smb2->should_sign;
3026 1759706 : state->smb2.should_encrypt = session->smb2->should_encrypt;
3027 3296421 : state->smb2.require_signed_response =
3028 3296421 : session->smb2->require_signed_response;
3029 :
3030 1797871 : if (cmd == SMB2_OP_SESSSETUP &&
3031 85868 : !smb2_signing_key_valid(session->smb2_channel.signing_key) &&
3032 42822 : smb2_signing_key_valid(session->smb2->signing_key))
3033 : {
3034 : /*
3035 : * a session bind needs to be signed
3036 : */
3037 2392 : state->smb2.should_sign = true;
3038 : }
3039 :
3040 1797871 : if (cmd == SMB2_OP_SESSSETUP &&
3041 43046 : !smb2_signing_key_valid(session->smb2_channel.signing_key)) {
3042 42822 : state->smb2.should_encrypt = false;
3043 : }
3044 :
3045 1759706 : if (additional_flags & SMB2_HDR_FLAG_SIGNED) {
3046 35379 : if (!smb2_signing_key_valid(session->smb2_channel.signing_key)) {
3047 0 : tevent_req_nterror(req, NT_STATUS_NO_USER_SESSION_KEY);
3048 0 : return req;
3049 : }
3050 :
3051 35379 : additional_flags &= ~SMB2_HDR_FLAG_SIGNED;
3052 35379 : state->smb2.should_sign = true;
3053 : }
3054 : }
3055 :
3056 1784958 : if (tcon) {
3057 1680136 : tid = tcon->smb2.tcon_id;
3058 :
3059 1680136 : if (tcon->smb2.should_sign) {
3060 1000159 : state->smb2.should_sign = true;
3061 : }
3062 1680136 : if (tcon->smb2.should_encrypt) {
3063 4345 : state->smb2.should_encrypt = true;
3064 : }
3065 : }
3066 :
3067 1784958 : if (state->smb2.should_encrypt) {
3068 5058 : state->smb2.should_sign = false;
3069 : }
3070 :
3071 1784958 : state->smb2.recv_iov = talloc_zero_array(state, struct iovec, 3);
3072 1784958 : if (state->smb2.recv_iov == NULL) {
3073 0 : TALLOC_FREE(req);
3074 0 : return NULL;
3075 : }
3076 :
3077 1784958 : flags |= additional_flags;
3078 1784958 : flags &= ~clear_flags;
3079 :
3080 1784958 : state->smb2.fixed = fixed;
3081 1784958 : state->smb2.fixed_len = fixed_len;
3082 1784958 : state->smb2.dyn = dyn;
3083 1784958 : state->smb2.dyn_len = dyn_len;
3084 1784958 : state->smb2.max_dyn_len = max_dyn_len;
3085 :
3086 1784958 : if (state->smb2.should_encrypt) {
3087 5058 : SIVAL(state->smb2.transform, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3088 5058 : SBVAL(state->smb2.transform, SMB2_TF_SESSION_ID, uid);
3089 : }
3090 :
3091 1784958 : SIVAL(state->smb2.hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
3092 1784958 : SSVAL(state->smb2.hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
3093 1784958 : SSVAL(state->smb2.hdr, SMB2_HDR_OPCODE, cmd);
3094 1784958 : SSVAL(state->smb2.hdr, SMB2_HDR_CHANNEL_SEQUENCE, channel_sequence);
3095 1784958 : SIVAL(state->smb2.hdr, SMB2_HDR_FLAGS, flags);
3096 1784958 : SIVAL(state->smb2.hdr, SMB2_HDR_PID, 0); /* reserved */
3097 1784958 : SIVAL(state->smb2.hdr, SMB2_HDR_TID, tid);
3098 1784958 : SBVAL(state->smb2.hdr, SMB2_HDR_SESSION_ID, uid);
3099 :
3100 1784958 : switch (cmd) {
3101 1604 : case SMB2_OP_CANCEL:
3102 1604 : state->one_way = true;
3103 1604 : break;
3104 2180 : case SMB2_OP_BREAK:
3105 : /*
3106 : * If this is a dummy request, it will have
3107 : * UINT64_MAX as message id.
3108 : * If we send on break acknowledgement,
3109 : * this gets overwritten later.
3110 : */
3111 2180 : SBVAL(state->smb2.hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
3112 2180 : break;
3113 : }
3114 :
3115 1784958 : if (timeout_msec > 0) {
3116 1779755 : state->endtime = timeval_current_ofs_msec(timeout_msec);
3117 1779755 : if (!tevent_req_set_endtime(req, ev, state->endtime)) {
3118 0 : return req;
3119 : }
3120 : }
3121 :
3122 1775913 : return req;
3123 : }
3124 :
3125 1146464 : void smb2cli_req_set_notify_async(struct tevent_req *req)
3126 : {
3127 1017940 : struct smbXcli_req_state *state =
3128 1146464 : tevent_req_data(req,
3129 : struct smbXcli_req_state);
3130 :
3131 1146464 : state->smb2.notify_async = true;
3132 1146464 : }
3133 :
3134 : static void smb2cli_req_writev_done(struct tevent_req *subreq);
3135 : static NTSTATUS smb2cli_conn_dispatch_incoming(struct smbXcli_conn *conn,
3136 : TALLOC_CTX *tmp_mem,
3137 : uint8_t *inbuf);
3138 :
3139 1782795 : NTSTATUS smb2cli_req_compound_submit(struct tevent_req **reqs,
3140 : int num_reqs)
3141 : {
3142 : struct smbXcli_req_state *state;
3143 : struct tevent_req *subreq;
3144 : struct iovec *iov;
3145 : int i, num_iov, nbt_len;
3146 1782795 : int tf_iov = -1;
3147 1782795 : struct smb2_signing_key *encryption_key = NULL;
3148 1782795 : uint64_t encryption_session_id = 0;
3149 1782795 : uint64_t nonce_high = UINT64_MAX;
3150 1782795 : uint64_t nonce_low = UINT64_MAX;
3151 :
3152 : /*
3153 : * 1 for the nbt length, optional TRANSFORM
3154 : * per request: HDR, fixed, dyn, padding
3155 : * -1 because the last one does not need padding
3156 : */
3157 :
3158 1782795 : iov = talloc_array(reqs[0], struct iovec, 1 + 1 + 4*num_reqs - 1);
3159 1782795 : if (iov == NULL) {
3160 0 : return NT_STATUS_NO_MEMORY;
3161 : }
3162 :
3163 1773750 : num_iov = 1;
3164 1773750 : nbt_len = 0;
3165 :
3166 : /*
3167 : * the session of the first request that requires encryption
3168 : * specifies the encryption key.
3169 : */
3170 3551777 : for (i=0; i<num_reqs; i++) {
3171 1783109 : if (!tevent_req_is_in_progress(reqs[i])) {
3172 0 : return NT_STATUS_INTERNAL_ERROR;
3173 : }
3174 :
3175 1783109 : state = tevent_req_data(reqs[i], struct smbXcli_req_state);
3176 :
3177 1783109 : if (!smbXcli_conn_is_connected(state->conn)) {
3178 38 : return NT_STATUS_CONNECTION_DISCONNECTED;
3179 : }
3180 :
3181 3320851 : if ((state->conn->protocol != PROTOCOL_NONE) &&
3182 1752379 : (state->conn->protocol < PROTOCOL_SMB2_02)) {
3183 0 : return NT_STATUS_REVISION_MISMATCH;
3184 : }
3185 :
3186 1783071 : if (state->session == NULL) {
3187 23403 : continue;
3188 : }
3189 :
3190 1759668 : if (!state->smb2.should_encrypt) {
3191 1754624 : continue;
3192 : }
3193 :
3194 5044 : encryption_key = state->session->smb2->encryption_key;
3195 5044 : if (!smb2_signing_key_valid(encryption_key)) {
3196 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
3197 : }
3198 :
3199 5044 : encryption_session_id = state->session->smb2->session_id;
3200 :
3201 5044 : state->session->smb2->nonce_low += 1;
3202 5044 : if (state->session->smb2->nonce_low == 0) {
3203 0 : state->session->smb2->nonce_high += 1;
3204 0 : state->session->smb2->nonce_low += 1;
3205 : }
3206 :
3207 : /*
3208 : * CCM and GCM algorithms must never have their
3209 : * nonce wrap, or the security of the whole
3210 : * communication and the keys is destroyed.
3211 : * We must drop the connection once we have
3212 : * transfered too much data.
3213 : *
3214 : * NOTE: We assume nonces greater than 8 bytes.
3215 : */
3216 9263 : if (state->session->smb2->nonce_high >=
3217 5044 : state->session->smb2->nonce_high_max)
3218 : {
3219 0 : return NT_STATUS_ENCRYPTION_FAILED;
3220 : }
3221 :
3222 5044 : nonce_high = state->session->smb2->nonce_high_random;
3223 5044 : nonce_high += state->session->smb2->nonce_high;
3224 5044 : nonce_low = state->session->smb2->nonce_low;
3225 :
3226 5044 : tf_iov = num_iov;
3227 5044 : iov[num_iov].iov_base = state->smb2.transform;
3228 5044 : iov[num_iov].iov_len = sizeof(state->smb2.transform);
3229 5044 : num_iov += 1;
3230 :
3231 5044 : SBVAL(state->smb2.transform, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3232 5044 : SBVAL(state->smb2.transform, SMB2_TF_NONCE,
3233 : nonce_low);
3234 5044 : SBVAL(state->smb2.transform, SMB2_TF_NONCE+8,
3235 : nonce_high);
3236 5044 : SBVAL(state->smb2.transform, SMB2_TF_SESSION_ID,
3237 : encryption_session_id);
3238 :
3239 5044 : nbt_len += SMB2_TF_HDR_SIZE;
3240 5044 : break;
3241 : }
3242 :
3243 3565828 : for (i=0; i<num_reqs; i++) {
3244 : int hdr_iov;
3245 : size_t reqlen;
3246 : bool ret;
3247 : uint16_t opcode;
3248 : uint64_t avail;
3249 : uint16_t charge;
3250 : uint16_t credits;
3251 : uint64_t mid;
3252 1783071 : struct smb2_signing_key *signing_key = NULL;
3253 :
3254 1783071 : if (!tevent_req_is_in_progress(reqs[i])) {
3255 0 : return NT_STATUS_INTERNAL_ERROR;
3256 : }
3257 :
3258 1783071 : state = tevent_req_data(reqs[i], struct smbXcli_req_state);
3259 :
3260 1783071 : if (!smbXcli_conn_is_connected(state->conn)) {
3261 0 : return NT_STATUS_CONNECTION_DISCONNECTED;
3262 : }
3263 :
3264 3320851 : if ((state->conn->protocol != PROTOCOL_NONE) &&
3265 1752379 : (state->conn->protocol < PROTOCOL_SMB2_02)) {
3266 0 : return NT_STATUS_REVISION_MISMATCH;
3267 : }
3268 :
3269 1783071 : opcode = SVAL(state->smb2.hdr, SMB2_HDR_OPCODE);
3270 1783071 : if (opcode == SMB2_OP_CANCEL) {
3271 1604 : goto skip_credits;
3272 : }
3273 :
3274 1781467 : avail = UINT64_MAX - state->conn->smb2.mid;
3275 1781467 : if (avail < 1) {
3276 0 : return NT_STATUS_CONNECTION_ABORTED;
3277 : }
3278 :
3279 1781467 : if (state->conn->smb2.server.capabilities & SMB2_CAP_LARGE_MTU) {
3280 1353763 : uint32_t max_dyn_len = 1;
3281 :
3282 1353763 : max_dyn_len = MAX(max_dyn_len, state->smb2.dyn_len);
3283 1353763 : max_dyn_len = MAX(max_dyn_len, state->smb2.max_dyn_len);
3284 :
3285 1353763 : charge = (max_dyn_len - 1)/ 65536 + 1;
3286 : } else {
3287 427314 : charge = 1;
3288 : }
3289 :
3290 1781467 : charge = MAX(state->smb2.credit_charge, charge);
3291 :
3292 1781467 : avail = MIN(avail, state->conn->smb2.cur_credits);
3293 1781467 : if (avail < charge) {
3294 0 : DBG_ERR("Insufficient credits. "
3295 : "%"PRIu64" available, %"PRIu16" needed\n",
3296 : avail, charge);
3297 0 : return NT_STATUS_INTERNAL_ERROR;
3298 : }
3299 :
3300 1781467 : credits = 0;
3301 1781467 : if (state->conn->smb2.max_credits > state->conn->smb2.cur_credits) {
3302 173014 : credits = state->conn->smb2.max_credits -
3303 94145 : state->conn->smb2.cur_credits;
3304 : }
3305 1781467 : if (state->conn->smb2.max_credits >= state->conn->smb2.cur_credits) {
3306 1633374 : credits += 1;
3307 : }
3308 :
3309 1781467 : mid = state->conn->smb2.mid;
3310 1781467 : state->conn->smb2.mid += charge;
3311 1781467 : state->conn->smb2.cur_credits -= charge;
3312 :
3313 1781467 : if (state->conn->smb2.server.capabilities & SMB2_CAP_LARGE_MTU) {
3314 1353763 : SSVAL(state->smb2.hdr, SMB2_HDR_CREDIT_CHARGE, charge);
3315 : }
3316 1781467 : SSVAL(state->smb2.hdr, SMB2_HDR_CREDIT, credits);
3317 1781467 : SBVAL(state->smb2.hdr, SMB2_HDR_MESSAGE_ID, mid);
3318 :
3319 1781467 : state->smb2.cancel_flags = SVAL(state->smb2.hdr, SMB2_HDR_FLAGS);
3320 1781467 : state->smb2.cancel_flags &= ~SMB2_HDR_FLAG_CHAINED;
3321 1781467 : state->smb2.cancel_mid = mid;
3322 1781467 : state->smb2.cancel_aid = 0;
3323 :
3324 1783071 : skip_credits:
3325 1783071 : if (state->session && encryption_key == NULL) {
3326 : /*
3327 : * We prefer the channel signing key if it is
3328 : * already there.
3329 : */
3330 1754624 : if (state->smb2.should_sign) {
3331 1033254 : signing_key = state->session->smb2_channel.signing_key;
3332 : }
3333 :
3334 : /*
3335 : * If it is a channel binding, we already have the main
3336 : * signing key and try that one.
3337 : */
3338 2580774 : if (signing_key != NULL &&
3339 1033254 : !smb2_signing_key_valid(signing_key)) {
3340 2464 : signing_key = state->session->smb2->signing_key;
3341 : }
3342 :
3343 : /*
3344 : * If we do not have any session key yet, we skip the
3345 : * signing of SMB2_OP_SESSSETUP requests.
3346 : */
3347 2581176 : if (signing_key != NULL &&
3348 1033254 : !smb2_signing_key_valid(signing_key)) {
3349 0 : signing_key = NULL;
3350 : }
3351 : }
3352 :
3353 1783071 : hdr_iov = num_iov;
3354 1783071 : iov[num_iov].iov_base = state->smb2.hdr;
3355 1783071 : iov[num_iov].iov_len = sizeof(state->smb2.hdr);
3356 1783071 : num_iov += 1;
3357 :
3358 1783071 : iov[num_iov].iov_base = discard_const(state->smb2.fixed);
3359 1783071 : iov[num_iov].iov_len = state->smb2.fixed_len;
3360 1783071 : num_iov += 1;
3361 :
3362 1783071 : if (state->smb2.dyn != NULL) {
3363 1705176 : iov[num_iov].iov_base = discard_const(state->smb2.dyn);
3364 1705176 : iov[num_iov].iov_len = state->smb2.dyn_len;
3365 1705176 : num_iov += 1;
3366 : }
3367 :
3368 1783071 : reqlen = sizeof(state->smb2.hdr);
3369 1783071 : reqlen += state->smb2.fixed_len;
3370 1783071 : reqlen += state->smb2.dyn_len;
3371 :
3372 1783071 : if (i < num_reqs-1) {
3373 314 : if ((reqlen % 8) > 0) {
3374 164 : uint8_t pad = 8 - (reqlen % 8);
3375 164 : iov[num_iov].iov_base = state->smb2.pad;
3376 164 : iov[num_iov].iov_len = pad;
3377 164 : num_iov += 1;
3378 164 : reqlen += pad;
3379 : }
3380 314 : SIVAL(state->smb2.hdr, SMB2_HDR_NEXT_COMMAND, reqlen);
3381 : }
3382 :
3383 1783071 : state->smb2.encryption_session_id = encryption_session_id;
3384 :
3385 1783071 : if (signing_key != NULL) {
3386 : NTSTATUS status;
3387 :
3388 1851553 : status = smb2_signing_sign_pdu(signing_key,
3389 1025001 : &iov[hdr_iov], num_iov - hdr_iov);
3390 1033254 : if (!NT_STATUS_IS_OK(status)) {
3391 0 : return status;
3392 : }
3393 : }
3394 :
3395 1783071 : nbt_len += reqlen;
3396 :
3397 1783071 : ret = smbXcli_req_set_pending(reqs[i]);
3398 1783071 : if (!ret) {
3399 0 : return NT_STATUS_NO_MEMORY;
3400 : }
3401 : }
3402 :
3403 1782757 : state = tevent_req_data(reqs[0], struct smbXcli_req_state);
3404 1782757 : _smb_setlen_tcp(state->length_hdr, nbt_len);
3405 1782757 : iov[0].iov_base = state->length_hdr;
3406 1782757 : iov[0].iov_len = sizeof(state->length_hdr);
3407 :
3408 1782757 : if (encryption_key != NULL) {
3409 : NTSTATUS status;
3410 5044 : size_t buflen = nbt_len - SMB2_TF_HDR_SIZE;
3411 : uint8_t *buf;
3412 : int vi;
3413 :
3414 5044 : buf = talloc_array(iov, uint8_t, buflen);
3415 5044 : if (buf == NULL) {
3416 0 : return NT_STATUS_NO_MEMORY;
3417 : }
3418 :
3419 : /*
3420 : * We copy the buffers before encrypting them,
3421 : * this is at least currently needed for the
3422 : * to keep state->smb2.hdr.
3423 : *
3424 : * Also the callers may expect there buffers
3425 : * to be const.
3426 : */
3427 19334 : for (vi = tf_iov + 1; vi < num_iov; vi++) {
3428 14290 : struct iovec *v = &iov[vi];
3429 14290 : const uint8_t *o = (const uint8_t *)v->iov_base;
3430 :
3431 14290 : memcpy(buf, o, v->iov_len);
3432 14290 : v->iov_base = (void *)buf;
3433 14290 : buf += v->iov_len;
3434 : }
3435 :
3436 9263 : status = smb2_signing_encrypt_pdu(encryption_key,
3437 5044 : &iov[tf_iov], num_iov - tf_iov);
3438 5044 : if (!NT_STATUS_IS_OK(status)) {
3439 0 : return status;
3440 : }
3441 : }
3442 :
3443 1782757 : if (state->conn->dispatch_incoming == NULL) {
3444 0 : state->conn->dispatch_incoming = smb2cli_conn_dispatch_incoming;
3445 : }
3446 :
3447 1782757 : subreq = writev_send(state, state->ev, state->conn->outgoing,
3448 1773712 : state->conn->sock_fd, false, iov, num_iov);
3449 1782757 : if (subreq == NULL) {
3450 0 : return NT_STATUS_NO_MEMORY;
3451 : }
3452 1782757 : tevent_req_set_callback(subreq, smb2cli_req_writev_done, reqs[0]);
3453 1782757 : state->write_req = subreq;
3454 :
3455 1782757 : return NT_STATUS_OK;
3456 : }
3457 :
3458 35449 : void smb2cli_req_set_credit_charge(struct tevent_req *req, uint16_t charge)
3459 : {
3460 28437 : struct smbXcli_req_state *state =
3461 35449 : tevent_req_data(req,
3462 : struct smbXcli_req_state);
3463 :
3464 35449 : state->smb2.credit_charge = charge;
3465 35449 : }
3466 :
3467 635041 : struct tevent_req *smb2cli_req_send(TALLOC_CTX *mem_ctx,
3468 : struct tevent_context *ev,
3469 : struct smbXcli_conn *conn,
3470 : uint16_t cmd,
3471 : uint32_t additional_flags,
3472 : uint32_t clear_flags,
3473 : uint32_t timeout_msec,
3474 : struct smbXcli_tcon *tcon,
3475 : struct smbXcli_session *session,
3476 : const uint8_t *fixed,
3477 : uint16_t fixed_len,
3478 : const uint8_t *dyn,
3479 : uint32_t dyn_len,
3480 : uint32_t max_dyn_len)
3481 : {
3482 : struct tevent_req *req;
3483 : NTSTATUS status;
3484 :
3485 635041 : req = smb2cli_req_create(mem_ctx, ev, conn, cmd,
3486 : additional_flags, clear_flags,
3487 : timeout_msec,
3488 : tcon, session,
3489 : fixed, fixed_len,
3490 : dyn, dyn_len,
3491 : max_dyn_len);
3492 635041 : if (req == NULL) {
3493 0 : return NULL;
3494 : }
3495 635041 : if (!tevent_req_is_in_progress(req)) {
3496 0 : return tevent_req_post(req, ev);
3497 : }
3498 635041 : status = smb2cli_req_compound_submit(&req, 1);
3499 635041 : if (tevent_req_nterror(req, status)) {
3500 4 : return tevent_req_post(req, ev);
3501 : }
3502 635037 : return req;
3503 : }
3504 :
3505 1776061 : static void smb2cli_req_writev_done(struct tevent_req *subreq)
3506 : {
3507 1559930 : struct tevent_req *req =
3508 1776061 : tevent_req_callback_data(subreq,
3509 : struct tevent_req);
3510 1559930 : struct smbXcli_req_state *state =
3511 1776061 : tevent_req_data(req,
3512 : struct smbXcli_req_state);
3513 : ssize_t nwritten;
3514 : int err;
3515 :
3516 1776061 : state->write_req = NULL;
3517 :
3518 1776061 : nwritten = writev_recv(subreq, &err);
3519 1776061 : TALLOC_FREE(subreq);
3520 1776061 : if (nwritten == -1) {
3521 : /* here, we need to notify all pending requests */
3522 2 : NTSTATUS status = map_nt_error_from_unix_common(err);
3523 2 : smbXcli_conn_disconnect(state->conn, status);
3524 2 : return;
3525 : }
3526 : }
3527 :
3528 5052 : static struct smbXcli_session* smbXcli_session_by_uid(struct smbXcli_conn *conn,
3529 : uint64_t uid)
3530 : {
3531 5052 : struct smbXcli_session *s = conn->sessions;
3532 :
3533 14053 : for (; s; s = s->next) {
3534 7472 : if (s->smb2->session_id != uid) {
3535 2420 : continue;
3536 : }
3537 5052 : break;
3538 : }
3539 :
3540 5052 : return s;
3541 : }
3542 :
3543 1907698 : static NTSTATUS smb2cli_inbuf_parse_compound(struct smbXcli_conn *conn,
3544 : uint8_t *buf,
3545 : size_t buflen,
3546 : TALLOC_CTX *mem_ctx,
3547 : struct iovec **piov,
3548 : size_t *pnum_iov)
3549 : {
3550 : struct iovec *iov;
3551 1907698 : int num_iov = 0;
3552 1907698 : size_t taken = 0;
3553 1907698 : uint8_t *first_hdr = buf;
3554 1907698 : size_t verified_buflen = 0;
3555 1907698 : uint8_t *tf = NULL;
3556 1907698 : size_t tf_len = 0;
3557 :
3558 1907698 : iov = talloc_array(mem_ctx, struct iovec, num_iov);
3559 1907698 : if (iov == NULL) {
3560 0 : return NT_STATUS_NO_MEMORY;
3561 : }
3562 :
3563 5469189 : while (taken < buflen) {
3564 1908006 : size_t len = buflen - taken;
3565 1908006 : uint8_t *hdr = first_hdr + taken;
3566 : struct iovec *cur;
3567 : size_t full_size;
3568 : size_t next_command_ofs;
3569 : uint16_t body_size;
3570 : struct iovec *iov_tmp;
3571 :
3572 1908006 : if (verified_buflen > taken) {
3573 0 : len = verified_buflen - taken;
3574 : } else {
3575 1896075 : tf = NULL;
3576 1896075 : tf_len = 0;
3577 : }
3578 :
3579 1908006 : if (len < 4) {
3580 0 : DEBUG(10, ("%d bytes left, expected at least %d\n",
3581 : (int)len, 4));
3582 0 : goto inval;
3583 : }
3584 1908006 : if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
3585 : struct smbXcli_session *s;
3586 : uint64_t uid;
3587 : struct iovec tf_iov[2];
3588 : size_t enc_len;
3589 : NTSTATUS status;
3590 :
3591 5046 : if (len < SMB2_TF_HDR_SIZE) {
3592 0 : DEBUG(10, ("%d bytes left, expected at least %d\n",
3593 : (int)len, SMB2_TF_HDR_SIZE));
3594 0 : goto inval;
3595 : }
3596 5046 : tf = hdr;
3597 5046 : tf_len = SMB2_TF_HDR_SIZE;
3598 5046 : taken += tf_len;
3599 :
3600 5046 : hdr = first_hdr + taken;
3601 5046 : enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
3602 5046 : uid = BVAL(tf, SMB2_TF_SESSION_ID);
3603 :
3604 5046 : if (len < SMB2_TF_HDR_SIZE + enc_len) {
3605 0 : DEBUG(10, ("%d bytes left, expected at least %d\n",
3606 : (int)len,
3607 : (int)(SMB2_TF_HDR_SIZE + enc_len)));
3608 0 : goto inval;
3609 : }
3610 :
3611 5046 : s = smbXcli_session_by_uid(conn, uid);
3612 5046 : if (s == NULL) {
3613 0 : DEBUG(10, ("unknown session_id %llu\n",
3614 : (unsigned long long)uid));
3615 0 : goto inval;
3616 : }
3617 :
3618 5046 : tf_iov[0].iov_base = (void *)tf;
3619 5046 : tf_iov[0].iov_len = tf_len;
3620 5046 : tf_iov[1].iov_base = (void *)hdr;
3621 5046 : tf_iov[1].iov_len = enc_len;
3622 :
3623 5046 : status = smb2_signing_decrypt_pdu(s->smb2->decryption_key,
3624 : tf_iov, 2);
3625 5046 : if (!NT_STATUS_IS_OK(status)) {
3626 0 : TALLOC_FREE(iov);
3627 0 : return status;
3628 : }
3629 :
3630 5046 : verified_buflen = taken + enc_len;
3631 5046 : len = enc_len;
3632 : }
3633 :
3634 : /*
3635 : * We need the header plus the body length field
3636 : */
3637 :
3638 1908006 : if (len < SMB2_HDR_BODY + 2) {
3639 0 : DEBUG(10, ("%d bytes left, expected at least %d\n",
3640 : (int)len, SMB2_HDR_BODY));
3641 0 : goto inval;
3642 : }
3643 1908006 : if (IVAL(hdr, 0) != SMB2_MAGIC) {
3644 0 : DEBUG(10, ("Got non-SMB2 PDU: %x\n",
3645 : IVAL(hdr, 0)));
3646 0 : goto inval;
3647 : }
3648 1908006 : if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
3649 0 : DEBUG(10, ("Got HDR len %d, expected %d\n",
3650 : SVAL(hdr, 4), SMB2_HDR_BODY));
3651 0 : goto inval;
3652 : }
3653 :
3654 1908006 : full_size = len;
3655 1908006 : next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
3656 1908006 : body_size = SVAL(hdr, SMB2_HDR_BODY);
3657 :
3658 1908006 : if (next_command_ofs != 0) {
3659 308 : if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
3660 0 : goto inval;
3661 : }
3662 308 : if (next_command_ofs > full_size) {
3663 0 : goto inval;
3664 : }
3665 308 : full_size = next_command_ofs;
3666 : }
3667 1908006 : if (body_size < 2) {
3668 0 : goto inval;
3669 : }
3670 1908006 : body_size &= 0xfffe;
3671 :
3672 1908006 : if (body_size > (full_size - SMB2_HDR_BODY)) {
3673 0 : goto inval;
3674 : }
3675 :
3676 1908006 : iov_tmp = talloc_realloc(mem_ctx, iov, struct iovec,
3677 : num_iov + 4);
3678 1908006 : if (iov_tmp == NULL) {
3679 0 : TALLOC_FREE(iov);
3680 0 : return NT_STATUS_NO_MEMORY;
3681 : }
3682 1908006 : iov = iov_tmp;
3683 1908006 : cur = &iov[num_iov];
3684 1908006 : num_iov += 4;
3685 :
3686 1908006 : cur[0].iov_base = tf;
3687 1908006 : cur[0].iov_len = tf_len;
3688 1908006 : cur[1].iov_base = hdr;
3689 1908006 : cur[1].iov_len = SMB2_HDR_BODY;
3690 1908006 : cur[2].iov_base = hdr + SMB2_HDR_BODY;
3691 1908006 : cur[2].iov_len = body_size;
3692 1908006 : cur[3].iov_base = hdr + SMB2_HDR_BODY + body_size;
3693 1908006 : cur[3].iov_len = full_size - (SMB2_HDR_BODY + body_size);
3694 :
3695 1908006 : taken += full_size;
3696 : }
3697 :
3698 1907698 : *piov = iov;
3699 1907698 : *pnum_iov = num_iov;
3700 1907698 : return NT_STATUS_OK;
3701 :
3702 0 : inval:
3703 0 : TALLOC_FREE(iov);
3704 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
3705 : }
3706 :
3707 1908006 : static struct tevent_req *smb2cli_conn_find_pending(struct smbXcli_conn *conn,
3708 : uint64_t mid)
3709 : {
3710 1908006 : size_t num_pending = talloc_array_length(conn->pending);
3711 : size_t i;
3712 :
3713 1917531 : for (i=0; i<num_pending; i++) {
3714 1917529 : struct tevent_req *req = conn->pending[i];
3715 1674160 : struct smbXcli_req_state *state =
3716 1917529 : tevent_req_data(req,
3717 : struct smbXcli_req_state);
3718 :
3719 1917529 : if (mid == BVAL(state->smb2.hdr, SMB2_HDR_MESSAGE_ID)) {
3720 1896073 : return req;
3721 : }
3722 : }
3723 2 : return NULL;
3724 : }
3725 :
3726 1907698 : static NTSTATUS smb2cli_conn_dispatch_incoming(struct smbXcli_conn *conn,
3727 : TALLOC_CTX *tmp_mem,
3728 : uint8_t *inbuf)
3729 : {
3730 : struct tevent_req *req;
3731 1907698 : struct smbXcli_req_state *state = NULL;
3732 1907698 : struct iovec *iov = NULL;
3733 1907698 : size_t i, num_iov = 0;
3734 : NTSTATUS status;
3735 1907698 : bool defer = true;
3736 1907698 : struct smbXcli_session *last_session = NULL;
3737 1907698 : size_t inbuf_len = smb_len_tcp(inbuf);
3738 :
3739 1907698 : status = smb2cli_inbuf_parse_compound(conn,
3740 : inbuf + NBT_HDR_SIZE,
3741 : inbuf_len,
3742 : tmp_mem,
3743 : &iov, &num_iov);
3744 1907698 : if (!NT_STATUS_IS_OK(status)) {
3745 0 : return status;
3746 : }
3747 :
3748 3803767 : for (i=0; i<num_iov; i+=4) {
3749 1908006 : uint8_t *inbuf_ref = NULL;
3750 1908006 : struct iovec *cur = &iov[i];
3751 1908006 : uint8_t *inhdr = (uint8_t *)cur[1].iov_base;
3752 1908006 : uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
3753 1908006 : uint32_t flags = IVAL(inhdr, SMB2_HDR_FLAGS);
3754 1908006 : uint64_t mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
3755 : uint16_t req_opcode;
3756 : uint32_t req_flags;
3757 1908006 : uint16_t credits = SVAL(inhdr, SMB2_HDR_CREDIT);
3758 : uint32_t new_credits;
3759 1908006 : struct smbXcli_session *session = NULL;
3760 1908006 : struct smb2_signing_key *signing_key = NULL;
3761 1908006 : bool was_encrypted = false;
3762 :
3763 1908006 : new_credits = conn->smb2.cur_credits;
3764 1908006 : new_credits += credits;
3765 1908006 : if (new_credits > UINT16_MAX) {
3766 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
3767 : }
3768 1908006 : conn->smb2.cur_credits += credits;
3769 :
3770 1908006 : req = smb2cli_conn_find_pending(conn, mid);
3771 1908006 : if (req == NULL) {
3772 2 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
3773 : }
3774 1908004 : state = tevent_req_data(req, struct smbXcli_req_state);
3775 :
3776 1908004 : req_opcode = SVAL(state->smb2.hdr, SMB2_HDR_OPCODE);
3777 1908004 : if (opcode != req_opcode) {
3778 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
3779 : }
3780 1908004 : req_flags = SVAL(state->smb2.hdr, SMB2_HDR_FLAGS);
3781 :
3782 1908004 : if (!(flags & SMB2_HDR_FLAG_REDIRECT)) {
3783 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
3784 : }
3785 :
3786 1908004 : status = NT_STATUS(IVAL(inhdr, SMB2_HDR_STATUS));
3787 2087036 : if ((flags & SMB2_HDR_FLAG_ASYNC) &&
3788 227516 : NT_STATUS_EQUAL(status, NT_STATUS_PENDING)) {
3789 116751 : uint64_t async_id = BVAL(inhdr, SMB2_HDR_ASYNC_ID);
3790 :
3791 116751 : if (state->smb2.got_async) {
3792 : /* We only expect one STATUS_PENDING response */
3793 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
3794 : }
3795 116751 : state->smb2.got_async = true;
3796 :
3797 : /*
3798 : * async interim responses are not signed,
3799 : * even if the SMB2_HDR_FLAG_SIGNED flag
3800 : * is set.
3801 : */
3802 116751 : state->smb2.cancel_flags |= SMB2_HDR_FLAG_ASYNC;
3803 116751 : state->smb2.cancel_aid = async_id;
3804 :
3805 116751 : if (state->smb2.notify_async) {
3806 1622 : tevent_req_defer_callback(req, state->ev);
3807 1622 : tevent_req_notify_callback(req);
3808 : }
3809 116751 : continue;
3810 : }
3811 :
3812 1791253 : session = state->session;
3813 1791253 : if (req_flags & SMB2_HDR_FLAG_CHAINED) {
3814 254 : session = last_session;
3815 : }
3816 1791253 : last_session = session;
3817 :
3818 1791253 : if (flags & SMB2_HDR_FLAG_SIGNED) {
3819 1048228 : uint64_t uid = BVAL(inhdr, SMB2_HDR_SESSION_ID);
3820 :
3821 1048228 : if (session == NULL) {
3822 6 : session = smbXcli_session_by_uid(state->conn,
3823 : uid);
3824 : }
3825 :
3826 1048228 : if (session == NULL) {
3827 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
3828 : }
3829 :
3830 1048228 : last_session = session;
3831 1048228 : signing_key = session->smb2_channel.signing_key;
3832 : }
3833 :
3834 1791253 : if (opcode == SMB2_OP_SESSSETUP) {
3835 : /*
3836 : * We prefer the channel signing key, if it is
3837 : * already there.
3838 : *
3839 : * If we do not have a channel signing key yet,
3840 : * we try the main signing key, if it is not
3841 : * the final response.
3842 : */
3843 63308 : if (signing_key != NULL &&
3844 44178 : !smb2_signing_key_valid(signing_key) &&
3845 23866 : !NT_STATUS_IS_OK(status)) {
3846 1746 : signing_key = session->smb2->signing_key;
3847 : }
3848 :
3849 63308 : if (signing_key != NULL &&
3850 23990 : !smb2_signing_key_valid(signing_key)) {
3851 : /*
3852 : * If we do not have a session key to
3853 : * verify the signature, we defer the
3854 : * signing check to the caller.
3855 : *
3856 : * The caller gets NT_STATUS_OK, it
3857 : * has to call
3858 : * smb2cli_session_set_session_key()
3859 : * or
3860 : * smb2cli_session_set_channel_key()
3861 : * which will check the signature
3862 : * with the channel signing key.
3863 : */
3864 22282 : signing_key = NULL;
3865 : }
3866 :
3867 43046 : if (!NT_STATUS_IS_OK(status)) {
3868 : /*
3869 : * Only check the signature of the last response
3870 : * of a successfull session auth. This matches
3871 : * Windows behaviour for NTLM auth and reauth.
3872 : */
3873 20132 : state->smb2.require_signed_response = false;
3874 : }
3875 : }
3876 :
3877 2542800 : if (state->smb2.should_sign ||
3878 764537 : state->smb2.require_signed_response)
3879 : {
3880 1026720 : if (!(flags & SMB2_HDR_FLAG_SIGNED)) {
3881 0 : return NT_STATUS_ACCESS_DENIED;
3882 : }
3883 : }
3884 :
3885 2543437 : if (!smb2_signing_key_valid(signing_key) &&
3886 765379 : state->smb2.require_signed_response) {
3887 0 : signing_key = session->smb2_channel.signing_key;
3888 : }
3889 :
3890 1791253 : if (cur[0].iov_len == SMB2_TF_HDR_SIZE) {
3891 4969 : const uint8_t *tf = (const uint8_t *)cur[0].iov_base;
3892 4969 : uint64_t uid = BVAL(tf, SMB2_TF_SESSION_ID);
3893 :
3894 : /*
3895 : * If the response was encrypted in a SMB2_TRANSFORM
3896 : * pdu, which belongs to the correct session,
3897 : * we do not need to do signing checks
3898 : *
3899 : * It could be the session the response belongs to
3900 : * or the session that was used to encrypt the
3901 : * SMB2_TRANSFORM request.
3902 : */
3903 4969 : if ((session && session->smb2->session_id == uid) ||
3904 0 : (state->smb2.encryption_session_id == uid)) {
3905 4969 : signing_key = NULL;
3906 4969 : was_encrypted = true;
3907 : }
3908 : }
3909 :
3910 1791253 : if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
3911 : /*
3912 : * if the server returns NT_STATUS_USER_SESSION_DELETED
3913 : * the response is not signed and we should
3914 : * propagate the NT_STATUS_USER_SESSION_DELETED
3915 : * status to the caller.
3916 : */
3917 930 : state->smb2.signing_skipped = true;
3918 930 : signing_key = NULL;
3919 : }
3920 1791253 : if (NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_OUT_OF_SEQUENCE)) {
3921 : /*
3922 : * if the server returns
3923 : * NT_STATUS_REQUEST_OUT_OF_SEQUENCE for a session setup
3924 : * request, the response is not signed and we should
3925 : * propagate the NT_STATUS_REQUEST_OUT_OF_SEQUENCE
3926 : * status to the caller
3927 : */
3928 232 : if (opcode == SMB2_OP_SESSSETUP) {
3929 232 : state->smb2.signing_skipped = true;
3930 232 : signing_key = NULL;
3931 : }
3932 : }
3933 1791253 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
3934 : /*
3935 : * if the server returns NT_STATUS_NOT_SUPPORTED
3936 : * for a session setup request, the response is not
3937 : * signed and we should propagate the NT_STATUS_NOT_SUPPORTED
3938 : * status to the caller.
3939 : */
3940 247 : if (opcode == SMB2_OP_SESSSETUP) {
3941 232 : state->smb2.signing_skipped = true;
3942 232 : signing_key = NULL;
3943 : }
3944 : }
3945 1791253 : if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
3946 : /*
3947 : * if the server returns
3948 : * NT_STATUS_ACCESS_DENIED for a session setup
3949 : * request, the response is not signed and we should
3950 : * propagate the NT_STATUS_ACCESS_DENIED
3951 : * status to the caller without disconnecting
3952 : * the connection because we where not able to
3953 : * verify the response signature.
3954 : */
3955 2726 : if (opcode == SMB2_OP_SESSSETUP) {
3956 66 : state->smb2.signing_skipped = true;
3957 66 : signing_key = NULL;
3958 : }
3959 : }
3960 :
3961 1791253 : if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
3962 : /*
3963 : * if the server returns
3964 : * NT_STATUS_INVALID_PARAMETER
3965 : * the response might not be encrypted.
3966 : */
3967 2714 : if (state->smb2.should_encrypt && !was_encrypted) {
3968 0 : state->smb2.signing_skipped = true;
3969 0 : signing_key = NULL;
3970 : }
3971 : }
3972 :
3973 1791253 : if (state->smb2.should_encrypt && !was_encrypted) {
3974 16 : if (!state->smb2.signing_skipped) {
3975 0 : return NT_STATUS_ACCESS_DENIED;
3976 : }
3977 : }
3978 :
3979 3355325 : if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED) ||
3980 3352311 : NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED) ||
3981 1778731 : NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
3982 : /*
3983 : * if the server returns
3984 : * NT_STATUS_NETWORK_NAME_DELETED
3985 : * NT_STATUS_FILE_CLOSED
3986 : * NT_STATUS_INVALID_PARAMETER
3987 : * the response might not be signed
3988 : * as this happens before the signing checks.
3989 : *
3990 : * If server echos the signature (or all zeros)
3991 : * we should report the status from the server
3992 : * to the caller.
3993 : */
3994 6263 : if (signing_key) {
3995 : int cmp;
3996 :
3997 1929 : cmp = memcmp(inhdr+SMB2_HDR_SIGNATURE,
3998 1929 : state->smb2.hdr+SMB2_HDR_SIGNATURE,
3999 : 16);
4000 1929 : if (cmp == 0) {
4001 14 : state->smb2.signing_skipped = true;
4002 14 : signing_key = NULL;
4003 : }
4004 : }
4005 6263 : if (signing_key) {
4006 : bool zero;
4007 1915 : zero = all_zero(inhdr+SMB2_HDR_SIGNATURE, 16);
4008 1915 : if (zero) {
4009 0 : state->smb2.signing_skipped = true;
4010 0 : signing_key = NULL;
4011 : }
4012 : }
4013 : }
4014 :
4015 1791253 : if (signing_key) {
4016 : NTSTATUS signing_status;
4017 :
4018 1024934 : signing_status = smb2_signing_check_pdu(signing_key,
4019 1024934 : &cur[1], 3);
4020 1024934 : if (!NT_STATUS_IS_OK(signing_status)) {
4021 : /*
4022 : * If the signing check fails, we disconnect
4023 : * the connection.
4024 : */
4025 0 : return signing_status;
4026 : }
4027 : }
4028 :
4029 1791253 : if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED) &&
4030 136 : (session != NULL) && session->disconnect_expired)
4031 : {
4032 : /*
4033 : * this should be a short term hack
4034 : * until the upper layers have implemented
4035 : * re-authentication.
4036 : */
4037 4 : return status;
4038 : }
4039 :
4040 1791249 : smbXcli_req_unset_pending(req);
4041 :
4042 : /*
4043 : * There might be more than one response
4044 : * we need to defer the notifications
4045 : */
4046 1791249 : if ((num_iov == 5) && (talloc_array_length(conn->pending) == 0)) {
4047 0 : defer = false;
4048 : }
4049 :
4050 1791249 : if (defer) {
4051 1791249 : tevent_req_defer_callback(req, state->ev);
4052 : }
4053 :
4054 : /*
4055 : * Note: here we use talloc_reference() in a way
4056 : * that does not expose it to the caller.
4057 : */
4058 1791249 : inbuf_ref = talloc_reference(state->smb2.recv_iov, inbuf);
4059 1791249 : if (tevent_req_nomem(inbuf_ref, req)) {
4060 0 : continue;
4061 : }
4062 :
4063 : /* copy the related buffers */
4064 1791249 : state->smb2.recv_iov[0] = cur[1];
4065 1791249 : state->smb2.recv_iov[1] = cur[2];
4066 1791249 : state->smb2.recv_iov[2] = cur[3];
4067 :
4068 1791249 : tevent_req_done(req);
4069 : }
4070 :
4071 1907692 : if (defer) {
4072 1907692 : return NT_STATUS_RETRY;
4073 : }
4074 :
4075 0 : return NT_STATUS_OK;
4076 : }
4077 :
4078 1793449 : NTSTATUS smb2cli_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
4079 : struct iovec **piov,
4080 : const struct smb2cli_req_expected_response *expected,
4081 : size_t num_expected)
4082 : {
4083 1575272 : struct smbXcli_req_state *state =
4084 1793449 : tevent_req_data(req,
4085 : struct smbXcli_req_state);
4086 : NTSTATUS status;
4087 : size_t body_size;
4088 1793449 : bool found_status = false;
4089 1793449 : bool found_size = false;
4090 : size_t i;
4091 :
4092 1793449 : if (piov != NULL) {
4093 1718222 : *piov = NULL;
4094 : }
4095 :
4096 1793449 : if (tevent_req_is_in_progress(req) && state->smb2.got_async) {
4097 1622 : return NT_STATUS_PENDING;
4098 : }
4099 :
4100 1791827 : if (tevent_req_is_nterror(req, &status)) {
4101 598 : for (i=0; i < num_expected; i++) {
4102 14 : if (NT_STATUS_EQUAL(status, expected[i].status)) {
4103 0 : return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
4104 : }
4105 : }
4106 :
4107 584 : return status;
4108 : }
4109 :
4110 1791243 : if (num_expected == 0) {
4111 1147009 : found_status = true;
4112 1147009 : found_size = true;
4113 : }
4114 :
4115 1791243 : status = NT_STATUS(IVAL(state->smb2.recv_iov[0].iov_base, SMB2_HDR_STATUS));
4116 1791243 : body_size = SVAL(state->smb2.recv_iov[1].iov_base, 0);
4117 :
4118 1877288 : for (i=0; i < num_expected; i++) {
4119 708723 : if (!NT_STATUS_EQUAL(status, expected[i].status)) {
4120 86045 : continue;
4121 : }
4122 :
4123 622678 : found_status = true;
4124 622678 : if (expected[i].body_size == 0) {
4125 0 : found_size = true;
4126 0 : break;
4127 : }
4128 :
4129 622678 : if (expected[i].body_size == body_size) {
4130 613708 : found_size = true;
4131 613708 : break;
4132 : }
4133 : }
4134 :
4135 1791243 : if (!found_status) {
4136 21556 : return status;
4137 : }
4138 :
4139 1769687 : if (state->smb2.signing_skipped) {
4140 242 : if (num_expected > 0) {
4141 0 : return NT_STATUS_ACCESS_DENIED;
4142 : }
4143 242 : if (!NT_STATUS_IS_ERR(status)) {
4144 0 : return NT_STATUS_ACCESS_DENIED;
4145 : }
4146 : }
4147 :
4148 1769687 : if (!found_size) {
4149 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
4150 : }
4151 :
4152 1769687 : if (piov != NULL) {
4153 1694614 : *piov = talloc_move(mem_ctx, &state->smb2.recv_iov);
4154 : }
4155 :
4156 1769687 : return status;
4157 : }
4158 :
4159 59021 : NTSTATUS smb2cli_req_get_sent_iov(struct tevent_req *req,
4160 : struct iovec *sent_iov)
4161 : {
4162 52400 : struct smbXcli_req_state *state =
4163 59021 : tevent_req_data(req,
4164 : struct smbXcli_req_state);
4165 :
4166 59021 : if (tevent_req_is_in_progress(req)) {
4167 0 : return NT_STATUS_PENDING;
4168 : }
4169 :
4170 59021 : sent_iov[0].iov_base = state->smb2.hdr;
4171 59021 : sent_iov[0].iov_len = sizeof(state->smb2.hdr);
4172 :
4173 59021 : sent_iov[1].iov_base = discard_const(state->smb2.fixed);
4174 59021 : sent_iov[1].iov_len = state->smb2.fixed_len;
4175 :
4176 59021 : if (state->smb2.dyn != NULL) {
4177 59021 : sent_iov[2].iov_base = discard_const(state->smb2.dyn);
4178 59021 : sent_iov[2].iov_len = state->smb2.dyn_len;
4179 : } else {
4180 0 : sent_iov[2].iov_base = NULL;
4181 0 : sent_iov[2].iov_len = 0;
4182 : }
4183 :
4184 59021 : return NT_STATUS_OK;
4185 : }
4186 :
4187 : static const struct {
4188 : enum protocol_types proto;
4189 : const char *smb1_name;
4190 : } smb1cli_prots[] = {
4191 : {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
4192 : {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
4193 : {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
4194 : {PROTOCOL_LANMAN1, "LANMAN1.0"},
4195 : {PROTOCOL_LANMAN2, "LM1.2X002"},
4196 : {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
4197 : {PROTOCOL_LANMAN2, "LANMAN2.1"},
4198 : {PROTOCOL_LANMAN2, "Samba"},
4199 : {PROTOCOL_NT1, "NT LANMAN 1.0"},
4200 : {PROTOCOL_NT1, "NT LM 0.12"},
4201 : {PROTOCOL_SMB2_02, "SMB 2.002"},
4202 : {PROTOCOL_SMB2_10, "SMB 2.???"},
4203 : };
4204 :
4205 : static const struct {
4206 : enum protocol_types proto;
4207 : uint16_t smb2_dialect;
4208 : } smb2cli_prots[] = {
4209 : {PROTOCOL_SMB2_02, SMB2_DIALECT_REVISION_202},
4210 : {PROTOCOL_SMB2_10, SMB2_DIALECT_REVISION_210},
4211 : {PROTOCOL_SMB3_00, SMB3_DIALECT_REVISION_300},
4212 : {PROTOCOL_SMB3_02, SMB3_DIALECT_REVISION_302},
4213 : {PROTOCOL_SMB3_11, SMB3_DIALECT_REVISION_311},
4214 : };
4215 :
4216 : struct smbXcli_negprot_state {
4217 : struct smbXcli_conn *conn;
4218 : struct tevent_context *ev;
4219 : uint32_t timeout_msec;
4220 :
4221 : struct {
4222 : uint8_t fixed[36];
4223 : } smb2;
4224 : };
4225 :
4226 : static void smbXcli_negprot_invalid_done(struct tevent_req *subreq);
4227 : static struct tevent_req *smbXcli_negprot_smb1_subreq(struct smbXcli_negprot_state *state);
4228 : static void smbXcli_negprot_smb1_done(struct tevent_req *subreq);
4229 : static struct tevent_req *smbXcli_negprot_smb2_subreq(struct smbXcli_negprot_state *state);
4230 : static void smbXcli_negprot_smb2_done(struct tevent_req *subreq);
4231 : static NTSTATUS smbXcli_negprot_dispatch_incoming(struct smbXcli_conn *conn,
4232 : TALLOC_CTX *frame,
4233 : uint8_t *inbuf);
4234 :
4235 30221 : struct tevent_req *smbXcli_negprot_send(TALLOC_CTX *mem_ctx,
4236 : struct tevent_context *ev,
4237 : struct smbXcli_conn *conn,
4238 : uint32_t timeout_msec,
4239 : enum protocol_types min_protocol,
4240 : enum protocol_types max_protocol,
4241 : uint16_t max_credits)
4242 : {
4243 : struct tevent_req *req, *subreq;
4244 : struct smbXcli_negprot_state *state;
4245 :
4246 30221 : req = tevent_req_create(mem_ctx, &state,
4247 : struct smbXcli_negprot_state);
4248 30221 : if (req == NULL) {
4249 0 : return NULL;
4250 : }
4251 30221 : state->conn = conn;
4252 30221 : state->ev = ev;
4253 30221 : state->timeout_msec = timeout_msec;
4254 :
4255 30221 : if (min_protocol == PROTOCOL_NONE) {
4256 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
4257 0 : return tevent_req_post(req, ev);
4258 : }
4259 :
4260 30221 : if (max_protocol == PROTOCOL_NONE) {
4261 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
4262 0 : return tevent_req_post(req, ev);
4263 : }
4264 :
4265 30221 : if (min_protocol > max_protocol) {
4266 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
4267 0 : return tevent_req_post(req, ev);
4268 : }
4269 :
4270 30221 : conn->min_protocol = min_protocol;
4271 30221 : conn->max_protocol = max_protocol;
4272 30221 : conn->protocol = PROTOCOL_NONE;
4273 :
4274 30221 : if (max_protocol >= PROTOCOL_SMB2_02) {
4275 23393 : conn->smb2.max_credits = max_credits;
4276 : }
4277 :
4278 30751 : if ((min_protocol < PROTOCOL_SMB2_02) &&
4279 530 : (max_protocol < PROTOCOL_SMB2_02)) {
4280 : /*
4281 : * SMB1 only...
4282 : */
4283 6828 : conn->dispatch_incoming = smb1cli_conn_dispatch_incoming;
4284 :
4285 6828 : subreq = smbXcli_negprot_smb1_subreq(state);
4286 6828 : if (tevent_req_nomem(subreq, req)) {
4287 0 : return tevent_req_post(req, ev);
4288 : }
4289 6828 : tevent_req_set_callback(subreq, smbXcli_negprot_smb1_done, req);
4290 6828 : return req;
4291 : }
4292 :
4293 23783 : if ((min_protocol >= PROTOCOL_SMB2_02) &&
4294 390 : (max_protocol >= PROTOCOL_SMB2_02)) {
4295 : /*
4296 : * SMB2 only...
4297 : */
4298 7490 : conn->dispatch_incoming = smb2cli_conn_dispatch_incoming;
4299 :
4300 7490 : subreq = smbXcli_negprot_smb2_subreq(state);
4301 7490 : if (tevent_req_nomem(subreq, req)) {
4302 0 : return tevent_req_post(req, ev);
4303 : }
4304 7490 : tevent_req_set_callback(subreq, smbXcli_negprot_smb2_done, req);
4305 7490 : return req;
4306 : }
4307 :
4308 : /*
4309 : * We send an SMB1 negprot with the SMB2 dialects
4310 : * and expect a SMB1 or a SMB2 response.
4311 : *
4312 : * smbXcli_negprot_dispatch_incoming() will fix the
4313 : * callback to match protocol of the response.
4314 : */
4315 15903 : conn->dispatch_incoming = smbXcli_negprot_dispatch_incoming;
4316 :
4317 15903 : subreq = smbXcli_negprot_smb1_subreq(state);
4318 15903 : if (tevent_req_nomem(subreq, req)) {
4319 0 : return tevent_req_post(req, ev);
4320 : }
4321 15903 : tevent_req_set_callback(subreq, smbXcli_negprot_invalid_done, req);
4322 15903 : return req;
4323 : }
4324 :
4325 0 : static void smbXcli_negprot_invalid_done(struct tevent_req *subreq)
4326 : {
4327 0 : struct tevent_req *req =
4328 0 : tevent_req_callback_data(subreq,
4329 : struct tevent_req);
4330 : NTSTATUS status;
4331 :
4332 : /*
4333 : * we just want the low level error
4334 : */
4335 0 : status = tevent_req_simple_recv_ntstatus(subreq);
4336 0 : TALLOC_FREE(subreq);
4337 0 : if (tevent_req_nterror(req, status)) {
4338 0 : return;
4339 : }
4340 :
4341 : /* this should never happen */
4342 0 : tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
4343 : }
4344 :
4345 22731 : static struct tevent_req *smbXcli_negprot_smb1_subreq(struct smbXcli_negprot_state *state)
4346 : {
4347 : size_t i;
4348 22731 : DATA_BLOB bytes = data_blob_null;
4349 : uint8_t flags;
4350 : uint16_t flags2;
4351 :
4352 : /* setup the protocol strings */
4353 295503 : for (i=0; i < ARRAY_SIZE(smb1cli_prots); i++) {
4354 272772 : uint8_t c = 2;
4355 : bool ok;
4356 :
4357 272772 : if (smb1cli_prots[i].proto < state->conn->min_protocol) {
4358 116566 : continue;
4359 : }
4360 :
4361 215236 : if (smb1cli_prots[i].proto > state->conn->max_protocol) {
4362 13742 : continue;
4363 : }
4364 :
4365 201494 : ok = data_blob_append(state, &bytes, &c, sizeof(c));
4366 201494 : if (!ok) {
4367 0 : return NULL;
4368 : }
4369 :
4370 : /*
4371 : * We now it is already ascii and
4372 : * we want NULL termination.
4373 : */
4374 383516 : ok = data_blob_append(state, &bytes,
4375 198534 : smb1cli_prots[i].smb1_name,
4376 201494 : strlen(smb1cli_prots[i].smb1_name)+1);
4377 201494 : if (!ok) {
4378 0 : return NULL;
4379 : }
4380 : }
4381 :
4382 23261 : smb1cli_req_flags(state->conn->max_protocol,
4383 22731 : state->conn->smb1.client.capabilities,
4384 : SMBnegprot,
4385 : 0, 0, &flags,
4386 : 0, 0, &flags2);
4387 :
4388 22731 : return smb1cli_req_send(state, state->ev, state->conn,
4389 : SMBnegprot,
4390 : flags, ~flags,
4391 : flags2, ~flags2,
4392 : state->timeout_msec,
4393 : 0xFFFE, 0, NULL, /* pid, tid, session */
4394 : 0, NULL, /* wct, vwv */
4395 22731 : bytes.length, bytes.data);
4396 : }
4397 :
4398 6828 : static void smbXcli_negprot_smb1_done(struct tevent_req *subreq)
4399 : {
4400 6248 : struct tevent_req *req =
4401 6828 : tevent_req_callback_data(subreq,
4402 : struct tevent_req);
4403 6248 : struct smbXcli_negprot_state *state =
4404 6828 : tevent_req_data(req,
4405 : struct smbXcli_negprot_state);
4406 6828 : struct smbXcli_conn *conn = state->conn;
4407 6828 : struct iovec *recv_iov = NULL;
4408 6828 : uint8_t *inhdr = NULL;
4409 : uint8_t wct;
4410 : uint16_t *vwv;
4411 : uint32_t num_bytes;
4412 : uint8_t *bytes;
4413 : NTSTATUS status;
4414 : uint16_t protnum;
4415 : size_t i;
4416 6828 : size_t num_prots = 0;
4417 : uint8_t flags;
4418 6828 : uint32_t client_capabilities = conn->smb1.client.capabilities;
4419 : uint32_t both_capabilities;
4420 6828 : uint32_t server_capabilities = 0;
4421 : uint32_t capabilities;
4422 6828 : uint32_t client_max_xmit = conn->smb1.client.max_xmit;
4423 6828 : uint32_t server_max_xmit = 0;
4424 : uint32_t max_xmit;
4425 6828 : uint32_t server_max_mux = 0;
4426 6828 : uint16_t server_security_mode = 0;
4427 6828 : uint32_t server_session_key = 0;
4428 6828 : bool server_readbraw = false;
4429 6828 : bool server_writebraw = false;
4430 6828 : bool server_lockread = false;
4431 6828 : bool server_writeunlock = false;
4432 6828 : struct GUID server_guid = GUID_zero();
4433 6828 : DATA_BLOB server_gss_blob = data_blob_null;
4434 : uint8_t server_challenge[8];
4435 6828 : char *server_workgroup = NULL;
4436 6828 : char *server_name = NULL;
4437 6828 : int server_time_zone = 0;
4438 6828 : NTTIME server_system_time = 0;
4439 : static const struct smb1cli_req_expected_response expected[] = {
4440 : {
4441 : .status = NT_STATUS_OK,
4442 : .wct = 0x11, /* NT1 */
4443 : },
4444 : {
4445 : .status = NT_STATUS_OK,
4446 : .wct = 0x0D, /* LM */
4447 : },
4448 : {
4449 : .status = NT_STATUS_OK,
4450 : .wct = 0x01, /* CORE */
4451 : }
4452 : };
4453 :
4454 6828 : ZERO_STRUCT(server_challenge);
4455 :
4456 6828 : status = smb1cli_req_recv(subreq, state,
4457 : &recv_iov,
4458 : &inhdr,
4459 : &wct,
4460 : &vwv,
4461 : NULL, /* pvwv_offset */
4462 : &num_bytes,
4463 : &bytes,
4464 : NULL, /* pbytes_offset */
4465 : NULL, /* pinbuf */
4466 : expected, ARRAY_SIZE(expected));
4467 6828 : TALLOC_FREE(subreq);
4468 6828 : if (inhdr == NULL || tevent_req_nterror(req, status)) {
4469 1523 : return;
4470 : }
4471 :
4472 6234 : flags = CVAL(inhdr, HDR_FLG);
4473 :
4474 6234 : protnum = SVAL(vwv, 0);
4475 :
4476 57784 : for (i=0; i < ARRAY_SIZE(smb1cli_prots); i++) {
4477 57350 : if (smb1cli_prots[i].proto < state->conn->min_protocol) {
4478 736 : continue;
4479 : }
4480 :
4481 56614 : if (smb1cli_prots[i].proto > state->conn->max_protocol) {
4482 886 : continue;
4483 : }
4484 :
4485 55728 : if (protnum != num_prots) {
4486 49928 : num_prots++;
4487 49928 : continue;
4488 : }
4489 :
4490 5800 : conn->protocol = smb1cli_prots[i].proto;
4491 5800 : break;
4492 : }
4493 :
4494 6234 : if (conn->protocol == PROTOCOL_NONE) {
4495 434 : DBG_ERR("No compatible protocol selected by server.\n");
4496 434 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4497 434 : return;
4498 : }
4499 :
4500 5800 : if ((conn->protocol < PROTOCOL_NT1) && conn->mandatory_signing) {
4501 0 : DEBUG(0,("smbXcli_negprot: SMB signing is mandatory "
4502 : "and the selected protocol level doesn't support it.\n"));
4503 0 : tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
4504 0 : return;
4505 : }
4506 :
4507 5800 : if (flags & FLAG_SUPPORT_LOCKREAD) {
4508 24 : server_lockread = true;
4509 24 : server_writeunlock = true;
4510 : }
4511 :
4512 5800 : if (conn->protocol >= PROTOCOL_NT1) {
4513 5774 : const char *client_signing = NULL;
4514 5774 : bool server_mandatory = false;
4515 5774 : bool server_allowed = false;
4516 5774 : const char *server_signing = NULL;
4517 : bool ok;
4518 : uint8_t key_len;
4519 :
4520 5774 : if (wct != 0x11) {
4521 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4522 0 : return;
4523 : }
4524 :
4525 : /* NT protocol */
4526 5774 : server_security_mode = CVAL(vwv + 1, 0);
4527 5774 : server_max_mux = SVAL(vwv + 1, 1);
4528 5774 : server_max_xmit = IVAL(vwv + 3, 1);
4529 5774 : server_session_key = IVAL(vwv + 7, 1);
4530 5774 : server_time_zone = SVALS(vwv + 15, 1);
4531 5774 : server_time_zone *= 60;
4532 : /* this time arrives in real GMT */
4533 5774 : server_system_time = BVAL(vwv + 11, 1);
4534 5774 : server_capabilities = IVAL(vwv + 9, 1);
4535 :
4536 5774 : key_len = CVAL(vwv + 16, 1);
4537 :
4538 5774 : if (server_capabilities & CAP_RAW_MODE) {
4539 4985 : server_readbraw = true;
4540 4985 : server_writebraw = true;
4541 : }
4542 5774 : if (server_capabilities & CAP_LOCK_AND_READ) {
4543 5774 : server_lockread = true;
4544 : }
4545 :
4546 5774 : if (server_capabilities & CAP_EXTENDED_SECURITY) {
4547 : DATA_BLOB blob1, blob2;
4548 :
4549 5692 : if (num_bytes < 16) {
4550 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4551 0 : return;
4552 : }
4553 :
4554 5692 : blob1 = data_blob_const(bytes, 16);
4555 5692 : status = GUID_from_data_blob(&blob1, &server_guid);
4556 5692 : if (tevent_req_nterror(req, status)) {
4557 0 : return;
4558 : }
4559 :
4560 5692 : blob1 = data_blob_const(bytes+16, num_bytes-16);
4561 5692 : blob2 = data_blob_dup_talloc(state, blob1);
4562 11384 : if (blob1.length > 0 &&
4563 5692 : tevent_req_nomem(blob2.data, req)) {
4564 0 : return;
4565 : }
4566 5692 : server_gss_blob = blob2;
4567 : } else {
4568 : DATA_BLOB blob1, blob2;
4569 :
4570 82 : if (num_bytes < key_len) {
4571 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4572 0 : return;
4573 : }
4574 :
4575 82 : if (key_len != 0 && key_len != 8) {
4576 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4577 0 : return;
4578 : }
4579 :
4580 82 : if (key_len == 8) {
4581 82 : memcpy(server_challenge, bytes, 8);
4582 : }
4583 :
4584 82 : blob1 = data_blob_const(bytes+key_len, num_bytes-key_len);
4585 82 : blob2 = data_blob_const(bytes+key_len, num_bytes-key_len);
4586 82 : if (blob1.length > 0) {
4587 : size_t len;
4588 :
4589 82 : len = utf16_len_n(blob1.data,
4590 : blob1.length);
4591 82 : blob1.length = len;
4592 :
4593 154 : ok = convert_string_talloc(state,
4594 : CH_UTF16LE,
4595 : CH_UNIX,
4596 82 : blob1.data,
4597 : blob1.length,
4598 : &server_workgroup,
4599 : &len);
4600 82 : if (!ok) {
4601 0 : status = map_nt_error_from_unix_common(errno);
4602 0 : tevent_req_nterror(req, status);
4603 0 : return;
4604 : }
4605 : }
4606 :
4607 82 : blob2.data += blob1.length;
4608 82 : blob2.length -= blob1.length;
4609 82 : if (blob2.length > 0) {
4610 : size_t len;
4611 :
4612 82 : len = utf16_len_n(blob1.data,
4613 : blob1.length);
4614 82 : blob1.length = len;
4615 :
4616 154 : ok = convert_string_talloc(state,
4617 : CH_UTF16LE,
4618 : CH_UNIX,
4619 82 : blob2.data,
4620 : blob2.length,
4621 : &server_name,
4622 : &len);
4623 82 : if (!ok) {
4624 0 : status = map_nt_error_from_unix_common(errno);
4625 0 : tevent_req_nterror(req, status);
4626 0 : return;
4627 : }
4628 : }
4629 : }
4630 :
4631 5774 : client_signing = "disabled";
4632 5774 : if (conn->allow_signing) {
4633 5772 : client_signing = "allowed";
4634 : }
4635 5774 : if (conn->mandatory_signing) {
4636 258 : client_signing = "required";
4637 : }
4638 :
4639 5774 : server_signing = "not supported";
4640 5774 : if (server_security_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
4641 1620 : server_signing = "supported";
4642 1620 : server_allowed = true;
4643 4022 : } else if (conn->mandatory_signing) {
4644 : /*
4645 : * We have mandatory signing as client
4646 : * lets assume the server will look at our
4647 : * FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED
4648 : * flag in the session setup
4649 : */
4650 243 : server_signing = "not announced";
4651 243 : server_allowed = true;
4652 : }
4653 5774 : if (server_security_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
4654 1646 : server_signing = "required";
4655 1646 : server_mandatory = true;
4656 : }
4657 :
4658 5774 : ok = smb_signing_set_negotiated(conn->smb1.signing,
4659 : server_allowed,
4660 : server_mandatory);
4661 5774 : if (!ok) {
4662 0 : DEBUG(1,("cli_negprot: SMB signing is required, "
4663 : "but client[%s] and server[%s] mismatch\n",
4664 : client_signing, server_signing));
4665 0 : tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
4666 0 : return;
4667 : }
4668 :
4669 26 : } else if (conn->protocol >= PROTOCOL_LANMAN1) {
4670 : DATA_BLOB blob1;
4671 : uint8_t key_len;
4672 : time_t t;
4673 :
4674 26 : if (wct != 0x0D) {
4675 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4676 0 : return;
4677 : }
4678 :
4679 26 : server_security_mode = SVAL(vwv + 1, 0);
4680 26 : server_max_xmit = SVAL(vwv + 2, 0);
4681 26 : server_max_mux = SVAL(vwv + 3, 0);
4682 26 : server_readbraw = ((SVAL(vwv + 5, 0) & 0x1) != 0);
4683 26 : server_writebraw = ((SVAL(vwv + 5, 0) & 0x2) != 0);
4684 26 : server_session_key = IVAL(vwv + 6, 0);
4685 26 : server_time_zone = SVALS(vwv + 10, 0);
4686 26 : server_time_zone *= 60;
4687 : /* this time is converted to GMT by make_unix_date */
4688 26 : t = pull_dos_date((const uint8_t *)(vwv + 8), server_time_zone);
4689 26 : unix_to_nt_time(&server_system_time, t);
4690 26 : key_len = SVAL(vwv + 11, 0);
4691 :
4692 26 : if (num_bytes < key_len) {
4693 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4694 0 : return;
4695 : }
4696 :
4697 26 : if (key_len != 0 && key_len != 8) {
4698 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4699 0 : return;
4700 : }
4701 :
4702 26 : if (key_len == 8) {
4703 26 : memcpy(server_challenge, bytes, 8);
4704 : }
4705 :
4706 26 : blob1 = data_blob_const(bytes+key_len, num_bytes-key_len);
4707 26 : if (blob1.length > 0) {
4708 : size_t len;
4709 : bool ok;
4710 :
4711 2 : len = utf16_len_n(blob1.data,
4712 : blob1.length);
4713 2 : blob1.length = len;
4714 :
4715 3 : ok = convert_string_talloc(state,
4716 : CH_DOS,
4717 : CH_UNIX,
4718 2 : blob1.data,
4719 : blob1.length,
4720 : &server_workgroup,
4721 : &len);
4722 2 : if (!ok) {
4723 0 : status = map_nt_error_from_unix_common(errno);
4724 0 : tevent_req_nterror(req, status);
4725 0 : return;
4726 : }
4727 : }
4728 :
4729 : } else {
4730 : /* the old core protocol */
4731 0 : server_time_zone = get_time_zone(time(NULL));
4732 0 : server_max_xmit = 1024;
4733 0 : server_max_mux = 1;
4734 : }
4735 :
4736 5800 : if (server_max_xmit < 1024) {
4737 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4738 0 : return;
4739 : }
4740 :
4741 5800 : if (server_max_mux < 1) {
4742 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4743 0 : return;
4744 : }
4745 :
4746 : /*
4747 : * Now calculate the negotiated capabilities
4748 : * based on the mask for:
4749 : * - client only flags
4750 : * - flags used in both directions
4751 : * - server only flags
4752 : */
4753 5800 : both_capabilities = client_capabilities & server_capabilities;
4754 5800 : capabilities = client_capabilities & SMB_CAP_CLIENT_MASK;
4755 5800 : capabilities |= both_capabilities & SMB_CAP_BOTH_MASK;
4756 5800 : capabilities |= server_capabilities & SMB_CAP_SERVER_MASK;
4757 :
4758 5800 : max_xmit = MIN(client_max_xmit, server_max_xmit);
4759 :
4760 5800 : conn->smb1.server.capabilities = server_capabilities;
4761 5800 : conn->smb1.capabilities = capabilities;
4762 :
4763 5800 : conn->smb1.server.max_xmit = server_max_xmit;
4764 5800 : conn->smb1.max_xmit = max_xmit;
4765 :
4766 5800 : conn->smb1.server.max_mux = server_max_mux;
4767 :
4768 5800 : conn->smb1.server.security_mode = server_security_mode;
4769 :
4770 5800 : conn->smb1.server.readbraw = server_readbraw;
4771 5800 : conn->smb1.server.writebraw = server_writebraw;
4772 5800 : conn->smb1.server.lockread = server_lockread;
4773 5800 : conn->smb1.server.writeunlock = server_writeunlock;
4774 :
4775 5800 : conn->smb1.server.session_key = server_session_key;
4776 :
4777 5800 : talloc_steal(conn, server_gss_blob.data);
4778 5800 : conn->smb1.server.gss_blob = server_gss_blob;
4779 5800 : conn->smb1.server.guid = server_guid;
4780 5932 : memcpy(conn->smb1.server.challenge, server_challenge, 8);
4781 5800 : conn->smb1.server.workgroup = talloc_move(conn, &server_workgroup);
4782 5800 : conn->smb1.server.name = talloc_move(conn, &server_name);
4783 :
4784 5800 : conn->smb1.server.time_zone = server_time_zone;
4785 5800 : conn->smb1.server.system_time = server_system_time;
4786 :
4787 5800 : tevent_req_done(req);
4788 : }
4789 :
4790 21389 : static size_t smbXcli_padding_helper(uint32_t offset, size_t n)
4791 : {
4792 21779 : if ((offset & (n-1)) == 0) return 0;
4793 21779 : return n - (offset & (n-1));
4794 : }
4795 :
4796 22037 : static struct tevent_req *smbXcli_negprot_smb2_subreq(struct smbXcli_negprot_state *state)
4797 : {
4798 : size_t i;
4799 : uint8_t *buf;
4800 22037 : uint16_t dialect_count = 0;
4801 22037 : DATA_BLOB dyn = data_blob_null;
4802 :
4803 132222 : for (i=0; i < ARRAY_SIZE(smb2cli_prots); i++) {
4804 : bool ok;
4805 : uint8_t val[2];
4806 :
4807 110185 : if (smb2cli_prots[i].proto < state->conn->min_protocol) {
4808 5576 : continue;
4809 : }
4810 :
4811 107333 : if (smb2cli_prots[i].proto > state->conn->max_protocol) {
4812 670 : continue;
4813 : }
4814 :
4815 106663 : SSVAL(val, 0, smb2cli_prots[i].smb2_dialect);
4816 :
4817 106663 : ok = data_blob_append(state, &dyn, val, sizeof(val));
4818 106663 : if (!ok) {
4819 0 : return NULL;
4820 : }
4821 :
4822 106663 : dialect_count++;
4823 : }
4824 :
4825 22037 : buf = state->smb2.fixed;
4826 22037 : SSVAL(buf, 0, 36);
4827 22037 : SSVAL(buf, 2, dialect_count);
4828 22037 : SSVAL(buf, 4, state->conn->smb2.client.security_mode);
4829 22037 : SSVAL(buf, 6, 0); /* Reserved */
4830 22037 : if (state->conn->max_protocol >= PROTOCOL_SMB3_00) {
4831 21855 : SIVAL(buf, 8, state->conn->smb2.client.capabilities);
4832 : } else {
4833 182 : SIVAL(buf, 8, 0); /* Capabilities */
4834 : }
4835 22037 : if (state->conn->max_protocol >= PROTOCOL_SMB2_10) {
4836 : NTSTATUS status;
4837 21989 : struct GUID_ndr_buf guid_buf = { .buf = {0}, };
4838 :
4839 21989 : status = GUID_to_ndr_buf(&state->conn->smb2.client.guid,
4840 : &guid_buf);
4841 21989 : if (!NT_STATUS_IS_OK(status)) {
4842 0 : return NULL;
4843 : }
4844 22379 : memcpy(buf+12, guid_buf.buf, 16); /* ClientGuid */
4845 : } else {
4846 48 : memset(buf+12, 0, 16); /* ClientGuid */
4847 : }
4848 :
4849 22037 : if (state->conn->max_protocol >= PROTOCOL_SMB3_11) {
4850 21779 : const struct smb3_signing_capabilities *client_sign_algos =
4851 21389 : &state->conn->smb2.client.smb3_capabilities.signing;
4852 21779 : const struct smb3_encryption_capabilities *client_ciphers =
4853 21389 : &state->conn->smb2.client.smb3_capabilities.encryption;
4854 : NTSTATUS status;
4855 21779 : struct smb2_negotiate_contexts c = { .num_contexts = 0, };
4856 21779 : uint8_t *netname_utf16 = NULL;
4857 21779 : size_t netname_utf16_len = 0;
4858 : uint32_t offset;
4859 : DATA_BLOB b;
4860 : uint8_t p[38];
4861 21779 : const uint8_t zeros[8] = {0, };
4862 : size_t pad;
4863 : bool ok;
4864 :
4865 21779 : SSVAL(p, 0, 1); /* HashAlgorithmCount */
4866 21779 : SSVAL(p, 2, 32); /* SaltLength */
4867 21779 : SSVAL(p, 4, SMB2_PREAUTH_INTEGRITY_SHA512);
4868 21779 : generate_random_buffer(p + 6, 32);
4869 :
4870 21779 : status = smb2_negotiate_context_add(
4871 : state, &c, SMB2_PREAUTH_INTEGRITY_CAPABILITIES, p, 38);
4872 21779 : if (!NT_STATUS_IS_OK(status)) {
4873 0 : return NULL;
4874 : }
4875 :
4876 21779 : if (client_ciphers->num_algos > 0) {
4877 21779 : size_t ofs = 0;
4878 21779 : SSVAL(p, ofs, client_ciphers->num_algos);
4879 21779 : ofs += 2;
4880 :
4881 108175 : for (i = 0; i < client_ciphers->num_algos; i++) {
4882 86396 : size_t next_ofs = ofs + 2;
4883 86396 : SMB_ASSERT(next_ofs < ARRAY_SIZE(p));
4884 86396 : SSVAL(p, ofs, client_ciphers->algos[i]);
4885 86396 : ofs = next_ofs;
4886 : }
4887 :
4888 21779 : status = smb2_negotiate_context_add(
4889 : state, &c, SMB2_ENCRYPTION_CAPABILITIES, p, ofs);
4890 21779 : if (!NT_STATUS_IS_OK(status)) {
4891 0 : return NULL;
4892 : }
4893 : }
4894 :
4895 21779 : if (client_sign_algos->num_algos > 0) {
4896 21779 : size_t ofs = 0;
4897 21779 : SSVAL(p, ofs, client_sign_algos->num_algos);
4898 21779 : ofs += 2;
4899 :
4900 86020 : for (i = 0; i < client_sign_algos->num_algos; i++) {
4901 64241 : size_t next_ofs = ofs + 2;
4902 64241 : SMB_ASSERT(next_ofs < ARRAY_SIZE(p));
4903 64241 : SSVAL(p, ofs, client_sign_algos->algos[i]);
4904 64241 : ofs = next_ofs;
4905 : }
4906 :
4907 21779 : status = smb2_negotiate_context_add(
4908 : state, &c, SMB2_SIGNING_CAPABILITIES, p, ofs);
4909 21779 : if (!NT_STATUS_IS_OK(status)) {
4910 0 : return NULL;
4911 : }
4912 : }
4913 :
4914 40052 : ok = convert_string_talloc(state, CH_UNIX, CH_UTF16,
4915 21389 : state->conn->remote_name,
4916 21779 : strlen(state->conn->remote_name),
4917 : &netname_utf16, &netname_utf16_len);
4918 21779 : if (!ok) {
4919 0 : return NULL;
4920 : }
4921 :
4922 21779 : status = smb2_negotiate_context_add(state, &c,
4923 : SMB2_NETNAME_NEGOTIATE_CONTEXT_ID,
4924 : netname_utf16, netname_utf16_len);
4925 21779 : if (!NT_STATUS_IS_OK(status)) {
4926 0 : return NULL;
4927 : }
4928 :
4929 21779 : status = smb2_negotiate_context_push(state, &b, c);
4930 21779 : if (!NT_STATUS_IS_OK(status)) {
4931 0 : return NULL;
4932 : }
4933 :
4934 21779 : offset = SMB2_HDR_BODY + sizeof(state->smb2.fixed) + dyn.length;
4935 21779 : pad = smbXcli_padding_helper(offset, 8);
4936 :
4937 21779 : ok = data_blob_append(state, &dyn, zeros, pad);
4938 21779 : if (!ok) {
4939 0 : return NULL;
4940 : }
4941 21779 : offset += pad;
4942 :
4943 21779 : ok = data_blob_append(state, &dyn, b.data, b.length);
4944 21779 : if (!ok) {
4945 0 : return NULL;
4946 : }
4947 :
4948 21779 : SIVAL(buf, 28, offset); /* NegotiateContextOffset */
4949 21779 : SSVAL(buf, 32, c.num_contexts); /* NegotiateContextCount */
4950 21779 : SSVAL(buf, 34, 0); /* Reserved */
4951 : } else {
4952 258 : SBVAL(buf, 28, 0); /* Reserved/ClientStartTime */
4953 : }
4954 :
4955 40897 : return smb2cli_req_send(state, state->ev,
4956 : state->conn, SMB2_OP_NEGPROT,
4957 : 0, 0, /* flags */
4958 : state->timeout_msec,
4959 : NULL, NULL, /* tcon, session */
4960 21647 : state->smb2.fixed, sizeof(state->smb2.fixed),
4961 40897 : dyn.data, dyn.length,
4962 : UINT16_MAX); /* max_dyn_len */
4963 : }
4964 :
4965 : static NTSTATUS smbXcli_negprot_smb3_check_capabilities(struct tevent_req *req);
4966 :
4967 37940 : static void smbXcli_negprot_smb2_done(struct tevent_req *subreq)
4968 : {
4969 32849 : struct tevent_req *req =
4970 37940 : tevent_req_callback_data(subreq,
4971 : struct tevent_req);
4972 32849 : struct smbXcli_negprot_state *state =
4973 37940 : tevent_req_data(req,
4974 : struct smbXcli_negprot_state);
4975 37940 : struct smbXcli_conn *conn = state->conn;
4976 : size_t security_offset, security_length;
4977 : DATA_BLOB blob;
4978 : NTSTATUS status;
4979 37940 : struct iovec *iov = NULL;
4980 : uint8_t *body;
4981 : size_t i;
4982 : uint16_t dialect_revision;
4983 37940 : struct smb2_negotiate_contexts c = { .num_contexts = 0, };
4984 37940 : uint32_t negotiate_context_offset = 0;
4985 37940 : uint16_t negotiate_context_count = 0;
4986 37940 : DATA_BLOB negotiate_context_blob = data_blob_null;
4987 : size_t avail;
4988 : size_t ctx_ofs;
4989 : size_t needed;
4990 37940 : struct smb2_negotiate_context *preauth = NULL;
4991 : uint16_t hash_count;
4992 : uint16_t salt_length;
4993 : uint16_t hash_selected;
4994 37940 : gnutls_hash_hd_t hash_hnd = NULL;
4995 37940 : struct smb2_negotiate_context *sign_algo = NULL;
4996 37940 : struct smb2_negotiate_context *cipher = NULL;
4997 37940 : struct iovec sent_iov[3] = {{0}, {0}, {0}};
4998 : static const struct smb2cli_req_expected_response expected[] = {
4999 : {
5000 : .status = NT_STATUS_OK,
5001 : .body_size = 0x41
5002 : }
5003 : };
5004 : int rc;
5005 :
5006 37940 : status = smb2cli_req_recv(subreq, state, &iov,
5007 : expected, ARRAY_SIZE(expected));
5008 37940 : if (tevent_req_nterror(req, status) || iov == NULL) {
5009 18645 : return;
5010 : }
5011 :
5012 37936 : body = (uint8_t *)iov[1].iov_base;
5013 :
5014 37936 : dialect_revision = SVAL(body, 4);
5015 :
5016 190341 : for (i=0; i < ARRAY_SIZE(smb2cli_prots); i++) {
5017 175794 : if (smb2cli_prots[i].proto < state->conn->min_protocol) {
5018 2836 : continue;
5019 : }
5020 :
5021 172958 : if (smb2cli_prots[i].proto > state->conn->max_protocol) {
5022 108 : continue;
5023 : }
5024 :
5025 172850 : if (smb2cli_prots[i].smb2_dialect != dialect_revision) {
5026 149461 : continue;
5027 : }
5028 :
5029 23389 : conn->protocol = smb2cli_prots[i].proto;
5030 23389 : break;
5031 : }
5032 :
5033 37936 : if (conn->protocol == PROTOCOL_NONE) {
5034 14547 : TALLOC_FREE(subreq);
5035 :
5036 14547 : if (state->conn->min_protocol >= PROTOCOL_SMB2_02) {
5037 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
5038 0 : return;
5039 : }
5040 :
5041 14547 : if (dialect_revision != SMB2_DIALECT_REVISION_2FF) {
5042 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
5043 0 : return;
5044 : }
5045 :
5046 : /* make sure we do not loop forever */
5047 14547 : state->conn->min_protocol = PROTOCOL_SMB2_02;
5048 :
5049 : /*
5050 : * send a SMB2 negprot, in order to negotiate
5051 : * the SMB2 dialect.
5052 : */
5053 14547 : subreq = smbXcli_negprot_smb2_subreq(state);
5054 14547 : if (tevent_req_nomem(subreq, req)) {
5055 0 : return;
5056 : }
5057 14547 : tevent_req_set_callback(subreq, smbXcli_negprot_smb2_done, req);
5058 14547 : return;
5059 : }
5060 :
5061 23389 : conn->smb2.server.security_mode = SVAL(body, 2);
5062 23389 : if (conn->protocol >= PROTOCOL_SMB3_11) {
5063 19299 : negotiate_context_count = SVAL(body, 6);
5064 : }
5065 :
5066 23389 : blob = data_blob_const(body + 8, 16);
5067 23389 : status = GUID_from_data_blob(&blob, &conn->smb2.server.guid);
5068 23389 : if (tevent_req_nterror(req, status)) {
5069 0 : return;
5070 : }
5071 :
5072 23389 : conn->smb2.server.capabilities = IVAL(body, 24);
5073 23389 : conn->smb2.server.max_trans_size= IVAL(body, 28);
5074 23389 : conn->smb2.server.max_read_size = IVAL(body, 32);
5075 23389 : conn->smb2.server.max_write_size= IVAL(body, 36);
5076 23389 : conn->smb2.server.system_time = BVAL(body, 40);
5077 23389 : conn->smb2.server.start_time = BVAL(body, 48);
5078 :
5079 23389 : security_offset = SVAL(body, 56);
5080 23389 : security_length = SVAL(body, 58);
5081 :
5082 23389 : if (security_offset != SMB2_HDR_BODY + iov[1].iov_len) {
5083 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
5084 0 : return;
5085 : }
5086 :
5087 23389 : if (security_length > iov[2].iov_len) {
5088 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
5089 0 : return;
5090 : }
5091 :
5092 23389 : conn->smb2.server.gss_blob = data_blob_talloc(conn,
5093 : iov[2].iov_base,
5094 : security_length);
5095 23389 : if (tevent_req_nomem(conn->smb2.server.gss_blob.data, req)) {
5096 0 : return;
5097 : }
5098 :
5099 23389 : if (conn->protocol >= PROTOCOL_SMB3_00) {
5100 19375 : conn->smb2.server.sign_algo = SMB2_SIGNING_AES128_CMAC;
5101 : } else {
5102 4014 : conn->smb2.server.sign_algo = SMB2_SIGNING_HMAC_SHA256;
5103 : }
5104 :
5105 23389 : if (conn->protocol < PROTOCOL_SMB3_11) {
5106 4090 : TALLOC_FREE(subreq);
5107 :
5108 4090 : if (conn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION) {
5109 64 : conn->smb2.server.cipher = SMB2_ENCRYPTION_AES128_CCM;
5110 : }
5111 :
5112 4090 : status = smbXcli_negprot_smb3_check_capabilities(req);
5113 4090 : if (tevent_req_nterror(req, status)) {
5114 0 : return;
5115 : }
5116 :
5117 4090 : tevent_req_done(req);
5118 4090 : return;
5119 : }
5120 :
5121 : /*
5122 : * Here we are now at SMB3_11, so encryption should be
5123 : * negotiated via context, not capabilities.
5124 : */
5125 :
5126 19299 : if (conn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION) {
5127 : /*
5128 : * Server set SMB2_CAP_ENCRYPTION capability,
5129 : * but *SHOULD* not, not *MUST* not. Just mask it off.
5130 : * NetApp seems to do this:
5131 : * BUG: https://bugzilla.samba.org/show_bug.cgi?id=13009
5132 : */
5133 0 : conn->smb2.server.capabilities &= ~SMB2_CAP_ENCRYPTION;
5134 : }
5135 :
5136 19299 : negotiate_context_offset = IVAL(body, 60);
5137 19299 : if (negotiate_context_offset < security_offset) {
5138 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
5139 0 : return;
5140 : }
5141 :
5142 19299 : ctx_ofs = negotiate_context_offset - security_offset;
5143 19299 : if (ctx_ofs > iov[2].iov_len) {
5144 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
5145 0 : return;
5146 : }
5147 19299 : avail = iov[2].iov_len - security_length;
5148 19299 : needed = iov[2].iov_len - ctx_ofs;
5149 19299 : if (needed > avail) {
5150 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
5151 0 : return;
5152 : }
5153 :
5154 19299 : negotiate_context_blob.data = (uint8_t *)iov[2].iov_base;
5155 19299 : negotiate_context_blob.length = iov[2].iov_len;
5156 :
5157 19299 : negotiate_context_blob.data += ctx_ofs;
5158 19299 : negotiate_context_blob.length -= ctx_ofs;
5159 :
5160 19299 : status = smb2_negotiate_context_parse(state,
5161 : negotiate_context_blob,
5162 : negotiate_context_count,
5163 : &c);
5164 19299 : if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
5165 0 : status = NT_STATUS_INVALID_NETWORK_RESPONSE;
5166 : }
5167 19299 : if (tevent_req_nterror(req, status)) {
5168 0 : return;
5169 : }
5170 :
5171 19299 : preauth = smb2_negotiate_context_find(&c,
5172 : SMB2_PREAUTH_INTEGRITY_CAPABILITIES);
5173 19299 : if (preauth == NULL) {
5174 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
5175 0 : return;
5176 : }
5177 :
5178 19299 : if (preauth->data.length < 6) {
5179 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
5180 0 : return;
5181 : }
5182 :
5183 19299 : hash_count = SVAL(preauth->data.data, 0);
5184 19299 : salt_length = SVAL(preauth->data.data, 2);
5185 19299 : hash_selected = SVAL(preauth->data.data, 4);
5186 :
5187 19299 : if (hash_count != 1) {
5188 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
5189 0 : return;
5190 : }
5191 :
5192 19299 : if (preauth->data.length != (6 + salt_length)) {
5193 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
5194 0 : return;
5195 : }
5196 :
5197 19299 : if (hash_selected != SMB2_PREAUTH_INTEGRITY_SHA512) {
5198 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
5199 0 : return;
5200 : }
5201 :
5202 19299 : sign_algo = smb2_negotiate_context_find(&c, SMB2_SIGNING_CAPABILITIES);
5203 19299 : if (sign_algo != NULL) {
5204 19299 : const struct smb3_signing_capabilities *client_sign_algos =
5205 19299 : &state->conn->smb2.client.smb3_capabilities.signing;
5206 19299 : bool found_selected = false;
5207 : uint16_t sign_algo_count;
5208 : uint16_t sign_algo_selected;
5209 :
5210 19299 : if (client_sign_algos->num_algos == 0) {
5211 : /*
5212 : * We didn't ask for SMB2_ENCRYPTION_CAPABILITIES
5213 : */
5214 0 : tevent_req_nterror(req,
5215 : NT_STATUS_INVALID_NETWORK_RESPONSE);
5216 0 : return;
5217 : }
5218 :
5219 19299 : if (sign_algo->data.length < 2) {
5220 0 : tevent_req_nterror(req,
5221 : NT_STATUS_INVALID_NETWORK_RESPONSE);
5222 0 : return;
5223 : }
5224 :
5225 19299 : sign_algo_count = SVAL(sign_algo->data.data, 0);
5226 19299 : if (sign_algo_count != 1) {
5227 0 : tevent_req_nterror(req,
5228 : NT_STATUS_INVALID_NETWORK_RESPONSE);
5229 0 : return;
5230 : }
5231 :
5232 19299 : if (sign_algo->data.length < (2 + 2 * sign_algo_count)) {
5233 0 : tevent_req_nterror(req,
5234 : NT_STATUS_INVALID_NETWORK_RESPONSE);
5235 0 : return;
5236 : }
5237 19299 : sign_algo_selected = SVAL(sign_algo->data.data, 2);
5238 :
5239 19299 : for (i = 0; i < client_sign_algos->num_algos; i++) {
5240 19299 : if (client_sign_algos->algos[i] == sign_algo_selected) {
5241 : /*
5242 : * We found a match
5243 : */
5244 18909 : found_selected = true;
5245 18909 : break;
5246 : }
5247 : }
5248 :
5249 19299 : if (!found_selected) {
5250 : /*
5251 : * The server send a sign_algo we didn't offer.
5252 : */
5253 0 : tevent_req_nterror(req,
5254 : NT_STATUS_INVALID_NETWORK_RESPONSE);
5255 0 : return;
5256 : }
5257 :
5258 19299 : conn->smb2.server.sign_algo = sign_algo_selected;
5259 : }
5260 :
5261 19299 : cipher = smb2_negotiate_context_find(&c, SMB2_ENCRYPTION_CAPABILITIES);
5262 19299 : if (cipher != NULL) {
5263 19103 : const struct smb3_encryption_capabilities *client_ciphers =
5264 19103 : &state->conn->smb2.client.smb3_capabilities.encryption;
5265 19103 : bool found_selected = false;
5266 : uint16_t cipher_count;
5267 : uint16_t cipher_selected;
5268 :
5269 19103 : if (client_ciphers->num_algos == 0) {
5270 : /*
5271 : * We didn't ask for SMB2_ENCRYPTION_CAPABILITIES
5272 : */
5273 0 : tevent_req_nterror(req,
5274 : NT_STATUS_INVALID_NETWORK_RESPONSE);
5275 0 : return;
5276 : }
5277 :
5278 19103 : if (cipher->data.length < 2) {
5279 0 : tevent_req_nterror(req,
5280 : NT_STATUS_INVALID_NETWORK_RESPONSE);
5281 0 : return;
5282 : }
5283 :
5284 19103 : cipher_count = SVAL(cipher->data.data, 0);
5285 19103 : if (cipher_count != 1) {
5286 0 : tevent_req_nterror(req,
5287 : NT_STATUS_INVALID_NETWORK_RESPONSE);
5288 0 : return;
5289 : }
5290 :
5291 19103 : if (cipher->data.length < (2 + 2 * cipher_count)) {
5292 0 : tevent_req_nterror(req,
5293 : NT_STATUS_INVALID_NETWORK_RESPONSE);
5294 0 : return;
5295 : }
5296 19103 : cipher_selected = SVAL(cipher->data.data, 2);
5297 :
5298 19103 : for (i = 0; i < client_ciphers->num_algos; i++) {
5299 19103 : if (cipher_selected == SMB2_ENCRYPTION_NONE) {
5300 : /*
5301 : * encryption not supported
5302 : */
5303 0 : found_selected = true;
5304 0 : break;
5305 : }
5306 19103 : if (client_ciphers->algos[i] == cipher_selected) {
5307 : /*
5308 : * We found a match
5309 : */
5310 18713 : found_selected = true;
5311 18713 : break;
5312 : }
5313 : }
5314 :
5315 19103 : if (!found_selected) {
5316 : /*
5317 : * The server send a cipher we didn't offer.
5318 : */
5319 0 : tevent_req_nterror(req,
5320 : NT_STATUS_INVALID_NETWORK_RESPONSE);
5321 0 : return;
5322 : }
5323 :
5324 19103 : conn->smb2.server.cipher = cipher_selected;
5325 : }
5326 :
5327 : /* First we hash the request */
5328 19299 : smb2cli_req_get_sent_iov(subreq, sent_iov);
5329 :
5330 19299 : rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_SHA512);
5331 19299 : if (rc < 0) {
5332 0 : tevent_req_nterror(req,
5333 : gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED));
5334 0 : return;
5335 : }
5336 :
5337 19299 : rc = gnutls_hash(hash_hnd,
5338 19299 : conn->smb2.preauth_sha512,
5339 : sizeof(conn->smb2.preauth_sha512));
5340 19299 : if (rc < 0) {
5341 0 : gnutls_hash_deinit(hash_hnd, NULL);
5342 0 : tevent_req_nterror(req,
5343 : gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED));
5344 0 : return;
5345 : }
5346 76806 : for (i = 0; i < 3; i++) {
5347 108735 : rc = gnutls_hash(hash_hnd,
5348 57897 : sent_iov[i].iov_base,
5349 : sent_iov[i].iov_len);
5350 57897 : if (rc < 0) {
5351 0 : gnutls_hash_deinit(hash_hnd, NULL);
5352 0 : tevent_req_nterror(req,
5353 : gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED));
5354 0 : return;
5355 : }
5356 : }
5357 :
5358 19299 : if (rc < 0) {
5359 0 : gnutls_hash_deinit(hash_hnd, NULL);
5360 0 : tevent_req_nterror(req,
5361 : gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED));
5362 0 : return;
5363 : }
5364 :
5365 : /* This resets the hash state */
5366 19299 : gnutls_hash_output(hash_hnd, conn->smb2.preauth_sha512);
5367 19299 : TALLOC_FREE(subreq);
5368 :
5369 : /* And now we hash the response */
5370 19299 : rc = gnutls_hash(hash_hnd,
5371 18909 : conn->smb2.preauth_sha512,
5372 : sizeof(conn->smb2.preauth_sha512));
5373 19299 : if (rc < 0) {
5374 0 : gnutls_hash_deinit(hash_hnd, NULL);
5375 0 : tevent_req_nterror(req,
5376 : gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED));
5377 0 : return;
5378 : }
5379 76806 : for (i = 0; i < 3; i++) {
5380 108735 : rc = gnutls_hash(hash_hnd,
5381 57897 : iov[i].iov_base,
5382 57897 : iov[i].iov_len);
5383 57897 : if (rc < 0) {
5384 0 : gnutls_hash_deinit(hash_hnd, NULL);
5385 0 : tevent_req_nterror(req,
5386 : gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED));
5387 0 : return;
5388 : }
5389 : }
5390 19299 : gnutls_hash_deinit(hash_hnd, conn->smb2.preauth_sha512);
5391 19299 : if (rc < 0) {
5392 0 : tevent_req_nterror(req,
5393 : NT_STATUS_UNSUCCESSFUL);
5394 0 : return;
5395 : }
5396 :
5397 19299 : status = smbXcli_negprot_smb3_check_capabilities(req);
5398 19299 : if (tevent_req_nterror(req, status)) {
5399 0 : return;
5400 : }
5401 :
5402 19299 : tevent_req_done(req);
5403 : }
5404 :
5405 23389 : static NTSTATUS smbXcli_negprot_smb3_check_capabilities(struct tevent_req *req)
5406 : {
5407 19887 : struct smbXcli_negprot_state *state =
5408 23389 : tevent_req_data(req,
5409 : struct smbXcli_negprot_state);
5410 23389 : struct smbXcli_conn *conn = state->conn;
5411 :
5412 66665 : return smb311_capabilities_check(&conn->smb2.client.smb3_capabilities,
5413 : "smbXcli_negprot",
5414 : DBGLVL_ERR,
5415 23389 : NT_STATUS_ACCESS_DENIED,
5416 : "client",
5417 : conn->protocol,
5418 23389 : conn->smb2.server.sign_algo,
5419 23389 : conn->smb2.server.cipher);
5420 : }
5421 :
5422 15903 : static NTSTATUS smbXcli_negprot_dispatch_incoming(struct smbXcli_conn *conn,
5423 : TALLOC_CTX *tmp_mem,
5424 : uint8_t *inbuf)
5425 : {
5426 15903 : size_t num_pending = talloc_array_length(conn->pending);
5427 : struct tevent_req *subreq;
5428 : struct smbXcli_req_state *substate;
5429 : struct tevent_req *req;
5430 : uint32_t protocol_magic;
5431 15903 : size_t inbuf_len = smb_len_nbt(inbuf);
5432 :
5433 15903 : if (num_pending != 1) {
5434 0 : return NT_STATUS_INTERNAL_ERROR;
5435 : }
5436 :
5437 15903 : if (inbuf_len < 4) {
5438 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
5439 : }
5440 :
5441 15903 : subreq = conn->pending[0];
5442 15903 : substate = tevent_req_data(subreq, struct smbXcli_req_state);
5443 15903 : req = tevent_req_callback_data(subreq, struct tevent_req);
5444 :
5445 15903 : protocol_magic = IVAL(inbuf, 4);
5446 :
5447 15903 : switch (protocol_magic) {
5448 0 : case SMB_MAGIC:
5449 0 : tevent_req_set_callback(subreq, smbXcli_negprot_smb1_done, req);
5450 0 : conn->dispatch_incoming = smb1cli_conn_dispatch_incoming;
5451 0 : return smb1cli_conn_dispatch_incoming(conn, tmp_mem, inbuf);
5452 :
5453 15903 : case SMB2_MAGIC:
5454 15903 : if (substate->smb2.recv_iov == NULL) {
5455 : /*
5456 : * For the SMB1 negprot we have move it.
5457 : */
5458 15903 : substate->smb2.recv_iov = substate->smb1.recv_iov;
5459 15903 : substate->smb1.recv_iov = NULL;
5460 : }
5461 :
5462 : /*
5463 : * we got an SMB2 answer, which consumed sequence number 0
5464 : * so we need to use 1 as the next one.
5465 : *
5466 : * we also need to set the current credits to 0
5467 : * as we consumed the initial one. The SMB2 answer
5468 : * hopefully grant us a new credit.
5469 : */
5470 15903 : conn->smb2.mid = 1;
5471 15903 : conn->smb2.cur_credits = 0;
5472 15903 : tevent_req_set_callback(subreq, smbXcli_negprot_smb2_done, req);
5473 15903 : conn->dispatch_incoming = smb2cli_conn_dispatch_incoming;
5474 15903 : return smb2cli_conn_dispatch_incoming(conn, tmp_mem, inbuf);
5475 : }
5476 :
5477 0 : DEBUG(10, ("Got non-SMB PDU\n"));
5478 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
5479 : }
5480 :
5481 29627 : NTSTATUS smbXcli_negprot_recv(struct tevent_req *req)
5482 : {
5483 29627 : return tevent_req_simple_recv_ntstatus(req);
5484 : }
5485 :
5486 9956 : NTSTATUS smbXcli_negprot(struct smbXcli_conn *conn,
5487 : uint32_t timeout_msec,
5488 : enum protocol_types min_protocol,
5489 : enum protocol_types max_protocol)
5490 : {
5491 9956 : TALLOC_CTX *frame = talloc_stackframe();
5492 : struct tevent_context *ev;
5493 : struct tevent_req *req;
5494 9956 : NTSTATUS status = NT_STATUS_NO_MEMORY;
5495 : bool ok;
5496 :
5497 9956 : if (smbXcli_conn_has_async_calls(conn)) {
5498 : /*
5499 : * Can't use sync call while an async call is in flight
5500 : */
5501 0 : status = NT_STATUS_INVALID_PARAMETER_MIX;
5502 0 : goto fail;
5503 : }
5504 9956 : ev = samba_tevent_context_init(frame);
5505 9956 : if (ev == NULL) {
5506 0 : goto fail;
5507 : }
5508 9956 : req = smbXcli_negprot_send(frame, ev, conn, timeout_msec,
5509 : min_protocol, max_protocol,
5510 : WINDOWS_CLIENT_PURE_SMB2_NEGPROT_INITIAL_CREDIT_ASK);
5511 9956 : if (req == NULL) {
5512 0 : goto fail;
5513 : }
5514 9956 : ok = tevent_req_poll_ntstatus(req, ev, &status);
5515 9956 : if (!ok) {
5516 0 : goto fail;
5517 : }
5518 9956 : status = smbXcli_negprot_recv(req);
5519 9956 : fail:
5520 9956 : TALLOC_FREE(frame);
5521 9956 : return status;
5522 : }
5523 :
5524 : struct smb2cli_validate_negotiate_info_state {
5525 : struct smbXcli_conn *conn;
5526 : DATA_BLOB in_input_buffer;
5527 : DATA_BLOB in_output_buffer;
5528 : DATA_BLOB out_input_buffer;
5529 : DATA_BLOB out_output_buffer;
5530 : uint16_t dialect;
5531 : };
5532 :
5533 : static void smb2cli_validate_negotiate_info_done(struct tevent_req *subreq);
5534 :
5535 4142 : struct tevent_req *smb2cli_validate_negotiate_info_send(TALLOC_CTX *mem_ctx,
5536 : struct tevent_context *ev,
5537 : struct smbXcli_conn *conn,
5538 : uint32_t timeout_msec,
5539 : struct smbXcli_session *session,
5540 : struct smbXcli_tcon *tcon)
5541 : {
5542 : struct tevent_req *req;
5543 : struct smb2cli_validate_negotiate_info_state *state;
5544 : uint8_t *buf;
5545 4142 : uint16_t dialect_count = 0;
5546 : struct tevent_req *subreq;
5547 : bool _save_should_sign;
5548 : size_t i;
5549 :
5550 4142 : req = tevent_req_create(mem_ctx, &state,
5551 : struct smb2cli_validate_negotiate_info_state);
5552 4142 : if (req == NULL) {
5553 0 : return NULL;
5554 : }
5555 4142 : state->conn = conn;
5556 :
5557 4142 : state->in_input_buffer = data_blob_talloc_zero(state,
5558 : 4 + 16 + 1 + 1 + 2);
5559 4142 : if (tevent_req_nomem(state->in_input_buffer.data, req)) {
5560 0 : return tevent_req_post(req, ev);
5561 : }
5562 4142 : buf = state->in_input_buffer.data;
5563 :
5564 4142 : if (state->conn->max_protocol >= PROTOCOL_SMB3_00) {
5565 3956 : SIVAL(buf, 0, conn->smb2.client.capabilities);
5566 : } else {
5567 186 : SIVAL(buf, 0, 0); /* Capabilities */
5568 : }
5569 4142 : if (state->conn->max_protocol >= PROTOCOL_SMB2_10) {
5570 : NTSTATUS status;
5571 4086 : struct GUID_ndr_buf guid_buf = { .buf = {0}, };
5572 :
5573 4086 : status = GUID_to_ndr_buf(&conn->smb2.client.guid,
5574 : &guid_buf);
5575 4086 : if (!NT_STATUS_IS_OK(status)) {
5576 0 : return NULL;
5577 : }
5578 4086 : memcpy(buf+4, guid_buf.buf, 16); /* ClientGuid */
5579 : } else {
5580 56 : memset(buf+4, 0, 16); /* ClientGuid */
5581 : }
5582 4142 : if (state->conn->min_protocol >= PROTOCOL_SMB2_02) {
5583 2820 : SCVAL(buf, 20, conn->smb2.client.security_mode);
5584 : } else {
5585 1322 : SCVAL(buf, 20, 0);
5586 : }
5587 4142 : SCVAL(buf, 21, 0); /* reserved */
5588 :
5589 24852 : for (i=0; i < ARRAY_SIZE(smb2cli_prots); i++) {
5590 : bool ok;
5591 : size_t ofs;
5592 :
5593 20710 : if (smb2cli_prots[i].proto < state->conn->min_protocol) {
5594 272 : continue;
5595 : }
5596 :
5597 20438 : if (smb2cli_prots[i].proto > state->conn->max_protocol) {
5598 684 : continue;
5599 : }
5600 :
5601 19754 : if (smb2cli_prots[i].proto == state->conn->protocol) {
5602 4142 : state->dialect = smb2cli_prots[i].smb2_dialect;
5603 : }
5604 :
5605 19754 : ofs = state->in_input_buffer.length;
5606 19754 : ok = data_blob_realloc(state, &state->in_input_buffer,
5607 : ofs + 2);
5608 19754 : if (!ok) {
5609 0 : tevent_req_oom(req);
5610 0 : return tevent_req_post(req, ev);
5611 : }
5612 :
5613 19754 : buf = state->in_input_buffer.data;
5614 19754 : SSVAL(buf, ofs, smb2cli_prots[i].smb2_dialect);
5615 :
5616 19754 : dialect_count++;
5617 : }
5618 4142 : buf = state->in_input_buffer.data;
5619 4142 : SSVAL(buf, 22, dialect_count);
5620 :
5621 4142 : _save_should_sign = smb2cli_tcon_is_signing_on(tcon);
5622 4142 : smb2cli_tcon_should_sign(tcon, true);
5623 4142 : subreq = smb2cli_ioctl_send(state, ev, conn,
5624 : timeout_msec, session, tcon,
5625 : UINT64_MAX, /* in_fid_persistent */
5626 : UINT64_MAX, /* in_fid_volatile */
5627 : FSCTL_VALIDATE_NEGOTIATE_INFO,
5628 : 0, /* in_max_input_length */
5629 4142 : &state->in_input_buffer,
5630 : 24, /* in_max_output_length */
5631 4142 : &state->in_output_buffer,
5632 : SMB2_IOCTL_FLAG_IS_FSCTL);
5633 4142 : smb2cli_tcon_should_sign(tcon, _save_should_sign);
5634 4142 : if (tevent_req_nomem(subreq, req)) {
5635 0 : return tevent_req_post(req, ev);
5636 : }
5637 4142 : tevent_req_set_callback(subreq,
5638 : smb2cli_validate_negotiate_info_done,
5639 : req);
5640 :
5641 4142 : return req;
5642 : }
5643 :
5644 4142 : static void smb2cli_validate_negotiate_info_done(struct tevent_req *subreq)
5645 : {
5646 2951 : struct tevent_req *req =
5647 4142 : tevent_req_callback_data(subreq,
5648 : struct tevent_req);
5649 2951 : struct smb2cli_validate_negotiate_info_state *state =
5650 4142 : tevent_req_data(req,
5651 : struct smb2cli_validate_negotiate_info_state);
5652 : NTSTATUS status;
5653 : const uint8_t *buf;
5654 : uint32_t capabilities;
5655 : DATA_BLOB guid_blob;
5656 : struct GUID server_guid;
5657 : uint16_t security_mode;
5658 : uint16_t dialect;
5659 :
5660 4142 : status = smb2cli_ioctl_recv(subreq, state,
5661 : &state->out_input_buffer,
5662 : &state->out_output_buffer);
5663 4142 : TALLOC_FREE(subreq);
5664 :
5665 : /*
5666 : * This response must be signed correctly for
5667 : * these "normal" error codes to be processed.
5668 : * If the packet wasn't signed correctly we will get
5669 : * NT_STATUS_ACCESS_DENIED or NT_STATUS_HMAC_NOT_SUPPORTED,
5670 : * or NT_STATUS_INVALID_NETWORK_RESPONSE
5671 : * from smb2_signing_check_pdu().
5672 : *
5673 : * We must never ignore the above errors here.
5674 : */
5675 :
5676 4142 : if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED)) {
5677 : /*
5678 : * The response was signed, but not supported
5679 : *
5680 : * Older Windows and Samba releases return
5681 : * NT_STATUS_FILE_CLOSED.
5682 : */
5683 64 : tevent_req_done(req);
5684 64 : return;
5685 : }
5686 4078 : if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_DEVICE_REQUEST)) {
5687 : /*
5688 : * The response was signed, but not supported
5689 : *
5690 : * This is returned by the NTVFS based Samba 4.x file server
5691 : * for file shares.
5692 : */
5693 548 : tevent_req_done(req);
5694 548 : return;
5695 : }
5696 3530 : if (NT_STATUS_EQUAL(status, NT_STATUS_FS_DRIVER_REQUIRED)) {
5697 : /*
5698 : * The response was signed, but not supported
5699 : *
5700 : * This is returned by the NTVFS based Samba 4.x file server
5701 : * for ipc shares.
5702 : */
5703 1077 : tevent_req_done(req);
5704 1077 : return;
5705 : }
5706 2453 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
5707 : /*
5708 : * The response was signed, but not supported
5709 : *
5710 : * This might be returned by older Windows versions or by
5711 : * NetApp SMB server implementations.
5712 : *
5713 : * See
5714 : *
5715 : * https://blogs.msdn.microsoft.com/openspecification/2012/06/28/smb3-secure-dialect-negotiation/
5716 : *
5717 : */
5718 0 : tevent_req_done(req);
5719 0 : return;
5720 : }
5721 2453 : if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
5722 : /*
5723 : * The response was signed, but not supported
5724 : *
5725 : * This might be returned by NetApp Ontap 7.3.7 SMB server
5726 : * implementations.
5727 : *
5728 : * BUG: https://bugzilla.samba.org/show_bug.cgi?id=14607
5729 : *
5730 : */
5731 0 : tevent_req_done(req);
5732 0 : return;
5733 : }
5734 2453 : if (tevent_req_nterror(req, status)) {
5735 0 : return;
5736 : }
5737 :
5738 2453 : if (state->out_output_buffer.length != 24) {
5739 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
5740 0 : return;
5741 : }
5742 :
5743 2453 : buf = state->out_output_buffer.data;
5744 :
5745 2453 : capabilities = IVAL(buf, 0);
5746 2453 : guid_blob = data_blob_const(buf + 4, 16);
5747 2453 : status = GUID_from_data_blob(&guid_blob, &server_guid);
5748 2453 : if (tevent_req_nterror(req, status)) {
5749 0 : return;
5750 : }
5751 2453 : security_mode = CVAL(buf, 20);
5752 2453 : dialect = SVAL(buf, 22);
5753 :
5754 2453 : if (capabilities != state->conn->smb2.server.capabilities) {
5755 0 : tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
5756 0 : return;
5757 : }
5758 :
5759 2453 : if (!GUID_equal(&server_guid, &state->conn->smb2.server.guid)) {
5760 0 : tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
5761 0 : return;
5762 : }
5763 :
5764 2453 : if (security_mode != state->conn->smb2.server.security_mode) {
5765 0 : tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
5766 0 : return;
5767 : }
5768 :
5769 2453 : if (dialect != state->dialect) {
5770 0 : tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
5771 0 : return;
5772 : }
5773 :
5774 2453 : tevent_req_done(req);
5775 : }
5776 :
5777 4142 : NTSTATUS smb2cli_validate_negotiate_info_recv(struct tevent_req *req)
5778 : {
5779 4142 : return tevent_req_simple_recv_ntstatus(req);
5780 : }
5781 :
5782 39912 : static int smbXcli_session_destructor(struct smbXcli_session *session)
5783 : {
5784 39912 : if (session->conn == NULL) {
5785 506 : return 0;
5786 : }
5787 :
5788 39406 : DLIST_REMOVE(session->conn->sessions, session);
5789 38889 : return 0;
5790 : }
5791 :
5792 43933 : struct smbXcli_session *smbXcli_session_create(TALLOC_CTX *mem_ctx,
5793 : struct smbXcli_conn *conn)
5794 : {
5795 : struct smbXcli_session *session;
5796 : NTSTATUS status;
5797 :
5798 43933 : session = talloc_zero(mem_ctx, struct smbXcli_session);
5799 43933 : if (session == NULL) {
5800 0 : return NULL;
5801 : }
5802 43933 : session->smb2 = talloc_zero(session, struct smb2cli_session);
5803 43933 : if (session->smb2 == NULL) {
5804 0 : talloc_free(session);
5805 0 : return NULL;
5806 : }
5807 43933 : talloc_set_destructor(session, smbXcli_session_destructor);
5808 :
5809 82747 : status = smb2_signing_key_sign_create(session->smb2,
5810 43933 : conn->smb2.server.sign_algo,
5811 : NULL, /* no master key */
5812 : NULL, /* derivations */
5813 43933 : &session->smb2->signing_key);
5814 43933 : if (!NT_STATUS_IS_OK(status)) {
5815 0 : talloc_free(session);
5816 0 : return NULL;
5817 : }
5818 :
5819 43933 : DLIST_ADD_END(conn->sessions, session);
5820 43933 : session->conn = conn;
5821 :
5822 82747 : status = smb2_signing_key_sign_create(session,
5823 43933 : conn->smb2.server.sign_algo,
5824 : NULL, /* no master key */
5825 : NULL, /* derivations */
5826 : &session->smb2_channel.signing_key);
5827 43933 : if (!NT_STATUS_IS_OK(status)) {
5828 0 : talloc_free(session);
5829 0 : return NULL;
5830 : }
5831 :
5832 44455 : memcpy(session->smb2_channel.preauth_sha512,
5833 43933 : conn->smb2.preauth_sha512,
5834 : sizeof(session->smb2_channel.preauth_sha512));
5835 :
5836 43933 : return session;
5837 : }
5838 :
5839 18 : struct smbXcli_session *smbXcli_session_shallow_copy(TALLOC_CTX *mem_ctx,
5840 : struct smbXcli_session *src)
5841 : {
5842 : struct smbXcli_session *session;
5843 : struct timespec ts;
5844 : NTTIME nt;
5845 :
5846 18 : session = talloc_zero(mem_ctx, struct smbXcli_session);
5847 18 : if (session == NULL) {
5848 0 : return NULL;
5849 : }
5850 18 : session->smb2 = talloc_zero(session, struct smb2cli_session);
5851 18 : if (session->smb2 == NULL) {
5852 0 : talloc_free(session);
5853 0 : return NULL;
5854 : }
5855 :
5856 : /*
5857 : * Note we keep a pointer to the session keys of the
5858 : * main session and rely on the caller to free the
5859 : * shallow copy first!
5860 : */
5861 18 : session->conn = src->conn;
5862 18 : *session->smb2 = *src->smb2;
5863 18 : session->smb2_channel = src->smb2_channel;
5864 18 : session->disconnect_expired = src->disconnect_expired;
5865 :
5866 : /*
5867 : * This is only supposed to be called in test code
5868 : * but we should not reuse nonces!
5869 : *
5870 : * Add the current timestamp as NTTIME to nonce_high
5871 : * and set nonce_low to a value we can recognize in captures.
5872 : */
5873 18 : clock_gettime_mono(&ts);
5874 18 : nt = unix_timespec_to_nt_time(ts);
5875 18 : nt &= session->smb2->nonce_high_max;
5876 18 : if (nt == session->smb2->nonce_high_max || nt < UINT8_MAX) {
5877 0 : talloc_free(session);
5878 0 : return NULL;
5879 : }
5880 18 : session->smb2->nonce_high += nt;
5881 18 : session->smb2->nonce_low = UINT32_MAX;
5882 :
5883 18 : DLIST_ADD_END(src->conn->sessions, session);
5884 18 : talloc_set_destructor(session, smbXcli_session_destructor);
5885 :
5886 18 : return session;
5887 : }
5888 :
5889 14198 : bool smbXcli_session_is_guest(struct smbXcli_session *session)
5890 : {
5891 14198 : if (session == NULL) {
5892 0 : return false;
5893 : }
5894 :
5895 14198 : if (session->conn == NULL) {
5896 0 : return false;
5897 : }
5898 :
5899 14198 : if (session->conn->mandatory_signing) {
5900 3115 : return false;
5901 : }
5902 :
5903 11083 : if (session->conn->protocol >= PROTOCOL_SMB2_02) {
5904 8386 : if (session->smb2->session_flags & SMB2_SESSION_FLAG_IS_GUEST) {
5905 16 : return true;
5906 : }
5907 8370 : return false;
5908 : }
5909 :
5910 2697 : if (session->smb1.action & SMB_SETUP_GUEST) {
5911 0 : return true;
5912 : }
5913 :
5914 2697 : return false;
5915 : }
5916 :
5917 72570 : bool smbXcli_session_is_authenticated(struct smbXcli_session *session)
5918 : {
5919 : const DATA_BLOB *application_key;
5920 :
5921 72570 : if (session == NULL) {
5922 0 : return false;
5923 : }
5924 :
5925 72570 : if (session->conn == NULL) {
5926 0 : return false;
5927 : }
5928 :
5929 : /*
5930 : * If we have an application key we had a session key negotiated
5931 : * at auth time.
5932 : */
5933 72570 : if (session->conn->protocol >= PROTOCOL_SMB2_02) {
5934 72570 : if (!smb2_signing_key_valid(session->smb2->application_key)) {
5935 1882 : return false;
5936 : }
5937 70684 : application_key = &session->smb2->application_key->blob;
5938 : } else {
5939 0 : application_key = &session->smb1.application_key;
5940 : }
5941 :
5942 70684 : if (application_key->length == 0) {
5943 0 : return false;
5944 : }
5945 :
5946 70684 : return true;
5947 : }
5948 :
5949 0 : NTSTATUS smb2cli_session_signing_key(struct smbXcli_session *session,
5950 : TALLOC_CTX *mem_ctx,
5951 : DATA_BLOB *key)
5952 : {
5953 0 : const struct smb2_signing_key *sig = NULL;
5954 :
5955 0 : if (session->conn == NULL) {
5956 0 : return NT_STATUS_NO_USER_SESSION_KEY;
5957 : }
5958 :
5959 : /*
5960 : * Use channel signing key if there is one, otherwise fallback
5961 : * to session.
5962 : */
5963 :
5964 0 : if (smb2_signing_key_valid(session->smb2_channel.signing_key)) {
5965 0 : sig = session->smb2_channel.signing_key;
5966 0 : } else if (smb2_signing_key_valid(session->smb2->signing_key)) {
5967 0 : sig = session->smb2->signing_key;
5968 : } else {
5969 0 : return NT_STATUS_NO_USER_SESSION_KEY;
5970 : }
5971 :
5972 0 : *key = data_blob_dup_talloc(mem_ctx, sig->blob);
5973 0 : if (key->data == NULL) {
5974 0 : return NT_STATUS_NO_MEMORY;
5975 : }
5976 :
5977 0 : return NT_STATUS_OK;
5978 : }
5979 :
5980 0 : NTSTATUS smb2cli_session_encryption_key(struct smbXcli_session *session,
5981 : TALLOC_CTX *mem_ctx,
5982 : DATA_BLOB *key)
5983 : {
5984 0 : if (session->conn == NULL) {
5985 0 : return NT_STATUS_NO_USER_SESSION_KEY;
5986 : }
5987 :
5988 0 : if (session->conn->protocol < PROTOCOL_SMB3_00) {
5989 0 : return NT_STATUS_NO_USER_SESSION_KEY;
5990 : }
5991 :
5992 0 : if (!smb2_signing_key_valid(session->smb2->encryption_key)) {
5993 0 : return NT_STATUS_NO_USER_SESSION_KEY;
5994 : }
5995 :
5996 0 : *key = data_blob_dup_talloc(mem_ctx, session->smb2->encryption_key->blob);
5997 0 : if (key->data == NULL) {
5998 0 : return NT_STATUS_NO_MEMORY;
5999 : }
6000 :
6001 0 : return NT_STATUS_OK;
6002 : }
6003 :
6004 0 : NTSTATUS smb2cli_session_decryption_key(struct smbXcli_session *session,
6005 : TALLOC_CTX *mem_ctx,
6006 : DATA_BLOB *key)
6007 : {
6008 0 : if (session->conn == NULL) {
6009 0 : return NT_STATUS_NO_USER_SESSION_KEY;
6010 : }
6011 :
6012 0 : if (session->conn->protocol < PROTOCOL_SMB3_00) {
6013 0 : return NT_STATUS_NO_USER_SESSION_KEY;
6014 : }
6015 :
6016 0 : if (!smb2_signing_key_valid(session->smb2->decryption_key)) {
6017 0 : return NT_STATUS_NO_USER_SESSION_KEY;
6018 : }
6019 :
6020 0 : *key = data_blob_dup_talloc(mem_ctx, session->smb2->decryption_key->blob);
6021 0 : if (key->data == NULL) {
6022 0 : return NT_STATUS_NO_MEMORY;
6023 : }
6024 :
6025 0 : return NT_STATUS_OK;
6026 : }
6027 :
6028 17278 : NTSTATUS smbXcli_session_application_key(struct smbXcli_session *session,
6029 : TALLOC_CTX *mem_ctx,
6030 : DATA_BLOB *key)
6031 : {
6032 : const DATA_BLOB *application_key;
6033 :
6034 17278 : *key = data_blob_null;
6035 :
6036 17278 : if (session->conn == NULL) {
6037 0 : return NT_STATUS_NO_USER_SESSION_KEY;
6038 : }
6039 :
6040 17278 : if (session->conn->protocol >= PROTOCOL_SMB2_02) {
6041 16923 : if (!smb2_signing_key_valid(session->smb2->application_key)) {
6042 336 : return NT_STATUS_NO_USER_SESSION_KEY;
6043 : }
6044 16587 : application_key = &session->smb2->application_key->blob;
6045 : } else {
6046 355 : application_key = &session->smb1.application_key;
6047 : }
6048 :
6049 16942 : if (application_key->length == 0) {
6050 16 : return NT_STATUS_NO_USER_SESSION_KEY;
6051 : }
6052 :
6053 16926 : *key = data_blob_dup_talloc(mem_ctx, *application_key);
6054 16926 : if (key->data == NULL) {
6055 0 : return NT_STATUS_NO_MEMORY;
6056 : }
6057 :
6058 16926 : return NT_STATUS_OK;
6059 : }
6060 :
6061 8 : void smbXcli_session_set_disconnect_expired(struct smbXcli_session *session)
6062 : {
6063 8 : session->disconnect_expired = true;
6064 8 : }
6065 :
6066 859 : uint16_t smb1cli_session_current_id(struct smbXcli_session *session)
6067 : {
6068 859 : return session->smb1.session_id;
6069 : }
6070 :
6071 503195 : void smb1cli_session_set_id(struct smbXcli_session *session,
6072 : uint16_t session_id)
6073 : {
6074 503195 : session->smb1.session_id = session_id;
6075 503195 : }
6076 :
6077 5939 : void smb1cli_session_set_action(struct smbXcli_session *session,
6078 : uint16_t action)
6079 : {
6080 5939 : session->smb1.action = action;
6081 5939 : }
6082 :
6083 5718 : NTSTATUS smb1cli_session_set_session_key(struct smbXcli_session *session,
6084 : const DATA_BLOB _session_key)
6085 : {
6086 5718 : struct smbXcli_conn *conn = session->conn;
6087 : uint8_t session_key[16];
6088 :
6089 5718 : if (conn == NULL) {
6090 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
6091 : }
6092 :
6093 5718 : if (session->smb1.application_key.length != 0) {
6094 : /*
6095 : * TODO: do not allow this...
6096 : *
6097 : * return NT_STATUS_INVALID_PARAMETER_MIX;
6098 : */
6099 27 : data_blob_clear_free(&session->smb1.application_key);
6100 27 : session->smb1.protected_key = false;
6101 : }
6102 :
6103 5718 : if (_session_key.length == 0) {
6104 0 : return NT_STATUS_OK;
6105 : }
6106 :
6107 5718 : ZERO_STRUCT(session_key);
6108 5850 : memcpy(session_key, _session_key.data,
6109 5718 : MIN(_session_key.length, sizeof(session_key)));
6110 :
6111 5718 : session->smb1.application_key = data_blob_talloc(session,
6112 : session_key,
6113 : sizeof(session_key));
6114 5718 : ZERO_STRUCT(session_key);
6115 5718 : if (session->smb1.application_key.data == NULL) {
6116 0 : return NT_STATUS_NO_MEMORY;
6117 : }
6118 :
6119 5718 : session->smb1.protected_key = false;
6120 :
6121 5718 : return NT_STATUS_OK;
6122 : }
6123 :
6124 4712 : NTSTATUS smb1cli_session_protect_session_key(struct smbXcli_session *session)
6125 : {
6126 : NTSTATUS status;
6127 :
6128 4712 : if (session->smb1.protected_key) {
6129 : /* already protected */
6130 0 : return NT_STATUS_OK;
6131 : }
6132 :
6133 4712 : if (session->smb1.application_key.length != 16) {
6134 37 : return NT_STATUS_INVALID_PARAMETER_MIX;
6135 : }
6136 :
6137 4675 : status = smb_key_derivation(session->smb1.application_key.data,
6138 : session->smb1.application_key.length,
6139 : session->smb1.application_key.data);
6140 4675 : if (!NT_STATUS_IS_OK(status)) {
6141 0 : return status;
6142 : }
6143 :
6144 4675 : session->smb1.protected_key = true;
6145 :
6146 4675 : return NT_STATUS_OK;
6147 : }
6148 :
6149 43046 : uint8_t smb2cli_session_security_mode(struct smbXcli_session *session)
6150 : {
6151 43046 : struct smbXcli_conn *conn = session->conn;
6152 43046 : uint8_t security_mode = 0;
6153 :
6154 43046 : if (conn == NULL) {
6155 0 : return security_mode;
6156 : }
6157 :
6158 43046 : security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED;
6159 43046 : if (conn->mandatory_signing) {
6160 14645 : security_mode |= SMB2_NEGOTIATE_SIGNING_REQUIRED;
6161 : }
6162 43046 : if (session->smb2->should_sign) {
6163 1510 : security_mode |= SMB2_NEGOTIATE_SIGNING_REQUIRED;
6164 : }
6165 :
6166 42654 : return security_mode;
6167 : }
6168 :
6169 56397 : uint64_t smb2cli_session_current_id(struct smbXcli_session *session)
6170 : {
6171 56397 : return session->smb2->session_id;
6172 : }
6173 :
6174 384 : uint16_t smb2cli_session_get_flags(struct smbXcli_session *session)
6175 : {
6176 384 : return session->smb2->session_flags;
6177 : }
6178 :
6179 40121 : void smb2cli_session_set_id_and_flags(struct smbXcli_session *session,
6180 : uint64_t session_id,
6181 : uint16_t session_flags)
6182 : {
6183 40121 : session->smb2->session_id = session_id;
6184 40121 : session->smb2->session_flags = session_flags;
6185 40121 : }
6186 :
6187 915 : void smb2cli_session_increment_channel_sequence(struct smbXcli_session *session)
6188 : {
6189 915 : session->smb2->channel_sequence += 1;
6190 915 : }
6191 :
6192 628 : uint16_t smb2cli_session_reset_channel_sequence(struct smbXcli_session *session,
6193 : uint16_t channel_sequence)
6194 : {
6195 : uint16_t prev_cs;
6196 :
6197 628 : prev_cs = session->smb2->channel_sequence;
6198 628 : session->smb2->channel_sequence = channel_sequence;
6199 :
6200 628 : return prev_cs;
6201 : }
6202 :
6203 408 : uint16_t smb2cli_session_current_channel_sequence(struct smbXcli_session *session)
6204 : {
6205 408 : return session->smb2->channel_sequence;
6206 : }
6207 :
6208 466 : void smb2cli_session_start_replay(struct smbXcli_session *session)
6209 : {
6210 466 : session->smb2->replay_active = true;
6211 466 : }
6212 :
6213 426 : void smb2cli_session_stop_replay(struct smbXcli_session *session)
6214 : {
6215 426 : session->smb2->replay_active = false;
6216 426 : }
6217 :
6218 40 : void smb2cli_session_require_signed_response(struct smbXcli_session *session,
6219 : bool require_signed_response)
6220 : {
6221 40 : session->smb2->require_signed_response = require_signed_response;
6222 40 : }
6223 :
6224 56530 : NTSTATUS smb2cli_session_update_preauth(struct smbXcli_session *session,
6225 : const struct iovec *iov)
6226 : {
6227 56530 : gnutls_hash_hd_t hash_hnd = NULL;
6228 : size_t i;
6229 : int rc;
6230 :
6231 56530 : if (session->conn == NULL) {
6232 0 : return NT_STATUS_INTERNAL_ERROR;
6233 : }
6234 :
6235 56530 : if (session->conn->protocol < PROTOCOL_SMB3_11) {
6236 6142 : return NT_STATUS_OK;
6237 : }
6238 :
6239 50388 : if (smb2_signing_key_valid(session->smb2_channel.signing_key)) {
6240 286 : return NT_STATUS_OK;
6241 : }
6242 :
6243 50102 : rc = gnutls_hash_init(&hash_hnd,
6244 : GNUTLS_DIG_SHA512);
6245 50102 : if (rc < 0) {
6246 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
6247 : }
6248 :
6249 50102 : rc = gnutls_hash(hash_hnd,
6250 50102 : session->smb2_channel.preauth_sha512,
6251 : sizeof(session->smb2_channel.preauth_sha512));
6252 50102 : if (rc < 0) {
6253 0 : gnutls_hash_deinit(hash_hnd, NULL);
6254 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
6255 : }
6256 200014 : for (i = 0; i < 3; i++) {
6257 289335 : rc = gnutls_hash(hash_hnd,
6258 150306 : iov[i].iov_base,
6259 150306 : iov[i].iov_len);
6260 150306 : if (rc < 0) {
6261 0 : gnutls_hash_deinit(hash_hnd, NULL);
6262 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
6263 : }
6264 : }
6265 50102 : gnutls_hash_deinit(hash_hnd, session->smb2_channel.preauth_sha512);
6266 :
6267 50102 : return NT_STATUS_OK;
6268 : }
6269 :
6270 21314 : NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session,
6271 : const DATA_BLOB _session_key,
6272 : const struct iovec *recv_iov)
6273 : {
6274 21314 : struct smbXcli_conn *conn = session->conn;
6275 21314 : uint16_t no_sign_flags = 0;
6276 21314 : bool check_signature = true;
6277 : uint32_t hdr_flags;
6278 : NTSTATUS status;
6279 21314 : struct smb2_signing_derivations derivations = {
6280 : .signing = NULL,
6281 : };
6282 21314 : DATA_BLOB preauth_hash = data_blob_null;
6283 21314 : size_t nonce_size = 0;
6284 :
6285 21314 : if (conn == NULL) {
6286 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
6287 : }
6288 :
6289 21314 : if (recv_iov[0].iov_len != SMB2_HDR_BODY) {
6290 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
6291 : }
6292 :
6293 21314 : if (!conn->mandatory_signing) {
6294 : /*
6295 : * only allow guest sessions without
6296 : * mandatory signing.
6297 : *
6298 : * If we try an authentication with username != ""
6299 : * and the server let us in without verifying the
6300 : * password we don't have a negotiated session key
6301 : * for signing.
6302 : */
6303 11931 : no_sign_flags = SMB2_SESSION_FLAG_IS_GUEST;
6304 : }
6305 :
6306 21314 : if (session->smb2->session_flags & no_sign_flags) {
6307 2 : session->smb2->should_sign = false;
6308 2 : return NT_STATUS_OK;
6309 : }
6310 :
6311 21312 : if (smb2_signing_key_valid(session->smb2->signing_key)) {
6312 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
6313 : }
6314 :
6315 21312 : if (conn->protocol >= PROTOCOL_SMB3_11) {
6316 17411 : preauth_hash = data_blob_const(session->smb2_channel.preauth_sha512,
6317 : sizeof(session->smb2_channel.preauth_sha512));
6318 : }
6319 :
6320 21312 : smb2_signing_derivations_fill_const_stack(&derivations,
6321 : conn->protocol,
6322 : preauth_hash);
6323 :
6324 39561 : status = smb2_signing_key_sign_create(session->smb2,
6325 21312 : conn->smb2.server.sign_algo,
6326 : &_session_key,
6327 : derivations.signing,
6328 21312 : &session->smb2->signing_key);
6329 21312 : if (!NT_STATUS_IS_OK(status)) {
6330 0 : return status;
6331 : }
6332 :
6333 39561 : status = smb2_signing_key_cipher_create(session->smb2,
6334 21312 : conn->smb2.server.cipher,
6335 : &_session_key,
6336 : derivations.cipher_c2s,
6337 21312 : &session->smb2->encryption_key);
6338 21312 : if (!NT_STATUS_IS_OK(status)) {
6339 0 : return status;
6340 : }
6341 :
6342 39561 : status = smb2_signing_key_cipher_create(session->smb2,
6343 21312 : conn->smb2.server.cipher,
6344 : &_session_key,
6345 : derivations.cipher_s2c,
6346 21312 : &session->smb2->decryption_key);
6347 21312 : if (!NT_STATUS_IS_OK(status)) {
6348 0 : return status;
6349 : }
6350 :
6351 39561 : status = smb2_signing_key_sign_create(session->smb2,
6352 21312 : conn->smb2.server.sign_algo,
6353 : &_session_key,
6354 : derivations.application,
6355 21312 : &session->smb2->application_key);
6356 21312 : if (!NT_STATUS_IS_OK(status)) {
6357 0 : return status;
6358 : }
6359 :
6360 39561 : status = smb2_signing_key_copy(session,
6361 21312 : session->smb2->signing_key,
6362 : &session->smb2_channel.signing_key);
6363 21312 : if (!NT_STATUS_IS_OK(status)) {
6364 0 : return status;
6365 : }
6366 :
6367 21312 : check_signature = conn->mandatory_signing;
6368 :
6369 21312 : hdr_flags = IVAL(recv_iov[0].iov_base, SMB2_HDR_FLAGS);
6370 21312 : if (hdr_flags & SMB2_HDR_FLAG_SIGNED) {
6371 : /*
6372 : * Sadly some vendors don't sign the
6373 : * final SMB2 session setup response
6374 : *
6375 : * At least Windows and Samba are always doing this
6376 : * if there's a session key available.
6377 : *
6378 : * We only check the signature if it's mandatory
6379 : * or SMB2_HDR_FLAG_SIGNED is provided.
6380 : */
6381 21312 : check_signature = true;
6382 : }
6383 :
6384 21312 : if (conn->protocol >= PROTOCOL_SMB3_11) {
6385 17023 : check_signature = true;
6386 : }
6387 :
6388 20924 : if (check_signature) {
6389 21312 : status = smb2_signing_check_pdu(session->smb2_channel.signing_key,
6390 : recv_iov, 3);
6391 21312 : if (!NT_STATUS_IS_OK(status)) {
6392 0 : return status;
6393 : }
6394 : }
6395 :
6396 21312 : session->smb2->should_sign = false;
6397 21312 : session->smb2->should_encrypt = false;
6398 :
6399 21312 : if (conn->desire_signing) {
6400 9383 : session->smb2->should_sign = true;
6401 : }
6402 :
6403 21312 : if (conn->smb2.server.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) {
6404 8460 : session->smb2->should_sign = true;
6405 : }
6406 :
6407 21312 : if (session->smb2->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) {
6408 0 : session->smb2->should_encrypt = true;
6409 : }
6410 :
6411 21312 : if (conn->protocol < PROTOCOL_SMB3_00) {
6412 3845 : session->smb2->should_encrypt = false;
6413 : }
6414 :
6415 21312 : if (conn->smb2.server.cipher == 0) {
6416 4040 : session->smb2->should_encrypt = false;
6417 : }
6418 :
6419 : /*
6420 : * CCM and GCM algorithms must never have their
6421 : * nonce wrap, or the security of the whole
6422 : * communication and the keys is destroyed.
6423 : * We must drop the connection once we have
6424 : * transfered too much data.
6425 : *
6426 : * NOTE: We assume nonces greater than 8 bytes.
6427 : */
6428 21312 : generate_nonce_buffer((uint8_t *)&session->smb2->nonce_high_random,
6429 : sizeof(session->smb2->nonce_high_random));
6430 21312 : switch (conn->smb2.server.cipher) {
6431 94 : case SMB2_ENCRYPTION_AES128_CCM:
6432 94 : nonce_size = SMB2_AES_128_CCM_NONCE_SIZE;
6433 94 : break;
6434 17158 : case SMB2_ENCRYPTION_AES128_GCM:
6435 17158 : nonce_size = gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_GCM);
6436 17158 : break;
6437 10 : case SMB2_ENCRYPTION_AES256_CCM:
6438 10 : nonce_size = SMB2_AES_128_CCM_NONCE_SIZE;
6439 10 : break;
6440 10 : case SMB2_ENCRYPTION_AES256_GCM:
6441 10 : nonce_size = gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_256_GCM);
6442 10 : break;
6443 4040 : default:
6444 4040 : nonce_size = 0;
6445 4040 : break;
6446 : }
6447 21312 : session->smb2->nonce_high_max = SMB2_NONCE_HIGH_MAX(nonce_size);
6448 21312 : session->smb2->nonce_high = 0;
6449 21312 : session->smb2->nonce_low = 0;
6450 :
6451 21312 : return NT_STATUS_OK;
6452 : }
6453 :
6454 1890 : NTSTATUS smb2cli_session_create_channel(TALLOC_CTX *mem_ctx,
6455 : struct smbXcli_session *session1,
6456 : struct smbXcli_conn *conn,
6457 : struct smbXcli_session **_session2)
6458 : {
6459 : struct smbXcli_session *session2;
6460 : NTSTATUS status;
6461 :
6462 1890 : if (!smb2_signing_key_valid(session1->smb2->signing_key)) {
6463 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
6464 : }
6465 :
6466 1890 : if (conn == NULL) {
6467 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
6468 : }
6469 :
6470 1890 : session2 = talloc_zero(mem_ctx, struct smbXcli_session);
6471 1890 : if (session2 == NULL) {
6472 0 : return NT_STATUS_NO_MEMORY;
6473 : }
6474 1890 : session2->smb2 = talloc_reference(session2, session1->smb2);
6475 1890 : if (session2->smb2 == NULL) {
6476 0 : talloc_free(session2);
6477 0 : return NT_STATUS_NO_MEMORY;
6478 : }
6479 :
6480 1890 : talloc_set_destructor(session2, smbXcli_session_destructor);
6481 1890 : DLIST_ADD_END(conn->sessions, session2);
6482 1890 : session2->conn = conn;
6483 :
6484 3251 : status = smb2_signing_key_sign_create(session2,
6485 1890 : conn->smb2.server.sign_algo,
6486 : NULL, /* no master key */
6487 : NULL, /* derivations */
6488 : &session2->smb2_channel.signing_key);
6489 1890 : if (!NT_STATUS_IS_OK(status)) {
6490 0 : talloc_free(session2);
6491 0 : return NT_STATUS_NO_MEMORY;
6492 : }
6493 :
6494 1890 : memcpy(session2->smb2_channel.preauth_sha512,
6495 1890 : conn->smb2.preauth_sha512,
6496 : sizeof(session2->smb2_channel.preauth_sha512));
6497 :
6498 1890 : *_session2 = session2;
6499 1890 : return NT_STATUS_OK;
6500 : }
6501 :
6502 808 : NTSTATUS smb2cli_session_set_channel_key(struct smbXcli_session *session,
6503 : const DATA_BLOB _channel_key,
6504 : const struct iovec *recv_iov)
6505 : {
6506 808 : struct smbXcli_conn *conn = session->conn;
6507 : uint8_t channel_key[16];
6508 : NTSTATUS status;
6509 : struct _derivation {
6510 : DATA_BLOB label;
6511 : DATA_BLOB context;
6512 : };
6513 : struct {
6514 : struct _derivation signing;
6515 808 : } derivation = {
6516 : .signing.label.length = 0,
6517 : };
6518 :
6519 808 : if (conn == NULL) {
6520 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
6521 : }
6522 :
6523 808 : if (smb2_signing_key_valid(session->smb2_channel.signing_key)) {
6524 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
6525 : }
6526 :
6527 808 : if (conn->protocol >= PROTOCOL_SMB3_11) {
6528 : struct _derivation *d;
6529 : DATA_BLOB p;
6530 :
6531 808 : p = data_blob_const(session->smb2_channel.preauth_sha512,
6532 : sizeof(session->smb2_channel.preauth_sha512));
6533 :
6534 808 : d = &derivation.signing;
6535 808 : d->label = data_blob_string_const_null("SMBSigningKey");
6536 808 : d->context = p;
6537 0 : } else if (conn->protocol >= PROTOCOL_SMB3_00) {
6538 : struct _derivation *d;
6539 :
6540 0 : d = &derivation.signing;
6541 0 : d->label = data_blob_string_const_null("SMB2AESCMAC");
6542 0 : d->context = data_blob_string_const_null("SmbSign");
6543 : }
6544 :
6545 808 : ZERO_STRUCT(channel_key);
6546 808 : memcpy(channel_key, _channel_key.data,
6547 808 : MIN(_channel_key.length, sizeof(channel_key)));
6548 :
6549 808 : session->smb2_channel.signing_key->blob =
6550 808 : data_blob_talloc(session->smb2_channel.signing_key,
6551 : channel_key,
6552 : sizeof(channel_key));
6553 808 : if (!smb2_signing_key_valid(session->smb2_channel.signing_key)) {
6554 0 : ZERO_STRUCT(channel_key);
6555 0 : return NT_STATUS_NO_MEMORY;
6556 : }
6557 :
6558 808 : if (conn->protocol >= PROTOCOL_SMB3_00) {
6559 808 : struct _derivation *d = &derivation.signing;
6560 :
6561 2680 : status = smb2_key_derivation(channel_key, sizeof(channel_key),
6562 808 : d->label.data, d->label.length,
6563 808 : d->context.data, d->context.length,
6564 808 : session->smb2_channel.signing_key->blob.data,
6565 808 : session->smb2_channel.signing_key->blob.length);
6566 808 : if (!NT_STATUS_IS_OK(status)) {
6567 0 : return status;
6568 : }
6569 : }
6570 808 : ZERO_STRUCT(channel_key);
6571 :
6572 808 : status = smb2_signing_check_pdu(session->smb2_channel.signing_key,
6573 : recv_iov, 3);
6574 808 : if (!NT_STATUS_IS_OK(status)) {
6575 0 : return status;
6576 : }
6577 :
6578 808 : return NT_STATUS_OK;
6579 : }
6580 :
6581 615 : NTSTATUS smb2cli_session_encryption_on(struct smbXcli_session *session)
6582 : {
6583 615 : if (!session->smb2->should_sign) {
6584 : /*
6585 : * We need required signing on the session
6586 : * in order to prevent man in the middle attacks.
6587 : */
6588 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
6589 : }
6590 :
6591 615 : if (session->smb2->should_encrypt) {
6592 120 : return NT_STATUS_OK;
6593 : }
6594 :
6595 495 : if (session->conn->protocol < PROTOCOL_SMB3_00) {
6596 2 : return NT_STATUS_NOT_SUPPORTED;
6597 : }
6598 :
6599 493 : if (session->conn->smb2.server.cipher == 0) {
6600 36 : return NT_STATUS_NOT_SUPPORTED;
6601 : }
6602 :
6603 457 : if (!smb2_signing_key_valid(session->smb2->signing_key)) {
6604 0 : return NT_STATUS_NOT_SUPPORTED;
6605 : }
6606 457 : session->smb2->should_encrypt = true;
6607 457 : return NT_STATUS_OK;
6608 : }
6609 :
6610 7669 : uint16_t smb2cli_session_get_encryption_cipher(struct smbXcli_session *session)
6611 : {
6612 7669 : if (session->conn->protocol < PROTOCOL_SMB3_00) {
6613 2432 : return 0;
6614 : }
6615 :
6616 5237 : if (!session->smb2->should_encrypt) {
6617 4606 : return 0;
6618 : }
6619 :
6620 5 : return session->conn->smb2.server.cipher;
6621 : }
6622 :
6623 46024 : struct smbXcli_tcon *smbXcli_tcon_create(TALLOC_CTX *mem_ctx)
6624 : {
6625 : struct smbXcli_tcon *tcon;
6626 :
6627 46024 : tcon = talloc_zero(mem_ctx, struct smbXcli_tcon);
6628 46024 : if (tcon == NULL) {
6629 0 : return NULL;
6630 : }
6631 :
6632 46024 : return tcon;
6633 : }
6634 :
6635 : /*
6636 : * Return a deep structure copy of a struct smbXcli_tcon *
6637 : */
6638 :
6639 4 : struct smbXcli_tcon *smbXcli_tcon_copy(TALLOC_CTX *mem_ctx,
6640 : const struct smbXcli_tcon *tcon_in)
6641 : {
6642 : struct smbXcli_tcon *tcon;
6643 :
6644 4 : tcon = talloc_memdup(mem_ctx, tcon_in, sizeof(struct smbXcli_tcon));
6645 4 : if (tcon == NULL) {
6646 0 : return NULL;
6647 : }
6648 :
6649 : /* Deal with the SMB1 strings. */
6650 4 : if (tcon_in->smb1.service != NULL) {
6651 0 : tcon->smb1.service = talloc_strdup(tcon, tcon_in->smb1.service);
6652 0 : if (tcon->smb1.service == NULL) {
6653 0 : TALLOC_FREE(tcon);
6654 0 : return NULL;
6655 : }
6656 : }
6657 4 : if (tcon->smb1.fs_type != NULL) {
6658 0 : tcon->smb1.fs_type = talloc_strdup(tcon, tcon_in->smb1.fs_type);
6659 0 : if (tcon->smb1.fs_type == NULL) {
6660 0 : TALLOC_FREE(tcon);
6661 0 : return NULL;
6662 : }
6663 : }
6664 4 : return tcon;
6665 : }
6666 :
6667 40 : void smbXcli_tcon_set_fs_attributes(struct smbXcli_tcon *tcon,
6668 : uint32_t fs_attributes)
6669 : {
6670 40 : tcon->fs_attributes = fs_attributes;
6671 40 : }
6672 :
6673 0 : uint32_t smbXcli_tcon_get_fs_attributes(struct smbXcli_tcon *tcon)
6674 : {
6675 0 : return tcon->fs_attributes;
6676 : }
6677 :
6678 954442 : bool smbXcli_tcon_is_dfs_share(struct smbXcli_tcon *tcon)
6679 : {
6680 954442 : if (tcon == NULL) {
6681 4 : return false;
6682 : }
6683 :
6684 954438 : if (tcon->is_smb1) {
6685 885071 : if (tcon->smb1.optional_support & SMB_SHARE_IN_DFS) {
6686 352 : return true;
6687 : }
6688 :
6689 884719 : return false;
6690 : }
6691 :
6692 69367 : if (tcon->smb2.capabilities & SMB2_SHARE_CAP_DFS) {
6693 14572 : return true;
6694 : }
6695 :
6696 54795 : return false;
6697 : }
6698 :
6699 2595 : uint16_t smb1cli_tcon_current_id(struct smbXcli_tcon *tcon)
6700 : {
6701 2595 : return tcon->smb1.tcon_id;
6702 : }
6703 :
6704 494144 : void smb1cli_tcon_set_id(struct smbXcli_tcon *tcon, uint16_t tcon_id)
6705 : {
6706 494144 : tcon->is_smb1 = true;
6707 494144 : tcon->smb1.tcon_id = tcon_id;
6708 494144 : }
6709 :
6710 5556 : bool smb1cli_tcon_set_values(struct smbXcli_tcon *tcon,
6711 : uint16_t tcon_id,
6712 : uint16_t optional_support,
6713 : uint32_t maximal_access,
6714 : uint32_t guest_maximal_access,
6715 : const char *service,
6716 : const char *fs_type)
6717 : {
6718 5556 : tcon->is_smb1 = true;
6719 5556 : tcon->fs_attributes = 0;
6720 5556 : tcon->smb1.tcon_id = tcon_id;
6721 5556 : tcon->smb1.optional_support = optional_support;
6722 5556 : tcon->smb1.maximal_access = maximal_access;
6723 5556 : tcon->smb1.guest_maximal_access = guest_maximal_access;
6724 :
6725 5556 : TALLOC_FREE(tcon->smb1.service);
6726 5556 : tcon->smb1.service = talloc_strdup(tcon, service);
6727 5556 : if (service != NULL && tcon->smb1.service == NULL) {
6728 0 : return false;
6729 : }
6730 :
6731 5556 : TALLOC_FREE(tcon->smb1.fs_type);
6732 5556 : tcon->smb1.fs_type = talloc_strdup(tcon, fs_type);
6733 5556 : if (fs_type != NULL && tcon->smb1.fs_type == NULL) {
6734 0 : return false;
6735 : }
6736 :
6737 5556 : return true;
6738 : }
6739 :
6740 16486 : uint32_t smb2cli_tcon_current_id(struct smbXcli_tcon *tcon)
6741 : {
6742 16486 : return tcon->smb2.tcon_id;
6743 : }
6744 :
6745 20 : void smb2cli_tcon_set_id(struct smbXcli_tcon *tcon, uint32_t tcon_id)
6746 : {
6747 20 : tcon->smb2.tcon_id = tcon_id;
6748 20 : }
6749 :
6750 140 : uint32_t smb2cli_tcon_capabilities(struct smbXcli_tcon *tcon)
6751 : {
6752 140 : return tcon->smb2.capabilities;
6753 : }
6754 :
6755 4 : uint32_t smb2cli_tcon_flags(struct smbXcli_tcon *tcon)
6756 : {
6757 4 : return tcon->smb2.flags;
6758 : }
6759 :
6760 58868 : void smb2cli_tcon_set_values(struct smbXcli_tcon *tcon,
6761 : struct smbXcli_session *session,
6762 : uint32_t tcon_id,
6763 : uint8_t type,
6764 : uint32_t flags,
6765 : uint32_t capabilities,
6766 : uint32_t maximal_access)
6767 : {
6768 58868 : tcon->is_smb1 = false;
6769 58868 : tcon->fs_attributes = 0;
6770 58868 : tcon->smb2.tcon_id = tcon_id;
6771 58868 : tcon->smb2.type = type;
6772 58868 : tcon->smb2.flags = flags;
6773 58868 : tcon->smb2.capabilities = capabilities;
6774 58868 : tcon->smb2.maximal_access = maximal_access;
6775 :
6776 58868 : tcon->smb2.should_sign = false;
6777 58868 : tcon->smb2.should_encrypt = false;
6778 :
6779 58868 : if (session == NULL) {
6780 22623 : return;
6781 : }
6782 :
6783 36245 : tcon->smb2.should_sign = session->smb2->should_sign;
6784 36245 : tcon->smb2.should_encrypt = session->smb2->should_encrypt;
6785 :
6786 36245 : if (flags & SMB2_SHAREFLAG_ENCRYPT_DATA) {
6787 220 : tcon->smb2.should_encrypt = true;
6788 : }
6789 : }
6790 :
6791 8328 : void smb2cli_tcon_should_sign(struct smbXcli_tcon *tcon,
6792 : bool should_sign)
6793 : {
6794 8328 : tcon->smb2.should_sign = should_sign;
6795 8328 : }
6796 :
6797 4142 : bool smb2cli_tcon_is_signing_on(struct smbXcli_tcon *tcon)
6798 : {
6799 4142 : if (tcon->smb2.should_encrypt) {
6800 24 : return true;
6801 : }
6802 :
6803 4118 : return tcon->smb2.should_sign;
6804 : }
6805 :
6806 0 : void smb2cli_tcon_should_encrypt(struct smbXcli_tcon *tcon,
6807 : bool should_encrypt)
6808 : {
6809 0 : tcon->smb2.should_encrypt = should_encrypt;
6810 0 : }
6811 :
6812 160 : bool smb2cli_tcon_is_encryption_on(struct smbXcli_tcon *tcon)
6813 : {
6814 160 : return tcon->smb2.should_encrypt;
6815 : }
6816 :
6817 12 : void smb2cli_conn_set_mid(struct smbXcli_conn *conn, uint64_t mid)
6818 : {
6819 12 : conn->smb2.mid = mid;
6820 12 : }
6821 :
6822 4 : uint64_t smb2cli_conn_get_mid(struct smbXcli_conn *conn)
6823 : {
6824 4 : return conn->smb2.mid;
6825 : }
6826 :
6827 696367 : NTSTATUS smb2cli_parse_dyn_buffer(uint32_t dyn_offset,
6828 : const DATA_BLOB dyn_buffer,
6829 : uint32_t min_offset,
6830 : uint32_t buffer_offset,
6831 : uint32_t buffer_length,
6832 : uint32_t max_length,
6833 : uint32_t *next_offset,
6834 : DATA_BLOB *buffer)
6835 : {
6836 : uint32_t offset;
6837 : bool oob;
6838 :
6839 696367 : *buffer = data_blob_null;
6840 696367 : *next_offset = dyn_offset;
6841 :
6842 696367 : if (buffer_offset == 0) {
6843 : /*
6844 : * If the offset is 0, we better ignore
6845 : * the buffer_length field.
6846 : */
6847 45162 : return NT_STATUS_OK;
6848 : }
6849 :
6850 651205 : if (buffer_length == 0) {
6851 : /*
6852 : * If the length is 0, we better ignore
6853 : * the buffer_offset field.
6854 : */
6855 298061 : return NT_STATUS_OK;
6856 : }
6857 :
6858 353144 : if ((buffer_offset % 8) != 0) {
6859 : /*
6860 : * The offset needs to be 8 byte aligned.
6861 : */
6862 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
6863 : }
6864 :
6865 : /*
6866 : * We used to enforce buffer_offset to be
6867 : * an exact match of the expected minimum,
6868 : * but the NetApp Ontap 7.3.7 SMB server
6869 : * gets the padding wrong and aligns the
6870 : * input_buffer_offset by a value of 8.
6871 : *
6872 : * So we just enforce that the offset is
6873 : * not lower than the expected value.
6874 : */
6875 353144 : SMB_ASSERT(min_offset >= dyn_offset);
6876 353144 : if (buffer_offset < min_offset) {
6877 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
6878 : }
6879 :
6880 : /*
6881 : * Make [input|output]_buffer_offset relative to "dyn_buffer"
6882 : */
6883 353144 : offset = buffer_offset - dyn_offset;
6884 353144 : oob = smb_buffer_oob(dyn_buffer.length, offset, buffer_length);
6885 353144 : if (oob) {
6886 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
6887 : }
6888 :
6889 : /*
6890 : * Give the caller a hint what we consumed,
6891 : * the caller may need to add possible padding.
6892 : */
6893 353144 : *next_offset = buffer_offset + buffer_length;
6894 :
6895 353144 : if (max_length == 0) {
6896 : /*
6897 : * If max_input_length is 0 we ignore the
6898 : * input_buffer_length, because Windows 2008 echos the
6899 : * DCERPC request from the requested input_buffer to
6900 : * the response input_buffer.
6901 : *
6902 : * We just use the same logic also for max_output_length...
6903 : */
6904 0 : buffer_length = 0;
6905 : }
6906 :
6907 353144 : if (buffer_length > max_length) {
6908 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
6909 : }
6910 :
6911 353144 : *buffer = (DATA_BLOB) {
6912 353144 : .data = dyn_buffer.data + offset,
6913 : .length = buffer_length,
6914 : };
6915 353144 : return NT_STATUS_OK;
6916 : }
|