LCOV - code coverage report
Current view: top level - libcli/smb - smbXcli_base.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 2764 3421 80.8 %
Date: 2024-05-31 13:13:24 Functions: 150 170 88.2 %

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

Generated by: LCOV version 1.14