s4:dsdb/common: add a replication metadata stamp for an empty logonHours attribute
[Samba.git] / libcli / smb / smbXcli_base.c
blob0a2473ef632d6d965ff58875546330e5378e9b6a
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
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.
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.
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/>.
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 "lib/crypto/sha512.h"
37 #include "lib/crypto/aes.h"
38 #include "lib/crypto/aes_ccm_128.h"
39 #include "lib/crypto/aes_gcm_128.h"
41 struct smbXcli_conn;
42 struct smbXcli_req;
43 struct smbXcli_session;
44 struct smbXcli_tcon;
46 struct smbXcli_conn {
47 int sock_fd;
48 struct sockaddr_storage local_ss;
49 struct sockaddr_storage remote_ss;
50 const char *remote_name;
52 struct tevent_queue *outgoing;
53 struct tevent_req **pending;
54 struct tevent_req *read_smb_req;
55 struct tevent_req *suicide_req;
57 enum protocol_types min_protocol;
58 enum protocol_types max_protocol;
59 enum protocol_types protocol;
60 bool allow_signing;
61 bool desire_signing;
62 bool mandatory_signing;
65 * The incoming dispatch function should return:
66 * - NT_STATUS_RETRY, if more incoming PDUs are expected.
67 * - NT_STATUS_OK, if no more processing is desired, e.g.
68 * the dispatch function called
69 * tevent_req_done().
70 * - All other return values disconnect the connection.
72 NTSTATUS (*dispatch_incoming)(struct smbXcli_conn *conn,
73 TALLOC_CTX *tmp_mem,
74 uint8_t *inbuf);
76 struct {
77 struct {
78 uint32_t capabilities;
79 uint32_t max_xmit;
80 } client;
82 struct {
83 uint32_t capabilities;
84 uint32_t max_xmit;
85 uint16_t max_mux;
86 uint16_t security_mode;
87 bool readbraw;
88 bool writebraw;
89 bool lockread;
90 bool writeunlock;
91 uint32_t session_key;
92 struct GUID guid;
93 DATA_BLOB gss_blob;
94 uint8_t challenge[8];
95 const char *workgroup;
96 const char *name;
97 int time_zone;
98 NTTIME system_time;
99 } server;
101 uint32_t capabilities;
102 uint32_t max_xmit;
104 uint16_t mid;
106 struct smb_signing_state *signing;
107 struct smb_trans_enc_state *trans_enc;
109 struct tevent_req *read_braw_req;
110 } smb1;
112 struct {
113 struct {
114 uint32_t capabilities;
115 uint16_t security_mode;
116 struct GUID guid;
117 } client;
119 struct {
120 uint32_t capabilities;
121 uint16_t security_mode;
122 struct GUID guid;
123 uint32_t max_trans_size;
124 uint32_t max_read_size;
125 uint32_t max_write_size;
126 NTTIME system_time;
127 NTTIME start_time;
128 DATA_BLOB gss_blob;
129 uint16_t cipher;
130 } server;
132 uint64_t mid;
133 uint16_t cur_credits;
134 uint16_t max_credits;
136 uint32_t cc_chunk_len;
137 uint32_t cc_max_chunks;
139 uint8_t io_priority;
141 uint8_t preauth_sha512[64];
142 } smb2;
144 struct smbXcli_session *sessions;
147 struct smb2cli_session {
148 uint64_t session_id;
149 uint16_t session_flags;
150 DATA_BLOB application_key;
151 DATA_BLOB signing_key;
152 bool should_sign;
153 bool should_encrypt;
154 DATA_BLOB encryption_key;
155 DATA_BLOB decryption_key;
156 uint64_t nonce_high_random;
157 uint64_t nonce_high_max;
158 uint64_t nonce_high;
159 uint64_t nonce_low;
160 uint16_t channel_sequence;
161 bool replay_active;
164 struct smbXcli_session {
165 struct smbXcli_session *prev, *next;
166 struct smbXcli_conn *conn;
168 struct {
169 uint16_t session_id;
170 uint16_t action;
171 DATA_BLOB application_key;
172 bool protected_key;
173 } smb1;
175 struct smb2cli_session *smb2;
177 struct {
178 DATA_BLOB signing_key;
179 uint8_t preauth_sha512[64];
180 } smb2_channel;
183 * this should be a short term hack
184 * until the upper layers have implemented
185 * re-authentication.
187 bool disconnect_expired;
190 struct smbXcli_tcon {
191 bool is_smb1;
192 uint32_t fs_attributes;
194 struct {
195 uint16_t tcon_id;
196 uint16_t optional_support;
197 uint32_t maximal_access;
198 uint32_t guest_maximal_access;
199 char *service;
200 char *fs_type;
201 } smb1;
203 struct {
204 uint32_t tcon_id;
205 uint8_t type;
206 uint32_t flags;
207 uint32_t capabilities;
208 uint32_t maximal_access;
209 bool should_sign;
210 bool should_encrypt;
211 } smb2;
214 struct smbXcli_req_state {
215 struct tevent_context *ev;
216 struct smbXcli_conn *conn;
217 struct smbXcli_session *session; /* maybe NULL */
218 struct smbXcli_tcon *tcon; /* maybe NULL */
220 uint8_t length_hdr[4];
222 bool one_way;
224 uint8_t *inbuf;
226 struct tevent_req *write_req;
228 struct {
229 /* Space for the header including the wct */
230 uint8_t hdr[HDR_VWV];
233 * For normal requests, smb1cli_req_send chooses a mid.
234 * SecondaryV trans requests need to use the mid of the primary
235 * request, so we need a place to store it.
236 * Assume it is set if != 0.
238 uint16_t mid;
240 uint16_t *vwv;
241 uint8_t bytecount_buf[2];
243 #define MAX_SMB_IOV 10
244 /* length_hdr, hdr, words, byte_count, buffers */
245 struct iovec iov[1 + 3 + MAX_SMB_IOV];
246 int iov_count;
248 bool one_way_seqnum;
249 uint32_t seqnum;
250 struct tevent_req **chained_requests;
252 uint8_t recv_cmd;
253 NTSTATUS recv_status;
254 /* always an array of 3 talloc elements */
255 struct iovec *recv_iov;
256 } smb1;
258 struct {
259 const uint8_t *fixed;
260 uint16_t fixed_len;
261 const uint8_t *dyn;
262 uint32_t dyn_len;
264 uint8_t transform[SMB2_TF_HDR_SIZE];
265 uint8_t hdr[SMB2_HDR_BODY];
266 uint8_t pad[7]; /* padding space for compounding */
269 * always an array of 3 talloc elements
270 * (without a SMB2_TRANSFORM header!)
272 * HDR, BODY, DYN
274 struct iovec *recv_iov;
277 * the expected max for the response dyn_len
279 uint32_t max_dyn_len;
281 uint16_t credit_charge;
283 bool should_sign;
284 bool should_encrypt;
285 uint64_t encryption_session_id;
287 bool signing_skipped;
288 bool notify_async;
289 bool got_async;
290 uint16_t cancel_flags;
291 uint64_t cancel_mid;
292 uint64_t cancel_aid;
293 } smb2;
296 static int smbXcli_conn_destructor(struct smbXcli_conn *conn)
299 * NT_STATUS_OK, means we do not notify the callers
301 smbXcli_conn_disconnect(conn, NT_STATUS_OK);
303 while (conn->sessions) {
304 conn->sessions->conn = NULL;
305 DLIST_REMOVE(conn->sessions, conn->sessions);
308 if (conn->smb1.trans_enc) {
309 TALLOC_FREE(conn->smb1.trans_enc);
312 return 0;
315 struct smbXcli_conn *smbXcli_conn_create(TALLOC_CTX *mem_ctx,
316 int fd,
317 const char *remote_name,
318 enum smb_signing_setting signing_state,
319 uint32_t smb1_capabilities,
320 struct GUID *client_guid,
321 uint32_t smb2_capabilities)
323 struct smbXcli_conn *conn = NULL;
324 void *ss = NULL;
325 struct sockaddr *sa = NULL;
326 socklen_t sa_length;
327 int ret;
329 conn = talloc_zero(mem_ctx, struct smbXcli_conn);
330 if (!conn) {
331 return NULL;
334 conn->sock_fd = fd;
336 conn->remote_name = talloc_strdup(conn, remote_name);
337 if (conn->remote_name == NULL) {
338 goto error;
341 ss = (void *)&conn->local_ss;
342 sa = (struct sockaddr *)ss;
343 sa_length = sizeof(conn->local_ss);
344 ret = getsockname(fd, sa, &sa_length);
345 if (ret == -1) {
346 goto error;
348 ss = (void *)&conn->remote_ss;
349 sa = (struct sockaddr *)ss;
350 sa_length = sizeof(conn->remote_ss);
351 ret = getpeername(fd, sa, &sa_length);
352 if (ret == -1) {
353 goto error;
356 conn->outgoing = tevent_queue_create(conn, "smbXcli_outgoing");
357 if (conn->outgoing == NULL) {
358 goto error;
360 conn->pending = NULL;
362 conn->min_protocol = PROTOCOL_NONE;
363 conn->max_protocol = PROTOCOL_NONE;
364 conn->protocol = PROTOCOL_NONE;
366 switch (signing_state) {
367 case SMB_SIGNING_OFF:
368 /* never */
369 conn->allow_signing = false;
370 conn->desire_signing = false;
371 conn->mandatory_signing = false;
372 break;
373 case SMB_SIGNING_DEFAULT:
374 case SMB_SIGNING_IF_REQUIRED:
375 /* if the server requires it */
376 conn->allow_signing = true;
377 conn->desire_signing = false;
378 conn->mandatory_signing = false;
379 break;
380 case SMB_SIGNING_DESIRED:
381 /* if the server desires it */
382 conn->allow_signing = true;
383 conn->desire_signing = true;
384 conn->mandatory_signing = false;
385 break;
386 case SMB_SIGNING_IPC_DEFAULT:
387 case SMB_SIGNING_REQUIRED:
388 /* always */
389 conn->allow_signing = true;
390 conn->desire_signing = true;
391 conn->mandatory_signing = true;
392 break;
395 conn->smb1.client.capabilities = smb1_capabilities;
396 conn->smb1.client.max_xmit = UINT16_MAX;
398 conn->smb1.capabilities = conn->smb1.client.capabilities;
399 conn->smb1.max_xmit = 1024;
401 conn->smb1.mid = 1;
403 /* initialise signing */
404 conn->smb1.signing = smb_signing_init(conn,
405 conn->allow_signing,
406 conn->desire_signing,
407 conn->mandatory_signing);
408 if (!conn->smb1.signing) {
409 goto error;
412 conn->smb2.client.security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED;
413 if (conn->mandatory_signing) {
414 conn->smb2.client.security_mode |= SMB2_NEGOTIATE_SIGNING_REQUIRED;
416 if (client_guid) {
417 conn->smb2.client.guid = *client_guid;
419 conn->smb2.client.capabilities = smb2_capabilities;
421 conn->smb2.cur_credits = 1;
422 conn->smb2.max_credits = 0;
423 conn->smb2.io_priority = 1;
426 * Samba and Windows servers accept a maximum of 16 MiB with a maximum
427 * chunk length of 1 MiB.
429 conn->smb2.cc_chunk_len = 1024 * 1024;
430 conn->smb2.cc_max_chunks = 16;
432 talloc_set_destructor(conn, smbXcli_conn_destructor);
433 return conn;
435 error:
436 TALLOC_FREE(conn);
437 return NULL;
440 bool smbXcli_conn_is_connected(struct smbXcli_conn *conn)
442 if (conn == NULL) {
443 return false;
446 if (conn->sock_fd == -1) {
447 return false;
450 return true;
453 enum protocol_types smbXcli_conn_protocol(struct smbXcli_conn *conn)
455 return conn->protocol;
458 bool smbXcli_conn_use_unicode(struct smbXcli_conn *conn)
460 if (conn->protocol >= PROTOCOL_SMB2_02) {
461 return true;
464 if (conn->smb1.capabilities & CAP_UNICODE) {
465 return true;
468 return false;
471 void smbXcli_conn_set_sockopt(struct smbXcli_conn *conn, const char *options)
473 set_socket_options(conn->sock_fd, options);
476 const struct sockaddr_storage *smbXcli_conn_local_sockaddr(struct smbXcli_conn *conn)
478 return &conn->local_ss;
481 const struct sockaddr_storage *smbXcli_conn_remote_sockaddr(struct smbXcli_conn *conn)
483 return &conn->remote_ss;
486 const char *smbXcli_conn_remote_name(struct smbXcli_conn *conn)
488 return conn->remote_name;
491 uint16_t smbXcli_conn_max_requests(struct smbXcli_conn *conn)
493 if (conn->protocol >= PROTOCOL_SMB2_02) {
495 * TODO...
497 return 1;
500 return conn->smb1.server.max_mux;
503 NTTIME smbXcli_conn_server_system_time(struct smbXcli_conn *conn)
505 if (conn->protocol >= PROTOCOL_SMB2_02) {
506 return conn->smb2.server.system_time;
509 return conn->smb1.server.system_time;
512 const DATA_BLOB *smbXcli_conn_server_gss_blob(struct smbXcli_conn *conn)
514 if (conn->protocol >= PROTOCOL_SMB2_02) {
515 return &conn->smb2.server.gss_blob;
518 return &conn->smb1.server.gss_blob;
521 const struct GUID *smbXcli_conn_server_guid(struct smbXcli_conn *conn)
523 if (conn->protocol >= PROTOCOL_SMB2_02) {
524 return &conn->smb2.server.guid;
527 return &conn->smb1.server.guid;
530 struct smbXcli_conn_samba_suicide_state {
531 struct smbXcli_conn *conn;
532 struct iovec iov;
533 uint8_t buf[9];
534 struct tevent_req *write_req;
537 static void smbXcli_conn_samba_suicide_cleanup(struct tevent_req *req,
538 enum tevent_req_state req_state);
539 static void smbXcli_conn_samba_suicide_done(struct tevent_req *subreq);
541 struct tevent_req *smbXcli_conn_samba_suicide_send(TALLOC_CTX *mem_ctx,
542 struct tevent_context *ev,
543 struct smbXcli_conn *conn,
544 uint8_t exitcode)
546 struct tevent_req *req, *subreq;
547 struct smbXcli_conn_samba_suicide_state *state;
549 req = tevent_req_create(mem_ctx, &state,
550 struct smbXcli_conn_samba_suicide_state);
551 if (req == NULL) {
552 return NULL;
554 state->conn = conn;
555 SIVAL(state->buf, 4, 0x74697865);
556 SCVAL(state->buf, 8, exitcode);
557 _smb_setlen_nbt(state->buf, sizeof(state->buf)-4);
559 if (conn->suicide_req != NULL) {
560 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
561 return tevent_req_post(req, ev);
564 state->iov.iov_base = state->buf;
565 state->iov.iov_len = sizeof(state->buf);
567 subreq = writev_send(state, ev, conn->outgoing, conn->sock_fd,
568 false, &state->iov, 1);
569 if (tevent_req_nomem(subreq, req)) {
570 return tevent_req_post(req, ev);
572 tevent_req_set_callback(subreq, smbXcli_conn_samba_suicide_done, req);
573 state->write_req = subreq;
575 tevent_req_set_cleanup_fn(req, smbXcli_conn_samba_suicide_cleanup);
578 * We need to use tevent_req_defer_callback()
579 * in order to allow smbXcli_conn_disconnect()
580 * to do a safe cleanup.
582 tevent_req_defer_callback(req, ev);
583 conn->suicide_req = req;
585 return req;
588 static void smbXcli_conn_samba_suicide_cleanup(struct tevent_req *req,
589 enum tevent_req_state req_state)
591 struct smbXcli_conn_samba_suicide_state *state = tevent_req_data(
592 req, struct smbXcli_conn_samba_suicide_state);
594 TALLOC_FREE(state->write_req);
596 if (state->conn == NULL) {
597 return;
600 if (state->conn->suicide_req == req) {
601 state->conn->suicide_req = NULL;
603 state->conn = NULL;
606 static void smbXcli_conn_samba_suicide_done(struct tevent_req *subreq)
608 struct tevent_req *req = tevent_req_callback_data(
609 subreq, struct tevent_req);
610 struct smbXcli_conn_samba_suicide_state *state = tevent_req_data(
611 req, struct smbXcli_conn_samba_suicide_state);
612 ssize_t nwritten;
613 int err;
615 state->write_req = NULL;
617 nwritten = writev_recv(subreq, &err);
618 TALLOC_FREE(subreq);
619 if (nwritten == -1) {
620 /* here, we need to notify all pending requests */
621 NTSTATUS status = map_nt_error_from_unix_common(err);
622 smbXcli_conn_disconnect(state->conn, status);
623 return;
625 tevent_req_done(req);
628 NTSTATUS smbXcli_conn_samba_suicide_recv(struct tevent_req *req)
630 return tevent_req_simple_recv_ntstatus(req);
633 NTSTATUS smbXcli_conn_samba_suicide(struct smbXcli_conn *conn,
634 uint8_t exitcode)
636 TALLOC_CTX *frame = talloc_stackframe();
637 struct tevent_context *ev;
638 struct tevent_req *req;
639 NTSTATUS status = NT_STATUS_NO_MEMORY;
640 bool ok;
642 if (smbXcli_conn_has_async_calls(conn)) {
644 * Can't use sync call while an async call is in flight
646 status = NT_STATUS_INVALID_PARAMETER_MIX;
647 goto fail;
649 ev = samba_tevent_context_init(frame);
650 if (ev == NULL) {
651 goto fail;
653 req = smbXcli_conn_samba_suicide_send(frame, ev, conn, exitcode);
654 if (req == NULL) {
655 goto fail;
657 ok = tevent_req_poll_ntstatus(req, ev, &status);
658 if (!ok) {
659 goto fail;
661 status = smbXcli_conn_samba_suicide_recv(req);
662 fail:
663 TALLOC_FREE(frame);
664 return status;
667 uint32_t smb1cli_conn_capabilities(struct smbXcli_conn *conn)
669 return conn->smb1.capabilities;
672 uint32_t smb1cli_conn_max_xmit(struct smbXcli_conn *conn)
674 return conn->smb1.max_xmit;
677 bool smb1cli_conn_req_possible(struct smbXcli_conn *conn)
679 size_t pending = talloc_array_length(conn->pending);
680 uint16_t possible = conn->smb1.server.max_mux;
682 if (pending >= possible) {
683 return false;
686 return true;
689 uint32_t smb1cli_conn_server_session_key(struct smbXcli_conn *conn)
691 return conn->smb1.server.session_key;
694 const uint8_t *smb1cli_conn_server_challenge(struct smbXcli_conn *conn)
696 return conn->smb1.server.challenge;
699 uint16_t smb1cli_conn_server_security_mode(struct smbXcli_conn *conn)
701 return conn->smb1.server.security_mode;
704 bool smb1cli_conn_server_readbraw(struct smbXcli_conn *conn)
706 return conn->smb1.server.readbraw;
709 bool smb1cli_conn_server_writebraw(struct smbXcli_conn *conn)
711 return conn->smb1.server.writebraw;
714 bool smb1cli_conn_server_lockread(struct smbXcli_conn *conn)
716 return conn->smb1.server.lockread;
719 bool smb1cli_conn_server_writeunlock(struct smbXcli_conn *conn)
721 return conn->smb1.server.writeunlock;
724 int smb1cli_conn_server_time_zone(struct smbXcli_conn *conn)
726 return conn->smb1.server.time_zone;
729 bool smb1cli_conn_activate_signing(struct smbXcli_conn *conn,
730 const DATA_BLOB user_session_key,
731 const DATA_BLOB response)
733 return smb_signing_activate(conn->smb1.signing,
734 user_session_key,
735 response);
738 bool smb1cli_conn_check_signing(struct smbXcli_conn *conn,
739 const uint8_t *buf, uint32_t seqnum)
741 const uint8_t *hdr = buf + NBT_HDR_SIZE;
742 size_t len = smb_len_nbt(buf);
744 return smb_signing_check_pdu(conn->smb1.signing, hdr, len, seqnum);
747 bool smb1cli_conn_signing_is_active(struct smbXcli_conn *conn)
749 return smb_signing_is_active(conn->smb1.signing);
752 void smb1cli_conn_set_encryption(struct smbXcli_conn *conn,
753 struct smb_trans_enc_state *es)
755 /* Replace the old state, if any. */
756 if (conn->smb1.trans_enc) {
757 TALLOC_FREE(conn->smb1.trans_enc);
759 conn->smb1.trans_enc = es;
762 bool smb1cli_conn_encryption_on(struct smbXcli_conn *conn)
764 return common_encryption_on(conn->smb1.trans_enc);
768 static NTSTATUS smb1cli_pull_raw_error(const uint8_t *hdr)
770 uint32_t flags2 = SVAL(hdr, HDR_FLG2);
771 NTSTATUS status = NT_STATUS(IVAL(hdr, HDR_RCLS));
773 if (NT_STATUS_IS_OK(status)) {
774 return NT_STATUS_OK;
777 if (flags2 & FLAGS2_32_BIT_ERROR_CODES) {
778 return status;
781 return NT_STATUS_DOS(CVAL(hdr, HDR_RCLS), SVAL(hdr, HDR_ERR));
785 * Is the SMB command able to hold an AND_X successor
786 * @param[in] cmd The SMB command in question
787 * @retval Can we add a chained request after "cmd"?
789 bool smb1cli_is_andx_req(uint8_t cmd)
791 switch (cmd) {
792 case SMBtconX:
793 case SMBlockingX:
794 case SMBopenX:
795 case SMBreadX:
796 case SMBwriteX:
797 case SMBsesssetupX:
798 case SMBulogoffX:
799 case SMBntcreateX:
800 return true;
801 break;
802 default:
803 break;
806 return false;
809 static uint16_t smb1cli_alloc_mid(struct smbXcli_conn *conn)
811 size_t num_pending = talloc_array_length(conn->pending);
812 uint16_t result;
814 if (conn->protocol == PROTOCOL_NONE) {
816 * This is what windows sends on the SMB1 Negprot request
817 * and some vendors reuse the SMB1 MID as SMB2 sequence number.
819 return 0;
822 while (true) {
823 size_t i;
825 result = conn->smb1.mid++;
826 if ((result == 0) || (result == 0xffff)) {
827 continue;
830 for (i=0; i<num_pending; i++) {
831 if (result == smb1cli_req_mid(conn->pending[i])) {
832 break;
836 if (i == num_pending) {
837 return result;
842 void smbXcli_req_unset_pending(struct tevent_req *req)
844 struct smbXcli_req_state *state =
845 tevent_req_data(req,
846 struct smbXcli_req_state);
847 struct smbXcli_conn *conn = state->conn;
848 size_t num_pending = talloc_array_length(conn->pending);
849 size_t i;
851 TALLOC_FREE(state->write_req);
853 if (state->smb1.mid != 0) {
855 * This is a [nt]trans[2] request which waits
856 * for more than one reply.
858 return;
861 tevent_req_set_cleanup_fn(req, NULL);
863 if (num_pending == 1) {
865 * The pending read_smb tevent_req is a child of
866 * conn->pending. So if nothing is pending anymore, we need to
867 * delete the socket read fde.
869 TALLOC_FREE(conn->pending);
870 conn->read_smb_req = NULL;
871 return;
874 for (i=0; i<num_pending; i++) {
875 if (req == conn->pending[i]) {
876 break;
879 if (i == num_pending) {
881 * Something's seriously broken. Just returning here is the
882 * right thing nevertheless, the point of this routine is to
883 * remove ourselves from conn->pending.
885 return;
889 * Remove ourselves from the conn->pending array
891 for (; i < (num_pending - 1); i++) {
892 conn->pending[i] = conn->pending[i+1];
896 * No NULL check here, we're shrinking by sizeof(void *), and
897 * talloc_realloc just adjusts the size for this.
899 conn->pending = talloc_realloc(NULL, conn->pending, struct tevent_req *,
900 num_pending - 1);
901 return;
904 static void smbXcli_req_cleanup(struct tevent_req *req,
905 enum tevent_req_state req_state)
907 struct smbXcli_req_state *state =
908 tevent_req_data(req,
909 struct smbXcli_req_state);
911 TALLOC_FREE(state->write_req);
913 switch (req_state) {
914 case TEVENT_REQ_RECEIVED:
916 * Make sure we really remove it from
917 * the pending array on destruction.
919 state->smb1.mid = 0;
920 smbXcli_req_unset_pending(req);
921 return;
922 default:
923 return;
927 static bool smb1cli_req_cancel(struct tevent_req *req);
928 static bool smb2cli_req_cancel(struct tevent_req *req);
930 static bool smbXcli_req_cancel(struct tevent_req *req)
932 struct smbXcli_req_state *state =
933 tevent_req_data(req,
934 struct smbXcli_req_state);
936 if (!smbXcli_conn_is_connected(state->conn)) {
937 return false;
940 if (state->conn->protocol == PROTOCOL_NONE) {
941 return false;
944 if (state->conn->protocol >= PROTOCOL_SMB2_02) {
945 return smb2cli_req_cancel(req);
948 return smb1cli_req_cancel(req);
951 static bool smbXcli_conn_receive_next(struct smbXcli_conn *conn);
953 bool smbXcli_req_set_pending(struct tevent_req *req)
955 struct smbXcli_req_state *state =
956 tevent_req_data(req,
957 struct smbXcli_req_state);
958 struct smbXcli_conn *conn;
959 struct tevent_req **pending;
960 size_t num_pending;
962 conn = state->conn;
964 if (!smbXcli_conn_is_connected(conn)) {
965 return false;
968 num_pending = talloc_array_length(conn->pending);
970 pending = talloc_realloc(conn, conn->pending, struct tevent_req *,
971 num_pending+1);
972 if (pending == NULL) {
973 return false;
975 pending[num_pending] = req;
976 conn->pending = pending;
977 tevent_req_set_cleanup_fn(req, smbXcli_req_cleanup);
978 tevent_req_set_cancel_fn(req, smbXcli_req_cancel);
980 if (!smbXcli_conn_receive_next(conn)) {
982 * the caller should notify the current request
984 * And all other pending requests get notified
985 * by smbXcli_conn_disconnect().
987 smbXcli_req_unset_pending(req);
988 smbXcli_conn_disconnect(conn, NT_STATUS_NO_MEMORY);
989 return false;
992 return true;
995 static void smbXcli_conn_received(struct tevent_req *subreq);
997 static bool smbXcli_conn_receive_next(struct smbXcli_conn *conn)
999 size_t num_pending = talloc_array_length(conn->pending);
1000 struct tevent_req *req;
1001 struct smbXcli_req_state *state;
1003 if (conn->read_smb_req != NULL) {
1004 return true;
1007 if (num_pending == 0) {
1008 if (conn->smb2.mid < UINT64_MAX) {
1009 /* no more pending requests, so we are done for now */
1010 return true;
1014 * If there are no more SMB2 requests possible,
1015 * because we are out of message ids,
1016 * we need to disconnect.
1018 smbXcli_conn_disconnect(conn, NT_STATUS_CONNECTION_ABORTED);
1019 return true;
1022 req = conn->pending[0];
1023 state = tevent_req_data(req, struct smbXcli_req_state);
1026 * We're the first ones, add the read_smb request that waits for the
1027 * answer from the server
1029 conn->read_smb_req = read_smb_send(conn->pending,
1030 state->ev,
1031 conn->sock_fd);
1032 if (conn->read_smb_req == NULL) {
1033 return false;
1035 tevent_req_set_callback(conn->read_smb_req, smbXcli_conn_received, conn);
1036 return true;
1039 void smbXcli_conn_disconnect(struct smbXcli_conn *conn, NTSTATUS status)
1041 struct smbXcli_session *session;
1042 int sock_fd = conn->sock_fd;
1044 tevent_queue_stop(conn->outgoing);
1046 conn->sock_fd = -1;
1048 session = conn->sessions;
1049 if (talloc_array_length(conn->pending) == 0) {
1051 * if we do not have pending requests
1052 * there is no need to update the channel_sequence
1054 session = NULL;
1056 for (; session; session = session->next) {
1057 smb2cli_session_increment_channel_sequence(session);
1060 if (conn->suicide_req != NULL) {
1062 * smbXcli_conn_samba_suicide_send()
1063 * used tevent_req_defer_callback() already.
1065 if (!NT_STATUS_IS_OK(status)) {
1066 tevent_req_nterror(conn->suicide_req, status);
1068 conn->suicide_req = NULL;
1072 * Cancel all pending requests. We do not do a for-loop walking
1073 * conn->pending because that array changes in
1074 * smbXcli_req_unset_pending.
1076 while (talloc_array_length(conn->pending) > 0) {
1077 struct tevent_req *req;
1078 struct smbXcli_req_state *state;
1079 struct tevent_req **chain;
1080 size_t num_chained;
1081 size_t i;
1083 req = conn->pending[0];
1084 state = tevent_req_data(req, struct smbXcli_req_state);
1086 if (state->smb1.chained_requests == NULL) {
1088 * We're dead. No point waiting for trans2
1089 * replies.
1091 state->smb1.mid = 0;
1093 smbXcli_req_unset_pending(req);
1095 if (NT_STATUS_IS_OK(status)) {
1096 /* do not notify the callers */
1097 continue;
1101 * we need to defer the callback, because we may notify
1102 * more then one caller.
1104 tevent_req_defer_callback(req, state->ev);
1105 tevent_req_nterror(req, status);
1106 continue;
1109 chain = talloc_move(conn, &state->smb1.chained_requests);
1110 num_chained = talloc_array_length(chain);
1112 for (i=0; i<num_chained; i++) {
1113 req = chain[i];
1114 state = tevent_req_data(req, struct smbXcli_req_state);
1117 * We're dead. No point waiting for trans2
1118 * replies.
1120 state->smb1.mid = 0;
1122 smbXcli_req_unset_pending(req);
1124 if (NT_STATUS_IS_OK(status)) {
1125 /* do not notify the callers */
1126 continue;
1130 * we need to defer the callback, because we may notify
1131 * more than one caller.
1133 tevent_req_defer_callback(req, state->ev);
1134 tevent_req_nterror(req, status);
1136 TALLOC_FREE(chain);
1139 if (sock_fd != -1) {
1140 close(sock_fd);
1145 * Fetch a smb request's mid. Only valid after the request has been sent by
1146 * smb1cli_req_send().
1148 uint16_t smb1cli_req_mid(struct tevent_req *req)
1150 struct smbXcli_req_state *state =
1151 tevent_req_data(req,
1152 struct smbXcli_req_state);
1154 if (state->smb1.mid != 0) {
1155 return state->smb1.mid;
1158 return SVAL(state->smb1.hdr, HDR_MID);
1161 void smb1cli_req_set_mid(struct tevent_req *req, uint16_t mid)
1163 struct smbXcli_req_state *state =
1164 tevent_req_data(req,
1165 struct smbXcli_req_state);
1167 state->smb1.mid = mid;
1170 uint32_t smb1cli_req_seqnum(struct tevent_req *req)
1172 struct smbXcli_req_state *state =
1173 tevent_req_data(req,
1174 struct smbXcli_req_state);
1176 return state->smb1.seqnum;
1179 void smb1cli_req_set_seqnum(struct tevent_req *req, uint32_t seqnum)
1181 struct smbXcli_req_state *state =
1182 tevent_req_data(req,
1183 struct smbXcli_req_state);
1185 state->smb1.seqnum = seqnum;
1188 static size_t smbXcli_iov_len(const struct iovec *iov, int count)
1190 ssize_t ret = iov_buflen(iov, count);
1192 /* Ignore the overflow case for now ... */
1193 return ret;
1196 static uint8_t *smbXcli_iov_concat(TALLOC_CTX *mem_ctx,
1197 const struct iovec *iov,
1198 int count)
1200 ssize_t buflen;
1201 uint8_t *buf;
1203 buflen = iov_buflen(iov, count);
1204 if (buflen == -1) {
1205 return NULL;
1208 buf = talloc_array(mem_ctx, uint8_t, buflen);
1209 if (buf == NULL) {
1210 return NULL;
1213 iov_buf(iov, count, buf, buflen);
1215 return buf;
1218 static void smb1cli_req_flags(enum protocol_types protocol,
1219 uint32_t smb1_capabilities,
1220 uint8_t smb_command,
1221 uint8_t additional_flags,
1222 uint8_t clear_flags,
1223 uint8_t *_flags,
1224 uint16_t additional_flags2,
1225 uint16_t clear_flags2,
1226 uint16_t *_flags2)
1228 uint8_t flags = 0;
1229 uint16_t flags2 = 0;
1231 if (protocol >= PROTOCOL_LANMAN1) {
1232 flags |= FLAG_CASELESS_PATHNAMES;
1233 flags |= FLAG_CANONICAL_PATHNAMES;
1236 if (protocol >= PROTOCOL_LANMAN2) {
1237 flags2 |= FLAGS2_LONG_PATH_COMPONENTS;
1238 flags2 |= FLAGS2_EXTENDED_ATTRIBUTES;
1241 if (protocol >= PROTOCOL_NT1) {
1242 flags2 |= FLAGS2_IS_LONG_NAME;
1244 if (smb1_capabilities & CAP_UNICODE) {
1245 flags2 |= FLAGS2_UNICODE_STRINGS;
1247 if (smb1_capabilities & CAP_STATUS32) {
1248 flags2 |= FLAGS2_32_BIT_ERROR_CODES;
1250 if (smb1_capabilities & CAP_EXTENDED_SECURITY) {
1251 flags2 |= FLAGS2_EXTENDED_SECURITY;
1255 flags |= additional_flags;
1256 flags &= ~clear_flags;
1257 flags2 |= additional_flags2;
1258 flags2 &= ~clear_flags2;
1260 *_flags = flags;
1261 *_flags2 = flags2;
1264 static void smb1cli_req_cancel_done(struct tevent_req *subreq);
1266 static bool smb1cli_req_cancel(struct tevent_req *req)
1268 struct smbXcli_req_state *state =
1269 tevent_req_data(req,
1270 struct smbXcli_req_state);
1271 uint8_t flags;
1272 uint16_t flags2;
1273 uint32_t pid;
1274 uint16_t mid;
1275 struct tevent_req *subreq;
1276 NTSTATUS status;
1278 flags = CVAL(state->smb1.hdr, HDR_FLG);
1279 flags2 = SVAL(state->smb1.hdr, HDR_FLG2);
1280 pid = SVAL(state->smb1.hdr, HDR_PID);
1281 pid |= SVAL(state->smb1.hdr, HDR_PIDHIGH)<<16;
1282 mid = SVAL(state->smb1.hdr, HDR_MID);
1284 subreq = smb1cli_req_create(state, state->ev,
1285 state->conn,
1286 SMBntcancel,
1287 flags, 0,
1288 flags2, 0,
1289 0, /* timeout */
1290 pid,
1291 state->tcon,
1292 state->session,
1293 0, NULL, /* vwv */
1294 0, NULL); /* bytes */
1295 if (subreq == NULL) {
1296 return false;
1298 smb1cli_req_set_mid(subreq, mid);
1300 status = smb1cli_req_chain_submit(&subreq, 1);
1301 if (!NT_STATUS_IS_OK(status)) {
1302 TALLOC_FREE(subreq);
1303 return false;
1305 smb1cli_req_set_mid(subreq, 0);
1307 tevent_req_set_callback(subreq, smb1cli_req_cancel_done, NULL);
1309 return true;
1312 static void smb1cli_req_cancel_done(struct tevent_req *subreq)
1314 /* we do not care about the result */
1315 TALLOC_FREE(subreq);
1318 struct tevent_req *smb1cli_req_create(TALLOC_CTX *mem_ctx,
1319 struct tevent_context *ev,
1320 struct smbXcli_conn *conn,
1321 uint8_t smb_command,
1322 uint8_t additional_flags,
1323 uint8_t clear_flags,
1324 uint16_t additional_flags2,
1325 uint16_t clear_flags2,
1326 uint32_t timeout_msec,
1327 uint32_t pid,
1328 struct smbXcli_tcon *tcon,
1329 struct smbXcli_session *session,
1330 uint8_t wct, uint16_t *vwv,
1331 int iov_count,
1332 struct iovec *bytes_iov)
1334 struct tevent_req *req;
1335 struct smbXcli_req_state *state;
1336 uint8_t flags = 0;
1337 uint16_t flags2 = 0;
1338 uint16_t uid = 0;
1339 uint16_t tid = 0;
1340 ssize_t num_bytes;
1342 if (iov_count > MAX_SMB_IOV) {
1344 * Should not happen :-)
1346 return NULL;
1349 req = tevent_req_create(mem_ctx, &state,
1350 struct smbXcli_req_state);
1351 if (req == NULL) {
1352 return NULL;
1354 state->ev = ev;
1355 state->conn = conn;
1356 state->session = session;
1357 state->tcon = tcon;
1359 if (session) {
1360 uid = session->smb1.session_id;
1363 if (tcon) {
1364 tid = tcon->smb1.tcon_id;
1366 if (tcon->fs_attributes & FILE_CASE_SENSITIVE_SEARCH) {
1367 clear_flags |= FLAG_CASELESS_PATHNAMES;
1368 } else {
1369 /* Default setting, case insensitive. */
1370 additional_flags |= FLAG_CASELESS_PATHNAMES;
1373 if (smbXcli_conn_dfs_supported(conn) &&
1374 smbXcli_tcon_is_dfs_share(tcon))
1376 additional_flags2 |= FLAGS2_DFS_PATHNAMES;
1380 state->smb1.recv_cmd = 0xFF;
1381 state->smb1.recv_status = NT_STATUS_INTERNAL_ERROR;
1382 state->smb1.recv_iov = talloc_zero_array(state, struct iovec, 3);
1383 if (state->smb1.recv_iov == NULL) {
1384 TALLOC_FREE(req);
1385 return NULL;
1388 smb1cli_req_flags(conn->protocol,
1389 conn->smb1.capabilities,
1390 smb_command,
1391 additional_flags,
1392 clear_flags,
1393 &flags,
1394 additional_flags2,
1395 clear_flags2,
1396 &flags2);
1398 SIVAL(state->smb1.hdr, 0, SMB_MAGIC);
1399 SCVAL(state->smb1.hdr, HDR_COM, smb_command);
1400 SIVAL(state->smb1.hdr, HDR_RCLS, NT_STATUS_V(NT_STATUS_OK));
1401 SCVAL(state->smb1.hdr, HDR_FLG, flags);
1402 SSVAL(state->smb1.hdr, HDR_FLG2, flags2);
1403 SSVAL(state->smb1.hdr, HDR_PIDHIGH, pid >> 16);
1404 SSVAL(state->smb1.hdr, HDR_TID, tid);
1405 SSVAL(state->smb1.hdr, HDR_PID, pid);
1406 SSVAL(state->smb1.hdr, HDR_UID, uid);
1407 SSVAL(state->smb1.hdr, HDR_MID, 0); /* this comes later */
1408 SCVAL(state->smb1.hdr, HDR_WCT, wct);
1410 state->smb1.vwv = vwv;
1412 num_bytes = iov_buflen(bytes_iov, iov_count);
1413 if (num_bytes == -1) {
1415 * I'd love to add a check for num_bytes<=UINT16_MAX here, but
1416 * the smbclient->samba connections can lie and transfer more.
1418 TALLOC_FREE(req);
1419 return NULL;
1422 SSVAL(state->smb1.bytecount_buf, 0, num_bytes);
1424 state->smb1.iov[0].iov_base = (void *)state->length_hdr;
1425 state->smb1.iov[0].iov_len = sizeof(state->length_hdr);
1426 state->smb1.iov[1].iov_base = (void *)state->smb1.hdr;
1427 state->smb1.iov[1].iov_len = sizeof(state->smb1.hdr);
1428 state->smb1.iov[2].iov_base = (void *)state->smb1.vwv;
1429 state->smb1.iov[2].iov_len = wct * sizeof(uint16_t);
1430 state->smb1.iov[3].iov_base = (void *)state->smb1.bytecount_buf;
1431 state->smb1.iov[3].iov_len = sizeof(uint16_t);
1433 if (iov_count != 0) {
1434 memcpy(&state->smb1.iov[4], bytes_iov,
1435 iov_count * sizeof(*bytes_iov));
1437 state->smb1.iov_count = iov_count + 4;
1439 if (timeout_msec > 0) {
1440 struct timeval endtime;
1442 endtime = timeval_current_ofs_msec(timeout_msec);
1443 if (!tevent_req_set_endtime(req, ev, endtime)) {
1444 return req;
1448 switch (smb_command) {
1449 case SMBtranss:
1450 case SMBtranss2:
1451 case SMBnttranss:
1452 state->one_way = true;
1453 break;
1454 case SMBntcancel:
1455 state->one_way = true;
1456 state->smb1.one_way_seqnum = true;
1457 break;
1458 case SMBlockingX:
1459 if ((wct == 8) &&
1460 (CVAL(vwv+3, 0) == LOCKING_ANDX_OPLOCK_RELEASE)) {
1461 state->one_way = true;
1463 break;
1466 return req;
1469 static NTSTATUS smb1cli_conn_signv(struct smbXcli_conn *conn,
1470 struct iovec *iov, int iov_count,
1471 uint32_t *seqnum,
1472 bool one_way_seqnum)
1474 TALLOC_CTX *frame = NULL;
1475 uint8_t *buf;
1478 * Obvious optimization: Make cli_calculate_sign_mac work with struct
1479 * iovec directly. MD5Update would do that just fine.
1482 if (iov_count < 4) {
1483 return NT_STATUS_INVALID_PARAMETER_MIX;
1485 if (iov[0].iov_len != NBT_HDR_SIZE) {
1486 return NT_STATUS_INVALID_PARAMETER_MIX;
1488 if (iov[1].iov_len != (MIN_SMB_SIZE-sizeof(uint16_t))) {
1489 return NT_STATUS_INVALID_PARAMETER_MIX;
1491 if (iov[2].iov_len > (0xFF * sizeof(uint16_t))) {
1492 return NT_STATUS_INVALID_PARAMETER_MIX;
1494 if (iov[3].iov_len != sizeof(uint16_t)) {
1495 return NT_STATUS_INVALID_PARAMETER_MIX;
1498 frame = talloc_stackframe();
1500 buf = smbXcli_iov_concat(frame, &iov[1], iov_count - 1);
1501 if (buf == NULL) {
1502 return NT_STATUS_NO_MEMORY;
1505 *seqnum = smb_signing_next_seqnum(conn->smb1.signing,
1506 one_way_seqnum);
1507 smb_signing_sign_pdu(conn->smb1.signing,
1508 buf, talloc_get_size(buf),
1509 *seqnum);
1510 memcpy(iov[1].iov_base, buf, iov[1].iov_len);
1512 TALLOC_FREE(frame);
1513 return NT_STATUS_OK;
1516 static void smb1cli_req_writev_done(struct tevent_req *subreq);
1517 static NTSTATUS smb1cli_conn_dispatch_incoming(struct smbXcli_conn *conn,
1518 TALLOC_CTX *tmp_mem,
1519 uint8_t *inbuf);
1521 static NTSTATUS smb1cli_req_writev_submit(struct tevent_req *req,
1522 struct smbXcli_req_state *state,
1523 struct iovec *iov, int iov_count)
1525 struct tevent_req *subreq;
1526 NTSTATUS status;
1527 uint8_t cmd;
1528 uint16_t mid;
1529 ssize_t nbtlen;
1531 if (!smbXcli_conn_is_connected(state->conn)) {
1532 return NT_STATUS_CONNECTION_DISCONNECTED;
1535 if (state->conn->protocol > PROTOCOL_NT1) {
1536 return NT_STATUS_REVISION_MISMATCH;
1539 if (iov_count < 4) {
1540 return NT_STATUS_INVALID_PARAMETER_MIX;
1542 if (iov[0].iov_len != NBT_HDR_SIZE) {
1543 return NT_STATUS_INVALID_PARAMETER_MIX;
1545 if (iov[1].iov_len != (MIN_SMB_SIZE-sizeof(uint16_t))) {
1546 return NT_STATUS_INVALID_PARAMETER_MIX;
1548 if (iov[2].iov_len > (0xFF * sizeof(uint16_t))) {
1549 return NT_STATUS_INVALID_PARAMETER_MIX;
1551 if (iov[3].iov_len != sizeof(uint16_t)) {
1552 return NT_STATUS_INVALID_PARAMETER_MIX;
1555 cmd = CVAL(iov[1].iov_base, HDR_COM);
1556 if (cmd == SMBreadBraw) {
1557 if (smbXcli_conn_has_async_calls(state->conn)) {
1558 return NT_STATUS_INVALID_PARAMETER_MIX;
1560 state->conn->smb1.read_braw_req = req;
1563 if (state->smb1.mid != 0) {
1564 mid = state->smb1.mid;
1565 } else {
1566 mid = smb1cli_alloc_mid(state->conn);
1568 SSVAL(iov[1].iov_base, HDR_MID, mid);
1570 nbtlen = iov_buflen(&iov[1], iov_count-1);
1571 if ((nbtlen == -1) || (nbtlen > 0x1FFFF)) {
1572 return NT_STATUS_INVALID_PARAMETER_MIX;
1575 _smb_setlen_nbt(iov[0].iov_base, nbtlen);
1577 status = smb1cli_conn_signv(state->conn, iov, iov_count,
1578 &state->smb1.seqnum,
1579 state->smb1.one_way_seqnum);
1581 if (!NT_STATUS_IS_OK(status)) {
1582 return status;
1586 * If we supported multiple encrytion contexts
1587 * here we'd look up based on tid.
1589 if (common_encryption_on(state->conn->smb1.trans_enc)) {
1590 char *buf, *enc_buf;
1592 buf = (char *)smbXcli_iov_concat(talloc_tos(), iov, iov_count);
1593 if (buf == NULL) {
1594 return NT_STATUS_NO_MEMORY;
1596 status = common_encrypt_buffer(state->conn->smb1.trans_enc,
1597 (char *)buf, &enc_buf);
1598 TALLOC_FREE(buf);
1599 if (!NT_STATUS_IS_OK(status)) {
1600 DEBUG(0, ("Error in encrypting client message: %s\n",
1601 nt_errstr(status)));
1602 return status;
1604 buf = (char *)talloc_memdup(state, enc_buf,
1605 smb_len_nbt(enc_buf)+4);
1606 SAFE_FREE(enc_buf);
1607 if (buf == NULL) {
1608 return NT_STATUS_NO_MEMORY;
1610 iov[0].iov_base = (void *)buf;
1611 iov[0].iov_len = talloc_get_size(buf);
1612 iov_count = 1;
1615 if (state->conn->dispatch_incoming == NULL) {
1616 state->conn->dispatch_incoming = smb1cli_conn_dispatch_incoming;
1619 if (!smbXcli_req_set_pending(req)) {
1620 return NT_STATUS_NO_MEMORY;
1623 tevent_req_set_cancel_fn(req, smbXcli_req_cancel);
1625 subreq = writev_send(state, state->ev, state->conn->outgoing,
1626 state->conn->sock_fd, false, iov, iov_count);
1627 if (subreq == NULL) {
1628 return NT_STATUS_NO_MEMORY;
1630 tevent_req_set_callback(subreq, smb1cli_req_writev_done, req);
1631 state->write_req = subreq;
1633 return NT_STATUS_OK;
1636 struct tevent_req *smb1cli_req_send(TALLOC_CTX *mem_ctx,
1637 struct tevent_context *ev,
1638 struct smbXcli_conn *conn,
1639 uint8_t smb_command,
1640 uint8_t additional_flags,
1641 uint8_t clear_flags,
1642 uint16_t additional_flags2,
1643 uint16_t clear_flags2,
1644 uint32_t timeout_msec,
1645 uint32_t pid,
1646 struct smbXcli_tcon *tcon,
1647 struct smbXcli_session *session,
1648 uint8_t wct, uint16_t *vwv,
1649 uint32_t num_bytes,
1650 const uint8_t *bytes)
1652 struct tevent_req *req;
1653 struct iovec iov;
1654 NTSTATUS status;
1656 iov.iov_base = discard_const_p(void, bytes);
1657 iov.iov_len = num_bytes;
1659 req = smb1cli_req_create(mem_ctx, ev, conn, smb_command,
1660 additional_flags, clear_flags,
1661 additional_flags2, clear_flags2,
1662 timeout_msec,
1663 pid, tcon, session,
1664 wct, vwv, 1, &iov);
1665 if (req == NULL) {
1666 return NULL;
1668 if (!tevent_req_is_in_progress(req)) {
1669 return tevent_req_post(req, ev);
1671 status = smb1cli_req_chain_submit(&req, 1);
1672 if (tevent_req_nterror(req, status)) {
1673 return tevent_req_post(req, ev);
1675 return req;
1678 static void smb1cli_req_writev_done(struct tevent_req *subreq)
1680 struct tevent_req *req =
1681 tevent_req_callback_data(subreq,
1682 struct tevent_req);
1683 struct smbXcli_req_state *state =
1684 tevent_req_data(req,
1685 struct smbXcli_req_state);
1686 ssize_t nwritten;
1687 int err;
1689 state->write_req = NULL;
1691 nwritten = writev_recv(subreq, &err);
1692 TALLOC_FREE(subreq);
1693 if (nwritten == -1) {
1694 /* here, we need to notify all pending requests */
1695 NTSTATUS status = map_nt_error_from_unix_common(err);
1696 smbXcli_conn_disconnect(state->conn, status);
1697 return;
1700 if (state->one_way) {
1701 state->inbuf = NULL;
1702 tevent_req_done(req);
1703 return;
1707 static void smbXcli_conn_received(struct tevent_req *subreq)
1709 struct smbXcli_conn *conn =
1710 tevent_req_callback_data(subreq,
1711 struct smbXcli_conn);
1712 TALLOC_CTX *frame = talloc_stackframe();
1713 NTSTATUS status;
1714 uint8_t *inbuf;
1715 ssize_t received;
1716 int err;
1718 if (subreq != conn->read_smb_req) {
1719 DEBUG(1, ("Internal error: cli_smb_received called with "
1720 "unexpected subreq\n"));
1721 smbXcli_conn_disconnect(conn, NT_STATUS_INTERNAL_ERROR);
1722 TALLOC_FREE(frame);
1723 return;
1725 conn->read_smb_req = NULL;
1727 received = read_smb_recv(subreq, frame, &inbuf, &err);
1728 TALLOC_FREE(subreq);
1729 if (received == -1) {
1730 status = map_nt_error_from_unix_common(err);
1731 smbXcli_conn_disconnect(conn, status);
1732 TALLOC_FREE(frame);
1733 return;
1736 status = conn->dispatch_incoming(conn, frame, inbuf);
1737 TALLOC_FREE(frame);
1738 if (NT_STATUS_IS_OK(status)) {
1740 * We should not do any more processing
1741 * as the dispatch function called
1742 * tevent_req_done().
1744 return;
1747 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
1749 * We got an error, so notify all pending requests
1751 smbXcli_conn_disconnect(conn, status);
1752 return;
1756 * We got NT_STATUS_RETRY, so we may ask for a
1757 * next incoming pdu.
1759 if (!smbXcli_conn_receive_next(conn)) {
1760 smbXcli_conn_disconnect(conn, NT_STATUS_NO_MEMORY);
1764 static NTSTATUS smb1cli_inbuf_parse_chain(uint8_t *buf, TALLOC_CTX *mem_ctx,
1765 struct iovec **piov, int *pnum_iov)
1767 struct iovec *iov;
1768 int num_iov;
1769 size_t buflen;
1770 size_t taken;
1771 size_t remaining;
1772 uint8_t *hdr;
1773 uint8_t cmd;
1774 uint32_t wct_ofs;
1775 NTSTATUS status;
1776 size_t min_size = MIN_SMB_SIZE;
1778 buflen = smb_len_tcp(buf);
1779 taken = 0;
1781 hdr = buf + NBT_HDR_SIZE;
1783 status = smb1cli_pull_raw_error(hdr);
1784 if (NT_STATUS_IS_ERR(status)) {
1786 * This is an ugly hack to support OS/2
1787 * which skips the byte_count in the DATA block
1788 * on some error responses.
1790 * See bug #9096
1792 min_size -= sizeof(uint16_t);
1795 if (buflen < min_size) {
1796 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1800 * This returns iovec elements in the following order:
1802 * - SMB header
1804 * - Parameter Block
1805 * - Data Block
1807 * - Parameter Block
1808 * - Data Block
1810 * - Parameter Block
1811 * - Data Block
1813 num_iov = 1;
1815 iov = talloc_array(mem_ctx, struct iovec, num_iov);
1816 if (iov == NULL) {
1817 return NT_STATUS_NO_MEMORY;
1819 iov[0].iov_base = hdr;
1820 iov[0].iov_len = HDR_WCT;
1821 taken += HDR_WCT;
1823 cmd = CVAL(hdr, HDR_COM);
1824 wct_ofs = HDR_WCT;
1826 while (true) {
1827 size_t len = buflen - taken;
1828 struct iovec *cur;
1829 struct iovec *iov_tmp;
1830 uint8_t wct;
1831 uint32_t bcc_ofs;
1832 uint16_t bcc;
1833 size_t needed;
1836 * we need at least WCT
1838 needed = sizeof(uint8_t);
1839 if (len < needed) {
1840 DEBUG(10, ("%s: %d bytes left, expected at least %d\n",
1841 __location__, (int)len, (int)needed));
1842 goto inval;
1846 * Now we check if the specified words are there
1848 wct = CVAL(hdr, wct_ofs);
1849 needed += wct * sizeof(uint16_t);
1850 if (len < needed) {
1851 DEBUG(10, ("%s: %d bytes left, expected at least %d\n",
1852 __location__, (int)len, (int)needed));
1853 goto inval;
1856 if ((num_iov == 1) &&
1857 (len == needed) &&
1858 NT_STATUS_IS_ERR(status))
1861 * This is an ugly hack to support OS/2
1862 * which skips the byte_count in the DATA block
1863 * on some error responses.
1865 * See bug #9096
1867 iov_tmp = talloc_realloc(mem_ctx, iov, struct iovec,
1868 num_iov + 2);
1869 if (iov_tmp == NULL) {
1870 TALLOC_FREE(iov);
1871 return NT_STATUS_NO_MEMORY;
1873 iov = iov_tmp;
1874 cur = &iov[num_iov];
1875 num_iov += 2;
1877 cur[0].iov_len = 0;
1878 cur[0].iov_base = hdr + (wct_ofs + sizeof(uint8_t));
1879 cur[1].iov_len = 0;
1880 cur[1].iov_base = cur[0].iov_base;
1882 taken += needed;
1883 break;
1887 * we need at least BCC
1889 needed += sizeof(uint16_t);
1890 if (len < needed) {
1891 DEBUG(10, ("%s: %d bytes left, expected at least %d\n",
1892 __location__, (int)len, (int)needed));
1893 goto inval;
1897 * Now we check if the specified bytes are there
1899 bcc_ofs = wct_ofs + sizeof(uint8_t) + wct * sizeof(uint16_t);
1900 bcc = SVAL(hdr, bcc_ofs);
1901 needed += bcc * sizeof(uint8_t);
1902 if (len < needed) {
1903 DEBUG(10, ("%s: %d bytes left, expected at least %d\n",
1904 __location__, (int)len, (int)needed));
1905 goto inval;
1909 * we allocate 2 iovec structures for words and bytes
1911 iov_tmp = talloc_realloc(mem_ctx, iov, struct iovec,
1912 num_iov + 2);
1913 if (iov_tmp == NULL) {
1914 TALLOC_FREE(iov);
1915 return NT_STATUS_NO_MEMORY;
1917 iov = iov_tmp;
1918 cur = &iov[num_iov];
1919 num_iov += 2;
1921 cur[0].iov_len = wct * sizeof(uint16_t);
1922 cur[0].iov_base = hdr + (wct_ofs + sizeof(uint8_t));
1923 cur[1].iov_len = bcc * sizeof(uint8_t);
1924 cur[1].iov_base = hdr + (bcc_ofs + sizeof(uint16_t));
1926 taken += needed;
1928 if (!smb1cli_is_andx_req(cmd)) {
1930 * If the current command does not have AndX chanining
1931 * we are done.
1933 break;
1936 if (wct == 0 && bcc == 0) {
1938 * An empty response also ends the chain,
1939 * most likely with an error.
1941 break;
1944 if (wct < 2) {
1945 DEBUG(10, ("%s: wct[%d] < 2 for cmd[0x%02X]\n",
1946 __location__, (int)wct, (int)cmd));
1947 goto inval;
1949 cmd = CVAL(cur[0].iov_base, 0);
1950 if (cmd == 0xFF) {
1952 * If it is the end of the chain we are also done.
1954 break;
1956 wct_ofs = SVAL(cur[0].iov_base, 2);
1958 if (wct_ofs < taken) {
1959 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1961 if (wct_ofs > buflen) {
1962 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1966 * we consumed everything up to the start of the next
1967 * parameter block.
1969 taken = wct_ofs;
1972 remaining = buflen - taken;
1974 if (remaining > 0 && num_iov >= 3) {
1976 * The last DATA block gets the remaining
1977 * bytes, this is needed to support
1978 * CAP_LARGE_WRITEX and CAP_LARGE_READX.
1980 iov[num_iov-1].iov_len += remaining;
1983 *piov = iov;
1984 *pnum_iov = num_iov;
1985 return NT_STATUS_OK;
1987 inval:
1988 TALLOC_FREE(iov);
1989 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1992 static NTSTATUS smb1cli_conn_dispatch_incoming(struct smbXcli_conn *conn,
1993 TALLOC_CTX *tmp_mem,
1994 uint8_t *inbuf)
1996 struct tevent_req *req;
1997 struct smbXcli_req_state *state;
1998 NTSTATUS status;
1999 size_t num_pending;
2000 size_t i;
2001 uint8_t cmd;
2002 uint16_t mid;
2003 bool oplock_break;
2004 uint8_t *inhdr = inbuf + NBT_HDR_SIZE;
2005 size_t len = smb_len_tcp(inbuf);
2006 struct iovec *iov = NULL;
2007 int num_iov = 0;
2008 struct tevent_req **chain = NULL;
2009 size_t num_chained = 0;
2010 size_t num_responses = 0;
2012 if (conn->smb1.read_braw_req != NULL) {
2013 req = conn->smb1.read_braw_req;
2014 conn->smb1.read_braw_req = NULL;
2015 state = tevent_req_data(req, struct smbXcli_req_state);
2017 smbXcli_req_unset_pending(req);
2019 if (state->smb1.recv_iov == NULL) {
2021 * For requests with more than
2022 * one response, we have to readd the
2023 * recv_iov array.
2025 state->smb1.recv_iov = talloc_zero_array(state,
2026 struct iovec,
2028 if (tevent_req_nomem(state->smb1.recv_iov, req)) {
2029 return NT_STATUS_OK;
2033 state->smb1.recv_iov[0].iov_base = (void *)(inhdr);
2034 state->smb1.recv_iov[0].iov_len = len;
2035 ZERO_STRUCT(state->smb1.recv_iov[1]);
2036 ZERO_STRUCT(state->smb1.recv_iov[2]);
2038 state->smb1.recv_cmd = SMBreadBraw;
2039 state->smb1.recv_status = NT_STATUS_OK;
2040 state->inbuf = talloc_move(state->smb1.recv_iov, &inbuf);
2042 tevent_req_done(req);
2043 return NT_STATUS_OK;
2046 if ((IVAL(inhdr, 0) != SMB_MAGIC) /* 0xFF"SMB" */
2047 && (SVAL(inhdr, 0) != 0x45ff)) /* 0xFF"E" */ {
2048 DEBUG(10, ("Got non-SMB PDU\n"));
2049 return NT_STATUS_INVALID_NETWORK_RESPONSE;
2053 * If we supported multiple encrytion contexts
2054 * here we'd look up based on tid.
2056 if (common_encryption_on(conn->smb1.trans_enc)
2057 && (CVAL(inbuf, 0) == 0)) {
2058 uint16_t enc_ctx_num;
2060 status = get_enc_ctx_num(inbuf, &enc_ctx_num);
2061 if (!NT_STATUS_IS_OK(status)) {
2062 DEBUG(10, ("get_enc_ctx_num returned %s\n",
2063 nt_errstr(status)));
2064 return status;
2067 if (enc_ctx_num != conn->smb1.trans_enc->enc_ctx_num) {
2068 DEBUG(10, ("wrong enc_ctx %d, expected %d\n",
2069 enc_ctx_num,
2070 conn->smb1.trans_enc->enc_ctx_num));
2071 return NT_STATUS_INVALID_HANDLE;
2074 status = common_decrypt_buffer(conn->smb1.trans_enc,
2075 (char *)inbuf);
2076 if (!NT_STATUS_IS_OK(status)) {
2077 DEBUG(10, ("common_decrypt_buffer returned %s\n",
2078 nt_errstr(status)));
2079 return status;
2081 inhdr = inbuf + NBT_HDR_SIZE;
2082 len = smb_len_nbt(inbuf);
2085 mid = SVAL(inhdr, HDR_MID);
2086 num_pending = talloc_array_length(conn->pending);
2088 for (i=0; i<num_pending; i++) {
2089 if (mid == smb1cli_req_mid(conn->pending[i])) {
2090 break;
2093 if (i == num_pending) {
2094 /* Dump unexpected reply */
2095 return NT_STATUS_RETRY;
2098 oplock_break = false;
2100 if (mid == 0xffff) {
2102 * Paranoia checks that this is really an oplock break request.
2104 oplock_break = (len == 51); /* hdr + 8 words */
2105 oplock_break &= ((CVAL(inhdr, HDR_FLG) & FLAG_REPLY) == 0);
2106 oplock_break &= (CVAL(inhdr, HDR_COM) == SMBlockingX);
2107 oplock_break &= (SVAL(inhdr, HDR_VWV+VWV(6)) == 0);
2108 oplock_break &= (SVAL(inhdr, HDR_VWV+VWV(7)) == 0);
2110 if (!oplock_break) {
2111 /* Dump unexpected reply */
2112 return NT_STATUS_RETRY;
2116 req = conn->pending[i];
2117 state = tevent_req_data(req, struct smbXcli_req_state);
2119 if (!oplock_break /* oplock breaks are not signed */
2120 && !smb_signing_check_pdu(conn->smb1.signing,
2121 inhdr, len, state->smb1.seqnum+1)) {
2122 DEBUG(10, ("cli_check_sign_mac failed\n"));
2123 return NT_STATUS_ACCESS_DENIED;
2126 status = smb1cli_inbuf_parse_chain(inbuf, tmp_mem,
2127 &iov, &num_iov);
2128 if (!NT_STATUS_IS_OK(status)) {
2129 DEBUG(10,("smb1cli_inbuf_parse_chain - %s\n",
2130 nt_errstr(status)));
2131 return status;
2134 cmd = CVAL(inhdr, HDR_COM);
2135 status = smb1cli_pull_raw_error(inhdr);
2137 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED) &&
2138 (state->session != NULL) && state->session->disconnect_expired)
2141 * this should be a short term hack
2142 * until the upper layers have implemented
2143 * re-authentication.
2145 return status;
2148 if (state->smb1.chained_requests == NULL) {
2149 if (num_iov != 3) {
2150 return NT_STATUS_INVALID_NETWORK_RESPONSE;
2153 smbXcli_req_unset_pending(req);
2155 if (state->smb1.recv_iov == NULL) {
2157 * For requests with more than
2158 * one response, we have to readd the
2159 * recv_iov array.
2161 state->smb1.recv_iov = talloc_zero_array(state,
2162 struct iovec,
2164 if (tevent_req_nomem(state->smb1.recv_iov, req)) {
2165 return NT_STATUS_OK;
2169 state->smb1.recv_cmd = cmd;
2170 state->smb1.recv_status = status;
2171 state->inbuf = talloc_move(state->smb1.recv_iov, &inbuf);
2173 state->smb1.recv_iov[0] = iov[0];
2174 state->smb1.recv_iov[1] = iov[1];
2175 state->smb1.recv_iov[2] = iov[2];
2177 if (talloc_array_length(conn->pending) == 0) {
2178 tevent_req_done(req);
2179 return NT_STATUS_OK;
2182 tevent_req_defer_callback(req, state->ev);
2183 tevent_req_done(req);
2184 return NT_STATUS_RETRY;
2187 chain = talloc_move(tmp_mem, &state->smb1.chained_requests);
2188 num_chained = talloc_array_length(chain);
2189 num_responses = (num_iov - 1)/2;
2191 if (num_responses > num_chained) {
2192 return NT_STATUS_INVALID_NETWORK_RESPONSE;
2195 for (i=0; i<num_chained; i++) {
2196 size_t iov_idx = 1 + (i*2);
2197 struct iovec *cur = &iov[iov_idx];
2198 uint8_t *inbuf_ref;
2200 req = chain[i];
2201 state = tevent_req_data(req, struct smbXcli_req_state);
2203 smbXcli_req_unset_pending(req);
2206 * as we finish multiple requests here
2207 * we need to defer the callbacks as
2208 * they could destroy our current stack state.
2210 tevent_req_defer_callback(req, state->ev);
2212 if (i >= num_responses) {
2213 tevent_req_nterror(req, NT_STATUS_REQUEST_ABORTED);
2214 continue;
2217 if (state->smb1.recv_iov == NULL) {
2219 * For requests with more than
2220 * one response, we have to readd the
2221 * recv_iov array.
2223 state->smb1.recv_iov = talloc_zero_array(state,
2224 struct iovec,
2226 if (tevent_req_nomem(state->smb1.recv_iov, req)) {
2227 continue;
2231 state->smb1.recv_cmd = cmd;
2233 if (i == (num_responses - 1)) {
2235 * The last request in the chain gets the status
2237 state->smb1.recv_status = status;
2238 } else {
2239 cmd = CVAL(cur[0].iov_base, 0);
2240 state->smb1.recv_status = NT_STATUS_OK;
2243 state->inbuf = inbuf;
2246 * Note: here we use talloc_reference() in a way
2247 * that does not expose it to the caller.
2249 inbuf_ref = talloc_reference(state->smb1.recv_iov, inbuf);
2250 if (tevent_req_nomem(inbuf_ref, req)) {
2251 continue;
2254 /* copy the related buffers */
2255 state->smb1.recv_iov[0] = iov[0];
2256 state->smb1.recv_iov[1] = cur[0];
2257 state->smb1.recv_iov[2] = cur[1];
2259 tevent_req_done(req);
2262 return NT_STATUS_RETRY;
2265 NTSTATUS smb1cli_req_recv(struct tevent_req *req,
2266 TALLOC_CTX *mem_ctx,
2267 struct iovec **piov,
2268 uint8_t **phdr,
2269 uint8_t *pwct,
2270 uint16_t **pvwv,
2271 uint32_t *pvwv_offset,
2272 uint32_t *pnum_bytes,
2273 uint8_t **pbytes,
2274 uint32_t *pbytes_offset,
2275 uint8_t **pinbuf,
2276 const struct smb1cli_req_expected_response *expected,
2277 size_t num_expected)
2279 struct smbXcli_req_state *state =
2280 tevent_req_data(req,
2281 struct smbXcli_req_state);
2282 NTSTATUS status = NT_STATUS_OK;
2283 struct iovec *recv_iov = NULL;
2284 uint8_t *hdr = NULL;
2285 uint8_t wct = 0;
2286 uint32_t vwv_offset = 0;
2287 uint16_t *vwv = NULL;
2288 uint32_t num_bytes = 0;
2289 uint32_t bytes_offset = 0;
2290 uint8_t *bytes = NULL;
2291 size_t i;
2292 bool found_status = false;
2293 bool found_size = false;
2295 if (piov != NULL) {
2296 *piov = NULL;
2298 if (phdr != NULL) {
2299 *phdr = 0;
2301 if (pwct != NULL) {
2302 *pwct = 0;
2304 if (pvwv != NULL) {
2305 *pvwv = NULL;
2307 if (pvwv_offset != NULL) {
2308 *pvwv_offset = 0;
2310 if (pnum_bytes != NULL) {
2311 *pnum_bytes = 0;
2313 if (pbytes != NULL) {
2314 *pbytes = NULL;
2316 if (pbytes_offset != NULL) {
2317 *pbytes_offset = 0;
2319 if (pinbuf != NULL) {
2320 *pinbuf = NULL;
2323 if (state->inbuf != NULL) {
2324 recv_iov = state->smb1.recv_iov;
2325 state->smb1.recv_iov = NULL;
2326 if (state->smb1.recv_cmd != SMBreadBraw) {
2327 hdr = (uint8_t *)recv_iov[0].iov_base;
2328 wct = recv_iov[1].iov_len/2;
2329 vwv = (uint16_t *)recv_iov[1].iov_base;
2330 vwv_offset = PTR_DIFF(vwv, hdr);
2331 num_bytes = recv_iov[2].iov_len;
2332 bytes = (uint8_t *)recv_iov[2].iov_base;
2333 bytes_offset = PTR_DIFF(bytes, hdr);
2337 if (tevent_req_is_nterror(req, &status)) {
2338 for (i=0; i < num_expected; i++) {
2339 if (NT_STATUS_EQUAL(status, expected[i].status)) {
2340 found_status = true;
2341 break;
2345 if (found_status) {
2346 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2349 return status;
2352 if (num_expected == 0) {
2353 found_status = true;
2354 found_size = true;
2357 status = state->smb1.recv_status;
2359 for (i=0; i < num_expected; i++) {
2360 if (!NT_STATUS_EQUAL(status, expected[i].status)) {
2361 continue;
2364 found_status = true;
2365 if (expected[i].wct == 0) {
2366 found_size = true;
2367 break;
2370 if (expected[i].wct == wct) {
2371 found_size = true;
2372 break;
2376 if (!found_status) {
2377 return status;
2380 if (!found_size) {
2381 return NT_STATUS_INVALID_NETWORK_RESPONSE;
2384 if (piov != NULL) {
2385 *piov = talloc_move(mem_ctx, &recv_iov);
2388 if (phdr != NULL) {
2389 *phdr = hdr;
2391 if (pwct != NULL) {
2392 *pwct = wct;
2394 if (pvwv != NULL) {
2395 *pvwv = vwv;
2397 if (pvwv_offset != NULL) {
2398 *pvwv_offset = vwv_offset;
2400 if (pnum_bytes != NULL) {
2401 *pnum_bytes = num_bytes;
2403 if (pbytes != NULL) {
2404 *pbytes = bytes;
2406 if (pbytes_offset != NULL) {
2407 *pbytes_offset = bytes_offset;
2409 if (pinbuf != NULL) {
2410 *pinbuf = state->inbuf;
2413 return status;
2416 size_t smb1cli_req_wct_ofs(struct tevent_req **reqs, int num_reqs)
2418 size_t wct_ofs;
2419 int i;
2421 wct_ofs = HDR_WCT;
2423 for (i=0; i<num_reqs; i++) {
2424 struct smbXcli_req_state *state;
2425 state = tevent_req_data(reqs[i], struct smbXcli_req_state);
2426 wct_ofs += smbXcli_iov_len(state->smb1.iov+2,
2427 state->smb1.iov_count-2);
2428 wct_ofs = (wct_ofs + 3) & ~3;
2430 return wct_ofs;
2433 NTSTATUS smb1cli_req_chain_submit(struct tevent_req **reqs, int num_reqs)
2435 struct smbXcli_req_state *first_state =
2436 tevent_req_data(reqs[0],
2437 struct smbXcli_req_state);
2438 struct smbXcli_req_state *state;
2439 size_t wct_offset;
2440 size_t chain_padding = 0;
2441 int i, iovlen;
2442 struct iovec *iov = NULL;
2443 struct iovec *this_iov;
2444 NTSTATUS status;
2445 ssize_t nbt_len;
2447 if (num_reqs == 1) {
2448 return smb1cli_req_writev_submit(reqs[0], first_state,
2449 first_state->smb1.iov,
2450 first_state->smb1.iov_count);
2453 iovlen = 0;
2454 for (i=0; i<num_reqs; i++) {
2455 if (!tevent_req_is_in_progress(reqs[i])) {
2456 return NT_STATUS_INTERNAL_ERROR;
2459 state = tevent_req_data(reqs[i], struct smbXcli_req_state);
2461 if (state->smb1.iov_count < 4) {
2462 return NT_STATUS_INVALID_PARAMETER_MIX;
2465 if (i == 0) {
2467 * The NBT and SMB header
2469 iovlen += 2;
2470 } else {
2472 * Chain padding
2474 iovlen += 1;
2478 * words and bytes
2480 iovlen += state->smb1.iov_count - 2;
2483 iov = talloc_zero_array(first_state, struct iovec, iovlen);
2484 if (iov == NULL) {
2485 return NT_STATUS_NO_MEMORY;
2488 first_state->smb1.chained_requests = (struct tevent_req **)talloc_memdup(
2489 first_state, reqs, sizeof(*reqs) * num_reqs);
2490 if (first_state->smb1.chained_requests == NULL) {
2491 TALLOC_FREE(iov);
2492 return NT_STATUS_NO_MEMORY;
2495 wct_offset = HDR_WCT;
2496 this_iov = iov;
2498 for (i=0; i<num_reqs; i++) {
2499 size_t next_padding = 0;
2500 uint16_t *vwv;
2502 state = tevent_req_data(reqs[i], struct smbXcli_req_state);
2504 if (i < num_reqs-1) {
2505 if (!smb1cli_is_andx_req(CVAL(state->smb1.hdr, HDR_COM))
2506 || CVAL(state->smb1.hdr, HDR_WCT) < 2) {
2507 TALLOC_FREE(iov);
2508 TALLOC_FREE(first_state->smb1.chained_requests);
2509 return NT_STATUS_INVALID_PARAMETER_MIX;
2513 wct_offset += smbXcli_iov_len(state->smb1.iov+2,
2514 state->smb1.iov_count-2) + 1;
2515 if ((wct_offset % 4) != 0) {
2516 next_padding = 4 - (wct_offset % 4);
2518 wct_offset += next_padding;
2519 vwv = state->smb1.vwv;
2521 if (i < num_reqs-1) {
2522 struct smbXcli_req_state *next_state =
2523 tevent_req_data(reqs[i+1],
2524 struct smbXcli_req_state);
2525 SCVAL(vwv+0, 0, CVAL(next_state->smb1.hdr, HDR_COM));
2526 SCVAL(vwv+0, 1, 0);
2527 SSVAL(vwv+1, 0, wct_offset);
2528 } else if (smb1cli_is_andx_req(CVAL(state->smb1.hdr, HDR_COM))) {
2529 /* properly end the chain */
2530 SCVAL(vwv+0, 0, 0xff);
2531 SCVAL(vwv+0, 1, 0xff);
2532 SSVAL(vwv+1, 0, 0);
2535 if (i == 0) {
2537 * The NBT and SMB header
2539 this_iov[0] = state->smb1.iov[0];
2540 this_iov[1] = state->smb1.iov[1];
2541 this_iov += 2;
2542 } else {
2544 * This one is a bit subtle. We have to add
2545 * chain_padding bytes between the requests, and we
2546 * have to also include the wct field of the
2547 * subsequent requests. We use the subsequent header
2548 * for the padding, it contains the wct field in its
2549 * last byte.
2551 this_iov[0].iov_len = chain_padding+1;
2552 this_iov[0].iov_base = (void *)&state->smb1.hdr[
2553 sizeof(state->smb1.hdr) - this_iov[0].iov_len];
2554 memset(this_iov[0].iov_base, 0, this_iov[0].iov_len-1);
2555 this_iov += 1;
2559 * copy the words and bytes
2561 memcpy(this_iov, state->smb1.iov+2,
2562 sizeof(struct iovec) * (state->smb1.iov_count-2));
2563 this_iov += state->smb1.iov_count - 2;
2564 chain_padding = next_padding;
2567 nbt_len = iov_buflen(&iov[1], iovlen-1);
2568 if ((nbt_len == -1) || (nbt_len > first_state->conn->smb1.max_xmit)) {
2569 TALLOC_FREE(iov);
2570 TALLOC_FREE(first_state->smb1.chained_requests);
2571 return NT_STATUS_INVALID_PARAMETER_MIX;
2574 status = smb1cli_req_writev_submit(reqs[0], first_state, iov, iovlen);
2575 if (!NT_STATUS_IS_OK(status)) {
2576 TALLOC_FREE(iov);
2577 TALLOC_FREE(first_state->smb1.chained_requests);
2578 return status;
2581 return NT_STATUS_OK;
2584 bool smbXcli_conn_has_async_calls(struct smbXcli_conn *conn)
2586 return ((tevent_queue_length(conn->outgoing) != 0)
2587 || (talloc_array_length(conn->pending) != 0));
2590 bool smbXcli_conn_dfs_supported(struct smbXcli_conn *conn)
2592 if (conn->protocol >= PROTOCOL_SMB2_02) {
2593 return (smb2cli_conn_server_capabilities(conn) & SMB2_CAP_DFS);
2596 return (smb1cli_conn_capabilities(conn) & CAP_DFS);
2599 bool smb2cli_conn_req_possible(struct smbXcli_conn *conn, uint32_t *max_dyn_len)
2601 uint16_t credits = 1;
2603 if (conn->smb2.cur_credits == 0) {
2604 if (max_dyn_len != NULL) {
2605 *max_dyn_len = 0;
2607 return false;
2610 if (conn->smb2.server.capabilities & SMB2_CAP_LARGE_MTU) {
2611 credits = conn->smb2.cur_credits;
2614 if (max_dyn_len != NULL) {
2615 *max_dyn_len = credits * 65536;
2618 return true;
2621 uint32_t smb2cli_conn_server_capabilities(struct smbXcli_conn *conn)
2623 return conn->smb2.server.capabilities;
2626 uint16_t smb2cli_conn_server_security_mode(struct smbXcli_conn *conn)
2628 return conn->smb2.server.security_mode;
2631 uint32_t smb2cli_conn_max_trans_size(struct smbXcli_conn *conn)
2633 return conn->smb2.server.max_trans_size;
2636 uint32_t smb2cli_conn_max_read_size(struct smbXcli_conn *conn)
2638 return conn->smb2.server.max_read_size;
2641 uint32_t smb2cli_conn_max_write_size(struct smbXcli_conn *conn)
2643 return conn->smb2.server.max_write_size;
2646 void smb2cli_conn_set_max_credits(struct smbXcli_conn *conn,
2647 uint16_t max_credits)
2649 conn->smb2.max_credits = max_credits;
2652 uint8_t smb2cli_conn_get_io_priority(struct smbXcli_conn *conn)
2654 if (conn->protocol < PROTOCOL_SMB3_11) {
2655 return 0;
2658 return conn->smb2.io_priority;
2661 void smb2cli_conn_set_io_priority(struct smbXcli_conn *conn,
2662 uint8_t io_priority)
2664 conn->smb2.io_priority = io_priority;
2667 uint32_t smb2cli_conn_cc_chunk_len(struct smbXcli_conn *conn)
2669 return conn->smb2.cc_chunk_len;
2672 void smb2cli_conn_set_cc_chunk_len(struct smbXcli_conn *conn,
2673 uint32_t chunk_len)
2675 conn->smb2.cc_chunk_len = chunk_len;
2678 uint32_t smb2cli_conn_cc_max_chunks(struct smbXcli_conn *conn)
2680 return conn->smb2.cc_max_chunks;
2683 void smb2cli_conn_set_cc_max_chunks(struct smbXcli_conn *conn,
2684 uint32_t max_chunks)
2686 conn->smb2.cc_max_chunks = max_chunks;
2689 static void smb2cli_req_cancel_done(struct tevent_req *subreq);
2691 static bool smb2cli_req_cancel(struct tevent_req *req)
2693 struct smbXcli_req_state *state =
2694 tevent_req_data(req,
2695 struct smbXcli_req_state);
2696 struct smbXcli_tcon *tcon = state->tcon;
2697 struct smbXcli_session *session = state->session;
2698 uint8_t *fixed = state->smb2.pad;
2699 uint16_t fixed_len = 4;
2700 struct tevent_req *subreq;
2701 struct smbXcli_req_state *substate;
2702 NTSTATUS status;
2704 SSVAL(fixed, 0, 0x04);
2705 SSVAL(fixed, 2, 0);
2707 subreq = smb2cli_req_create(state, state->ev,
2708 state->conn,
2709 SMB2_OP_CANCEL,
2710 0, 0, /* flags */
2711 0, /* timeout */
2712 tcon, session,
2713 fixed, fixed_len,
2714 NULL, 0, 0);
2715 if (subreq == NULL) {
2716 return false;
2718 substate = tevent_req_data(subreq, struct smbXcli_req_state);
2720 SIVAL(substate->smb2.hdr, SMB2_HDR_FLAGS, state->smb2.cancel_flags);
2721 SBVAL(substate->smb2.hdr, SMB2_HDR_MESSAGE_ID, state->smb2.cancel_mid);
2722 SBVAL(substate->smb2.hdr, SMB2_HDR_ASYNC_ID, state->smb2.cancel_aid);
2724 status = smb2cli_req_compound_submit(&subreq, 1);
2725 if (!NT_STATUS_IS_OK(status)) {
2726 TALLOC_FREE(subreq);
2727 return false;
2730 tevent_req_set_callback(subreq, smb2cli_req_cancel_done, NULL);
2732 return true;
2735 static void smb2cli_req_cancel_done(struct tevent_req *subreq)
2737 /* we do not care about the result */
2738 TALLOC_FREE(subreq);
2741 struct tevent_req *smb2cli_req_create(TALLOC_CTX *mem_ctx,
2742 struct tevent_context *ev,
2743 struct smbXcli_conn *conn,
2744 uint16_t cmd,
2745 uint32_t additional_flags,
2746 uint32_t clear_flags,
2747 uint32_t timeout_msec,
2748 struct smbXcli_tcon *tcon,
2749 struct smbXcli_session *session,
2750 const uint8_t *fixed,
2751 uint16_t fixed_len,
2752 const uint8_t *dyn,
2753 uint32_t dyn_len,
2754 uint32_t max_dyn_len)
2756 struct tevent_req *req;
2757 struct smbXcli_req_state *state;
2758 uint32_t flags = 0;
2759 uint32_t tid = 0;
2760 uint64_t uid = 0;
2761 bool use_channel_sequence = false;
2762 uint16_t channel_sequence = 0;
2763 bool use_replay_flag = false;
2765 req = tevent_req_create(mem_ctx, &state,
2766 struct smbXcli_req_state);
2767 if (req == NULL) {
2768 return NULL;
2771 state->ev = ev;
2772 state->conn = conn;
2773 state->session = session;
2774 state->tcon = tcon;
2776 if (conn->smb2.server.capabilities & SMB2_CAP_PERSISTENT_HANDLES) {
2777 use_channel_sequence = true;
2778 } else if (conn->smb2.server.capabilities & SMB2_CAP_MULTI_CHANNEL) {
2779 use_channel_sequence = true;
2782 if (smbXcli_conn_protocol(conn) >= PROTOCOL_SMB3_00) {
2783 use_replay_flag = true;
2786 if (smbXcli_conn_protocol(conn) >= PROTOCOL_SMB3_11) {
2787 flags |= SMB2_PRIORITY_VALUE_TO_MASK(conn->smb2.io_priority);
2790 if (session) {
2791 uid = session->smb2->session_id;
2793 if (use_channel_sequence) {
2794 channel_sequence = session->smb2->channel_sequence;
2797 if (use_replay_flag && session->smb2->replay_active) {
2798 additional_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
2801 state->smb2.should_sign = session->smb2->should_sign;
2802 state->smb2.should_encrypt = session->smb2->should_encrypt;
2804 if (cmd == SMB2_OP_SESSSETUP &&
2805 session->smb2_channel.signing_key.length == 0 &&
2806 session->smb2->signing_key.length != 0)
2809 * a session bind needs to be signed
2811 state->smb2.should_sign = true;
2814 if (cmd == SMB2_OP_SESSSETUP &&
2815 session->smb2_channel.signing_key.length == 0) {
2816 state->smb2.should_encrypt = false;
2819 if (additional_flags & SMB2_HDR_FLAG_SIGNED) {
2820 if (session->smb2_channel.signing_key.length == 0) {
2821 tevent_req_nterror(req, NT_STATUS_NO_USER_SESSION_KEY);
2822 return req;
2825 additional_flags &= ~SMB2_HDR_FLAG_SIGNED;
2826 state->smb2.should_sign = true;
2830 if (tcon) {
2831 tid = tcon->smb2.tcon_id;
2833 if (tcon->smb2.should_sign) {
2834 state->smb2.should_sign = true;
2836 if (tcon->smb2.should_encrypt) {
2837 state->smb2.should_encrypt = true;
2841 if (state->smb2.should_encrypt) {
2842 state->smb2.should_sign = false;
2845 state->smb2.recv_iov = talloc_zero_array(state, struct iovec, 3);
2846 if (state->smb2.recv_iov == NULL) {
2847 TALLOC_FREE(req);
2848 return NULL;
2851 flags |= additional_flags;
2852 flags &= ~clear_flags;
2854 state->smb2.fixed = fixed;
2855 state->smb2.fixed_len = fixed_len;
2856 state->smb2.dyn = dyn;
2857 state->smb2.dyn_len = dyn_len;
2858 state->smb2.max_dyn_len = max_dyn_len;
2860 if (state->smb2.should_encrypt) {
2861 SIVAL(state->smb2.transform, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2862 SBVAL(state->smb2.transform, SMB2_TF_SESSION_ID, uid);
2865 SIVAL(state->smb2.hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
2866 SSVAL(state->smb2.hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2867 SSVAL(state->smb2.hdr, SMB2_HDR_OPCODE, cmd);
2868 SSVAL(state->smb2.hdr, SMB2_HDR_CHANNEL_SEQUENCE, channel_sequence);
2869 SIVAL(state->smb2.hdr, SMB2_HDR_FLAGS, flags);
2870 SIVAL(state->smb2.hdr, SMB2_HDR_PID, 0); /* reserved */
2871 SIVAL(state->smb2.hdr, SMB2_HDR_TID, tid);
2872 SBVAL(state->smb2.hdr, SMB2_HDR_SESSION_ID, uid);
2874 switch (cmd) {
2875 case SMB2_OP_CANCEL:
2876 state->one_way = true;
2877 break;
2878 case SMB2_OP_BREAK:
2880 * If this is a dummy request, it will have
2881 * UINT64_MAX as message id.
2882 * If we send on break acknowledgement,
2883 * this gets overwritten later.
2885 SBVAL(state->smb2.hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2886 break;
2889 if (timeout_msec > 0) {
2890 struct timeval endtime;
2892 endtime = timeval_current_ofs_msec(timeout_msec);
2893 if (!tevent_req_set_endtime(req, ev, endtime)) {
2894 return req;
2898 return req;
2901 void smb2cli_req_set_notify_async(struct tevent_req *req)
2903 struct smbXcli_req_state *state =
2904 tevent_req_data(req,
2905 struct smbXcli_req_state);
2907 state->smb2.notify_async = true;
2910 static void smb2cli_req_writev_done(struct tevent_req *subreq);
2911 static NTSTATUS smb2cli_conn_dispatch_incoming(struct smbXcli_conn *conn,
2912 TALLOC_CTX *tmp_mem,
2913 uint8_t *inbuf);
2915 NTSTATUS smb2cli_req_compound_submit(struct tevent_req **reqs,
2916 int num_reqs)
2918 struct smbXcli_req_state *state;
2919 struct tevent_req *subreq;
2920 struct iovec *iov;
2921 int i, num_iov, nbt_len;
2922 int tf_iov = -1;
2923 const DATA_BLOB *encryption_key = NULL;
2924 uint64_t encryption_session_id = 0;
2925 uint64_t nonce_high = UINT64_MAX;
2926 uint64_t nonce_low = UINT64_MAX;
2929 * 1 for the nbt length, optional TRANSFORM
2930 * per request: HDR, fixed, dyn, padding
2931 * -1 because the last one does not need padding
2934 iov = talloc_array(reqs[0], struct iovec, 1 + 1 + 4*num_reqs - 1);
2935 if (iov == NULL) {
2936 return NT_STATUS_NO_MEMORY;
2939 num_iov = 1;
2940 nbt_len = 0;
2943 * the session of the first request that requires encryption
2944 * specifies the encryption key.
2946 for (i=0; i<num_reqs; i++) {
2947 if (!tevent_req_is_in_progress(reqs[i])) {
2948 return NT_STATUS_INTERNAL_ERROR;
2951 state = tevent_req_data(reqs[i], struct smbXcli_req_state);
2953 if (!smbXcli_conn_is_connected(state->conn)) {
2954 return NT_STATUS_CONNECTION_DISCONNECTED;
2957 if ((state->conn->protocol != PROTOCOL_NONE) &&
2958 (state->conn->protocol < PROTOCOL_SMB2_02)) {
2959 return NT_STATUS_REVISION_MISMATCH;
2962 if (state->session == NULL) {
2963 continue;
2966 if (!state->smb2.should_encrypt) {
2967 continue;
2970 encryption_key = &state->session->smb2->encryption_key;
2971 if (encryption_key->length == 0) {
2972 return NT_STATUS_INVALID_PARAMETER_MIX;
2975 encryption_session_id = state->session->smb2->session_id;
2977 state->session->smb2->nonce_low += 1;
2978 if (state->session->smb2->nonce_low == 0) {
2979 state->session->smb2->nonce_high += 1;
2980 state->session->smb2->nonce_low += 1;
2984 * CCM and GCM algorithms must never have their
2985 * nonce wrap, or the security of the whole
2986 * communication and the keys is destroyed.
2987 * We must drop the connection once we have
2988 * transfered too much data.
2990 * NOTE: We assume nonces greater than 8 bytes.
2992 if (state->session->smb2->nonce_high >=
2993 state->session->smb2->nonce_high_max)
2995 return NT_STATUS_ENCRYPTION_FAILED;
2998 nonce_high = state->session->smb2->nonce_high_random;
2999 nonce_high += state->session->smb2->nonce_high;
3000 nonce_low = state->session->smb2->nonce_low;
3002 tf_iov = num_iov;
3003 iov[num_iov].iov_base = state->smb2.transform;
3004 iov[num_iov].iov_len = sizeof(state->smb2.transform);
3005 num_iov += 1;
3007 SBVAL(state->smb2.transform, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3008 SBVAL(state->smb2.transform, SMB2_TF_NONCE,
3009 nonce_low);
3010 SBVAL(state->smb2.transform, SMB2_TF_NONCE+8,
3011 nonce_high);
3012 SBVAL(state->smb2.transform, SMB2_TF_SESSION_ID,
3013 encryption_session_id);
3015 nbt_len += SMB2_TF_HDR_SIZE;
3016 break;
3019 for (i=0; i<num_reqs; i++) {
3020 int hdr_iov;
3021 size_t reqlen;
3022 bool ret;
3023 uint16_t opcode;
3024 uint64_t avail;
3025 uint16_t charge;
3026 uint16_t credits;
3027 uint64_t mid;
3028 const DATA_BLOB *signing_key = NULL;
3030 if (!tevent_req_is_in_progress(reqs[i])) {
3031 return NT_STATUS_INTERNAL_ERROR;
3034 state = tevent_req_data(reqs[i], struct smbXcli_req_state);
3036 if (!smbXcli_conn_is_connected(state->conn)) {
3037 return NT_STATUS_CONNECTION_DISCONNECTED;
3040 if ((state->conn->protocol != PROTOCOL_NONE) &&
3041 (state->conn->protocol < PROTOCOL_SMB2_02)) {
3042 return NT_STATUS_REVISION_MISMATCH;
3045 opcode = SVAL(state->smb2.hdr, SMB2_HDR_OPCODE);
3046 if (opcode == SMB2_OP_CANCEL) {
3047 goto skip_credits;
3050 avail = UINT64_MAX - state->conn->smb2.mid;
3051 if (avail < 1) {
3052 return NT_STATUS_CONNECTION_ABORTED;
3055 if (state->conn->smb2.server.capabilities & SMB2_CAP_LARGE_MTU) {
3056 uint32_t max_dyn_len = 1;
3058 max_dyn_len = MAX(max_dyn_len, state->smb2.dyn_len);
3059 max_dyn_len = MAX(max_dyn_len, state->smb2.max_dyn_len);
3061 charge = (max_dyn_len - 1)/ 65536 + 1;
3062 } else {
3063 charge = 1;
3066 charge = MAX(state->smb2.credit_charge, charge);
3068 avail = MIN(avail, state->conn->smb2.cur_credits);
3069 if (avail < charge) {
3070 return NT_STATUS_INTERNAL_ERROR;
3073 credits = 0;
3074 if (state->conn->smb2.max_credits > state->conn->smb2.cur_credits) {
3075 credits = state->conn->smb2.max_credits -
3076 state->conn->smb2.cur_credits;
3078 if (state->conn->smb2.max_credits >= state->conn->smb2.cur_credits) {
3079 credits += 1;
3082 mid = state->conn->smb2.mid;
3083 state->conn->smb2.mid += charge;
3084 state->conn->smb2.cur_credits -= charge;
3086 if (state->conn->smb2.server.capabilities & SMB2_CAP_LARGE_MTU) {
3087 SSVAL(state->smb2.hdr, SMB2_HDR_CREDIT_CHARGE, charge);
3089 SSVAL(state->smb2.hdr, SMB2_HDR_CREDIT, credits);
3090 SBVAL(state->smb2.hdr, SMB2_HDR_MESSAGE_ID, mid);
3092 state->smb2.cancel_flags = 0;
3093 state->smb2.cancel_mid = mid;
3094 state->smb2.cancel_aid = 0;
3096 skip_credits:
3097 if (state->session && encryption_key == NULL) {
3099 * We prefer the channel signing key if it is
3100 * already there.
3102 if (state->smb2.should_sign) {
3103 signing_key = &state->session->smb2_channel.signing_key;
3107 * If it is a channel binding, we already have the main
3108 * signing key and try that one.
3110 if (signing_key && signing_key->length == 0) {
3111 signing_key = &state->session->smb2->signing_key;
3115 * If we do not have any session key yet, we skip the
3116 * signing of SMB2_OP_SESSSETUP requests.
3118 if (signing_key && signing_key->length == 0) {
3119 signing_key = NULL;
3123 hdr_iov = num_iov;
3124 iov[num_iov].iov_base = state->smb2.hdr;
3125 iov[num_iov].iov_len = sizeof(state->smb2.hdr);
3126 num_iov += 1;
3128 iov[num_iov].iov_base = discard_const(state->smb2.fixed);
3129 iov[num_iov].iov_len = state->smb2.fixed_len;
3130 num_iov += 1;
3132 if (state->smb2.dyn != NULL) {
3133 iov[num_iov].iov_base = discard_const(state->smb2.dyn);
3134 iov[num_iov].iov_len = state->smb2.dyn_len;
3135 num_iov += 1;
3138 reqlen = sizeof(state->smb2.hdr);
3139 reqlen += state->smb2.fixed_len;
3140 reqlen += state->smb2.dyn_len;
3142 if (i < num_reqs-1) {
3143 if ((reqlen % 8) > 0) {
3144 uint8_t pad = 8 - (reqlen % 8);
3145 iov[num_iov].iov_base = state->smb2.pad;
3146 iov[num_iov].iov_len = pad;
3147 num_iov += 1;
3148 reqlen += pad;
3150 SIVAL(state->smb2.hdr, SMB2_HDR_NEXT_COMMAND, reqlen);
3153 state->smb2.encryption_session_id = encryption_session_id;
3155 if (signing_key != NULL) {
3156 NTSTATUS status;
3158 status = smb2_signing_sign_pdu(*signing_key,
3159 state->session->conn->protocol,
3160 &iov[hdr_iov], num_iov - hdr_iov);
3161 if (!NT_STATUS_IS_OK(status)) {
3162 return status;
3166 nbt_len += reqlen;
3168 ret = smbXcli_req_set_pending(reqs[i]);
3169 if (!ret) {
3170 return NT_STATUS_NO_MEMORY;
3174 state = tevent_req_data(reqs[0], struct smbXcli_req_state);
3175 _smb_setlen_tcp(state->length_hdr, nbt_len);
3176 iov[0].iov_base = state->length_hdr;
3177 iov[0].iov_len = sizeof(state->length_hdr);
3179 if (encryption_key != NULL) {
3180 NTSTATUS status;
3181 size_t buflen = nbt_len - SMB2_TF_HDR_SIZE;
3182 uint8_t *buf;
3183 int vi;
3185 buf = talloc_array(iov, uint8_t, buflen);
3186 if (buf == NULL) {
3187 return NT_STATUS_NO_MEMORY;
3191 * We copy the buffers before encrypting them,
3192 * this is at least currently needed for the
3193 * to keep state->smb2.hdr.
3195 * Also the callers may expect there buffers
3196 * to be const.
3198 for (vi = tf_iov + 1; vi < num_iov; vi++) {
3199 struct iovec *v = &iov[vi];
3200 const uint8_t *o = (const uint8_t *)v->iov_base;
3202 memcpy(buf, o, v->iov_len);
3203 v->iov_base = (void *)buf;
3204 buf += v->iov_len;
3207 status = smb2_signing_encrypt_pdu(*encryption_key,
3208 state->conn->smb2.server.cipher,
3209 &iov[tf_iov], num_iov - tf_iov);
3210 if (!NT_STATUS_IS_OK(status)) {
3211 return status;
3215 if (state->conn->dispatch_incoming == NULL) {
3216 state->conn->dispatch_incoming = smb2cli_conn_dispatch_incoming;
3219 subreq = writev_send(state, state->ev, state->conn->outgoing,
3220 state->conn->sock_fd, false, iov, num_iov);
3221 if (subreq == NULL) {
3222 return NT_STATUS_NO_MEMORY;
3224 tevent_req_set_callback(subreq, smb2cli_req_writev_done, reqs[0]);
3225 state->write_req = subreq;
3227 return NT_STATUS_OK;
3230 void smb2cli_req_set_credit_charge(struct tevent_req *req, uint16_t charge)
3232 struct smbXcli_req_state *state =
3233 tevent_req_data(req,
3234 struct smbXcli_req_state);
3236 state->smb2.credit_charge = charge;
3239 struct tevent_req *smb2cli_req_send(TALLOC_CTX *mem_ctx,
3240 struct tevent_context *ev,
3241 struct smbXcli_conn *conn,
3242 uint16_t cmd,
3243 uint32_t additional_flags,
3244 uint32_t clear_flags,
3245 uint32_t timeout_msec,
3246 struct smbXcli_tcon *tcon,
3247 struct smbXcli_session *session,
3248 const uint8_t *fixed,
3249 uint16_t fixed_len,
3250 const uint8_t *dyn,
3251 uint32_t dyn_len,
3252 uint32_t max_dyn_len)
3254 struct tevent_req *req;
3255 NTSTATUS status;
3257 req = smb2cli_req_create(mem_ctx, ev, conn, cmd,
3258 additional_flags, clear_flags,
3259 timeout_msec,
3260 tcon, session,
3261 fixed, fixed_len,
3262 dyn, dyn_len,
3263 max_dyn_len);
3264 if (req == NULL) {
3265 return NULL;
3267 if (!tevent_req_is_in_progress(req)) {
3268 return tevent_req_post(req, ev);
3270 status = smb2cli_req_compound_submit(&req, 1);
3271 if (tevent_req_nterror(req, status)) {
3272 return tevent_req_post(req, ev);
3274 return req;
3277 static void smb2cli_req_writev_done(struct tevent_req *subreq)
3279 struct tevent_req *req =
3280 tevent_req_callback_data(subreq,
3281 struct tevent_req);
3282 struct smbXcli_req_state *state =
3283 tevent_req_data(req,
3284 struct smbXcli_req_state);
3285 ssize_t nwritten;
3286 int err;
3288 state->write_req = NULL;
3290 nwritten = writev_recv(subreq, &err);
3291 TALLOC_FREE(subreq);
3292 if (nwritten == -1) {
3293 /* here, we need to notify all pending requests */
3294 NTSTATUS status = map_nt_error_from_unix_common(err);
3295 smbXcli_conn_disconnect(state->conn, status);
3296 return;
3300 static struct smbXcli_session* smbXcli_session_by_uid(struct smbXcli_conn *conn,
3301 uint64_t uid)
3303 struct smbXcli_session *s = conn->sessions;
3305 for (; s; s = s->next) {
3306 if (s->smb2->session_id != uid) {
3307 continue;
3309 break;
3312 return s;
3315 static NTSTATUS smb2cli_inbuf_parse_compound(struct smbXcli_conn *conn,
3316 uint8_t *buf,
3317 size_t buflen,
3318 TALLOC_CTX *mem_ctx,
3319 struct iovec **piov, int *pnum_iov)
3321 struct iovec *iov;
3322 int num_iov = 0;
3323 size_t taken = 0;
3324 uint8_t *first_hdr = buf;
3325 size_t verified_buflen = 0;
3326 uint8_t *tf = NULL;
3327 size_t tf_len = 0;
3329 iov = talloc_array(mem_ctx, struct iovec, num_iov);
3330 if (iov == NULL) {
3331 return NT_STATUS_NO_MEMORY;
3334 while (taken < buflen) {
3335 size_t len = buflen - taken;
3336 uint8_t *hdr = first_hdr + taken;
3337 struct iovec *cur;
3338 size_t full_size;
3339 size_t next_command_ofs;
3340 uint16_t body_size;
3341 struct iovec *iov_tmp;
3343 if (verified_buflen > taken) {
3344 len = verified_buflen - taken;
3345 } else {
3346 tf = NULL;
3347 tf_len = 0;
3350 if (len < 4) {
3351 DEBUG(10, ("%d bytes left, expected at least %d\n",
3352 (int)len, 4));
3353 goto inval;
3355 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
3356 struct smbXcli_session *s;
3357 uint64_t uid;
3358 struct iovec tf_iov[2];
3359 size_t enc_len;
3360 NTSTATUS status;
3362 if (len < SMB2_TF_HDR_SIZE) {
3363 DEBUG(10, ("%d bytes left, expected at least %d\n",
3364 (int)len, SMB2_TF_HDR_SIZE));
3365 goto inval;
3367 tf = hdr;
3368 tf_len = SMB2_TF_HDR_SIZE;
3369 taken += tf_len;
3371 hdr = first_hdr + taken;
3372 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
3373 uid = BVAL(tf, SMB2_TF_SESSION_ID);
3375 if (len < SMB2_TF_HDR_SIZE + enc_len) {
3376 DEBUG(10, ("%d bytes left, expected at least %d\n",
3377 (int)len,
3378 (int)(SMB2_TF_HDR_SIZE + enc_len)));
3379 goto inval;
3382 s = smbXcli_session_by_uid(conn, uid);
3383 if (s == NULL) {
3384 DEBUG(10, ("unknown session_id %llu\n",
3385 (unsigned long long)uid));
3386 goto inval;
3389 tf_iov[0].iov_base = (void *)tf;
3390 tf_iov[0].iov_len = tf_len;
3391 tf_iov[1].iov_base = (void *)hdr;
3392 tf_iov[1].iov_len = enc_len;
3394 status = smb2_signing_decrypt_pdu(s->smb2->decryption_key,
3395 conn->smb2.server.cipher,
3396 tf_iov, 2);
3397 if (!NT_STATUS_IS_OK(status)) {
3398 TALLOC_FREE(iov);
3399 return status;
3402 verified_buflen = taken + enc_len;
3403 len = enc_len;
3407 * We need the header plus the body length field
3410 if (len < SMB2_HDR_BODY + 2) {
3411 DEBUG(10, ("%d bytes left, expected at least %d\n",
3412 (int)len, SMB2_HDR_BODY));
3413 goto inval;
3415 if (IVAL(hdr, 0) != SMB2_MAGIC) {
3416 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
3417 IVAL(hdr, 0)));
3418 goto inval;
3420 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
3421 DEBUG(10, ("Got HDR len %d, expected %d\n",
3422 SVAL(hdr, 4), SMB2_HDR_BODY));
3423 goto inval;
3426 full_size = len;
3427 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
3428 body_size = SVAL(hdr, SMB2_HDR_BODY);
3430 if (next_command_ofs != 0) {
3431 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
3432 goto inval;
3434 if (next_command_ofs > full_size) {
3435 goto inval;
3437 full_size = next_command_ofs;
3439 if (body_size < 2) {
3440 goto inval;
3442 body_size &= 0xfffe;
3444 if (body_size > (full_size - SMB2_HDR_BODY)) {
3445 goto inval;
3448 iov_tmp = talloc_realloc(mem_ctx, iov, struct iovec,
3449 num_iov + 4);
3450 if (iov_tmp == NULL) {
3451 TALLOC_FREE(iov);
3452 return NT_STATUS_NO_MEMORY;
3454 iov = iov_tmp;
3455 cur = &iov[num_iov];
3456 num_iov += 4;
3458 cur[0].iov_base = tf;
3459 cur[0].iov_len = tf_len;
3460 cur[1].iov_base = hdr;
3461 cur[1].iov_len = SMB2_HDR_BODY;
3462 cur[2].iov_base = hdr + SMB2_HDR_BODY;
3463 cur[2].iov_len = body_size;
3464 cur[3].iov_base = hdr + SMB2_HDR_BODY + body_size;
3465 cur[3].iov_len = full_size - (SMB2_HDR_BODY + body_size);
3467 taken += full_size;
3470 *piov = iov;
3471 *pnum_iov = num_iov;
3472 return NT_STATUS_OK;
3474 inval:
3475 TALLOC_FREE(iov);
3476 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3479 static struct tevent_req *smb2cli_conn_find_pending(struct smbXcli_conn *conn,
3480 uint64_t mid)
3482 size_t num_pending = talloc_array_length(conn->pending);
3483 size_t i;
3485 for (i=0; i<num_pending; i++) {
3486 struct tevent_req *req = conn->pending[i];
3487 struct smbXcli_req_state *state =
3488 tevent_req_data(req,
3489 struct smbXcli_req_state);
3491 if (mid == BVAL(state->smb2.hdr, SMB2_HDR_MESSAGE_ID)) {
3492 return req;
3495 return NULL;
3498 static NTSTATUS smb2cli_conn_dispatch_incoming(struct smbXcli_conn *conn,
3499 TALLOC_CTX *tmp_mem,
3500 uint8_t *inbuf)
3502 struct tevent_req *req;
3503 struct smbXcli_req_state *state = NULL;
3504 struct iovec *iov = NULL;
3505 int i, num_iov = 0;
3506 NTSTATUS status;
3507 bool defer = true;
3508 struct smbXcli_session *last_session = NULL;
3509 size_t inbuf_len = smb_len_tcp(inbuf);
3511 status = smb2cli_inbuf_parse_compound(conn,
3512 inbuf + NBT_HDR_SIZE,
3513 inbuf_len,
3514 tmp_mem,
3515 &iov, &num_iov);
3516 if (!NT_STATUS_IS_OK(status)) {
3517 return status;
3520 for (i=0; i<num_iov; i+=4) {
3521 uint8_t *inbuf_ref = NULL;
3522 struct iovec *cur = &iov[i];
3523 uint8_t *inhdr = (uint8_t *)cur[1].iov_base;
3524 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
3525 uint32_t flags = IVAL(inhdr, SMB2_HDR_FLAGS);
3526 uint64_t mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
3527 uint16_t req_opcode;
3528 uint32_t req_flags;
3529 uint16_t credits = SVAL(inhdr, SMB2_HDR_CREDIT);
3530 uint32_t new_credits;
3531 struct smbXcli_session *session = NULL;
3532 const DATA_BLOB *signing_key = NULL;
3533 bool was_encrypted = false;
3535 new_credits = conn->smb2.cur_credits;
3536 new_credits += credits;
3537 if (new_credits > UINT16_MAX) {
3538 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3540 conn->smb2.cur_credits += credits;
3542 req = smb2cli_conn_find_pending(conn, mid);
3543 if (req == NULL) {
3544 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3546 state = tevent_req_data(req, struct smbXcli_req_state);
3548 req_opcode = SVAL(state->smb2.hdr, SMB2_HDR_OPCODE);
3549 if (opcode != req_opcode) {
3550 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3552 req_flags = SVAL(state->smb2.hdr, SMB2_HDR_FLAGS);
3554 if (!(flags & SMB2_HDR_FLAG_REDIRECT)) {
3555 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3558 status = NT_STATUS(IVAL(inhdr, SMB2_HDR_STATUS));
3559 if ((flags & SMB2_HDR_FLAG_ASYNC) &&
3560 NT_STATUS_EQUAL(status, STATUS_PENDING)) {
3561 uint64_t async_id = BVAL(inhdr, SMB2_HDR_ASYNC_ID);
3563 if (state->smb2.got_async) {
3564 /* We only expect one STATUS_PENDING response */
3565 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3567 state->smb2.got_async = true;
3570 * async interim responses are not signed,
3571 * even if the SMB2_HDR_FLAG_SIGNED flag
3572 * is set.
3574 state->smb2.cancel_flags = SMB2_HDR_FLAG_ASYNC;
3575 state->smb2.cancel_mid = 0;
3576 state->smb2.cancel_aid = async_id;
3578 if (state->smb2.notify_async) {
3579 tevent_req_defer_callback(req, state->ev);
3580 tevent_req_notify_callback(req);
3582 continue;
3585 session = state->session;
3586 if (req_flags & SMB2_HDR_FLAG_CHAINED) {
3587 session = last_session;
3589 last_session = session;
3591 if (state->smb2.should_sign) {
3592 if (!(flags & SMB2_HDR_FLAG_SIGNED)) {
3593 return NT_STATUS_ACCESS_DENIED;
3597 if (flags & SMB2_HDR_FLAG_SIGNED) {
3598 uint64_t uid = BVAL(inhdr, SMB2_HDR_SESSION_ID);
3600 if (session == NULL) {
3601 session = smbXcli_session_by_uid(state->conn,
3602 uid);
3605 if (session == NULL) {
3606 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3609 last_session = session;
3610 signing_key = &session->smb2_channel.signing_key;
3613 if (opcode == SMB2_OP_SESSSETUP) {
3615 * We prefer the channel signing key, if it is
3616 * already there.
3618 * If we do not have a channel signing key yet,
3619 * we try the main signing key, if it is not
3620 * the final response.
3622 if (signing_key && signing_key->length == 0 &&
3623 !NT_STATUS_IS_OK(status)) {
3624 signing_key = &session->smb2->signing_key;
3627 if (signing_key && signing_key->length == 0) {
3629 * If we do not have a session key to
3630 * verify the signature, we defer the
3631 * signing check to the caller.
3633 * The caller gets NT_STATUS_OK, it
3634 * has to call
3635 * smb2cli_session_set_session_key()
3636 * or
3637 * smb2cli_session_set_channel_key()
3638 * which will check the signature
3639 * with the channel signing key.
3641 signing_key = NULL;
3645 if (cur[0].iov_len == SMB2_TF_HDR_SIZE) {
3646 const uint8_t *tf = (const uint8_t *)cur[0].iov_base;
3647 uint64_t uid = BVAL(tf, SMB2_TF_SESSION_ID);
3650 * If the response was encrypted in a SMB2_TRANSFORM
3651 * pdu, which belongs to the correct session,
3652 * we do not need to do signing checks
3654 * It could be the session the response belongs to
3655 * or the session that was used to encrypt the
3656 * SMB2_TRANSFORM request.
3658 if ((session && session->smb2->session_id == uid) ||
3659 (state->smb2.encryption_session_id == uid)) {
3660 signing_key = NULL;
3661 was_encrypted = true;
3665 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
3667 * if the server returns NT_STATUS_USER_SESSION_DELETED
3668 * the response is not signed and we should
3669 * propagate the NT_STATUS_USER_SESSION_DELETED
3670 * status to the caller.
3672 state->smb2.signing_skipped = true;
3673 signing_key = NULL;
3676 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
3678 * if the server returns
3679 * NT_STATUS_INVALID_PARAMETER
3680 * the response might not be encrypted.
3682 if (state->smb2.should_encrypt && !was_encrypted) {
3683 state->smb2.signing_skipped = true;
3684 signing_key = NULL;
3688 if (state->smb2.should_encrypt && !was_encrypted) {
3689 if (!state->smb2.signing_skipped) {
3690 return NT_STATUS_ACCESS_DENIED;
3694 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED) ||
3695 NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED) ||
3696 NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
3698 * if the server returns
3699 * NT_STATUS_NETWORK_NAME_DELETED
3700 * NT_STATUS_FILE_CLOSED
3701 * NT_STATUS_INVALID_PARAMETER
3702 * the response might not be signed
3703 * as this happens before the signing checks.
3705 * If server echos the signature (or all zeros)
3706 * we should report the status from the server
3707 * to the caller.
3709 if (signing_key) {
3710 int cmp;
3712 cmp = memcmp(inhdr+SMB2_HDR_SIGNATURE,
3713 state->smb2.hdr+SMB2_HDR_SIGNATURE,
3714 16);
3715 if (cmp == 0) {
3716 state->smb2.signing_skipped = true;
3717 signing_key = NULL;
3720 if (signing_key) {
3721 int cmp;
3722 static const uint8_t zeros[16];
3724 cmp = memcmp(inhdr+SMB2_HDR_SIGNATURE,
3725 zeros,
3726 16);
3727 if (cmp == 0) {
3728 state->smb2.signing_skipped = true;
3729 signing_key = NULL;
3734 if (signing_key) {
3735 status = smb2_signing_check_pdu(*signing_key,
3736 state->conn->protocol,
3737 &cur[1], 3);
3738 if (!NT_STATUS_IS_OK(status)) {
3740 * If the signing check fails, we disconnect
3741 * the connection.
3743 return status;
3747 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED) &&
3748 (session != NULL) && session->disconnect_expired)
3751 * this should be a short term hack
3752 * until the upper layers have implemented
3753 * re-authentication.
3755 return status;
3758 smbXcli_req_unset_pending(req);
3761 * There might be more than one response
3762 * we need to defer the notifications
3764 if ((num_iov == 5) && (talloc_array_length(conn->pending) == 0)) {
3765 defer = false;
3768 if (defer) {
3769 tevent_req_defer_callback(req, state->ev);
3773 * Note: here we use talloc_reference() in a way
3774 * that does not expose it to the caller.
3776 inbuf_ref = talloc_reference(state->smb2.recv_iov, inbuf);
3777 if (tevent_req_nomem(inbuf_ref, req)) {
3778 continue;
3781 /* copy the related buffers */
3782 state->smb2.recv_iov[0] = cur[1];
3783 state->smb2.recv_iov[1] = cur[2];
3784 state->smb2.recv_iov[2] = cur[3];
3786 tevent_req_done(req);
3789 if (defer) {
3790 return NT_STATUS_RETRY;
3793 return NT_STATUS_OK;
3796 NTSTATUS smb2cli_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
3797 struct iovec **piov,
3798 const struct smb2cli_req_expected_response *expected,
3799 size_t num_expected)
3801 struct smbXcli_req_state *state =
3802 tevent_req_data(req,
3803 struct smbXcli_req_state);
3804 NTSTATUS status;
3805 size_t body_size;
3806 bool found_status = false;
3807 bool found_size = false;
3808 size_t i;
3810 if (piov != NULL) {
3811 *piov = NULL;
3814 if (tevent_req_is_in_progress(req) && state->smb2.got_async) {
3815 return STATUS_PENDING;
3818 if (tevent_req_is_nterror(req, &status)) {
3819 for (i=0; i < num_expected; i++) {
3820 if (NT_STATUS_EQUAL(status, expected[i].status)) {
3821 found_status = true;
3822 break;
3826 if (found_status) {
3827 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
3830 return status;
3833 if (num_expected == 0) {
3834 found_status = true;
3835 found_size = true;
3838 status = NT_STATUS(IVAL(state->smb2.recv_iov[0].iov_base, SMB2_HDR_STATUS));
3839 body_size = SVAL(state->smb2.recv_iov[1].iov_base, 0);
3841 for (i=0; i < num_expected; i++) {
3842 if (!NT_STATUS_EQUAL(status, expected[i].status)) {
3843 continue;
3846 found_status = true;
3847 if (expected[i].body_size == 0) {
3848 found_size = true;
3849 break;
3852 if (expected[i].body_size == body_size) {
3853 found_size = true;
3854 break;
3858 if (!found_status) {
3859 return status;
3862 if (state->smb2.signing_skipped) {
3863 if (num_expected > 0) {
3864 return NT_STATUS_ACCESS_DENIED;
3866 if (!NT_STATUS_IS_ERR(status)) {
3867 return NT_STATUS_ACCESS_DENIED;
3871 if (!found_size) {
3872 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3875 if (piov != NULL) {
3876 *piov = talloc_move(mem_ctx, &state->smb2.recv_iov);
3879 return status;
3882 NTSTATUS smb2cli_req_get_sent_iov(struct tevent_req *req,
3883 struct iovec *sent_iov)
3885 struct smbXcli_req_state *state =
3886 tevent_req_data(req,
3887 struct smbXcli_req_state);
3889 if (tevent_req_is_in_progress(req)) {
3890 return STATUS_PENDING;
3893 sent_iov[0].iov_base = state->smb2.hdr;
3894 sent_iov[0].iov_len = sizeof(state->smb2.hdr);
3896 sent_iov[1].iov_base = discard_const(state->smb2.fixed);
3897 sent_iov[1].iov_len = state->smb2.fixed_len;
3899 if (state->smb2.dyn != NULL) {
3900 sent_iov[2].iov_base = discard_const(state->smb2.dyn);
3901 sent_iov[2].iov_len = state->smb2.dyn_len;
3902 } else {
3903 sent_iov[2].iov_base = NULL;
3904 sent_iov[2].iov_len = 0;
3907 return NT_STATUS_OK;
3910 static const struct {
3911 enum protocol_types proto;
3912 const char *smb1_name;
3913 } smb1cli_prots[] = {
3914 {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
3915 {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
3916 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
3917 {PROTOCOL_LANMAN1, "LANMAN1.0"},
3918 {PROTOCOL_LANMAN2, "LM1.2X002"},
3919 {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
3920 {PROTOCOL_LANMAN2, "LANMAN2.1"},
3921 {PROTOCOL_LANMAN2, "Samba"},
3922 {PROTOCOL_NT1, "NT LANMAN 1.0"},
3923 {PROTOCOL_NT1, "NT LM 0.12"},
3924 {PROTOCOL_SMB2_02, "SMB 2.002"},
3925 {PROTOCOL_SMB2_10, "SMB 2.???"},
3928 static const struct {
3929 enum protocol_types proto;
3930 uint16_t smb2_dialect;
3931 } smb2cli_prots[] = {
3932 {PROTOCOL_SMB2_02, SMB2_DIALECT_REVISION_202},
3933 {PROTOCOL_SMB2_10, SMB2_DIALECT_REVISION_210},
3934 {PROTOCOL_SMB2_22, SMB2_DIALECT_REVISION_222},
3935 {PROTOCOL_SMB2_24, SMB2_DIALECT_REVISION_224},
3936 {PROTOCOL_SMB3_00, SMB3_DIALECT_REVISION_300},
3937 {PROTOCOL_SMB3_02, SMB3_DIALECT_REVISION_302},
3938 {PROTOCOL_SMB3_10, SMB3_DIALECT_REVISION_310},
3939 {PROTOCOL_SMB3_11, SMB3_DIALECT_REVISION_311},
3942 struct smbXcli_negprot_state {
3943 struct smbXcli_conn *conn;
3944 struct tevent_context *ev;
3945 uint32_t timeout_msec;
3947 struct {
3948 uint8_t fixed[36];
3949 } smb2;
3952 static void smbXcli_negprot_invalid_done(struct tevent_req *subreq);
3953 static struct tevent_req *smbXcli_negprot_smb1_subreq(struct smbXcli_negprot_state *state);
3954 static void smbXcli_negprot_smb1_done(struct tevent_req *subreq);
3955 static struct tevent_req *smbXcli_negprot_smb2_subreq(struct smbXcli_negprot_state *state);
3956 static void smbXcli_negprot_smb2_done(struct tevent_req *subreq);
3957 static NTSTATUS smbXcli_negprot_dispatch_incoming(struct smbXcli_conn *conn,
3958 TALLOC_CTX *frame,
3959 uint8_t *inbuf);
3961 struct tevent_req *smbXcli_negprot_send(TALLOC_CTX *mem_ctx,
3962 struct tevent_context *ev,
3963 struct smbXcli_conn *conn,
3964 uint32_t timeout_msec,
3965 enum protocol_types min_protocol,
3966 enum protocol_types max_protocol)
3968 struct tevent_req *req, *subreq;
3969 struct smbXcli_negprot_state *state;
3971 req = tevent_req_create(mem_ctx, &state,
3972 struct smbXcli_negprot_state);
3973 if (req == NULL) {
3974 return NULL;
3976 state->conn = conn;
3977 state->ev = ev;
3978 state->timeout_msec = timeout_msec;
3980 if (min_protocol == PROTOCOL_NONE) {
3981 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3982 return tevent_req_post(req, ev);
3985 if (max_protocol == PROTOCOL_NONE) {
3986 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3987 return tevent_req_post(req, ev);
3990 if (min_protocol > max_protocol) {
3991 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3992 return tevent_req_post(req, ev);
3995 conn->min_protocol = min_protocol;
3996 conn->max_protocol = max_protocol;
3997 conn->protocol = PROTOCOL_NONE;
3999 if ((min_protocol < PROTOCOL_SMB2_02) &&
4000 (max_protocol < PROTOCOL_SMB2_02)) {
4002 * SMB1 only...
4004 conn->dispatch_incoming = smb1cli_conn_dispatch_incoming;
4006 subreq = smbXcli_negprot_smb1_subreq(state);
4007 if (tevent_req_nomem(subreq, req)) {
4008 return tevent_req_post(req, ev);
4010 tevent_req_set_callback(subreq, smbXcli_negprot_smb1_done, req);
4011 return req;
4014 if ((min_protocol >= PROTOCOL_SMB2_02) &&
4015 (max_protocol >= PROTOCOL_SMB2_02)) {
4017 * SMB2 only...
4019 conn->dispatch_incoming = smb2cli_conn_dispatch_incoming;
4022 * As we're starting with an SMB2 negprot, emulate Windows
4023 * and ask for 31 credits in the initial SMB2 negprot.
4024 * If we don't and leave requested credits at
4025 * zero, MacOSX servers return zero credits on
4026 * the negprot reply and we fail to connect.
4028 smb2cli_conn_set_max_credits(conn,
4029 WINDOWS_CLIENT_PURE_SMB2_NEGPROT_INITIAL_CREDIT_ASK);
4031 subreq = smbXcli_negprot_smb2_subreq(state);
4032 if (tevent_req_nomem(subreq, req)) {
4033 return tevent_req_post(req, ev);
4035 tevent_req_set_callback(subreq, smbXcli_negprot_smb2_done, req);
4036 return req;
4040 * We send an SMB1 negprot with the SMB2 dialects
4041 * and expect a SMB1 or a SMB2 response.
4043 * smbXcli_negprot_dispatch_incoming() will fix the
4044 * callback to match protocol of the response.
4046 conn->dispatch_incoming = smbXcli_negprot_dispatch_incoming;
4048 subreq = smbXcli_negprot_smb1_subreq(state);
4049 if (tevent_req_nomem(subreq, req)) {
4050 return tevent_req_post(req, ev);
4052 tevent_req_set_callback(subreq, smbXcli_negprot_invalid_done, req);
4053 return req;
4056 static void smbXcli_negprot_invalid_done(struct tevent_req *subreq)
4058 struct tevent_req *req =
4059 tevent_req_callback_data(subreq,
4060 struct tevent_req);
4061 NTSTATUS status;
4064 * we just want the low level error
4066 status = tevent_req_simple_recv_ntstatus(subreq);
4067 TALLOC_FREE(subreq);
4068 if (tevent_req_nterror(req, status)) {
4069 return;
4072 /* this should never happen */
4073 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
4076 static struct tevent_req *smbXcli_negprot_smb1_subreq(struct smbXcli_negprot_state *state)
4078 size_t i;
4079 DATA_BLOB bytes = data_blob_null;
4080 uint8_t flags;
4081 uint16_t flags2;
4083 /* setup the protocol strings */
4084 for (i=0; i < ARRAY_SIZE(smb1cli_prots); i++) {
4085 uint8_t c = 2;
4086 bool ok;
4088 if (smb1cli_prots[i].proto < state->conn->min_protocol) {
4089 continue;
4092 if (smb1cli_prots[i].proto > state->conn->max_protocol) {
4093 continue;
4096 ok = data_blob_append(state, &bytes, &c, sizeof(c));
4097 if (!ok) {
4098 return NULL;
4102 * We now it is already ascii and
4103 * we want NULL termination.
4105 ok = data_blob_append(state, &bytes,
4106 smb1cli_prots[i].smb1_name,
4107 strlen(smb1cli_prots[i].smb1_name)+1);
4108 if (!ok) {
4109 return NULL;
4113 smb1cli_req_flags(state->conn->max_protocol,
4114 state->conn->smb1.client.capabilities,
4115 SMBnegprot,
4116 0, 0, &flags,
4117 0, 0, &flags2);
4119 return smb1cli_req_send(state, state->ev, state->conn,
4120 SMBnegprot,
4121 flags, ~flags,
4122 flags2, ~flags2,
4123 state->timeout_msec,
4124 0xFFFE, 0, NULL, /* pid, tid, session */
4125 0, NULL, /* wct, vwv */
4126 bytes.length, bytes.data);
4129 static void smbXcli_negprot_smb1_done(struct tevent_req *subreq)
4131 struct tevent_req *req =
4132 tevent_req_callback_data(subreq,
4133 struct tevent_req);
4134 struct smbXcli_negprot_state *state =
4135 tevent_req_data(req,
4136 struct smbXcli_negprot_state);
4137 struct smbXcli_conn *conn = state->conn;
4138 struct iovec *recv_iov = NULL;
4139 uint8_t *inhdr;
4140 uint8_t wct;
4141 uint16_t *vwv;
4142 uint32_t num_bytes;
4143 uint8_t *bytes;
4144 NTSTATUS status;
4145 uint16_t protnum;
4146 size_t i;
4147 size_t num_prots = 0;
4148 uint8_t flags;
4149 uint32_t client_capabilities = conn->smb1.client.capabilities;
4150 uint32_t both_capabilities;
4151 uint32_t server_capabilities = 0;
4152 uint32_t capabilities;
4153 uint32_t client_max_xmit = conn->smb1.client.max_xmit;
4154 uint32_t server_max_xmit = 0;
4155 uint32_t max_xmit;
4156 uint32_t server_max_mux = 0;
4157 uint16_t server_security_mode = 0;
4158 uint32_t server_session_key = 0;
4159 bool server_readbraw = false;
4160 bool server_writebraw = false;
4161 bool server_lockread = false;
4162 bool server_writeunlock = false;
4163 struct GUID server_guid = GUID_zero();
4164 DATA_BLOB server_gss_blob = data_blob_null;
4165 uint8_t server_challenge[8];
4166 char *server_workgroup = NULL;
4167 char *server_name = NULL;
4168 int server_time_zone = 0;
4169 NTTIME server_system_time = 0;
4170 static const struct smb1cli_req_expected_response expected[] = {
4172 .status = NT_STATUS_OK,
4173 .wct = 0x11, /* NT1 */
4176 .status = NT_STATUS_OK,
4177 .wct = 0x0D, /* LM */
4180 .status = NT_STATUS_OK,
4181 .wct = 0x01, /* CORE */
4185 ZERO_STRUCT(server_challenge);
4187 status = smb1cli_req_recv(subreq, state,
4188 &recv_iov,
4189 &inhdr,
4190 &wct,
4191 &vwv,
4192 NULL, /* pvwv_offset */
4193 &num_bytes,
4194 &bytes,
4195 NULL, /* pbytes_offset */
4196 NULL, /* pinbuf */
4197 expected, ARRAY_SIZE(expected));
4198 TALLOC_FREE(subreq);
4199 if (tevent_req_nterror(req, status)) {
4200 return;
4203 flags = CVAL(inhdr, HDR_FLG);
4205 protnum = SVAL(vwv, 0);
4207 for (i=0; i < ARRAY_SIZE(smb1cli_prots); i++) {
4208 if (smb1cli_prots[i].proto < state->conn->min_protocol) {
4209 continue;
4212 if (smb1cli_prots[i].proto > state->conn->max_protocol) {
4213 continue;
4216 if (protnum != num_prots) {
4217 num_prots++;
4218 continue;
4221 conn->protocol = smb1cli_prots[i].proto;
4222 break;
4225 if (conn->protocol == PROTOCOL_NONE) {
4226 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4227 return;
4230 if ((conn->protocol < PROTOCOL_NT1) && conn->mandatory_signing) {
4231 DEBUG(0,("smbXcli_negprot: SMB signing is mandatory "
4232 "and the selected protocol level doesn't support it.\n"));
4233 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
4234 return;
4237 if (flags & FLAG_SUPPORT_LOCKREAD) {
4238 server_lockread = true;
4239 server_writeunlock = true;
4242 if (conn->protocol >= PROTOCOL_NT1) {
4243 const char *client_signing = NULL;
4244 bool server_mandatory = false;
4245 bool server_allowed = false;
4246 const char *server_signing = NULL;
4247 bool ok;
4248 uint8_t key_len;
4250 if (wct != 0x11) {
4251 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4252 return;
4255 /* NT protocol */
4256 server_security_mode = CVAL(vwv + 1, 0);
4257 server_max_mux = SVAL(vwv + 1, 1);
4258 server_max_xmit = IVAL(vwv + 3, 1);
4259 server_session_key = IVAL(vwv + 7, 1);
4260 server_time_zone = SVALS(vwv + 15, 1);
4261 server_time_zone *= 60;
4262 /* this time arrives in real GMT */
4263 server_system_time = BVAL(vwv + 11, 1);
4264 server_capabilities = IVAL(vwv + 9, 1);
4266 key_len = CVAL(vwv + 16, 1);
4268 if (server_capabilities & CAP_RAW_MODE) {
4269 server_readbraw = true;
4270 server_writebraw = true;
4272 if (server_capabilities & CAP_LOCK_AND_READ) {
4273 server_lockread = true;
4276 if (server_capabilities & CAP_EXTENDED_SECURITY) {
4277 DATA_BLOB blob1, blob2;
4279 if (num_bytes < 16) {
4280 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4281 return;
4284 blob1 = data_blob_const(bytes, 16);
4285 status = GUID_from_data_blob(&blob1, &server_guid);
4286 if (tevent_req_nterror(req, status)) {
4287 return;
4290 blob1 = data_blob_const(bytes+16, num_bytes-16);
4291 blob2 = data_blob_dup_talloc(state, blob1);
4292 if (blob1.length > 0 &&
4293 tevent_req_nomem(blob2.data, req)) {
4294 return;
4296 server_gss_blob = blob2;
4297 } else {
4298 DATA_BLOB blob1, blob2;
4300 if (num_bytes < key_len) {
4301 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4302 return;
4305 if (key_len != 0 && key_len != 8) {
4306 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4307 return;
4310 if (key_len == 8) {
4311 memcpy(server_challenge, bytes, 8);
4314 blob1 = data_blob_const(bytes+key_len, num_bytes-key_len);
4315 blob2 = data_blob_const(bytes+key_len, num_bytes-key_len);
4316 if (blob1.length > 0) {
4317 size_t len;
4319 len = utf16_len_n(blob1.data,
4320 blob1.length);
4321 blob1.length = len;
4323 ok = convert_string_talloc(state,
4324 CH_UTF16LE,
4325 CH_UNIX,
4326 blob1.data,
4327 blob1.length,
4328 &server_workgroup,
4329 &len);
4330 if (!ok) {
4331 status = map_nt_error_from_unix_common(errno);
4332 tevent_req_nterror(req, status);
4333 return;
4337 blob2.data += blob1.length;
4338 blob2.length -= blob1.length;
4339 if (blob2.length > 0) {
4340 size_t len;
4342 len = utf16_len_n(blob1.data,
4343 blob1.length);
4344 blob1.length = len;
4346 ok = convert_string_talloc(state,
4347 CH_UTF16LE,
4348 CH_UNIX,
4349 blob2.data,
4350 blob2.length,
4351 &server_name,
4352 &len);
4353 if (!ok) {
4354 status = map_nt_error_from_unix_common(errno);
4355 tevent_req_nterror(req, status);
4356 return;
4361 client_signing = "disabled";
4362 if (conn->allow_signing) {
4363 client_signing = "allowed";
4365 if (conn->mandatory_signing) {
4366 client_signing = "required";
4369 server_signing = "not supported";
4370 if (server_security_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
4371 server_signing = "supported";
4372 server_allowed = true;
4373 } else if (conn->mandatory_signing) {
4375 * We have mandatory signing as client
4376 * lets assume the server will look at our
4377 * FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED
4378 * flag in the session setup
4380 server_signing = "not announced";
4381 server_allowed = true;
4383 if (server_security_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
4384 server_signing = "required";
4385 server_mandatory = true;
4388 ok = smb_signing_set_negotiated(conn->smb1.signing,
4389 server_allowed,
4390 server_mandatory);
4391 if (!ok) {
4392 DEBUG(1,("cli_negprot: SMB signing is required, "
4393 "but client[%s] and server[%s] mismatch\n",
4394 client_signing, server_signing));
4395 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
4396 return;
4399 } else if (conn->protocol >= PROTOCOL_LANMAN1) {
4400 DATA_BLOB blob1;
4401 uint8_t key_len;
4402 time_t t;
4404 if (wct != 0x0D) {
4405 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4406 return;
4409 server_security_mode = SVAL(vwv + 1, 0);
4410 server_max_xmit = SVAL(vwv + 2, 0);
4411 server_max_mux = SVAL(vwv + 3, 0);
4412 server_readbraw = ((SVAL(vwv + 5, 0) & 0x1) != 0);
4413 server_writebraw = ((SVAL(vwv + 5, 0) & 0x2) != 0);
4414 server_session_key = IVAL(vwv + 6, 0);
4415 server_time_zone = SVALS(vwv + 10, 0);
4416 server_time_zone *= 60;
4417 /* this time is converted to GMT by make_unix_date */
4418 t = pull_dos_date((const uint8_t *)(vwv + 8), server_time_zone);
4419 unix_to_nt_time(&server_system_time, t);
4420 key_len = SVAL(vwv + 11, 0);
4422 if (num_bytes < key_len) {
4423 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4424 return;
4427 if (key_len != 0 && key_len != 8) {
4428 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4429 return;
4432 if (key_len == 8) {
4433 memcpy(server_challenge, bytes, 8);
4436 blob1 = data_blob_const(bytes+key_len, num_bytes-key_len);
4437 if (blob1.length > 0) {
4438 size_t len;
4439 bool ok;
4441 len = utf16_len_n(blob1.data,
4442 blob1.length);
4443 blob1.length = len;
4445 ok = convert_string_talloc(state,
4446 CH_DOS,
4447 CH_UNIX,
4448 blob1.data,
4449 blob1.length,
4450 &server_workgroup,
4451 &len);
4452 if (!ok) {
4453 status = map_nt_error_from_unix_common(errno);
4454 tevent_req_nterror(req, status);
4455 return;
4459 } else {
4460 /* the old core protocol */
4461 server_time_zone = get_time_zone(time(NULL));
4462 server_max_xmit = 1024;
4463 server_max_mux = 1;
4466 if (server_max_xmit < 1024) {
4467 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4468 return;
4471 if (server_max_mux < 1) {
4472 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4473 return;
4477 * Now calculate the negotiated capabilities
4478 * based on the mask for:
4479 * - client only flags
4480 * - flags used in both directions
4481 * - server only flags
4483 both_capabilities = client_capabilities & server_capabilities;
4484 capabilities = client_capabilities & SMB_CAP_CLIENT_MASK;
4485 capabilities |= both_capabilities & SMB_CAP_BOTH_MASK;
4486 capabilities |= server_capabilities & SMB_CAP_SERVER_MASK;
4488 max_xmit = MIN(client_max_xmit, server_max_xmit);
4490 conn->smb1.server.capabilities = server_capabilities;
4491 conn->smb1.capabilities = capabilities;
4493 conn->smb1.server.max_xmit = server_max_xmit;
4494 conn->smb1.max_xmit = max_xmit;
4496 conn->smb1.server.max_mux = server_max_mux;
4498 conn->smb1.server.security_mode = server_security_mode;
4500 conn->smb1.server.readbraw = server_readbraw;
4501 conn->smb1.server.writebraw = server_writebraw;
4502 conn->smb1.server.lockread = server_lockread;
4503 conn->smb1.server.writeunlock = server_writeunlock;
4505 conn->smb1.server.session_key = server_session_key;
4507 talloc_steal(conn, server_gss_blob.data);
4508 conn->smb1.server.gss_blob = server_gss_blob;
4509 conn->smb1.server.guid = server_guid;
4510 memcpy(conn->smb1.server.challenge, server_challenge, 8);
4511 conn->smb1.server.workgroup = talloc_move(conn, &server_workgroup);
4512 conn->smb1.server.name = talloc_move(conn, &server_name);
4514 conn->smb1.server.time_zone = server_time_zone;
4515 conn->smb1.server.system_time = server_system_time;
4517 tevent_req_done(req);
4520 static size_t smbXcli_padding_helper(uint32_t offset, size_t n)
4522 if ((offset & (n-1)) == 0) return 0;
4523 return n - (offset & (n-1));
4526 static struct tevent_req *smbXcli_negprot_smb2_subreq(struct smbXcli_negprot_state *state)
4528 size_t i;
4529 uint8_t *buf;
4530 uint16_t dialect_count = 0;
4531 DATA_BLOB dyn = data_blob_null;
4533 for (i=0; i < ARRAY_SIZE(smb2cli_prots); i++) {
4534 bool ok;
4535 uint8_t val[2];
4537 if (smb2cli_prots[i].proto < state->conn->min_protocol) {
4538 continue;
4541 if (smb2cli_prots[i].proto > state->conn->max_protocol) {
4542 continue;
4545 SSVAL(val, 0, smb2cli_prots[i].smb2_dialect);
4547 ok = data_blob_append(state, &dyn, val, sizeof(val));
4548 if (!ok) {
4549 return NULL;
4552 dialect_count++;
4555 buf = state->smb2.fixed;
4556 SSVAL(buf, 0, 36);
4557 SSVAL(buf, 2, dialect_count);
4558 SSVAL(buf, 4, state->conn->smb2.client.security_mode);
4559 SSVAL(buf, 6, 0); /* Reserved */
4560 if (state->conn->max_protocol >= PROTOCOL_SMB2_22) {
4561 SIVAL(buf, 8, state->conn->smb2.client.capabilities);
4562 } else {
4563 SIVAL(buf, 8, 0); /* Capabilities */
4565 if (state->conn->max_protocol >= PROTOCOL_SMB2_10) {
4566 NTSTATUS status;
4567 DATA_BLOB blob;
4569 status = GUID_to_ndr_blob(&state->conn->smb2.client.guid,
4570 state, &blob);
4571 if (!NT_STATUS_IS_OK(status)) {
4572 return NULL;
4574 memcpy(buf+12, blob.data, 16); /* ClientGuid */
4575 } else {
4576 memset(buf+12, 0, 16); /* ClientGuid */
4579 if (state->conn->max_protocol >= PROTOCOL_SMB3_10) {
4580 NTSTATUS status;
4581 struct smb2_negotiate_contexts c = { .num_contexts = 0, };
4582 uint32_t offset;
4583 DATA_BLOB b;
4584 uint8_t p[38];
4585 const uint8_t zeros[8] = {0, };
4586 size_t pad;
4587 bool ok;
4589 SSVAL(p, 0, 1); /* HashAlgorithmCount */
4590 SSVAL(p, 2, 32); /* SaltLength */
4591 SSVAL(p, 4, SMB2_PREAUTH_INTEGRITY_SHA512);
4592 generate_random_buffer(p + 6, 32);
4594 b = data_blob_const(p, 38);
4595 status = smb2_negotiate_context_add(state, &c,
4596 SMB2_PREAUTH_INTEGRITY_CAPABILITIES, b);
4597 if (!NT_STATUS_IS_OK(status)) {
4598 return NULL;
4601 SSVAL(p, 0, 2); /* ChiperCount */
4603 * For now we preferr CCM because our implementation
4604 * is faster than GCM, see bug #11451.
4606 SSVAL(p, 2, SMB2_ENCRYPTION_AES128_CCM);
4607 SSVAL(p, 4, SMB2_ENCRYPTION_AES128_GCM);
4609 b = data_blob_const(p, 6);
4610 status = smb2_negotiate_context_add(state, &c,
4611 SMB2_ENCRYPTION_CAPABILITIES, b);
4612 if (!NT_STATUS_IS_OK(status)) {
4613 return NULL;
4616 status = smb2_negotiate_context_push(state, &b, c);
4617 if (!NT_STATUS_IS_OK(status)) {
4618 return NULL;
4621 offset = SMB2_HDR_BODY + sizeof(state->smb2.fixed) + dyn.length;
4622 pad = smbXcli_padding_helper(offset, 8);
4624 ok = data_blob_append(state, &dyn, zeros, pad);
4625 if (!ok) {
4626 return NULL;
4628 offset += pad;
4630 ok = data_blob_append(state, &dyn, b.data, b.length);
4631 if (!ok) {
4632 return NULL;
4635 SIVAL(buf, 28, offset); /* NegotiateContextOffset */
4636 SSVAL(buf, 32, c.num_contexts); /* NegotiateContextCount */
4637 SSVAL(buf, 34, 0); /* Reserved */
4638 } else {
4639 SBVAL(buf, 28, 0); /* Reserved/ClientStartTime */
4642 return smb2cli_req_send(state, state->ev,
4643 state->conn, SMB2_OP_NEGPROT,
4644 0, 0, /* flags */
4645 state->timeout_msec,
4646 NULL, NULL, /* tcon, session */
4647 state->smb2.fixed, sizeof(state->smb2.fixed),
4648 dyn.data, dyn.length,
4649 UINT16_MAX); /* max_dyn_len */
4652 static void smbXcli_negprot_smb2_done(struct tevent_req *subreq)
4654 struct tevent_req *req =
4655 tevent_req_callback_data(subreq,
4656 struct tevent_req);
4657 struct smbXcli_negprot_state *state =
4658 tevent_req_data(req,
4659 struct smbXcli_negprot_state);
4660 struct smbXcli_conn *conn = state->conn;
4661 size_t security_offset, security_length;
4662 DATA_BLOB blob;
4663 NTSTATUS status;
4664 struct iovec *iov;
4665 uint8_t *body;
4666 size_t i;
4667 uint16_t dialect_revision;
4668 struct smb2_negotiate_contexts c = { .num_contexts = 0, };
4669 uint32_t negotiate_context_offset = 0;
4670 uint16_t negotiate_context_count = 0;
4671 DATA_BLOB negotiate_context_blob = data_blob_null;
4672 size_t avail;
4673 size_t ctx_ofs;
4674 size_t needed;
4675 struct smb2_negotiate_context *preauth = NULL;
4676 uint16_t hash_count;
4677 uint16_t salt_length;
4678 uint16_t hash_selected;
4679 struct hc_sha512state sctx;
4680 struct smb2_negotiate_context *cipher = NULL;
4681 struct iovec sent_iov[3];
4682 static const struct smb2cli_req_expected_response expected[] = {
4684 .status = NT_STATUS_OK,
4685 .body_size = 0x41
4689 status = smb2cli_req_recv(subreq, state, &iov,
4690 expected, ARRAY_SIZE(expected));
4691 if (tevent_req_nterror(req, status)) {
4692 return;
4695 body = (uint8_t *)iov[1].iov_base;
4697 dialect_revision = SVAL(body, 4);
4699 for (i=0; i < ARRAY_SIZE(smb2cli_prots); i++) {
4700 if (smb2cli_prots[i].proto < state->conn->min_protocol) {
4701 continue;
4704 if (smb2cli_prots[i].proto > state->conn->max_protocol) {
4705 continue;
4708 if (smb2cli_prots[i].smb2_dialect != dialect_revision) {
4709 continue;
4712 conn->protocol = smb2cli_prots[i].proto;
4713 break;
4716 if (conn->protocol == PROTOCOL_NONE) {
4717 TALLOC_FREE(subreq);
4719 if (state->conn->min_protocol >= PROTOCOL_SMB2_02) {
4720 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4721 return;
4724 if (dialect_revision != SMB2_DIALECT_REVISION_2FF) {
4725 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4726 return;
4729 /* make sure we do not loop forever */
4730 state->conn->min_protocol = PROTOCOL_SMB2_02;
4733 * send a SMB2 negprot, in order to negotiate
4734 * the SMB2 dialect.
4736 subreq = smbXcli_negprot_smb2_subreq(state);
4737 if (tevent_req_nomem(subreq, req)) {
4738 return;
4740 tevent_req_set_callback(subreq, smbXcli_negprot_smb2_done, req);
4741 return;
4744 conn->smb2.server.security_mode = SVAL(body, 2);
4745 if (conn->protocol >= PROTOCOL_SMB3_10) {
4746 negotiate_context_count = SVAL(body, 6);
4749 blob = data_blob_const(body + 8, 16);
4750 status = GUID_from_data_blob(&blob, &conn->smb2.server.guid);
4751 if (tevent_req_nterror(req, status)) {
4752 return;
4755 conn->smb2.server.capabilities = IVAL(body, 24);
4756 conn->smb2.server.max_trans_size= IVAL(body, 28);
4757 conn->smb2.server.max_read_size = IVAL(body, 32);
4758 conn->smb2.server.max_write_size= IVAL(body, 36);
4759 conn->smb2.server.system_time = BVAL(body, 40);
4760 conn->smb2.server.start_time = BVAL(body, 48);
4762 security_offset = SVAL(body, 56);
4763 security_length = SVAL(body, 58);
4765 if (security_offset != SMB2_HDR_BODY + iov[1].iov_len) {
4766 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4767 return;
4770 if (security_length > iov[2].iov_len) {
4771 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4772 return;
4775 conn->smb2.server.gss_blob = data_blob_talloc(conn,
4776 iov[2].iov_base,
4777 security_length);
4778 if (tevent_req_nomem(conn->smb2.server.gss_blob.data, req)) {
4779 return;
4782 if (conn->protocol < PROTOCOL_SMB3_10) {
4783 TALLOC_FREE(subreq);
4785 if (conn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION) {
4786 conn->smb2.server.cipher = SMB2_ENCRYPTION_AES128_CCM;
4788 tevent_req_done(req);
4789 return;
4792 if (conn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION) {
4793 tevent_req_nterror(req,
4794 NT_STATUS_INVALID_NETWORK_RESPONSE);
4795 return;
4798 negotiate_context_offset = IVAL(body, 60);
4799 if (negotiate_context_offset < security_offset) {
4800 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4801 return;
4804 ctx_ofs = negotiate_context_offset - security_offset;
4805 if (ctx_ofs > iov[2].iov_len) {
4806 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4807 return;
4809 avail = iov[2].iov_len - security_length;
4810 needed = iov[2].iov_len - ctx_ofs;
4811 if (needed > avail) {
4812 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4813 return;
4816 negotiate_context_blob.data = (uint8_t *)iov[2].iov_base;
4817 negotiate_context_blob.length = iov[2].iov_len;
4819 negotiate_context_blob.data += ctx_ofs;
4820 negotiate_context_blob.length -= ctx_ofs;
4822 status = smb2_negotiate_context_parse(state, negotiate_context_blob, &c);
4823 if (tevent_req_nterror(req, status)) {
4824 return;
4827 if (negotiate_context_count != c.num_contexts) {
4828 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4829 return;
4832 preauth = smb2_negotiate_context_find(&c,
4833 SMB2_PREAUTH_INTEGRITY_CAPABILITIES);
4834 if (preauth == NULL) {
4835 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4836 return;
4839 if (preauth->data.length < 6) {
4840 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4841 return;
4844 hash_count = SVAL(preauth->data.data, 0);
4845 salt_length = SVAL(preauth->data.data, 2);
4846 hash_selected = SVAL(preauth->data.data, 4);
4848 if (hash_count != 1) {
4849 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4850 return;
4853 if (preauth->data.length != (6 + salt_length)) {
4854 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4855 return;
4858 if (hash_selected != SMB2_PREAUTH_INTEGRITY_SHA512) {
4859 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4860 return;
4863 cipher = smb2_negotiate_context_find(&c, SMB2_ENCRYPTION_CAPABILITIES);
4864 if (cipher != NULL) {
4865 uint16_t cipher_count;
4867 if (cipher->data.length < 2) {
4868 tevent_req_nterror(req,
4869 NT_STATUS_INVALID_NETWORK_RESPONSE);
4870 return;
4873 cipher_count = SVAL(cipher->data.data, 0);
4875 if (cipher_count > 1) {
4876 tevent_req_nterror(req,
4877 NT_STATUS_INVALID_NETWORK_RESPONSE);
4878 return;
4881 if (cipher->data.length != (2 + 2 * cipher_count)) {
4882 tevent_req_nterror(req,
4883 NT_STATUS_INVALID_NETWORK_RESPONSE);
4884 return;
4887 if (cipher_count == 1) {
4888 uint16_t cipher_selected;
4890 cipher_selected = SVAL(cipher->data.data, 2);
4892 switch (cipher_selected) {
4893 case SMB2_ENCRYPTION_AES128_GCM:
4894 case SMB2_ENCRYPTION_AES128_CCM:
4895 conn->smb2.server.cipher = cipher_selected;
4896 break;
4901 /* First we hash the request */
4902 smb2cli_req_get_sent_iov(subreq, sent_iov);
4903 samba_SHA512_Init(&sctx);
4904 samba_SHA512_Update(&sctx, conn->smb2.preauth_sha512,
4905 sizeof(conn->smb2.preauth_sha512));
4906 for (i = 0; i < 3; i++) {
4907 samba_SHA512_Update(&sctx, sent_iov[i].iov_base, sent_iov[i].iov_len);
4909 samba_SHA512_Final(conn->smb2.preauth_sha512, &sctx);
4910 TALLOC_FREE(subreq);
4912 /* And now we hash the response */
4913 samba_SHA512_Init(&sctx);
4914 samba_SHA512_Update(&sctx, conn->smb2.preauth_sha512,
4915 sizeof(conn->smb2.preauth_sha512));
4916 for (i = 0; i < 3; i++) {
4917 samba_SHA512_Update(&sctx, iov[i].iov_base, iov[i].iov_len);
4919 samba_SHA512_Final(conn->smb2.preauth_sha512, &sctx);
4921 tevent_req_done(req);
4924 static NTSTATUS smbXcli_negprot_dispatch_incoming(struct smbXcli_conn *conn,
4925 TALLOC_CTX *tmp_mem,
4926 uint8_t *inbuf)
4928 size_t num_pending = talloc_array_length(conn->pending);
4929 struct tevent_req *subreq;
4930 struct smbXcli_req_state *substate;
4931 struct tevent_req *req;
4932 uint32_t protocol_magic;
4933 size_t inbuf_len = smb_len_nbt(inbuf);
4935 if (num_pending != 1) {
4936 return NT_STATUS_INTERNAL_ERROR;
4939 if (inbuf_len < 4) {
4940 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4943 subreq = conn->pending[0];
4944 substate = tevent_req_data(subreq, struct smbXcli_req_state);
4945 req = tevent_req_callback_data(subreq, struct tevent_req);
4947 protocol_magic = IVAL(inbuf, 4);
4949 switch (protocol_magic) {
4950 case SMB_MAGIC:
4951 tevent_req_set_callback(subreq, smbXcli_negprot_smb1_done, req);
4952 conn->dispatch_incoming = smb1cli_conn_dispatch_incoming;
4953 return smb1cli_conn_dispatch_incoming(conn, tmp_mem, inbuf);
4955 case SMB2_MAGIC:
4956 if (substate->smb2.recv_iov == NULL) {
4958 * For the SMB1 negprot we have move it.
4960 substate->smb2.recv_iov = substate->smb1.recv_iov;
4961 substate->smb1.recv_iov = NULL;
4965 * we got an SMB2 answer, which consumed sequence number 0
4966 * so we need to use 1 as the next one.
4968 * we also need to set the current credits to 0
4969 * as we consumed the initial one. The SMB2 answer
4970 * hopefully grant us a new credit.
4972 conn->smb2.mid = 1;
4973 conn->smb2.cur_credits = 0;
4974 tevent_req_set_callback(subreq, smbXcli_negprot_smb2_done, req);
4975 conn->dispatch_incoming = smb2cli_conn_dispatch_incoming;
4976 return smb2cli_conn_dispatch_incoming(conn, tmp_mem, inbuf);
4979 DEBUG(10, ("Got non-SMB PDU\n"));
4980 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4983 NTSTATUS smbXcli_negprot_recv(struct tevent_req *req)
4985 return tevent_req_simple_recv_ntstatus(req);
4988 NTSTATUS smbXcli_negprot(struct smbXcli_conn *conn,
4989 uint32_t timeout_msec,
4990 enum protocol_types min_protocol,
4991 enum protocol_types max_protocol)
4993 TALLOC_CTX *frame = talloc_stackframe();
4994 struct tevent_context *ev;
4995 struct tevent_req *req;
4996 NTSTATUS status = NT_STATUS_NO_MEMORY;
4997 bool ok;
4999 if (smbXcli_conn_has_async_calls(conn)) {
5001 * Can't use sync call while an async call is in flight
5003 status = NT_STATUS_INVALID_PARAMETER_MIX;
5004 goto fail;
5006 ev = samba_tevent_context_init(frame);
5007 if (ev == NULL) {
5008 goto fail;
5010 req = smbXcli_negprot_send(frame, ev, conn, timeout_msec,
5011 min_protocol, max_protocol);
5012 if (req == NULL) {
5013 goto fail;
5015 ok = tevent_req_poll_ntstatus(req, ev, &status);
5016 if (!ok) {
5017 goto fail;
5019 status = smbXcli_negprot_recv(req);
5020 fail:
5021 TALLOC_FREE(frame);
5022 return status;
5025 struct smb2cli_validate_negotiate_info_state {
5026 struct smbXcli_conn *conn;
5027 DATA_BLOB in_input_buffer;
5028 DATA_BLOB in_output_buffer;
5029 DATA_BLOB out_input_buffer;
5030 DATA_BLOB out_output_buffer;
5031 uint16_t dialect;
5034 static void smb2cli_validate_negotiate_info_done(struct tevent_req *subreq);
5036 struct tevent_req *smb2cli_validate_negotiate_info_send(TALLOC_CTX *mem_ctx,
5037 struct tevent_context *ev,
5038 struct smbXcli_conn *conn,
5039 uint32_t timeout_msec,
5040 struct smbXcli_session *session,
5041 struct smbXcli_tcon *tcon)
5043 struct tevent_req *req;
5044 struct smb2cli_validate_negotiate_info_state *state;
5045 uint8_t *buf;
5046 uint16_t dialect_count = 0;
5047 struct tevent_req *subreq;
5048 bool _save_should_sign;
5049 size_t i;
5051 req = tevent_req_create(mem_ctx, &state,
5052 struct smb2cli_validate_negotiate_info_state);
5053 if (req == NULL) {
5054 return NULL;
5056 state->conn = conn;
5058 state->in_input_buffer = data_blob_talloc_zero(state,
5059 4 + 16 + 1 + 1 + 2);
5060 if (tevent_req_nomem(state->in_input_buffer.data, req)) {
5061 return tevent_req_post(req, ev);
5063 buf = state->in_input_buffer.data;
5065 if (state->conn->max_protocol >= PROTOCOL_SMB2_22) {
5066 SIVAL(buf, 0, conn->smb2.client.capabilities);
5067 } else {
5068 SIVAL(buf, 0, 0); /* Capabilities */
5070 if (state->conn->max_protocol >= PROTOCOL_SMB2_10) {
5071 NTSTATUS status;
5072 DATA_BLOB blob;
5074 status = GUID_to_ndr_blob(&conn->smb2.client.guid,
5075 state, &blob);
5076 if (!NT_STATUS_IS_OK(status)) {
5077 return NULL;
5079 memcpy(buf+4, blob.data, 16); /* ClientGuid */
5080 } else {
5081 memset(buf+4, 0, 16); /* ClientGuid */
5083 if (state->conn->min_protocol >= PROTOCOL_SMB2_02) {
5084 SCVAL(buf, 20, conn->smb2.client.security_mode);
5085 } else {
5086 SCVAL(buf, 20, 0);
5088 SCVAL(buf, 21, 0); /* reserved */
5090 for (i=0; i < ARRAY_SIZE(smb2cli_prots); i++) {
5091 bool ok;
5092 size_t ofs;
5094 if (smb2cli_prots[i].proto < state->conn->min_protocol) {
5095 continue;
5098 if (smb2cli_prots[i].proto > state->conn->max_protocol) {
5099 continue;
5102 if (smb2cli_prots[i].proto == state->conn->protocol) {
5103 state->dialect = smb2cli_prots[i].smb2_dialect;
5106 ofs = state->in_input_buffer.length;
5107 ok = data_blob_realloc(state, &state->in_input_buffer,
5108 ofs + 2);
5109 if (!ok) {
5110 tevent_req_oom(req);
5111 return tevent_req_post(req, ev);
5114 buf = state->in_input_buffer.data;
5115 SSVAL(buf, ofs, smb2cli_prots[i].smb2_dialect);
5117 dialect_count++;
5119 buf = state->in_input_buffer.data;
5120 SSVAL(buf, 22, dialect_count);
5122 _save_should_sign = smb2cli_tcon_is_signing_on(tcon);
5123 smb2cli_tcon_should_sign(tcon, true);
5124 subreq = smb2cli_ioctl_send(state, ev, conn,
5125 timeout_msec, session, tcon,
5126 UINT64_MAX, /* in_fid_persistent */
5127 UINT64_MAX, /* in_fid_volatile */
5128 FSCTL_VALIDATE_NEGOTIATE_INFO,
5129 0, /* in_max_input_length */
5130 &state->in_input_buffer,
5131 24, /* in_max_output_length */
5132 &state->in_output_buffer,
5133 SMB2_IOCTL_FLAG_IS_FSCTL);
5134 smb2cli_tcon_should_sign(tcon, _save_should_sign);
5135 if (tevent_req_nomem(subreq, req)) {
5136 return tevent_req_post(req, ev);
5138 tevent_req_set_callback(subreq,
5139 smb2cli_validate_negotiate_info_done,
5140 req);
5142 return req;
5145 static void smb2cli_validate_negotiate_info_done(struct tevent_req *subreq)
5147 struct tevent_req *req =
5148 tevent_req_callback_data(subreq,
5149 struct tevent_req);
5150 struct smb2cli_validate_negotiate_info_state *state =
5151 tevent_req_data(req,
5152 struct smb2cli_validate_negotiate_info_state);
5153 NTSTATUS status;
5154 const uint8_t *buf;
5155 uint32_t capabilities;
5156 DATA_BLOB guid_blob;
5157 struct GUID server_guid;
5158 uint16_t security_mode;
5159 uint16_t dialect;
5161 status = smb2cli_ioctl_recv(subreq, state,
5162 &state->out_input_buffer,
5163 &state->out_output_buffer);
5164 TALLOC_FREE(subreq);
5165 if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED)) {
5167 * The response was signed, but not supported
5169 * Older Windows and Samba releases return
5170 * NT_STATUS_FILE_CLOSED.
5172 tevent_req_done(req);
5173 return;
5175 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_DEVICE_REQUEST)) {
5177 * The response was signed, but not supported
5179 * This is returned by the NTVFS based Samba 4.x file server
5180 * for file shares.
5182 tevent_req_done(req);
5183 return;
5185 if (NT_STATUS_EQUAL(status, NT_STATUS_FS_DRIVER_REQUIRED)) {
5187 * The response was signed, but not supported
5189 * This is returned by the NTVFS based Samba 4.x file server
5190 * for ipc shares.
5192 tevent_req_done(req);
5193 return;
5195 if (tevent_req_nterror(req, status)) {
5196 return;
5199 if (state->out_output_buffer.length != 24) {
5200 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
5201 return;
5204 buf = state->out_output_buffer.data;
5206 capabilities = IVAL(buf, 0);
5207 guid_blob = data_blob_const(buf + 4, 16);
5208 status = GUID_from_data_blob(&guid_blob, &server_guid);
5209 if (tevent_req_nterror(req, status)) {
5210 return;
5212 security_mode = CVAL(buf, 20);
5213 dialect = SVAL(buf, 22);
5215 if (capabilities != state->conn->smb2.server.capabilities) {
5216 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
5217 return;
5220 if (!GUID_equal(&server_guid, &state->conn->smb2.server.guid)) {
5221 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
5222 return;
5225 if (security_mode != state->conn->smb2.server.security_mode) {
5226 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
5227 return;
5230 if (dialect != state->dialect) {
5231 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
5232 return;
5235 tevent_req_done(req);
5238 NTSTATUS smb2cli_validate_negotiate_info_recv(struct tevent_req *req)
5240 return tevent_req_simple_recv_ntstatus(req);
5243 static int smbXcli_session_destructor(struct smbXcli_session *session)
5245 if (session->conn == NULL) {
5246 return 0;
5249 DLIST_REMOVE(session->conn->sessions, session);
5250 return 0;
5253 struct smbXcli_session *smbXcli_session_create(TALLOC_CTX *mem_ctx,
5254 struct smbXcli_conn *conn)
5256 struct smbXcli_session *session;
5258 session = talloc_zero(mem_ctx, struct smbXcli_session);
5259 if (session == NULL) {
5260 return NULL;
5262 session->smb2 = talloc_zero(session, struct smb2cli_session);
5263 if (session->smb2 == NULL) {
5264 talloc_free(session);
5265 return NULL;
5267 talloc_set_destructor(session, smbXcli_session_destructor);
5269 DLIST_ADD_END(conn->sessions, session);
5270 session->conn = conn;
5272 memcpy(session->smb2_channel.preauth_sha512,
5273 conn->smb2.preauth_sha512,
5274 sizeof(session->smb2_channel.preauth_sha512));
5276 return session;
5279 struct smbXcli_session *smbXcli_session_copy(TALLOC_CTX *mem_ctx,
5280 struct smbXcli_session *src)
5282 struct smbXcli_session *session;
5284 session = talloc_zero(mem_ctx, struct smbXcli_session);
5285 if (session == NULL) {
5286 return NULL;
5288 session->smb2 = talloc_zero(session, struct smb2cli_session);
5289 if (session->smb2 == NULL) {
5290 talloc_free(session);
5291 return NULL;
5294 session->conn = src->conn;
5295 *session->smb2 = *src->smb2;
5296 session->smb2_channel = src->smb2_channel;
5297 session->disconnect_expired = src->disconnect_expired;
5299 DLIST_ADD_END(src->conn->sessions, session);
5300 talloc_set_destructor(session, smbXcli_session_destructor);
5302 return session;
5305 bool smbXcli_session_is_guest(struct smbXcli_session *session)
5307 if (session == NULL) {
5308 return false;
5311 if (session->conn == NULL) {
5312 return false;
5315 if (session->conn->mandatory_signing) {
5316 return false;
5319 if (session->conn->protocol >= PROTOCOL_SMB2_02) {
5320 if (session->smb2->session_flags & SMB2_SESSION_FLAG_IS_GUEST) {
5321 return true;
5323 return false;
5326 if (session->smb1.action & SMB_SETUP_GUEST) {
5327 return true;
5330 return false;
5333 bool smbXcli_session_is_authenticated(struct smbXcli_session *session)
5335 const DATA_BLOB *application_key;
5337 if (session == NULL) {
5338 return false;
5341 if (session->conn == NULL) {
5342 return false;
5346 * If we have an application key we had a session key negotiated
5347 * at auth time.
5349 if (session->conn->protocol >= PROTOCOL_SMB2_02) {
5350 application_key = &session->smb2->application_key;
5351 } else {
5352 application_key = &session->smb1.application_key;
5355 if (application_key->length == 0) {
5356 return false;
5359 return true;
5362 NTSTATUS smbXcli_session_application_key(struct smbXcli_session *session,
5363 TALLOC_CTX *mem_ctx,
5364 DATA_BLOB *key)
5366 const DATA_BLOB *application_key;
5368 *key = data_blob_null;
5370 if (session->conn == NULL) {
5371 return NT_STATUS_NO_USER_SESSION_KEY;
5374 if (session->conn->protocol >= PROTOCOL_SMB2_02) {
5375 application_key = &session->smb2->application_key;
5376 } else {
5377 application_key = &session->smb1.application_key;
5380 if (application_key->length == 0) {
5381 return NT_STATUS_NO_USER_SESSION_KEY;
5384 *key = data_blob_dup_talloc(mem_ctx, *application_key);
5385 if (key->data == NULL) {
5386 return NT_STATUS_NO_MEMORY;
5389 return NT_STATUS_OK;
5392 void smbXcli_session_set_disconnect_expired(struct smbXcli_session *session)
5394 session->disconnect_expired = true;
5397 uint16_t smb1cli_session_current_id(struct smbXcli_session *session)
5399 return session->smb1.session_id;
5402 void smb1cli_session_set_id(struct smbXcli_session *session,
5403 uint16_t session_id)
5405 session->smb1.session_id = session_id;
5408 void smb1cli_session_set_action(struct smbXcli_session *session,
5409 uint16_t action)
5411 session->smb1.action = action;
5414 NTSTATUS smb1cli_session_set_session_key(struct smbXcli_session *session,
5415 const DATA_BLOB _session_key)
5417 struct smbXcli_conn *conn = session->conn;
5418 uint8_t session_key[16];
5420 if (conn == NULL) {
5421 return NT_STATUS_INVALID_PARAMETER_MIX;
5424 if (session->smb1.application_key.length != 0) {
5426 * TODO: do not allow this...
5428 * return NT_STATUS_INVALID_PARAMETER_MIX;
5430 data_blob_clear_free(&session->smb1.application_key);
5431 session->smb1.protected_key = false;
5434 if (_session_key.length == 0) {
5435 return NT_STATUS_OK;
5438 ZERO_STRUCT(session_key);
5439 memcpy(session_key, _session_key.data,
5440 MIN(_session_key.length, sizeof(session_key)));
5442 session->smb1.application_key = data_blob_talloc(session,
5443 session_key,
5444 sizeof(session_key));
5445 ZERO_STRUCT(session_key);
5446 if (session->smb1.application_key.data == NULL) {
5447 return NT_STATUS_NO_MEMORY;
5450 session->smb1.protected_key = false;
5452 return NT_STATUS_OK;
5455 NTSTATUS smb1cli_session_protect_session_key(struct smbXcli_session *session)
5457 if (session->smb1.protected_key) {
5458 /* already protected */
5459 return NT_STATUS_OK;
5462 if (session->smb1.application_key.length != 16) {
5463 return NT_STATUS_INVALID_PARAMETER_MIX;
5466 smb_key_derivation(session->smb1.application_key.data,
5467 session->smb1.application_key.length,
5468 session->smb1.application_key.data);
5470 session->smb1.protected_key = true;
5472 return NT_STATUS_OK;
5475 uint8_t smb2cli_session_security_mode(struct smbXcli_session *session)
5477 struct smbXcli_conn *conn = session->conn;
5478 uint8_t security_mode = 0;
5480 if (conn == NULL) {
5481 return security_mode;
5484 security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED;
5485 if (conn->mandatory_signing) {
5486 security_mode |= SMB2_NEGOTIATE_SIGNING_REQUIRED;
5488 if (session->smb2->should_sign) {
5489 security_mode |= SMB2_NEGOTIATE_SIGNING_REQUIRED;
5492 return security_mode;
5495 uint64_t smb2cli_session_current_id(struct smbXcli_session *session)
5497 return session->smb2->session_id;
5500 uint16_t smb2cli_session_get_flags(struct smbXcli_session *session)
5502 return session->smb2->session_flags;
5505 void smb2cli_session_set_id_and_flags(struct smbXcli_session *session,
5506 uint64_t session_id,
5507 uint16_t session_flags)
5509 session->smb2->session_id = session_id;
5510 session->smb2->session_flags = session_flags;
5513 void smb2cli_session_increment_channel_sequence(struct smbXcli_session *session)
5515 session->smb2->channel_sequence += 1;
5518 uint16_t smb2cli_session_reset_channel_sequence(struct smbXcli_session *session,
5519 uint16_t channel_sequence)
5521 uint16_t prev_cs;
5523 prev_cs = session->smb2->channel_sequence;
5524 session->smb2->channel_sequence = channel_sequence;
5526 return prev_cs;
5529 uint16_t smb2cli_session_current_channel_sequence(struct smbXcli_session *session)
5531 return session->smb2->channel_sequence;
5534 void smb2cli_session_start_replay(struct smbXcli_session *session)
5536 session->smb2->replay_active = true;
5539 void smb2cli_session_stop_replay(struct smbXcli_session *session)
5541 session->smb2->replay_active = false;
5544 NTSTATUS smb2cli_session_update_preauth(struct smbXcli_session *session,
5545 const struct iovec *iov)
5547 struct hc_sha512state sctx;
5548 size_t i;
5550 if (session->conn == NULL) {
5551 return NT_STATUS_INTERNAL_ERROR;
5554 if (session->conn->protocol < PROTOCOL_SMB3_10) {
5555 return NT_STATUS_OK;
5558 if (session->smb2_channel.signing_key.length != 0) {
5559 return NT_STATUS_OK;
5562 samba_SHA512_Init(&sctx);
5563 samba_SHA512_Update(&sctx, session->smb2_channel.preauth_sha512,
5564 sizeof(session->smb2_channel.preauth_sha512));
5565 for (i = 0; i < 3; i++) {
5566 samba_SHA512_Update(&sctx, iov[i].iov_base, iov[i].iov_len);
5568 samba_SHA512_Final(session->smb2_channel.preauth_sha512, &sctx);
5570 return NT_STATUS_OK;
5573 NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session,
5574 const DATA_BLOB _session_key,
5575 const struct iovec *recv_iov)
5577 struct smbXcli_conn *conn = session->conn;
5578 uint16_t no_sign_flags = 0;
5579 uint8_t session_key[16];
5580 bool check_signature = true;
5581 uint32_t hdr_flags;
5582 NTSTATUS status;
5583 struct _derivation {
5584 DATA_BLOB label;
5585 DATA_BLOB context;
5587 struct {
5588 struct _derivation signing;
5589 struct _derivation encryption;
5590 struct _derivation decryption;
5591 struct _derivation application;
5592 } derivation = { };
5593 size_t nonce_size = 0;
5595 if (conn == NULL) {
5596 return NT_STATUS_INVALID_PARAMETER_MIX;
5599 if (recv_iov[0].iov_len != SMB2_HDR_BODY) {
5600 return NT_STATUS_INVALID_PARAMETER_MIX;
5603 if (!conn->mandatory_signing) {
5605 * only allow guest sessions without
5606 * mandatory signing.
5608 * If we try an authentication with username != ""
5609 * and the server let us in without verifying the
5610 * password we don't have a negotiated session key
5611 * for signing.
5613 no_sign_flags = SMB2_SESSION_FLAG_IS_GUEST;
5616 if (session->smb2->session_flags & no_sign_flags) {
5617 session->smb2->should_sign = false;
5618 return NT_STATUS_OK;
5621 if (session->smb2->signing_key.length != 0) {
5622 return NT_STATUS_INVALID_PARAMETER_MIX;
5625 if (conn->protocol >= PROTOCOL_SMB3_10) {
5626 struct _derivation *d;
5627 DATA_BLOB p;
5629 p = data_blob_const(session->smb2_channel.preauth_sha512,
5630 sizeof(session->smb2_channel.preauth_sha512));
5632 d = &derivation.signing;
5633 d->label = data_blob_string_const_null("SMBSigningKey");
5634 d->context = p;
5636 d = &derivation.encryption;
5637 d->label = data_blob_string_const_null("SMBC2SCipherKey");
5638 d->context = p;
5640 d = &derivation.decryption;
5641 d->label = data_blob_string_const_null("SMBS2CCipherKey");
5642 d->context = p;
5644 d = &derivation.application;
5645 d->label = data_blob_string_const_null("SMBAppKey");
5646 d->context = p;
5648 } else if (conn->protocol >= PROTOCOL_SMB2_24) {
5649 struct _derivation *d;
5651 d = &derivation.signing;
5652 d->label = data_blob_string_const_null("SMB2AESCMAC");
5653 d->context = data_blob_string_const_null("SmbSign");
5655 d = &derivation.encryption;
5656 d->label = data_blob_string_const_null("SMB2AESCCM");
5657 d->context = data_blob_string_const_null("ServerIn ");
5659 d = &derivation.decryption;
5660 d->label = data_blob_string_const_null("SMB2AESCCM");
5661 d->context = data_blob_string_const_null("ServerOut");
5663 d = &derivation.application;
5664 d->label = data_blob_string_const_null("SMB2APP");
5665 d->context = data_blob_string_const_null("SmbRpc");
5668 ZERO_STRUCT(session_key);
5669 memcpy(session_key, _session_key.data,
5670 MIN(_session_key.length, sizeof(session_key)));
5672 session->smb2->signing_key = data_blob_talloc(session,
5673 session_key,
5674 sizeof(session_key));
5675 if (session->smb2->signing_key.data == NULL) {
5676 ZERO_STRUCT(session_key);
5677 return NT_STATUS_NO_MEMORY;
5680 if (conn->protocol >= PROTOCOL_SMB2_24) {
5681 struct _derivation *d = &derivation.signing;
5683 smb2_key_derivation(session_key, sizeof(session_key),
5684 d->label.data, d->label.length,
5685 d->context.data, d->context.length,
5686 session->smb2->signing_key.data);
5689 session->smb2->encryption_key = data_blob_dup_talloc(session,
5690 session->smb2->signing_key);
5691 if (session->smb2->encryption_key.data == NULL) {
5692 ZERO_STRUCT(session_key);
5693 return NT_STATUS_NO_MEMORY;
5696 if (conn->protocol >= PROTOCOL_SMB2_24) {
5697 struct _derivation *d = &derivation.encryption;
5699 smb2_key_derivation(session_key, sizeof(session_key),
5700 d->label.data, d->label.length,
5701 d->context.data, d->context.length,
5702 session->smb2->encryption_key.data);
5705 session->smb2->decryption_key = data_blob_dup_talloc(session,
5706 session->smb2->signing_key);
5707 if (session->smb2->decryption_key.data == NULL) {
5708 ZERO_STRUCT(session_key);
5709 return NT_STATUS_NO_MEMORY;
5712 if (conn->protocol >= PROTOCOL_SMB2_24) {
5713 struct _derivation *d = &derivation.decryption;
5715 smb2_key_derivation(session_key, sizeof(session_key),
5716 d->label.data, d->label.length,
5717 d->context.data, d->context.length,
5718 session->smb2->decryption_key.data);
5721 session->smb2->application_key = data_blob_dup_talloc(session,
5722 session->smb2->signing_key);
5723 if (session->smb2->application_key.data == NULL) {
5724 ZERO_STRUCT(session_key);
5725 return NT_STATUS_NO_MEMORY;
5728 if (conn->protocol >= PROTOCOL_SMB2_24) {
5729 struct _derivation *d = &derivation.application;
5731 smb2_key_derivation(session_key, sizeof(session_key),
5732 d->label.data, d->label.length,
5733 d->context.data, d->context.length,
5734 session->smb2->application_key.data);
5736 ZERO_STRUCT(session_key);
5738 session->smb2_channel.signing_key = data_blob_dup_talloc(session,
5739 session->smb2->signing_key);
5740 if (session->smb2_channel.signing_key.data == NULL) {
5741 return NT_STATUS_NO_MEMORY;
5744 check_signature = conn->mandatory_signing;
5746 hdr_flags = IVAL(recv_iov[0].iov_base, SMB2_HDR_FLAGS);
5747 if (hdr_flags & SMB2_HDR_FLAG_SIGNED) {
5749 * Sadly some vendors don't sign the
5750 * final SMB2 session setup response
5752 * At least Windows and Samba are always doing this
5753 * if there's a session key available.
5755 * We only check the signature if it's mandatory
5756 * or SMB2_HDR_FLAG_SIGNED is provided.
5758 check_signature = true;
5761 if (conn->protocol >= PROTOCOL_SMB3_10) {
5762 check_signature = true;
5765 if (check_signature) {
5766 status = smb2_signing_check_pdu(session->smb2_channel.signing_key,
5767 session->conn->protocol,
5768 recv_iov, 3);
5769 if (!NT_STATUS_IS_OK(status)) {
5770 return status;
5774 session->smb2->should_sign = false;
5775 session->smb2->should_encrypt = false;
5777 if (conn->desire_signing) {
5778 session->smb2->should_sign = true;
5781 if (conn->smb2.server.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) {
5782 session->smb2->should_sign = true;
5785 if (session->smb2->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) {
5786 session->smb2->should_encrypt = true;
5789 if (conn->protocol < PROTOCOL_SMB2_24) {
5790 session->smb2->should_encrypt = false;
5793 if (conn->smb2.server.cipher == 0) {
5794 session->smb2->should_encrypt = false;
5798 * CCM and GCM algorithms must never have their
5799 * nonce wrap, or the security of the whole
5800 * communication and the keys is destroyed.
5801 * We must drop the connection once we have
5802 * transfered too much data.
5804 * NOTE: We assume nonces greater than 8 bytes.
5806 generate_random_buffer((uint8_t *)&session->smb2->nonce_high_random,
5807 sizeof(session->smb2->nonce_high_random));
5808 switch (conn->smb2.server.cipher) {
5809 case SMB2_ENCRYPTION_AES128_CCM:
5810 nonce_size = AES_CCM_128_NONCE_SIZE;
5811 break;
5812 case SMB2_ENCRYPTION_AES128_GCM:
5813 nonce_size = AES_GCM_128_IV_SIZE;
5814 break;
5815 default:
5816 nonce_size = 0;
5817 break;
5819 session->smb2->nonce_high_max = SMB2_NONCE_HIGH_MAX(nonce_size);
5820 session->smb2->nonce_high = 0;
5821 session->smb2->nonce_low = 0;
5823 return NT_STATUS_OK;
5826 NTSTATUS smb2cli_session_create_channel(TALLOC_CTX *mem_ctx,
5827 struct smbXcli_session *session1,
5828 struct smbXcli_conn *conn,
5829 struct smbXcli_session **_session2)
5831 struct smbXcli_session *session2;
5833 if (session1->smb2->signing_key.length == 0) {
5834 return NT_STATUS_INVALID_PARAMETER_MIX;
5837 if (conn == NULL) {
5838 return NT_STATUS_INVALID_PARAMETER_MIX;
5841 session2 = talloc_zero(mem_ctx, struct smbXcli_session);
5842 if (session2 == NULL) {
5843 return NT_STATUS_NO_MEMORY;
5845 session2->smb2 = talloc_reference(session2, session1->smb2);
5846 if (session2->smb2 == NULL) {
5847 talloc_free(session2);
5848 return NT_STATUS_NO_MEMORY;
5851 talloc_set_destructor(session2, smbXcli_session_destructor);
5852 DLIST_ADD_END(conn->sessions, session2);
5853 session2->conn = conn;
5855 memcpy(session2->smb2_channel.preauth_sha512,
5856 conn->smb2.preauth_sha512,
5857 sizeof(session2->smb2_channel.preauth_sha512));
5859 *_session2 = session2;
5860 return NT_STATUS_OK;
5863 NTSTATUS smb2cli_session_set_channel_key(struct smbXcli_session *session,
5864 const DATA_BLOB _channel_key,
5865 const struct iovec *recv_iov)
5867 struct smbXcli_conn *conn = session->conn;
5868 uint8_t channel_key[16];
5869 NTSTATUS status;
5870 struct _derivation {
5871 DATA_BLOB label;
5872 DATA_BLOB context;
5874 struct {
5875 struct _derivation signing;
5876 } derivation = { };
5878 if (conn == NULL) {
5879 return NT_STATUS_INVALID_PARAMETER_MIX;
5882 if (session->smb2_channel.signing_key.length != 0) {
5883 return NT_STATUS_INVALID_PARAMETER_MIX;
5886 if (conn->protocol >= PROTOCOL_SMB3_10) {
5887 struct _derivation *d;
5888 DATA_BLOB p;
5890 p = data_blob_const(session->smb2_channel.preauth_sha512,
5891 sizeof(session->smb2_channel.preauth_sha512));
5893 d = &derivation.signing;
5894 d->label = data_blob_string_const_null("SMBSigningKey");
5895 d->context = p;
5896 } else if (conn->protocol >= PROTOCOL_SMB2_24) {
5897 struct _derivation *d;
5899 d = &derivation.signing;
5900 d->label = data_blob_string_const_null("SMB2AESCMAC");
5901 d->context = data_blob_string_const_null("SmbSign");
5904 ZERO_STRUCT(channel_key);
5905 memcpy(channel_key, _channel_key.data,
5906 MIN(_channel_key.length, sizeof(channel_key)));
5908 session->smb2_channel.signing_key = data_blob_talloc(session,
5909 channel_key,
5910 sizeof(channel_key));
5911 if (session->smb2_channel.signing_key.data == NULL) {
5912 ZERO_STRUCT(channel_key);
5913 return NT_STATUS_NO_MEMORY;
5916 if (conn->protocol >= PROTOCOL_SMB2_24) {
5917 struct _derivation *d = &derivation.signing;
5919 smb2_key_derivation(channel_key, sizeof(channel_key),
5920 d->label.data, d->label.length,
5921 d->context.data, d->context.length,
5922 session->smb2_channel.signing_key.data);
5924 ZERO_STRUCT(channel_key);
5926 status = smb2_signing_check_pdu(session->smb2_channel.signing_key,
5927 session->conn->protocol,
5928 recv_iov, 3);
5929 if (!NT_STATUS_IS_OK(status)) {
5930 return status;
5933 return NT_STATUS_OK;
5936 NTSTATUS smb2cli_session_encryption_on(struct smbXcli_session *session)
5938 if (!session->smb2->should_sign) {
5940 * We need required signing on the session
5941 * in order to prevent man in the middle attacks.
5943 return NT_STATUS_INVALID_PARAMETER_MIX;
5946 if (session->smb2->should_encrypt) {
5947 return NT_STATUS_OK;
5950 if (session->conn->protocol < PROTOCOL_SMB2_24) {
5951 return NT_STATUS_NOT_SUPPORTED;
5954 if (session->conn->smb2.server.cipher == 0) {
5955 return NT_STATUS_NOT_SUPPORTED;
5958 if (session->smb2->signing_key.data == NULL) {
5959 return NT_STATUS_NOT_SUPPORTED;
5961 session->smb2->should_encrypt = true;
5962 return NT_STATUS_OK;
5965 struct smbXcli_tcon *smbXcli_tcon_create(TALLOC_CTX *mem_ctx)
5967 struct smbXcli_tcon *tcon;
5969 tcon = talloc_zero(mem_ctx, struct smbXcli_tcon);
5970 if (tcon == NULL) {
5971 return NULL;
5974 return tcon;
5977 void smbXcli_tcon_set_fs_attributes(struct smbXcli_tcon *tcon,
5978 uint32_t fs_attributes)
5980 tcon->fs_attributes = fs_attributes;
5983 uint32_t smbXcli_tcon_get_fs_attributes(struct smbXcli_tcon *tcon)
5985 return tcon->fs_attributes;
5988 bool smbXcli_tcon_is_dfs_share(struct smbXcli_tcon *tcon)
5990 if (tcon == NULL) {
5991 return false;
5994 if (tcon->is_smb1) {
5995 if (tcon->smb1.optional_support & SMB_SHARE_IN_DFS) {
5996 return true;
5999 return false;
6002 if (tcon->smb2.capabilities & SMB2_SHARE_CAP_DFS) {
6003 return true;
6006 return false;
6009 uint16_t smb1cli_tcon_current_id(struct smbXcli_tcon *tcon)
6011 return tcon->smb1.tcon_id;
6014 void smb1cli_tcon_set_id(struct smbXcli_tcon *tcon, uint16_t tcon_id)
6016 tcon->is_smb1 = true;
6017 tcon->smb1.tcon_id = tcon_id;
6020 bool smb1cli_tcon_set_values(struct smbXcli_tcon *tcon,
6021 uint16_t tcon_id,
6022 uint16_t optional_support,
6023 uint32_t maximal_access,
6024 uint32_t guest_maximal_access,
6025 const char *service,
6026 const char *fs_type)
6028 tcon->is_smb1 = true;
6029 tcon->fs_attributes = 0;
6030 tcon->smb1.tcon_id = tcon_id;
6031 tcon->smb1.optional_support = optional_support;
6032 tcon->smb1.maximal_access = maximal_access;
6033 tcon->smb1.guest_maximal_access = guest_maximal_access;
6035 TALLOC_FREE(tcon->smb1.service);
6036 tcon->smb1.service = talloc_strdup(tcon, service);
6037 if (service != NULL && tcon->smb1.service == NULL) {
6038 return false;
6041 TALLOC_FREE(tcon->smb1.fs_type);
6042 tcon->smb1.fs_type = talloc_strdup(tcon, fs_type);
6043 if (fs_type != NULL && tcon->smb1.fs_type == NULL) {
6044 return false;
6047 return true;
6050 uint32_t smb2cli_tcon_current_id(struct smbXcli_tcon *tcon)
6052 return tcon->smb2.tcon_id;
6055 uint32_t smb2cli_tcon_capabilities(struct smbXcli_tcon *tcon)
6057 return tcon->smb2.capabilities;
6060 uint32_t smb2cli_tcon_flags(struct smbXcli_tcon *tcon)
6062 return tcon->smb2.flags;
6065 void smb2cli_tcon_set_values(struct smbXcli_tcon *tcon,
6066 struct smbXcli_session *session,
6067 uint32_t tcon_id,
6068 uint8_t type,
6069 uint32_t flags,
6070 uint32_t capabilities,
6071 uint32_t maximal_access)
6073 tcon->is_smb1 = false;
6074 tcon->fs_attributes = 0;
6075 tcon->smb2.tcon_id = tcon_id;
6076 tcon->smb2.type = type;
6077 tcon->smb2.flags = flags;
6078 tcon->smb2.capabilities = capabilities;
6079 tcon->smb2.maximal_access = maximal_access;
6081 tcon->smb2.should_sign = false;
6082 tcon->smb2.should_encrypt = false;
6084 if (session == NULL) {
6085 return;
6088 tcon->smb2.should_sign = session->smb2->should_sign;
6089 tcon->smb2.should_encrypt = session->smb2->should_encrypt;
6091 if (flags & SMB2_SHAREFLAG_ENCRYPT_DATA) {
6092 tcon->smb2.should_encrypt = true;
6096 void smb2cli_tcon_should_sign(struct smbXcli_tcon *tcon,
6097 bool should_sign)
6099 tcon->smb2.should_sign = should_sign;
6102 bool smb2cli_tcon_is_signing_on(struct smbXcli_tcon *tcon)
6104 if (tcon->smb2.should_encrypt) {
6105 return true;
6108 return tcon->smb2.should_sign;
6111 void smb2cli_tcon_should_encrypt(struct smbXcli_tcon *tcon,
6112 bool should_encrypt)
6114 tcon->smb2.should_encrypt = should_encrypt;
6117 bool smb2cli_tcon_is_encryption_on(struct smbXcli_tcon *tcon)
6119 return tcon->smb2.should_encrypt;