LCOV - code coverage report
Current view: top level - source3/libsmb - cliconnect.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 1284 1881 68.3 %
Date: 2024-05-31 13:13:24 Functions: 92 96 95.8 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    client connect/disconnect routines
       4             :    Copyright (C) Andrew Tridgell 1994-1998
       5             :    Copyright (C) Andrew Bartlett 2001-2003
       6             :    Copyright (C) Volker Lendecke 2011
       7             :    Copyright (C) Jeremy Allison 2011
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include "libsmb/libsmb.h"
      25             : #include "libsmb/namequery.h"
      26             : #include "../libcli/auth/libcli_auth.h"
      27             : #include "auth/credentials/credentials.h"
      28             : #include "auth/gensec/gensec.h"
      29             : #include "auth/ntlmssp/ntlmssp.h"
      30             : #include "auth_generic.h"
      31             : #include "../lib/util/tevent_ntstatus.h"
      32             : #include "async_smb.h"
      33             : #include "libsmb/nmblib.h"
      34             : #include "librpc/ndr/libndr.h"
      35             : #include "../libcli/smb/smbXcli_base.h"
      36             : #include "../libcli/smb/smb_seal.h"
      37             : #include "lib/param/param.h"
      38             : #include "../libcli/smb/smb2_negotiate_context.h"
      39             : 
      40             : static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
      41             :                                            const char *principal);
      42             : 
      43         671 : struct cli_credentials *cli_session_creds_init(TALLOC_CTX *mem_ctx,
      44             :                                                const char *username,
      45             :                                                const char *domain,
      46             :                                                const char *realm,
      47             :                                                const char *password,
      48             :                                                bool use_kerberos,
      49             :                                                bool fallback_after_kerberos,
      50             :                                                bool use_ccache,
      51             :                                                bool password_is_nt_hash)
      52             : {
      53         671 :         struct loadparm_context *lp_ctx = NULL;
      54         671 :         struct cli_credentials *creds = NULL;
      55         671 :         const char *principal = NULL;
      56         671 :         char *tmp = NULL;
      57         671 :         char *p = NULL;
      58          45 :         bool ok;
      59             : 
      60         671 :         creds = cli_credentials_init(mem_ctx);
      61         671 :         if (creds == NULL) {
      62           0 :                 return NULL;
      63             :         }
      64             : 
      65         671 :         lp_ctx = loadparm_init_s3(creds, loadparm_s3_helpers());
      66         671 :         if (lp_ctx == NULL) {
      67           0 :                 goto fail;
      68             :         }
      69         671 :         ok = cli_credentials_set_conf(creds, lp_ctx);
      70         671 :         if (!ok) {
      71           0 :                 goto fail;
      72             :         }
      73             : 
      74         671 :         if (username == NULL) {
      75           0 :                 username = "";
      76             :         }
      77             : 
      78         671 :         if (strlen(username) == 0) {
      79          53 :                 if (password != NULL && strlen(password) == 0) {
      80             :                         /*
      81             :                          * some callers pass "" as no password
      82             :                          *
      83             :                          * gensec only handles NULL as no password.
      84             :                          */
      85           8 :                         password = NULL;
      86             :                 }
      87           8 :                 if (password == NULL) {
      88          53 :                         cli_credentials_set_anonymous(creds);
      89          53 :                         return creds;
      90             :                 }
      91             :         }
      92             : 
      93         618 :         tmp = talloc_strdup(creds, username);
      94         618 :         if (tmp == NULL) {
      95           0 :                 goto fail;
      96             :         }
      97         618 :         username = tmp;
      98             : 
      99             :         /* allow for workgroups as part of the username */
     100        1236 :         if ((p = strchr_m(tmp, '\\')) ||
     101        1234 :             (p = strchr_m(tmp, '/')) ||
     102         616 :             (p = strchr_m(tmp, *lp_winbind_separator()))) {
     103           2 :                 *p = 0;
     104           2 :                 username = p + 1;
     105           2 :                 domain = tmp;
     106             :         }
     107             : 
     108         618 :         principal = username;
     109         618 :         username = cli_session_setup_get_account(creds, principal);
     110         618 :         if (username == NULL) {
     111           0 :                 goto fail;
     112             :         }
     113         618 :         ok = strequal(username, principal);
     114         618 :         if (ok) {
     115             :                 /*
     116             :                  * Ok still the same, so it's not a principal
     117             :                  */
     118         612 :                 principal = NULL;
     119             :         }
     120             : 
     121         672 :         if (use_kerberos && fallback_after_kerberos) {
     122             :                 /*
     123             :                  * Keep what we learned from the
     124             :                  * "client use kerberos" option.
     125             :                  */
     126           0 :                 enum credentials_use_kerberos current_krb5 =
     127          54 :                         cli_credentials_get_kerberos_state(creds);
     128          54 :                 cli_credentials_set_kerberos_state(creds,
     129             :                                                    current_krb5,
     130             :                                                    CRED_SPECIFIED);
     131         564 :         } else if (use_kerberos) {
     132           4 :                 cli_credentials_set_kerberos_state(creds,
     133             :                                                    CRED_USE_KERBEROS_REQUIRED,
     134             :                                                    CRED_SPECIFIED);
     135             :         } else {
     136         560 :                 cli_credentials_set_kerberos_state(creds,
     137             :                                                    CRED_USE_KERBEROS_DISABLED,
     138             :                                                    CRED_SPECIFIED);
     139             :         }
     140             : 
     141         618 :         if (use_ccache) {
     142           0 :                 uint32_t features;
     143             : 
     144          49 :                 features = cli_credentials_get_gensec_features(creds);
     145          49 :                 features |= GENSEC_FEATURE_NTLM_CCACHE;
     146          49 :                 cli_credentials_set_gensec_features(creds,
     147             :                                                     features,
     148             :                                                     CRED_SPECIFIED);
     149             : 
     150          49 :                 if (password != NULL && strlen(password) == 0) {
     151             :                         /*
     152             :                          * some callers pass "" as no password
     153             :                          *
     154             :                          * GENSEC_FEATURE_NTLM_CCACHE only handles
     155             :                          * NULL as no password.
     156             :                          */
     157           0 :                         password = NULL;
     158             :                 }
     159             :         }
     160             : 
     161         618 :         ok = cli_credentials_set_username(creds,
     162             :                                           username,
     163             :                                           CRED_SPECIFIED);
     164         618 :         if (!ok) {
     165           0 :                 goto fail;
     166             :         }
     167             : 
     168         618 :         if (domain != NULL) {
     169         618 :                 ok = cli_credentials_set_domain(creds,
     170             :                                                 domain,
     171             :                                                 CRED_SPECIFIED);
     172         618 :                 if (!ok) {
     173           0 :                         goto fail;
     174             :                 }
     175             :         }
     176             : 
     177         618 :         if (principal != NULL) {
     178           6 :                 ok = cli_credentials_set_principal(creds,
     179             :                                                    principal,
     180             :                                                    CRED_SPECIFIED);
     181           6 :                 if (!ok) {
     182           0 :                         goto fail;
     183             :                 }
     184             :         }
     185             : 
     186         618 :         if (realm != NULL) {
     187           0 :                 ok = cli_credentials_set_realm(creds,
     188             :                                                realm,
     189             :                                                CRED_SPECIFIED);
     190           0 :                 if (!ok) {
     191           0 :                         goto fail;
     192             :                 }
     193             :         }
     194             : 
     195         618 :         if (password != NULL && strlen(password) > 0) {
     196         616 :                 if (password_is_nt_hash) {
     197           0 :                         struct samr_Password nt_hash;
     198           0 :                         size_t converted;
     199             : 
     200           0 :                         converted = strhex_to_str((char *)nt_hash.hash,
     201             :                                                   sizeof(nt_hash.hash),
     202             :                                                   password,
     203             :                                                   strlen(password));
     204           0 :                         if (converted != sizeof(nt_hash.hash)) {
     205           0 :                                 goto fail;
     206             :                         }
     207             : 
     208           0 :                         ok = cli_credentials_set_nt_hash(creds,
     209             :                                                          &nt_hash,
     210             :                                                          CRED_SPECIFIED);
     211           0 :                         if (!ok) {
     212           0 :                                 goto fail;
     213             :                         }
     214             :                 } else {
     215         616 :                         ok = cli_credentials_set_password(creds,
     216             :                                                           password,
     217             :                                                           CRED_SPECIFIED);
     218         616 :                         if (!ok) {
     219           0 :                                 goto fail;
     220             :                         }
     221             :                 }
     222           2 :         } else if (use_kerberos && !fallback_after_kerberos) {
     223           2 :                 const char *error_string = NULL;
     224           0 :                 int rc;
     225             : 
     226           2 :                 rc = cli_credentials_set_ccache(creds,
     227             :                                                 lp_ctx,
     228             :                                                 NULL,
     229             :                                                 CRED_SPECIFIED,
     230             :                                                 &error_string);
     231           2 :                 if (rc != 0) {
     232           0 :                         fprintf(stderr,
     233             :                                 "Warning reading default "
     234             :                                 "krb5 credentials cache: %s\n",
     235             :                                 error_string);
     236             :                 }
     237             :         }
     238             : 
     239         618 :         return creds;
     240           0 : fail:
     241           0 :         TALLOC_FREE(creds);
     242           0 :         return NULL;
     243             : }
     244             : 
     245       33257 : static NTSTATUS cli_state_update_after_sesssetup(struct cli_state *cli,
     246             :                                                  const char *native_os,
     247             :                                                  const char *native_lm,
     248             :                                                  const char *primary_domain)
     249             : {
     250             : #define _VALID_STR(p) ((p) != NULL && (p)[0] != '\0')
     251             : 
     252       33257 :         if (!_VALID_STR(cli->server_os) && _VALID_STR(native_os)) {
     253        3857 :                 cli->server_os = talloc_strdup(cli, native_os);
     254        3857 :                 if (cli->server_os == NULL) {
     255           0 :                         return NT_STATUS_NO_MEMORY;
     256             :                 }
     257             :         }
     258             : 
     259       33257 :         if (!_VALID_STR(cli->server_type) && _VALID_STR(native_lm)) {
     260        3857 :                 cli->server_type = talloc_strdup(cli, native_lm);
     261        3857 :                 if (cli->server_type == NULL) {
     262           0 :                         return NT_STATUS_NO_MEMORY;
     263             :                 }
     264             :         }
     265             : 
     266       33257 :         if (!_VALID_STR(cli->server_domain) && _VALID_STR(primary_domain)) {
     267          61 :                 cli->server_domain = talloc_strdup(cli, primary_domain);
     268          61 :                 if (cli->server_domain == NULL) {
     269           0 :                         return NT_STATUS_NO_MEMORY;
     270             :                 }
     271             :         }
     272             : 
     273             : #undef _VALID_STRING
     274       33257 :         return NT_STATUS_OK;
     275             : }
     276             : 
     277             : /********************************************************
     278             :  Utility function to ensure we always return at least
     279             :  a valid char * pointer to an empty string for the
     280             :  cli->server_os, cli->server_type and cli->server_domain
     281             :  strings.
     282             : *******************************************************/
     283             : 
     284          15 : static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
     285             :                                         const uint8_t *hdr,
     286             :                                         char **dest,
     287             :                                         uint8_t *src,
     288             :                                         size_t srclen,
     289             :                                         ssize_t *destlen)
     290             : {
     291          30 :         *destlen = pull_string_talloc(mem_ctx,
     292             :                                       (const char *)hdr,
     293          15 :                                       SVAL(hdr, HDR_FLG2),
     294             :                                       dest,
     295             :                                       (char *)src,
     296             :                                       srclen,
     297             :                                       STR_TERMINATE);
     298          15 :         if (*destlen == -1) {
     299           0 :                 return NT_STATUS_NO_MEMORY;
     300             :         }
     301             : 
     302          15 :         if (*dest == NULL) {
     303           0 :                 *dest = talloc_strdup(mem_ctx, "");
     304           0 :                 if (*dest == NULL) {
     305           0 :                         return NT_STATUS_NO_MEMORY;
     306             :                 }
     307             :         }
     308          15 :         return NT_STATUS_OK;
     309             : }
     310             : 
     311             : /****************************************************************************
     312             :  Work out suitable capabilities to offer the server.
     313             : ****************************************************************************/
     314             : 
     315        7712 : static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
     316             :                                                uint32_t sesssetup_capabilities)
     317             : {
     318        7712 :         uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
     319             : 
     320             :         /*
     321             :          * We only send capabilities based on the mask for:
     322             :          * - client only flags
     323             :          * - flags used in both directions
     324             :          *
     325             :          * We do not echo the server only flags, except some legacy flags.
     326             :          *
     327             :          * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
     328             :          * CAP_LARGE_WRITEX in order to allow us to do large reads
     329             :          * against old Samba releases (<= 3.6.x).
     330             :          */
     331        7712 :         client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
     332             : 
     333             :         /*
     334             :          * Session Setup specific flags CAP_DYNAMIC_REAUTH
     335             :          * and CAP_EXTENDED_SECURITY are passed by the caller.
     336             :          * We need that in order to do guest logins even if
     337             :          * CAP_EXTENDED_SECURITY is negotiated.
     338             :          */
     339        7712 :         client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
     340        7712 :         sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
     341        7712 :         client_capabilities |= sesssetup_capabilities;
     342             : 
     343        7712 :         return client_capabilities;
     344             : }
     345             : 
     346             : /****************************************************************************
     347             :  Do a NT1 guest session setup.
     348             : ****************************************************************************/
     349             : 
     350             : struct cli_session_setup_guest_state {
     351             :         struct cli_state *cli;
     352             :         uint16_t vwv[13];
     353             :         struct iovec bytes;
     354             : };
     355             : 
     356             : static void cli_session_setup_guest_done(struct tevent_req *subreq);
     357             : 
     358           5 : struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
     359             :                                                   struct tevent_context *ev,
     360             :                                                   struct cli_state *cli,
     361             :                                                   struct tevent_req **psmbreq)
     362             : {
     363           0 :         struct tevent_req *req, *subreq;
     364           0 :         struct cli_session_setup_guest_state *state;
     365           0 :         uint16_t *vwv;
     366           0 :         uint8_t *bytes;
     367             : 
     368           5 :         req = tevent_req_create(mem_ctx, &state,
     369             :                                 struct cli_session_setup_guest_state);
     370           5 :         if (req == NULL) {
     371           0 :                 return NULL;
     372             :         }
     373           5 :         state->cli = cli;
     374           5 :         vwv = state->vwv;
     375             : 
     376           5 :         SCVAL(vwv+0, 0, 0xFF);
     377           5 :         SCVAL(vwv+0, 1, 0);
     378           5 :         SSVAL(vwv+1, 0, 0);
     379           5 :         SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
     380           5 :         SSVAL(vwv+3, 0, 2);
     381           5 :         SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
     382           5 :         SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
     383           5 :         SSVAL(vwv+7, 0, 0);
     384           5 :         SSVAL(vwv+8, 0, 0);
     385           5 :         SSVAL(vwv+9, 0, 0);
     386           5 :         SSVAL(vwv+10, 0, 0);
     387           5 :         SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
     388             : 
     389           5 :         bytes = talloc_array(state, uint8_t, 0);
     390             : 
     391           5 :         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "",  1, /* username */
     392             :                                    NULL);
     393           5 :         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
     394             :                                    NULL);
     395           5 :         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
     396           5 :         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
     397             : 
     398           5 :         if (bytes == NULL) {
     399           0 :                 TALLOC_FREE(req);
     400           0 :                 return NULL;
     401             :         }
     402             : 
     403           5 :         state->bytes.iov_base = (void *)bytes;
     404           5 :         state->bytes.iov_len = talloc_get_size(bytes);
     405             : 
     406           5 :         subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 0, 13,
     407           5 :                         vwv, 1, &state->bytes);
     408           5 :         if (subreq == NULL) {
     409           0 :                 TALLOC_FREE(req);
     410           0 :                 return NULL;
     411             :         }
     412           5 :         tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
     413           5 :         *psmbreq = subreq;
     414           5 :         return req;
     415             : }
     416             : 
     417           0 : struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
     418             :                                                 struct tevent_context *ev,
     419             :                                                 struct cli_state *cli)
     420             : {
     421           0 :         struct tevent_req *req, *subreq;
     422           0 :         NTSTATUS status;
     423             : 
     424           0 :         req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
     425           0 :         if (req == NULL) {
     426           0 :                 return NULL;
     427             :         }
     428             : 
     429           0 :         status = smb1cli_req_chain_submit(&subreq, 1);
     430           0 :         if (!NT_STATUS_IS_OK(status)) {
     431           0 :                 tevent_req_nterror(req, status);
     432           0 :                 return tevent_req_post(req, ev);
     433             :         }
     434           0 :         return req;
     435             : }
     436             : 
     437           5 : static void cli_session_setup_guest_done(struct tevent_req *subreq)
     438             : {
     439           5 :         struct tevent_req *req = tevent_req_callback_data(
     440             :                 subreq, struct tevent_req);
     441           5 :         struct cli_session_setup_guest_state *state = tevent_req_data(
     442             :                 req, struct cli_session_setup_guest_state);
     443           5 :         struct cli_state *cli = state->cli;
     444           0 :         uint32_t num_bytes;
     445           0 :         uint8_t *in;
     446           0 :         uint8_t *inhdr;
     447           0 :         uint8_t *bytes;
     448           0 :         uint8_t *p;
     449           0 :         NTSTATUS status;
     450           0 :         ssize_t ret;
     451           0 :         uint8_t wct;
     452           0 :         uint16_t *vwv;
     453             : 
     454           5 :         status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
     455             :                               &num_bytes, &bytes);
     456           5 :         TALLOC_FREE(subreq);
     457           5 :         if (!NT_STATUS_IS_OK(status)) {
     458           0 :                 tevent_req_nterror(req, status);
     459           0 :                 return;
     460             :         }
     461             : 
     462           5 :         inhdr = in + NBT_HDR_SIZE;
     463           5 :         p = bytes;
     464             : 
     465           5 :         cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
     466           5 :         smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
     467             : 
     468           5 :         status = smb_bytes_talloc_string(cli,
     469             :                                         inhdr,
     470             :                                         &cli->server_os,
     471             :                                         p,
     472           5 :                                         bytes+num_bytes-p,
     473             :                                         &ret);
     474             : 
     475           5 :         if (!NT_STATUS_IS_OK(status)) {
     476           0 :                 tevent_req_nterror(req, status);
     477           0 :                 return;
     478             :         }
     479           5 :         p += ret;
     480             : 
     481           5 :         status = smb_bytes_talloc_string(cli,
     482             :                                         inhdr,
     483             :                                         &cli->server_type,
     484             :                                         p,
     485           5 :                                         bytes+num_bytes-p,
     486             :                                         &ret);
     487             : 
     488           5 :         if (!NT_STATUS_IS_OK(status)) {
     489           0 :                 tevent_req_nterror(req, status);
     490           0 :                 return;
     491             :         }
     492           5 :         p += ret;
     493             : 
     494           5 :         status = smb_bytes_talloc_string(cli,
     495             :                                         inhdr,
     496             :                                         &cli->server_domain,
     497             :                                         p,
     498           5 :                                         bytes+num_bytes-p,
     499             :                                         &ret);
     500             : 
     501           5 :         if (!NT_STATUS_IS_OK(status)) {
     502           0 :                 tevent_req_nterror(req, status);
     503           0 :                 return;
     504             :         }
     505             : 
     506           5 :         tevent_req_done(req);
     507             : }
     508             : 
     509           5 : NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
     510             : {
     511           5 :         return tevent_req_simple_recv_ntstatus(req);
     512             : }
     513             : 
     514             : /* The following is calculated from :
     515             :  * (smb_size-4) = 35
     516             :  * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
     517             :  * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
     518             :  * end of packet.
     519             :  */
     520             : 
     521             : #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
     522             : 
     523             : struct cli_sesssetup_blob_state {
     524             :         struct tevent_context *ev;
     525             :         struct cli_state *cli;
     526             :         DATA_BLOB blob;
     527             :         uint16_t max_blob_size;
     528             : 
     529             :         DATA_BLOB this_blob;
     530             :         struct iovec *recv_iov;
     531             : 
     532             :         NTSTATUS status;
     533             :         const uint8_t *inbuf;
     534             :         DATA_BLOB ret_blob;
     535             : 
     536             :         char *out_native_os;
     537             :         char *out_native_lm;
     538             : };
     539             : 
     540             : static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
     541             :                                     struct tevent_req **psubreq);
     542             : static void cli_sesssetup_blob_done(struct tevent_req *subreq);
     543             : 
     544       33529 : static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
     545             :                                                   struct tevent_context *ev,
     546             :                                                   struct cli_state *cli,
     547             :                                                   DATA_BLOB blob)
     548             : {
     549           0 :         struct tevent_req *req, *subreq;
     550           0 :         struct cli_sesssetup_blob_state *state;
     551           0 :         uint32_t usable_space;
     552             : 
     553       33529 :         req = tevent_req_create(mem_ctx, &state,
     554             :                                 struct cli_sesssetup_blob_state);
     555       33529 :         if (req == NULL) {
     556           0 :                 return NULL;
     557             :         }
     558       33529 :         state->ev = ev;
     559       33529 :         state->blob = blob;
     560       33529 :         state->cli = cli;
     561             : 
     562       33529 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
     563       25902 :                 usable_space = UINT16_MAX;
     564             :         } else {
     565        7627 :                 usable_space = cli_state_available_size(cli,
     566             :                                 BASE_SESSSETUP_BLOB_PACKET_SIZE);
     567             :         }
     568             : 
     569       33529 :         if (usable_space == 0) {
     570           0 :                 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
     571             :                           "(not possible to send %u bytes)\n",
     572             :                           BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
     573           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     574           0 :                 return tevent_req_post(req, ev);
     575             :         }
     576       33529 :         state->max_blob_size = MIN(usable_space, 0xFFFF);
     577             : 
     578       33529 :         if (!cli_sesssetup_blob_next(state, &subreq)) {
     579           0 :                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
     580           0 :                 return tevent_req_post(req, ev);
     581             :         }
     582       33529 :         tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
     583       33529 :         return req;
     584             : }
     585             : 
     586       33529 : static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
     587             :                                     struct tevent_req **psubreq)
     588             : {
     589           0 :         struct tevent_req *subreq;
     590           0 :         uint16_t thistime;
     591             : 
     592       33529 :         thistime = MIN(state->blob.length, state->max_blob_size);
     593             : 
     594       33529 :         state->this_blob.data = state->blob.data;
     595       33529 :         state->this_blob.length = thistime;
     596             : 
     597       33529 :         state->blob.data += thistime;
     598       33529 :         state->blob.length -= thistime;
     599             : 
     600       33529 :         if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
     601       25902 :                 subreq = smb2cli_session_setup_send(state, state->ev,
     602       25902 :                                                     state->cli->conn,
     603       25902 :                                                     state->cli->timeout,
     604       25902 :                                                     state->cli->smb2.session,
     605             :                                                     0, /* in_flags */
     606             :                                                     SMB2_CAP_DFS, /* in_capabilities */
     607             :                                                     0, /* in_channel */
     608             :                                                     0, /* in_previous_session_id */
     609       25902 :                                                     &state->this_blob);
     610       25902 :                 if (subreq == NULL) {
     611           0 :                         return false;
     612             :                 }
     613             :         } else {
     614        7627 :                 uint16_t in_buf_size = 0;
     615        7627 :                 uint16_t in_mpx_max = 0;
     616        7627 :                 uint16_t in_vc_num = 0;
     617        7627 :                 uint32_t in_sess_key = 0;
     618        7627 :                 uint32_t in_capabilities = 0;
     619        7627 :                 const char *in_native_os = NULL;
     620        7627 :                 const char *in_native_lm = NULL;
     621             : 
     622        7627 :                 in_buf_size = CLI_BUFFER_SIZE;
     623        7627 :                 in_mpx_max = smbXcli_conn_max_requests(state->cli->conn);
     624        7627 :                 in_vc_num = cli_state_get_vc_num(state->cli);
     625        7627 :                 in_sess_key = smb1cli_conn_server_session_key(state->cli->conn);
     626        7627 :                 in_capabilities = cli_session_setup_capabilities(state->cli,
     627             :                                                                 CAP_EXTENDED_SECURITY);
     628        7627 :                 in_native_os = "Unix";
     629        7627 :                 in_native_lm = "Samba";
     630             : 
     631             :                 /*
     632             :                  * For now we keep the same values as before,
     633             :                  * we may remove these in a separate commit later.
     634             :                  */
     635        7627 :                 in_mpx_max = 2;
     636        7627 :                 in_vc_num = 1;
     637        7627 :                 in_sess_key = 0;
     638             : 
     639        7627 :                 subreq = smb1cli_session_setup_ext_send(state, state->ev,
     640        7627 :                                                         state->cli->conn,
     641        7627 :                                                         state->cli->timeout,
     642        7627 :                                                         state->cli->smb1.pid,
     643        7627 :                                                         state->cli->smb1.session,
     644             :                                                         in_buf_size,
     645             :                                                         in_mpx_max,
     646             :                                                         in_vc_num,
     647             :                                                         in_sess_key,
     648             :                                                         state->this_blob,
     649             :                                                         in_capabilities,
     650             :                                                         in_native_os,
     651             :                                                         in_native_lm);
     652        7627 :                 if (subreq == NULL) {
     653           0 :                         return false;
     654             :                 }
     655             :         }
     656       33529 :         *psubreq = subreq;
     657       33529 :         return true;
     658             : }
     659             : 
     660       33529 : static void cli_sesssetup_blob_done(struct tevent_req *subreq)
     661             : {
     662       33529 :         struct tevent_req *req = tevent_req_callback_data(
     663             :                 subreq, struct tevent_req);
     664       33529 :         struct cli_sesssetup_blob_state *state = tevent_req_data(
     665             :                 req, struct cli_sesssetup_blob_state);
     666           0 :         NTSTATUS status;
     667             : 
     668       33529 :         if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
     669       25902 :                 status = smb2cli_session_setup_recv(subreq, state,
     670             :                                                     &state->recv_iov,
     671             :                                                     &state->ret_blob);
     672             :         } else {
     673        7627 :                 status = smb1cli_session_setup_ext_recv(subreq, state,
     674             :                                                         &state->recv_iov,
     675             :                                                         &state->inbuf,
     676             :                                                         &state->ret_blob,
     677             :                                                         &state->out_native_os,
     678             :                                                         &state->out_native_lm);
     679             :         }
     680       33529 :         TALLOC_FREE(subreq);
     681       33529 :         if (!NT_STATUS_IS_OK(status)
     682       15947 :             && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     683         357 :                 tevent_req_nterror(req, status);
     684         357 :                 return;
     685             :         }
     686             : 
     687       33172 :         state->status = status;
     688             : 
     689       33172 :         status = cli_state_update_after_sesssetup(state->cli,
     690       33172 :                                                   state->out_native_os,
     691       33172 :                                                   state->out_native_lm,
     692             :                                                   NULL);
     693       33172 :         if (tevent_req_nterror(req, status)) {
     694           0 :                 return;
     695             :         }
     696             : 
     697       33172 :         if (state->blob.length != 0) {
     698             :                 /*
     699             :                  * More to send
     700             :                  */
     701           0 :                 if (!cli_sesssetup_blob_next(state, &subreq)) {
     702           0 :                         tevent_req_oom(req);
     703           0 :                         return;
     704             :                 }
     705           0 :                 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
     706           0 :                 return;
     707             :         }
     708       33172 :         tevent_req_done(req);
     709             : }
     710             : 
     711       33529 : static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
     712             :                                         TALLOC_CTX *mem_ctx,
     713             :                                         DATA_BLOB *pblob,
     714             :                                         const uint8_t **pinbuf,
     715             :                                         struct iovec **precv_iov)
     716             : {
     717       33529 :         struct cli_sesssetup_blob_state *state = tevent_req_data(
     718             :                 req, struct cli_sesssetup_blob_state);
     719           0 :         NTSTATUS status;
     720           0 :         struct iovec *recv_iov;
     721             : 
     722       33529 :         if (tevent_req_is_nterror(req, &status)) {
     723         357 :                 TALLOC_FREE(state->cli->smb2.session);
     724         357 :                 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
     725         357 :                 tevent_req_received(req);
     726         357 :                 return status;
     727             :         }
     728             : 
     729       33172 :         recv_iov = talloc_move(mem_ctx, &state->recv_iov);
     730       33172 :         if (pblob != NULL) {
     731       33172 :                 *pblob = state->ret_blob;
     732             :         }
     733       33172 :         if (pinbuf != NULL) {
     734       33172 :                 *pinbuf = state->inbuf;
     735             :         }
     736       33172 :         if (precv_iov != NULL) {
     737       33172 :                 *precv_iov = recv_iov;
     738             :         }
     739             :         /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
     740       33172 :         status = state->status;
     741       33172 :         tevent_req_received(req);
     742       33172 :         return status;
     743             : }
     744             : 
     745             : /****************************************************************************
     746             :  Do a spnego/NTLMSSP encrypted session setup.
     747             : ****************************************************************************/
     748             : 
     749             : struct cli_session_setup_gensec_state {
     750             :         struct tevent_context *ev;
     751             :         struct cli_state *cli;
     752             :         struct auth_generic_state *auth_generic;
     753             :         bool is_anonymous;
     754             :         DATA_BLOB blob_in;
     755             :         const uint8_t *inbuf;
     756             :         struct iovec *recv_iov;
     757             :         DATA_BLOB blob_out;
     758             :         bool local_ready;
     759             :         bool remote_ready;
     760             :         DATA_BLOB session_key;
     761             : };
     762             : 
     763       17961 : static int cli_session_setup_gensec_state_destructor(
     764             :         struct cli_session_setup_gensec_state *state)
     765             : {
     766       17961 :         TALLOC_FREE(state->auth_generic);
     767       17961 :         data_blob_clear_free(&state->session_key);
     768       17961 :         return 0;
     769             : }
     770             : 
     771             : static void cli_session_setup_gensec_local_next(struct tevent_req *req);
     772             : static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
     773             : static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
     774             : static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
     775             : static void cli_session_setup_gensec_ready(struct tevent_req *req);
     776             : 
     777       17961 : static struct tevent_req *cli_session_setup_gensec_send(
     778             :         TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
     779             :         struct cli_credentials *creds,
     780             :         const char *target_service,
     781             :         const char *target_hostname)
     782             : {
     783           0 :         struct tevent_req *req;
     784           0 :         struct cli_session_setup_gensec_state *state;
     785           0 :         NTSTATUS status;
     786       17961 :         const DATA_BLOB *b = NULL;
     787             : 
     788       17961 :         req = tevent_req_create(mem_ctx, &state,
     789             :                                 struct cli_session_setup_gensec_state);
     790       17961 :         if (req == NULL) {
     791           0 :                 return NULL;
     792             :         }
     793       17961 :         state->ev = ev;
     794       17961 :         state->cli = cli;
     795             : 
     796       17961 :         talloc_set_destructor(
     797             :                 state, cli_session_setup_gensec_state_destructor);
     798             : 
     799       17961 :         status = auth_generic_client_prepare(state, &state->auth_generic);
     800       17961 :         if (tevent_req_nterror(req, status)) {
     801           0 :                 return tevent_req_post(req, ev);
     802             :         }
     803             : 
     804       17961 :         status = auth_generic_set_creds(state->auth_generic, creds);
     805       17961 :         if (tevent_req_nterror(req, status)) {
     806           0 :                 return tevent_req_post(req, ev);
     807             :         }
     808             : 
     809       17961 :         gensec_want_feature(state->auth_generic->gensec_security,
     810             :                             GENSEC_FEATURE_SESSION_KEY);
     811             : 
     812       17961 :         if (target_service != NULL) {
     813       17961 :                 status = gensec_set_target_service(
     814       17961 :                                 state->auth_generic->gensec_security,
     815             :                                 target_service);
     816       17961 :                 if (tevent_req_nterror(req, status)) {
     817           0 :                         return tevent_req_post(req, ev);
     818             :                 }
     819             :         }
     820             : 
     821       17961 :         if (target_hostname != NULL) {
     822       17961 :                 status = gensec_set_target_hostname(
     823       17961 :                                 state->auth_generic->gensec_security,
     824             :                                 target_hostname);
     825       17961 :                 if (tevent_req_nterror(req, status)) {
     826           0 :                         return tevent_req_post(req, ev);
     827             :                 }
     828             :         }
     829             : 
     830       17961 :         b = smbXcli_conn_server_gss_blob(cli->conn);
     831       17961 :         if (b != NULL) {
     832       17961 :                 state->blob_in = *b;
     833             :         }
     834             : 
     835       17961 :         state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
     836             : 
     837       17961 :         status = auth_generic_client_start(state->auth_generic,
     838             :                                            GENSEC_OID_SPNEGO);
     839       17961 :         if (tevent_req_nterror(req, status)) {
     840           0 :                 return tevent_req_post(req, ev);
     841             :         }
     842             : 
     843       17961 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
     844       14135 :                 state->cli->smb2.session = smbXcli_session_create(cli,
     845             :                                                                   cli->conn);
     846       14135 :                 if (tevent_req_nomem(state->cli->smb2.session, req)) {
     847           0 :                         return tevent_req_post(req, ev);
     848             :                 }
     849             :         }
     850             : 
     851       17961 :         cli_session_setup_gensec_local_next(req);
     852       17961 :         if (!tevent_req_is_in_progress(req)) {
     853           0 :                 return tevent_req_post(req, ev);
     854             :         }
     855             : 
     856       17961 :         return req;
     857             : }
     858             : 
     859       51111 : static void cli_session_setup_gensec_local_next(struct tevent_req *req)
     860             : {
     861           0 :         struct cli_session_setup_gensec_state *state =
     862       51111 :                 tevent_req_data(req,
     863             :                 struct cli_session_setup_gensec_state);
     864       51111 :         struct tevent_req *subreq = NULL;
     865             : 
     866       51111 :         if (state->local_ready) {
     867           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
     868           0 :                 return;
     869             :         }
     870             : 
     871       51111 :         subreq = gensec_update_send(state, state->ev,
     872       51111 :                         state->auth_generic->gensec_security,
     873             :                         state->blob_in);
     874       51111 :         if (tevent_req_nomem(subreq, req)) {
     875           0 :                 return;
     876             :         }
     877       51111 :         tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
     878             : }
     879             : 
     880       51111 : static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
     881             : {
     882           0 :         struct tevent_req *req =
     883       51111 :                 tevent_req_callback_data(subreq,
     884             :                 struct tevent_req);
     885           0 :         struct cli_session_setup_gensec_state *state =
     886       51111 :                 tevent_req_data(req,
     887             :                 struct cli_session_setup_gensec_state);
     888           0 :         NTSTATUS status;
     889             : 
     890       51111 :         status = gensec_update_recv(subreq, state, &state->blob_out);
     891       51111 :         TALLOC_FREE(subreq);
     892       51111 :         state->blob_in = data_blob_null;
     893       51111 :         if (!NT_STATUS_IS_OK(status) &&
     894       33553 :             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
     895             :         {
     896          24 :                 tevent_req_nterror(req, status);
     897          24 :                 return;
     898             :         }
     899             : 
     900       51087 :         if (NT_STATUS_IS_OK(status)) {
     901       17558 :                 state->local_ready = true;
     902             :         }
     903             : 
     904       51087 :         if (state->local_ready && state->remote_ready) {
     905       17558 :                 cli_session_setup_gensec_ready(req);
     906       17558 :                 return;
     907             :         }
     908             : 
     909       33529 :         cli_session_setup_gensec_remote_next(req);
     910             : }
     911             : 
     912       33529 : static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
     913             : {
     914           0 :         struct cli_session_setup_gensec_state *state =
     915       33529 :                 tevent_req_data(req,
     916             :                 struct cli_session_setup_gensec_state);
     917       33529 :         struct tevent_req *subreq = NULL;
     918             : 
     919       33529 :         if (state->remote_ready) {
     920           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
     921           0 :                 return;
     922             :         }
     923             : 
     924       33529 :         subreq = cli_sesssetup_blob_send(state, state->ev,
     925             :                                          state->cli, state->blob_out);
     926       33529 :         if (tevent_req_nomem(subreq, req)) {
     927           0 :                 return;
     928             :         }
     929       33529 :         tevent_req_set_callback(subreq,
     930             :                                 cli_session_setup_gensec_remote_done,
     931             :                                 req);
     932             : }
     933             : 
     934       33529 : static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
     935             : {
     936           0 :         struct tevent_req *req =
     937       33529 :                 tevent_req_callback_data(subreq,
     938             :                 struct tevent_req);
     939           0 :         struct cli_session_setup_gensec_state *state =
     940       33529 :                 tevent_req_data(req,
     941             :                 struct cli_session_setup_gensec_state);
     942           0 :         NTSTATUS status;
     943             : 
     944       33529 :         state->inbuf = NULL;
     945       33529 :         TALLOC_FREE(state->recv_iov);
     946             : 
     947       33529 :         status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
     948             :                                          &state->inbuf, &state->recv_iov);
     949       33529 :         TALLOC_FREE(subreq);
     950       33529 :         data_blob_free(&state->blob_out);
     951       33529 :         if (!NT_STATUS_IS_OK(status) &&
     952       15947 :             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
     953             :         {
     954         357 :                 tevent_req_nterror(req, status);
     955         357 :                 return;
     956             :         }
     957             : 
     958       33172 :         if (NT_STATUS_IS_OK(status)) {
     959       17582 :                 struct smbXcli_session *session = NULL;
     960       17582 :                 bool is_guest = false;
     961             : 
     962       17582 :                 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
     963       13801 :                         session = state->cli->smb2.session;
     964             :                 } else {
     965        3781 :                         session = state->cli->smb1.session;
     966             :                 }
     967             : 
     968       17582 :                 is_guest = smbXcli_session_is_guest(session);
     969       17582 :                 if (is_guest) {
     970             :                         /*
     971             :                          * We can't finish the gensec handshake, we don't
     972             :                          * have a negotiated session key.
     973             :                          *
     974             :                          * So just pretend we are completely done,
     975             :                          * we need to continue as anonymous from this point,
     976             :                          * as we can't get a session key.
     977             :                          *
     978             :                          * Note that smbXcli_session_is_guest()
     979             :                          * always returns false if we require signing.
     980             :                          */
     981          22 :                         state->blob_in = data_blob_null;
     982          22 :                         state->local_ready = true;
     983          22 :                         state->is_anonymous = true;
     984             :                 }
     985             : 
     986       17582 :                 state->remote_ready = true;
     987             :         }
     988             : 
     989       33172 :         if (state->local_ready && state->remote_ready) {
     990          22 :                 cli_session_setup_gensec_ready(req);
     991          22 :                 return;
     992             :         }
     993             : 
     994       33150 :         cli_session_setup_gensec_local_next(req);
     995             : }
     996             : 
     997           0 : static void cli_session_dump_keys(TALLOC_CTX *mem_ctx,
     998             :                                   struct smbXcli_session *session,
     999             :                                   DATA_BLOB session_key)
    1000             : {
    1001           0 :         NTSTATUS status;
    1002           0 :         DATA_BLOB sig = data_blob_null;
    1003           0 :         DATA_BLOB app = data_blob_null;
    1004           0 :         DATA_BLOB enc = data_blob_null;
    1005           0 :         DATA_BLOB dec = data_blob_null;
    1006           0 :         uint64_t sid = smb2cli_session_current_id(session);
    1007             : 
    1008           0 :         status = smb2cli_session_signing_key(session, mem_ctx, &sig);
    1009           0 :         if (!NT_STATUS_IS_OK(status)) {
    1010           0 :                 goto out;
    1011             :         }
    1012           0 :         status = smbXcli_session_application_key(session, mem_ctx, &app);
    1013           0 :         if (!NT_STATUS_IS_OK(status)) {
    1014           0 :                 goto out;
    1015             :         }
    1016           0 :         status = smb2cli_session_encryption_key(session, mem_ctx, &enc);
    1017           0 :         if (!NT_STATUS_IS_OK(status)) {
    1018           0 :                 goto out;
    1019             :         }
    1020           0 :         status = smb2cli_session_decryption_key(session, mem_ctx, &dec);
    1021           0 :         if (!NT_STATUS_IS_OK(status)) {
    1022           0 :                 goto out;
    1023             :         }
    1024             : 
    1025           0 :         DEBUG(0, ("debug encryption: dumping generated session keys\n"));
    1026           0 :         DEBUGADD(0, ("Session Id    "));
    1027           0 :         dump_data(0, (uint8_t*)&sid, sizeof(sid));
    1028           0 :         DEBUGADD(0, ("Session Key   "));
    1029           0 :         dump_data(0, session_key.data, session_key.length);
    1030           0 :         DEBUGADD(0, ("Signing Key   "));
    1031           0 :         dump_data(0, sig.data, sig.length);
    1032           0 :         DEBUGADD(0, ("App Key       "));
    1033           0 :         dump_data(0, app.data, app.length);
    1034             : 
    1035             :         /* In client code, ServerIn is the encryption key */
    1036             : 
    1037           0 :         DEBUGADD(0, ("ServerIn Key  "));
    1038           0 :         dump_data(0, enc.data, enc.length);
    1039           0 :         DEBUGADD(0, ("ServerOut Key "));
    1040           0 :         dump_data(0, dec.data, dec.length);
    1041             : 
    1042           0 : out:
    1043           0 :         data_blob_clear_free(&sig);
    1044           0 :         data_blob_clear_free(&app);
    1045           0 :         data_blob_clear_free(&enc);
    1046           0 :         data_blob_clear_free(&dec);
    1047           0 : }
    1048             : 
    1049       17580 : static void cli_session_setup_gensec_ready(struct tevent_req *req)
    1050             : {
    1051           0 :         struct cli_session_setup_gensec_state *state =
    1052       17580 :                 tevent_req_data(req,
    1053             :                 struct cli_session_setup_gensec_state);
    1054       17580 :         const char *server_domain = NULL;
    1055           0 :         NTSTATUS status;
    1056             : 
    1057       17580 :         if (state->blob_in.length != 0) {
    1058           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
    1059           0 :                 return;
    1060             :         }
    1061             : 
    1062       17580 :         if (state->blob_out.length != 0) {
    1063           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
    1064           0 :                 return;
    1065             :         }
    1066             : 
    1067             :         /*
    1068             :          * gensec_ntlmssp_server_domain() returns NULL
    1069             :          * if NTLMSSP is not used.
    1070             :          *
    1071             :          * We can remove this later
    1072             :          * and leave the server domain empty for SMB2 and above
    1073             :          * in future releases.
    1074             :          */
    1075       17580 :         server_domain = gensec_ntlmssp_server_domain(
    1076       17580 :                                 state->auth_generic->gensec_security);
    1077             : 
    1078       17580 :         if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
    1079       15220 :                 TALLOC_FREE(state->cli->server_domain);
    1080       15220 :                 state->cli->server_domain = talloc_strdup(state->cli,
    1081             :                                         server_domain);
    1082       15220 :                 if (state->cli->server_domain == NULL) {
    1083           0 :                         tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
    1084           0 :                         return;
    1085             :                 }
    1086             :         }
    1087             : 
    1088       17580 :         if (state->is_anonymous) {
    1089             :                 /*
    1090             :                  * Windows server does not set the
    1091             :                  * SMB2_SESSION_FLAG_IS_NULL flag.
    1092             :                  *
    1093             :                  * This fix makes sure we do not try
    1094             :                  * to verify a signature on the final
    1095             :                  * session setup response.
    1096             :                  */
    1097         503 :                 tevent_req_done(req);
    1098         503 :                 return;
    1099             :         }
    1100             : 
    1101       17077 :         status = gensec_session_key(state->auth_generic->gensec_security,
    1102             :                                     state, &state->session_key);
    1103       17077 :         if (tevent_req_nterror(req, status)) {
    1104           0 :                 return;
    1105             :         }
    1106             : 
    1107       17077 :         if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
    1108       13336 :                 struct smbXcli_session *session = state->cli->smb2.session;
    1109             : 
    1110       13336 :                 status = smb2cli_session_set_session_key(session,
    1111             :                                                          state->session_key,
    1112       13336 :                                                          state->recv_iov);
    1113       13336 :                 if (tevent_req_nterror(req, status)) {
    1114           0 :                         return;
    1115             :                 }
    1116       13336 :                 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB3_00
    1117       11963 :                     && lp_debug_encryption())
    1118             :                 {
    1119           0 :                         cli_session_dump_keys(state, session, state->session_key);
    1120             :                 }
    1121             :         } else {
    1122        3741 :                 struct smbXcli_session *session = state->cli->smb1.session;
    1123           0 :                 bool active;
    1124             : 
    1125        3741 :                 status = smb1cli_session_set_session_key(session,
    1126             :                                                          state->session_key);
    1127        3741 :                 if (tevent_req_nterror(req, status)) {
    1128           0 :                         return;
    1129             :                 }
    1130             : 
    1131        3741 :                 active = smb1cli_conn_activate_signing(state->cli->conn,
    1132             :                                                        state->session_key,
    1133             :                                                        data_blob_null);
    1134        3741 :                 if (active) {
    1135           0 :                         bool ok;
    1136             : 
    1137         326 :                         ok = smb1cli_conn_check_signing(state->cli->conn,
    1138             :                                                         state->inbuf, 1);
    1139         326 :                         if (!ok) {
    1140           0 :                                 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
    1141           0 :                                 return;
    1142             :                         }
    1143             :                 }
    1144             :         }
    1145             : 
    1146       17077 :         tevent_req_done(req);
    1147             : }
    1148             : 
    1149       17961 : static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
    1150             : {
    1151           0 :         struct cli_session_setup_gensec_state *state =
    1152       17961 :                 tevent_req_data(req,
    1153             :                 struct cli_session_setup_gensec_state);
    1154           0 :         NTSTATUS status;
    1155             : 
    1156       17961 :         if (tevent_req_is_nterror(req, &status)) {
    1157         381 :                 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
    1158         381 :                 return status;
    1159             :         }
    1160       17580 :         return NT_STATUS_OK;
    1161             : }
    1162             : 
    1163         618 : static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
    1164             :                                            const char *principal)
    1165             : {
    1166           0 :         char *account, *p;
    1167             : 
    1168         618 :         account = talloc_strdup(mem_ctx, principal);
    1169         618 :         if (account == NULL) {
    1170           0 :                 return NULL;
    1171             :         }
    1172         618 :         p = strchr_m(account, '@');
    1173         618 :         if (p != NULL) {
    1174           6 :                 *p = '\0';
    1175             :         }
    1176         618 :         return account;
    1177             : }
    1178             : 
    1179             : /****************************************************************************
    1180             :  Do a spnego encrypted session setup.
    1181             : 
    1182             :  user_domain: The shortname of the domain the user/machine is a member of.
    1183             :  dest_realm: The realm we're connecting to, if NULL we use our default realm.
    1184             : ****************************************************************************/
    1185             : 
    1186             : struct cli_session_setup_spnego_state {
    1187             :         ADS_STATUS result;
    1188             : };
    1189             : 
    1190             : static void cli_session_setup_spnego_done(struct tevent_req *subreq);
    1191             : 
    1192       17961 : static struct tevent_req *cli_session_setup_spnego_send(
    1193             :         TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
    1194             :         struct cli_credentials *creds)
    1195             : {
    1196           0 :         struct tevent_req *req, *subreq;
    1197           0 :         struct cli_session_setup_spnego_state *state;
    1198       17961 :         const char *target_service = NULL;
    1199       17961 :         const char *target_hostname = NULL;
    1200             : 
    1201       17961 :         req = tevent_req_create(mem_ctx, &state,
    1202             :                                 struct cli_session_setup_spnego_state);
    1203       17961 :         if (req == NULL) {
    1204           0 :                 return NULL;
    1205             :         }
    1206             : 
    1207       17961 :         target_service = "cifs";
    1208       17961 :         target_hostname = smbXcli_conn_remote_name(cli->conn);
    1209             : 
    1210       17961 :         DBG_INFO("Connect to %s as %s using SPNEGO\n",
    1211             :                  target_hostname,
    1212             :                  cli_credentials_get_principal(creds, talloc_tos()));
    1213             : 
    1214       17961 :         subreq = cli_session_setup_gensec_send(state, ev, cli, creds,
    1215             :                                                target_service, target_hostname);
    1216       17961 :         if (tevent_req_nomem(subreq, req)) {
    1217           0 :                 return tevent_req_post(req, ev);
    1218             :         }
    1219       17961 :         tevent_req_set_callback(
    1220             :                 subreq, cli_session_setup_spnego_done, req);
    1221       17961 :         return req;
    1222             : }
    1223             : 
    1224       17961 : static void cli_session_setup_spnego_done(struct tevent_req *subreq)
    1225             : {
    1226       17961 :         struct tevent_req *req = tevent_req_callback_data(
    1227             :                 subreq, struct tevent_req);
    1228           0 :         NTSTATUS status;
    1229             : 
    1230       17961 :         status = cli_session_setup_gensec_recv(subreq);
    1231       17961 :         TALLOC_FREE(subreq);
    1232       17961 :         if (tevent_req_nterror(req, status)) {
    1233         381 :                 return;
    1234             :         }
    1235             : 
    1236       17580 :         tevent_req_done(req);
    1237             : }
    1238             : 
    1239       17961 : static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
    1240             : {
    1241       17961 :         struct cli_session_setup_spnego_state *state = tevent_req_data(
    1242             :                 req, struct cli_session_setup_spnego_state);
    1243           0 :         NTSTATUS status;
    1244             : 
    1245       17961 :         if (tevent_req_is_nterror(req, &status)) {
    1246         381 :                 state->result = ADS_ERROR_NT(status);
    1247             :         }
    1248             : 
    1249       17961 :         return state->result;
    1250             : }
    1251             : 
    1252             : struct cli_session_setup_creds_state {
    1253             :         struct cli_state *cli;
    1254             :         DATA_BLOB apassword_blob;
    1255             :         DATA_BLOB upassword_blob;
    1256             :         DATA_BLOB lm_session_key;
    1257             :         DATA_BLOB session_key;
    1258             :         char *out_native_os;
    1259             :         char *out_native_lm;
    1260             :         char *out_primary_domain;
    1261             : };
    1262             : 
    1263       36100 : static void cli_session_setup_creds_cleanup(struct tevent_req *req,
    1264             :                                             enum tevent_req_state req_state)
    1265             : {
    1266       36100 :         struct cli_session_setup_creds_state *state = tevent_req_data(
    1267             :                 req, struct cli_session_setup_creds_state);
    1268             : 
    1269       36100 :         if (req_state != TEVENT_REQ_RECEIVED) {
    1270       18050 :                 return;
    1271             :         }
    1272             : 
    1273             :         /*
    1274             :          * We only call data_blob_clear() as
    1275             :          * some of the blobs point to the same memory.
    1276             :          *
    1277             :          * We let the talloc hierarchy free the memory.
    1278             :          */
    1279       18050 :         data_blob_clear(&state->apassword_blob);
    1280       18050 :         data_blob_clear(&state->upassword_blob);
    1281       18050 :         data_blob_clear(&state->lm_session_key);
    1282       18050 :         data_blob_clear(&state->session_key);
    1283       18050 :         ZERO_STRUCTP(state);
    1284             : }
    1285             : 
    1286             : static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq);
    1287             : static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq);
    1288             : static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq);
    1289             : 
    1290             : /****************************************************************************
    1291             :  Send a session setup. The username and workgroup is in UNIX character
    1292             :  format and must be converted to DOS codepage format before sending. If the
    1293             :  password is in plaintext, the same should be done.
    1294             : ****************************************************************************/
    1295             : 
    1296       18050 : struct tevent_req *cli_session_setup_creds_send(TALLOC_CTX *mem_ctx,
    1297             :                                         struct tevent_context *ev,
    1298             :                                         struct cli_state *cli,
    1299             :                                         struct cli_credentials *creds)
    1300             : {
    1301           0 :         struct tevent_req *req, *subreq;
    1302           0 :         struct cli_session_setup_creds_state *state;
    1303       18050 :         uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
    1304       18050 :         bool use_spnego = false;
    1305       18050 :         int flags = 0;
    1306       18050 :         const char *username = "";
    1307       18050 :         const char *domain = "";
    1308       18050 :         DATA_BLOB target_info = data_blob_null;
    1309       18050 :         DATA_BLOB challenge = data_blob_null;
    1310       18050 :         uint16_t in_buf_size = 0;
    1311       18050 :         uint16_t in_mpx_max = 0;
    1312       18050 :         uint16_t in_vc_num = 0;
    1313       18050 :         uint32_t in_sess_key = 0;
    1314       18050 :         const char *in_native_os = NULL;
    1315       18050 :         const char *in_native_lm = NULL;
    1316           0 :         enum credentials_use_kerberos krb5_state =
    1317       18050 :                 cli_credentials_get_kerberos_state(creds);
    1318           0 :         NTSTATUS status;
    1319             : 
    1320       18050 :         req = tevent_req_create(mem_ctx, &state,
    1321             :                                 struct cli_session_setup_creds_state);
    1322       18050 :         if (req == NULL) {
    1323           0 :                 return NULL;
    1324             :         }
    1325       18050 :         state->cli = cli;
    1326             : 
    1327       18050 :         tevent_req_set_cleanup_fn(req, cli_session_setup_creds_cleanup);
    1328             : 
    1329             :         /*
    1330             :          * Now work out what sort of session setup we are going to
    1331             :          * do. I have split this into separate functions to make the flow a bit
    1332             :          * easier to understand (tridge).
    1333             :          */
    1334       18050 :         if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
    1335          24 :                 use_spnego = false;
    1336       18026 :         } else if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
    1337       14135 :                 use_spnego = true;
    1338        3891 :         } else if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
    1339             :                 /*
    1340             :                  * if the server supports extended security then use SPNEGO
    1341             :                  * even for anonymous connections.
    1342             :                  */
    1343        3826 :                 use_spnego = true;
    1344             :         } else {
    1345          65 :                 use_spnego = false;
    1346             :         }
    1347             : 
    1348       18050 :         if (use_spnego) {
    1349       17961 :                 subreq = cli_session_setup_spnego_send(
    1350             :                         state, ev, cli, creds);
    1351       17961 :                 if (tevent_req_nomem(subreq, req)) {
    1352           0 :                         return tevent_req_post(req, ev);
    1353             :                 }
    1354       17961 :                 tevent_req_set_callback(subreq, cli_session_setup_creds_done_spnego,
    1355             :                                         req);
    1356       17961 :                 return req;
    1357             :         }
    1358             : 
    1359          89 :         if (krb5_state == CRED_USE_KERBEROS_REQUIRED) {
    1360           0 :                 DBG_WARNING("Kerberos authentication requested, but "
    1361             :                             "the server does not support SPNEGO authentication\n");
    1362           0 :                 tevent_req_nterror(req, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT);
    1363           0 :                 return tevent_req_post(req, ev);
    1364             :         }
    1365             : 
    1366          89 :         if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
    1367             :                 /*
    1368             :                  * SessionSetupAndX was introduced by LANMAN 1.0. So we skip
    1369             :                  * this step against older servers.
    1370             :                  */
    1371           0 :                 tevent_req_done(req);
    1372           0 :                 return tevent_req_post(req, ev);
    1373             :         }
    1374             : 
    1375          89 :         if (cli_credentials_is_anonymous(creds)) {
    1376             :                 /*
    1377             :                  * Do an anonymous session setup
    1378             :                  */
    1379          33 :                 goto non_spnego_creds_done;
    1380             :         }
    1381             : 
    1382          56 :         if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
    1383             :                 /*
    1384             :                  * Do an anonymous session setup,
    1385             :                  * the password is passed via the tree connect.
    1386             :                  */
    1387           0 :                 goto non_spnego_creds_done;
    1388             :         }
    1389             : 
    1390          56 :         cli_credentials_get_ntlm_username_domain(creds, state,
    1391             :                                                  &username,
    1392             :                                                  &domain);
    1393          56 :         if (tevent_req_nomem(username, req)) {
    1394           0 :                 return tevent_req_post(req, ev);
    1395             :         }
    1396          56 :         if (tevent_req_nomem(domain, req)) {
    1397           0 :                 return tevent_req_post(req, ev);
    1398             :         }
    1399             : 
    1400          56 :         DBG_INFO("Connect to %s as %s using NTLM\n", domain, username);
    1401             : 
    1402          56 :         if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
    1403           0 :                 bool use_unicode = smbXcli_conn_use_unicode(cli->conn);
    1404           0 :                 uint8_t *bytes = NULL;
    1405           0 :                 size_t bytes_len = 0;
    1406           0 :                 const char *pw = cli_credentials_get_password(creds);
    1407           0 :                 size_t pw_len = 0;
    1408             : 
    1409           0 :                 if (pw == NULL) {
    1410           0 :                         pw = "";
    1411             :                 }
    1412           0 :                 pw_len = strlen(pw) + 1;
    1413             : 
    1414           0 :                 if (!lp_client_plaintext_auth()) {
    1415           0 :                         DEBUG(1, ("Server requested PLAINTEXT password but "
    1416             :                                   "'client plaintext auth = no'\n"));
    1417           0 :                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
    1418           0 :                         return tevent_req_post(req, ev);
    1419             :                 }
    1420             : 
    1421           0 :                 bytes = talloc_array(state, uint8_t, 0);
    1422           0 :                 bytes = trans2_bytes_push_str(bytes, use_unicode,
    1423             :                                               pw, pw_len, &bytes_len);
    1424           0 :                 if (tevent_req_nomem(bytes, req)) {
    1425           0 :                         return tevent_req_post(req, ev);
    1426             :                 }
    1427             : 
    1428           0 :                 if (use_unicode) {
    1429             :                         /*
    1430             :                          * CAP_UNICODE, can only be negotiated by NT1.
    1431             :                          */
    1432           0 :                         state->upassword_blob = data_blob_const(bytes,
    1433             :                                                                 bytes_len);
    1434             :                 } else {
    1435           0 :                         state->apassword_blob = data_blob_const(bytes,
    1436             :                                                                 bytes_len);
    1437             :                 }
    1438             : 
    1439           0 :                 goto non_spnego_creds_done;
    1440             :         }
    1441             : 
    1442          56 :         challenge = data_blob_const(smb1cli_conn_server_challenge(cli->conn), 8);
    1443             : 
    1444          56 :         if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
    1445          42 :                 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
    1446             :                         /*
    1447             :                          * Don't send an NTLMv2 response without NTLMSSP if we
    1448             :                          * want to use spnego support.
    1449             :                          */
    1450           0 :                         DEBUG(1, ("Server does not support EXTENDED_SECURITY "
    1451             :                                   " but 'client use spnego = yes'"
    1452             :                                   " and 'client ntlmv2 auth = yes' is set\n"));
    1453           0 :                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
    1454           0 :                         return tevent_req_post(req, ev);
    1455             :                 }
    1456             : 
    1457          42 :                 if (lp_client_ntlmv2_auth()) {
    1458           0 :                         flags |= CLI_CRED_NTLMv2_AUTH;
    1459             : 
    1460             :                         /*
    1461             :                          * note that the 'domain' here is a best
    1462             :                          * guess - we don't know the server's domain
    1463             :                          * at this point. Windows clients also don't
    1464             :                          * use hostname...
    1465             :                          */
    1466           0 :                         target_info = NTLMv2_generate_names_blob(state,
    1467             :                                                                  NULL,
    1468             :                                                                  domain);
    1469           0 :                         if (tevent_req_nomem(target_info.data, req)) {
    1470           0 :                                 return tevent_req_post(req, ev);
    1471             :                         }
    1472             :                 } else {
    1473          42 :                         flags |= CLI_CRED_NTLM_AUTH;
    1474          42 :                         if (lp_client_lanman_auth()) {
    1475          36 :                                 flags |= CLI_CRED_LANMAN_AUTH;
    1476             :                         }
    1477             :                 }
    1478             :         } else {
    1479          14 :                 if (!lp_client_lanman_auth()) {
    1480           0 :                         DEBUG(1, ("Server requested user level LM password but "
    1481             :                                   "'client lanman auth = no' is set.\n"));
    1482           0 :                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
    1483           0 :                         return tevent_req_post(req, ev);
    1484             :                 }
    1485             : 
    1486          14 :                 flags |= CLI_CRED_LANMAN_AUTH;
    1487             :         }
    1488             : 
    1489          56 :         status = cli_credentials_get_ntlm_response(creds, state, &flags,
    1490             :                                                    challenge, NULL,
    1491             :                                                    target_info,
    1492          56 :                                                    &state->apassword_blob,
    1493          56 :                                                    &state->upassword_blob,
    1494          56 :                                                    &state->lm_session_key,
    1495          56 :                                                    &state->session_key);
    1496          56 :         if (tevent_req_nterror(req, status)) {
    1497           0 :                 return tevent_req_post(req, ev);
    1498             :         }
    1499             : 
    1500          56 : non_spnego_creds_done:
    1501             : 
    1502          89 :         in_buf_size = CLI_BUFFER_SIZE;
    1503          89 :         in_mpx_max = smbXcli_conn_max_requests(cli->conn);
    1504          89 :         in_vc_num = cli_state_get_vc_num(cli);
    1505          89 :         in_sess_key = smb1cli_conn_server_session_key(cli->conn);
    1506          89 :         in_native_os = "Unix";
    1507          89 :         in_native_lm = "Samba";
    1508             : 
    1509          89 :         if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
    1510          65 :                 uint32_t in_capabilities = 0;
    1511             : 
    1512          65 :                 in_capabilities = cli_session_setup_capabilities(cli, 0);
    1513             : 
    1514             :                 /*
    1515             :                  * For now we keep the same values as before,
    1516             :                  * we may remove these in a separate commit later.
    1517             :                  */
    1518          65 :                 in_mpx_max = 2;
    1519             : 
    1520          65 :                 subreq = smb1cli_session_setup_nt1_send(state, ev,
    1521             :                                                         cli->conn,
    1522          65 :                                                         cli->timeout,
    1523             :                                                         cli->smb1.pid,
    1524             :                                                         cli->smb1.session,
    1525             :                                                         in_buf_size,
    1526             :                                                         in_mpx_max,
    1527             :                                                         in_vc_num,
    1528             :                                                         in_sess_key,
    1529             :                                                         username,
    1530             :                                                         domain,
    1531          65 :                                                         state->apassword_blob,
    1532          65 :                                                         state->upassword_blob,
    1533             :                                                         in_capabilities,
    1534             :                                                         in_native_os,
    1535             :                                                         in_native_lm);
    1536          65 :                 if (tevent_req_nomem(subreq, req)) {
    1537           0 :                         return tevent_req_post(req, ev);
    1538             :                 }
    1539          65 :                 tevent_req_set_callback(subreq, cli_session_setup_creds_done_nt1,
    1540             :                                         req);
    1541          65 :                 return req;
    1542             :         }
    1543             : 
    1544             :         /*
    1545             :          * For now we keep the same values as before,
    1546             :          * we may remove these in a separate commit later.
    1547             :          */
    1548          24 :         in_mpx_max = 2;
    1549          24 :         in_vc_num = 1;
    1550             : 
    1551          24 :         subreq = smb1cli_session_setup_lm21_send(state, ev,
    1552             :                                                  cli->conn,
    1553          24 :                                                  cli->timeout,
    1554             :                                                  cli->smb1.pid,
    1555             :                                                  cli->smb1.session,
    1556             :                                                  in_buf_size,
    1557             :                                                  in_mpx_max,
    1558             :                                                  in_vc_num,
    1559             :                                                  in_sess_key,
    1560             :                                                  username,
    1561             :                                                  domain,
    1562          24 :                                                  state->apassword_blob,
    1563             :                                                  in_native_os,
    1564             :                                                  in_native_lm);
    1565          24 :         if (tevent_req_nomem(subreq, req)) {
    1566           0 :                 return tevent_req_post(req, ev);
    1567             :         }
    1568          24 :         tevent_req_set_callback(subreq, cli_session_setup_creds_done_lm21,
    1569             :                                 req);
    1570          24 :         return req;
    1571             : }
    1572             : 
    1573       17961 : static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq)
    1574             : {
    1575       17961 :         struct tevent_req *req = tevent_req_callback_data(
    1576             :                 subreq, struct tevent_req);
    1577           0 :         ADS_STATUS status;
    1578             : 
    1579       17961 :         status = cli_session_setup_spnego_recv(subreq);
    1580       17961 :         TALLOC_FREE(subreq);
    1581       17961 :         if (!ADS_ERR_OK(status)) {
    1582         381 :                 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
    1583         381 :                 tevent_req_nterror(req, ads_ntstatus(status));
    1584         381 :                 return;
    1585             :         }
    1586       17580 :         tevent_req_done(req);
    1587             : }
    1588             : 
    1589          65 : static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq)
    1590             : {
    1591          65 :         struct tevent_req *req = tevent_req_callback_data(
    1592             :                 subreq, struct tevent_req);
    1593          65 :         struct cli_session_setup_creds_state *state = tevent_req_data(
    1594             :                 req, struct cli_session_setup_creds_state);
    1595          65 :         struct cli_state *cli = state->cli;
    1596           0 :         NTSTATUS status;
    1597          65 :         struct iovec *recv_iov = NULL;
    1598          65 :         const uint8_t *inbuf = NULL;
    1599           0 :         bool ok;
    1600             : 
    1601          65 :         status = smb1cli_session_setup_nt1_recv(subreq, state,
    1602             :                                                 &recv_iov,
    1603             :                                                 &inbuf,
    1604             :                                                 &state->out_native_os,
    1605             :                                                 &state->out_native_lm,
    1606             :                                                 &state->out_primary_domain);
    1607          65 :         TALLOC_FREE(subreq);
    1608          65 :         if (tevent_req_nterror(req, status)) {
    1609           4 :                 DEBUG(3, ("NT1 login failed: %s\n", nt_errstr(status)));
    1610           5 :                 return;
    1611             :         }
    1612             : 
    1613          61 :         status = cli_state_update_after_sesssetup(state->cli,
    1614          61 :                                                   state->out_native_os,
    1615          61 :                                                   state->out_native_lm,
    1616          61 :                                                   state->out_primary_domain);
    1617          61 :         if (tevent_req_nterror(req, status)) {
    1618           0 :                 return;
    1619             :         }
    1620             : 
    1621          61 :         ok = smb1cli_conn_activate_signing(cli->conn,
    1622             :                                            state->session_key,
    1623             :                                            state->upassword_blob);
    1624          61 :         if (ok) {
    1625           5 :                 ok = smb1cli_conn_check_signing(cli->conn, inbuf, 1);
    1626           5 :                 if (!ok) {
    1627           1 :                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
    1628           1 :                         return;
    1629             :                 }
    1630             :         }
    1631             : 
    1632          60 :         if (state->session_key.data) {
    1633          37 :                 struct smbXcli_session *session = cli->smb1.session;
    1634             : 
    1635          37 :                 status = smb1cli_session_set_session_key(session,
    1636             :                                                          state->session_key);
    1637          37 :                 if (tevent_req_nterror(req, status)) {
    1638           0 :                         return;
    1639             :                 }
    1640             :         }
    1641             : 
    1642          60 :         tevent_req_done(req);
    1643             : }
    1644             : 
    1645          24 : static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq)
    1646             : {
    1647          24 :         struct tevent_req *req = tevent_req_callback_data(
    1648             :                 subreq, struct tevent_req);
    1649          24 :         struct cli_session_setup_creds_state *state = tevent_req_data(
    1650             :                 req, struct cli_session_setup_creds_state);
    1651           0 :         NTSTATUS status;
    1652             : 
    1653          24 :         status = smb1cli_session_setup_lm21_recv(subreq, state,
    1654             :                                                  &state->out_native_os,
    1655             :                                                  &state->out_native_lm);
    1656          24 :         TALLOC_FREE(subreq);
    1657          24 :         if (tevent_req_nterror(req, status)) {
    1658           0 :                 DEBUG(3, ("LM21 login failed: %s\n", nt_errstr(status)));
    1659           0 :                 return;
    1660             :         }
    1661             : 
    1662          24 :         status = cli_state_update_after_sesssetup(state->cli,
    1663          24 :                                                   state->out_native_os,
    1664          24 :                                                   state->out_native_lm,
    1665             :                                                   NULL);
    1666          24 :         if (tevent_req_nterror(req, status)) {
    1667           0 :                 return;
    1668             :         }
    1669             : 
    1670          24 :         tevent_req_done(req);
    1671             : }
    1672             : 
    1673       18050 : NTSTATUS cli_session_setup_creds_recv(struct tevent_req *req)
    1674             : {
    1675       18050 :         return tevent_req_simple_recv_ntstatus(req);
    1676             : }
    1677             : 
    1678       12280 : NTSTATUS cli_session_setup_creds(struct cli_state *cli,
    1679             :                                  struct cli_credentials *creds)
    1680             : {
    1681           0 :         struct tevent_context *ev;
    1682           0 :         struct tevent_req *req;
    1683       12280 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    1684             : 
    1685       12280 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    1686           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1687             :         }
    1688       12280 :         ev = samba_tevent_context_init(talloc_tos());
    1689       12280 :         if (ev == NULL) {
    1690           0 :                 goto fail;
    1691             :         }
    1692       12280 :         req = cli_session_setup_creds_send(ev, ev, cli, creds);
    1693       12280 :         if (req == NULL) {
    1694           0 :                 goto fail;
    1695             :         }
    1696       12280 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    1697           0 :                 goto fail;
    1698             :         }
    1699       12280 :         status = cli_session_setup_creds_recv(req);
    1700       12280 :  fail:
    1701       12280 :         TALLOC_FREE(ev);
    1702       12280 :         return status;
    1703             : }
    1704             : 
    1705          50 : NTSTATUS cli_session_setup_anon(struct cli_state *cli)
    1706             : {
    1707           0 :         NTSTATUS status;
    1708          50 :         struct cli_credentials *creds = NULL;
    1709             : 
    1710          50 :         creds = cli_credentials_init_anon(cli);
    1711          50 :         if (creds == NULL) {
    1712           0 :                 return NT_STATUS_NO_MEMORY;
    1713             :         }
    1714             : 
    1715          50 :         status = cli_session_setup_creds(cli, creds);
    1716          50 :         TALLOC_FREE(creds);
    1717          50 :         if (!NT_STATUS_IS_OK(status)) {
    1718           0 :                 return status;
    1719             :         }
    1720             : 
    1721          50 :         return NT_STATUS_OK;
    1722             : }
    1723             : 
    1724             : /****************************************************************************
    1725             :  Send a uloggoff.
    1726             : *****************************************************************************/
    1727             : 
    1728             : struct cli_ulogoff_state {
    1729             :         struct cli_state *cli;
    1730             :         uint16_t vwv[3];
    1731             : };
    1732             : 
    1733             : static void cli_ulogoff_done(struct tevent_req *subreq);
    1734             : 
    1735           4 : static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
    1736             :                                     struct tevent_context *ev,
    1737             :                                     struct cli_state *cli)
    1738             : {
    1739           0 :         struct tevent_req *req, *subreq;
    1740           0 :         struct cli_ulogoff_state *state;
    1741             : 
    1742           4 :         req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
    1743           4 :         if (req == NULL) {
    1744           0 :                 return NULL;
    1745             :         }
    1746           4 :         state->cli = cli;
    1747             : 
    1748           4 :         SCVAL(state->vwv+0, 0, 0xFF);
    1749           4 :         SCVAL(state->vwv+1, 0, 0);
    1750           4 :         SSVAL(state->vwv+2, 0, 0);
    1751             : 
    1752           4 :         subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
    1753             :                               0, NULL);
    1754           4 :         if (tevent_req_nomem(subreq, req)) {
    1755           0 :                 return tevent_req_post(req, ev);
    1756             :         }
    1757           4 :         tevent_req_set_callback(subreq, cli_ulogoff_done, req);
    1758           4 :         return req;
    1759             : }
    1760             : 
    1761           4 : static void cli_ulogoff_done(struct tevent_req *subreq)
    1762             : {
    1763           4 :         struct tevent_req *req = tevent_req_callback_data(
    1764             :                 subreq, struct tevent_req);
    1765           4 :         struct cli_ulogoff_state *state = tevent_req_data(
    1766             :                 req, struct cli_ulogoff_state);
    1767           0 :         NTSTATUS status;
    1768             : 
    1769           4 :         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    1770           4 :         if (tevent_req_nterror(req, status)) {
    1771           0 :                 return;
    1772             :         }
    1773           4 :         cli_state_set_uid(state->cli, UID_FIELD_INVALID);
    1774           4 :         tevent_req_done(req);
    1775             : }
    1776             : 
    1777           4 : static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
    1778             : {
    1779           4 :         return tevent_req_simple_recv_ntstatus(req);
    1780             : }
    1781             : 
    1782           4 : NTSTATUS cli_ulogoff(struct cli_state *cli)
    1783             : {
    1784           0 :         struct tevent_context *ev;
    1785           0 :         struct tevent_req *req;
    1786           4 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    1787             : 
    1788           4 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
    1789           0 :                 status = smb2cli_logoff(cli->conn,
    1790           0 :                                         cli->timeout,
    1791             :                                         cli->smb2.session);
    1792           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1793           0 :                         return status;
    1794             :                 }
    1795           0 :                 smb2cli_session_set_id_and_flags(cli->smb2.session,
    1796             :                                                  UINT64_MAX, 0);
    1797           0 :                 return NT_STATUS_OK;
    1798             :         }
    1799             : 
    1800           4 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    1801           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1802             :         }
    1803           4 :         ev = samba_tevent_context_init(talloc_tos());
    1804           4 :         if (ev == NULL) {
    1805           0 :                 goto fail;
    1806             :         }
    1807           4 :         req = cli_ulogoff_send(ev, ev, cli);
    1808           4 :         if (req == NULL) {
    1809           0 :                 goto fail;
    1810             :         }
    1811           4 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    1812           0 :                 goto fail;
    1813             :         }
    1814           4 :         status = cli_ulogoff_recv(req);
    1815           4 : fail:
    1816           4 :         TALLOC_FREE(ev);
    1817           4 :         return status;
    1818             : }
    1819             : 
    1820             : /****************************************************************************
    1821             :  Send a tconX.
    1822             : ****************************************************************************/
    1823             : 
    1824             : struct cli_tcon_andx_state {
    1825             :         struct cli_state *cli;
    1826             :         uint16_t vwv[4];
    1827             :         struct iovec bytes;
    1828             : };
    1829             : 
    1830             : static void cli_tcon_andx_done(struct tevent_req *subreq);
    1831             : 
    1832        7303 : struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
    1833             :                                         struct tevent_context *ev,
    1834             :                                         struct cli_state *cli,
    1835             :                                         const char *share, const char *dev,
    1836             :                                         const char *pass, int passlen,
    1837             :                                         struct tevent_req **psmbreq)
    1838             : {
    1839           0 :         struct tevent_req *req, *subreq;
    1840           0 :         struct cli_tcon_andx_state *state;
    1841           0 :         uint8_t p24[24];
    1842           0 :         uint16_t *vwv;
    1843        7303 :         char *tmp = NULL;
    1844           0 :         uint8_t *bytes;
    1845        7303 :         uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
    1846        7303 :         uint16_t tcon_flags = 0;
    1847             : 
    1848        7303 :         *psmbreq = NULL;
    1849             : 
    1850        7303 :         req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
    1851        7303 :         if (req == NULL) {
    1852           0 :                 return NULL;
    1853             :         }
    1854        7303 :         state->cli = cli;
    1855        7303 :         vwv = state->vwv;
    1856             : 
    1857        7303 :         TALLOC_FREE(cli->smb1.tcon);
    1858        7303 :         cli->smb1.tcon = smbXcli_tcon_create(cli);
    1859        7303 :         if (tevent_req_nomem(cli->smb1.tcon, req)) {
    1860           0 :                 return tevent_req_post(req, ev);
    1861             :         }
    1862        7303 :         smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
    1863             : 
    1864        7303 :         cli->share = talloc_strdup(cli, share);
    1865        7303 :         if (!cli->share) {
    1866           0 :                 return NULL;
    1867             :         }
    1868             : 
    1869             :         /* in user level security don't send a password now */
    1870        7303 :         if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
    1871        7303 :                 passlen = 1;
    1872        7303 :                 pass = "";
    1873           0 :         } else if (pass == NULL) {
    1874           0 :                 DEBUG(1, ("Server not using user level security and no "
    1875             :                           "password supplied.\n"));
    1876           0 :                 goto access_denied;
    1877             :         }
    1878             : 
    1879        7303 :         if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
    1880        7303 :             *pass && passlen != 24) {
    1881           0 :                 if (!lp_client_lanman_auth()) {
    1882           0 :                         DEBUG(1, ("Server requested LANMAN password "
    1883             :                                   "(share-level security) but "
    1884             :                                   "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
    1885           0 :                         goto access_denied;
    1886             :                 }
    1887             : 
    1888             :                 /*
    1889             :                  * Non-encrypted passwords - convert to DOS codepage before
    1890             :                  * encryption.
    1891             :                  */
    1892           0 :                 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
    1893           0 :                 passlen = 24;
    1894           0 :                 pass = (const char *)p24;
    1895             :         } else {
    1896        7303 :                 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
    1897             :                                      |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
    1898             :                    == 0) {
    1899           0 :                         uint8_t *tmp_pass;
    1900             : 
    1901           0 :                         if (!lp_client_plaintext_auth() && (*pass)) {
    1902           0 :                                 DEBUG(1, ("Server requested PLAINTEXT "
    1903             :                                           "password but "
    1904             :                                           "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
    1905           0 :                                 goto access_denied;
    1906             :                         }
    1907             : 
    1908             :                         /*
    1909             :                          * Non-encrypted passwords - convert to DOS codepage
    1910             :                          * before using.
    1911             :                          */
    1912           0 :                         tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
    1913           0 :                         if (tevent_req_nomem(tmp_pass, req)) {
    1914           0 :                                 return tevent_req_post(req, ev);
    1915             :                         }
    1916           0 :                         tmp_pass = trans2_bytes_push_str(tmp_pass,
    1917             :                                                          false, /* always DOS */
    1918             :                                                          pass,
    1919             :                                                          passlen,
    1920             :                                                          NULL);
    1921           0 :                         if (tevent_req_nomem(tmp_pass, req)) {
    1922           0 :                                 return tevent_req_post(req, ev);
    1923             :                         }
    1924           0 :                         pass = (const char *)tmp_pass;
    1925           0 :                         passlen = talloc_get_size(tmp_pass);
    1926             :                 }
    1927             :         }
    1928             : 
    1929        7303 :         tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
    1930        7303 :         tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
    1931             : 
    1932        7303 :         SCVAL(vwv+0, 0, 0xFF);
    1933        7303 :         SCVAL(vwv+0, 1, 0);
    1934        7303 :         SSVAL(vwv+1, 0, 0);
    1935        7303 :         SSVAL(vwv+2, 0, tcon_flags);
    1936        7303 :         SSVAL(vwv+3, 0, passlen);
    1937             : 
    1938        7303 :         if (passlen && pass) {
    1939        7303 :                 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
    1940             :         } else {
    1941           0 :                 bytes = talloc_array(state, uint8_t, 0);
    1942             :         }
    1943             : 
    1944             :         /*
    1945             :          * Add the sharename
    1946             :          */
    1947        7303 :         tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
    1948             :                                          smbXcli_conn_remote_name(cli->conn), share);
    1949        7303 :         if (tmp == NULL) {
    1950           0 :                 TALLOC_FREE(req);
    1951           0 :                 return NULL;
    1952             :         }
    1953        7303 :         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
    1954             :                                    NULL);
    1955        7303 :         TALLOC_FREE(tmp);
    1956             : 
    1957             :         /*
    1958             :          * Add the devicetype
    1959             :          */
    1960        7303 :         tmp = talloc_strdup_upper(talloc_tos(), dev);
    1961        7303 :         if (tmp == NULL) {
    1962           0 :                 TALLOC_FREE(req);
    1963           0 :                 return NULL;
    1964             :         }
    1965        7303 :         bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
    1966        7303 :         TALLOC_FREE(tmp);
    1967             : 
    1968        7303 :         if (bytes == NULL) {
    1969           0 :                 TALLOC_FREE(req);
    1970           0 :                 return NULL;
    1971             :         }
    1972             : 
    1973        7303 :         state->bytes.iov_base = (void *)bytes;
    1974        7303 :         state->bytes.iov_len = talloc_get_size(bytes);
    1975             : 
    1976        7303 :         subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
    1977        7303 :                                     1, &state->bytes);
    1978        7303 :         if (subreq == NULL) {
    1979           0 :                 TALLOC_FREE(req);
    1980           0 :                 return NULL;
    1981             :         }
    1982        7303 :         tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
    1983        7303 :         *psmbreq = subreq;
    1984        7303 :         return req;
    1985             : 
    1986           0 :  access_denied:
    1987           0 :         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
    1988           0 :         return tevent_req_post(req, ev);
    1989             : }
    1990             : 
    1991        7298 : struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
    1992             :                                       struct tevent_context *ev,
    1993             :                                       struct cli_state *cli,
    1994             :                                       const char *share, const char *dev,
    1995             :                                       const char *pass, int passlen)
    1996             : {
    1997           0 :         struct tevent_req *req, *subreq;
    1998           0 :         NTSTATUS status;
    1999             : 
    2000        7298 :         req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
    2001             :                                    &subreq);
    2002        7298 :         if (req == NULL) {
    2003           0 :                 return NULL;
    2004             :         }
    2005        7298 :         if (subreq == NULL) {
    2006           0 :                 return req;
    2007             :         }
    2008        7298 :         status = smb1cli_req_chain_submit(&subreq, 1);
    2009        7298 :         if (tevent_req_nterror(req, status)) {
    2010           0 :                 return tevent_req_post(req, ev);
    2011             :         }
    2012        7298 :         return req;
    2013             : }
    2014             : 
    2015        7303 : static void cli_tcon_andx_done(struct tevent_req *subreq)
    2016             : {
    2017        7303 :         struct tevent_req *req = tevent_req_callback_data(
    2018             :                 subreq, struct tevent_req);
    2019        7303 :         struct cli_tcon_andx_state *state = tevent_req_data(
    2020             :                 req, struct cli_tcon_andx_state);
    2021        7303 :         struct cli_state *cli = state->cli;
    2022           0 :         uint8_t *in;
    2023           0 :         uint8_t *inhdr;
    2024           0 :         uint8_t wct;
    2025           0 :         uint16_t *vwv;
    2026           0 :         uint32_t num_bytes;
    2027           0 :         uint8_t *bytes;
    2028           0 :         NTSTATUS status;
    2029        7303 :         uint16_t optional_support = 0;
    2030             : 
    2031        7303 :         status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
    2032             :                               &num_bytes, &bytes);
    2033        7303 :         TALLOC_FREE(subreq);
    2034        7303 :         if (tevent_req_nterror(req, status)) {
    2035          36 :                 return;
    2036             :         }
    2037             : 
    2038        7267 :         inhdr = in + NBT_HDR_SIZE;
    2039             : 
    2040        7267 :         if (num_bytes) {
    2041        7267 :                 if (pull_string_talloc(cli,
    2042             :                                        (const char *)inhdr,
    2043        7267 :                                        SVAL(inhdr, HDR_FLG2),
    2044             :                                        &cli->dev,
    2045             :                                        bytes,
    2046             :                                        num_bytes,
    2047             :                                        STR_TERMINATE|STR_ASCII) == -1) {
    2048           0 :                         tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
    2049           0 :                         return;
    2050             :                 }
    2051             :         } else {
    2052           0 :                 cli->dev = talloc_strdup(cli, "");
    2053           0 :                 if (cli->dev == NULL) {
    2054           0 :                         tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
    2055           0 :                         return;
    2056             :                 }
    2057             :         }
    2058             : 
    2059        7267 :         if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
    2060             :                 /* almost certainly win95 - enable bug fixes */
    2061           0 :                 cli->win95 = True;
    2062             :         }
    2063             : 
    2064             :         /*
    2065             :          * Make sure that we have the optional support 16-bit field. WCT > 2.
    2066             :          * Avoids issues when connecting to Win9x boxes sharing files
    2067             :          */
    2068             : 
    2069        7267 :         if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
    2070        7243 :                 optional_support = SVAL(vwv+2, 0);
    2071             :         }
    2072             : 
    2073        7267 :         if (optional_support & SMB_EXTENDED_SIGNATURES) {
    2074        3708 :                 smb1cli_session_protect_session_key(cli->smb1.session);
    2075             :         }
    2076             : 
    2077        7267 :         smb1cli_tcon_set_values(state->cli->smb1.tcon,
    2078        7267 :                                 SVAL(inhdr, HDR_TID),
    2079             :                                 optional_support,
    2080             :                                 0, /* maximal_access */
    2081             :                                 0, /* guest_maximal_access */
    2082             :                                 NULL, /* service */
    2083             :                                 NULL); /* fs_type */
    2084             : 
    2085        7267 :         tevent_req_done(req);
    2086             : }
    2087             : 
    2088        7303 : NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
    2089             : {
    2090        7303 :         return tevent_req_simple_recv_ntstatus(req);
    2091             : }
    2092             : 
    2093           0 : NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
    2094             :                        const char *dev, const char *pass, int passlen)
    2095             : {
    2096           0 :         TALLOC_CTX *frame = talloc_stackframe();
    2097           0 :         struct tevent_context *ev;
    2098           0 :         struct tevent_req *req;
    2099           0 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    2100             : 
    2101           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    2102             :                 /*
    2103             :                  * Can't use sync call while an async call is in flight
    2104             :                  */
    2105           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    2106           0 :                 goto fail;
    2107             :         }
    2108             : 
    2109           0 :         ev = samba_tevent_context_init(frame);
    2110           0 :         if (ev == NULL) {
    2111           0 :                 goto fail;
    2112             :         }
    2113             : 
    2114           0 :         req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
    2115           0 :         if (req == NULL) {
    2116           0 :                 goto fail;
    2117             :         }
    2118             : 
    2119           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    2120           0 :                 goto fail;
    2121             :         }
    2122             : 
    2123           0 :         status = cli_tcon_andx_recv(req);
    2124           0 :  fail:
    2125           0 :         TALLOC_FREE(frame);
    2126           0 :         return status;
    2127             : }
    2128             : 
    2129             : struct cli_tree_connect_state {
    2130             :         struct cli_state *cli;
    2131             : };
    2132             : 
    2133             : static struct tevent_req *cli_raw_tcon_send(
    2134             :         TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
    2135             :         const char *service, const char *pass, const char *dev);
    2136             : static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
    2137             :                                   uint16_t *max_xmit, uint16_t *tid);
    2138             : 
    2139             : static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
    2140             : static void cli_tree_connect_andx_done(struct tevent_req *subreq);
    2141             : static void cli_tree_connect_raw_done(struct tevent_req *subreq);
    2142             : 
    2143       38069 : static struct tevent_req *cli_tree_connect_send(
    2144             :         TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
    2145             :         const char *share, const char *dev, const char *pass)
    2146             : {
    2147           0 :         struct tevent_req *req, *subreq;
    2148           0 :         struct cli_tree_connect_state *state;
    2149           0 :         int passlen;
    2150             : 
    2151       38069 :         if (pass == NULL) {
    2152       32483 :                 pass = "";
    2153             :         }
    2154       38069 :         passlen = strlen(pass) + 1;
    2155             : 
    2156       38069 :         req = tevent_req_create(mem_ctx, &state,
    2157             :                                 struct cli_tree_connect_state);
    2158       38069 :         if (req == NULL) {
    2159           0 :                 return NULL;
    2160             :         }
    2161       38069 :         state->cli = cli;
    2162             : 
    2163       38069 :         cli->share = talloc_strdup(cli, share);
    2164       38069 :         if (tevent_req_nomem(cli->share, req)) {
    2165           0 :                 return tevent_req_post(req, ev);
    2166             :         }
    2167             : 
    2168       38069 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
    2169           0 :                 char *unc;
    2170             : 
    2171       30771 :                 TALLOC_FREE(cli->smb2.tcon);
    2172       30771 :                 cli->smb2.tcon = smbXcli_tcon_create(cli);
    2173       30771 :                 if (tevent_req_nomem(cli->smb2.tcon, req)) {
    2174           0 :                         return tevent_req_post(req, ev);
    2175             :                 }
    2176             : 
    2177       30771 :                 unc = talloc_asprintf(state, "\\\\%s\\%s",
    2178             :                                       smbXcli_conn_remote_name(cli->conn),
    2179             :                                       share);
    2180       30771 :                 if (tevent_req_nomem(unc, req)) {
    2181           0 :                         return tevent_req_post(req, ev);
    2182             :                 }
    2183             : 
    2184       30771 :                 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
    2185             :                                            cli->smb2.session, cli->smb2.tcon,
    2186             :                                            0, /* flags */
    2187             :                                            unc);
    2188       30771 :                 if (tevent_req_nomem(subreq, req)) {
    2189           0 :                         return tevent_req_post(req, ev);
    2190             :                 }
    2191       30771 :                 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
    2192             :                                         req);
    2193       30771 :                 return req;
    2194             :         }
    2195             : 
    2196        7298 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
    2197        7298 :                 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
    2198             :                                             pass, passlen);
    2199        7298 :                 if (tevent_req_nomem(subreq, req)) {
    2200           0 :                         return tevent_req_post(req, ev);
    2201             :                 }
    2202        7298 :                 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
    2203             :                                         req);
    2204        7298 :                 return req;
    2205             :         }
    2206             : 
    2207           0 :         subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
    2208           0 :         if (tevent_req_nomem(subreq, req)) {
    2209           0 :                 return tevent_req_post(req, ev);
    2210             :         }
    2211           0 :         tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
    2212             : 
    2213           0 :         return req;
    2214             : }
    2215             : 
    2216       30771 : static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
    2217             : {
    2218       30771 :         NTSTATUS status = smb2cli_tcon_recv(subreq);
    2219       30771 :         tevent_req_simple_finish_ntstatus(subreq, status);
    2220       30771 : }
    2221             : 
    2222        7298 : static void cli_tree_connect_andx_done(struct tevent_req *subreq)
    2223             : {
    2224        7298 :         NTSTATUS status = cli_tcon_andx_recv(subreq);
    2225        7298 :         tevent_req_simple_finish_ntstatus(subreq, status);
    2226        7298 : }
    2227             : 
    2228           0 : static void cli_tree_connect_raw_done(struct tevent_req *subreq)
    2229             : {
    2230           0 :         struct tevent_req *req = tevent_req_callback_data(
    2231             :                 subreq, struct tevent_req);
    2232           0 :         struct cli_tree_connect_state *state = tevent_req_data(
    2233             :                 req, struct cli_tree_connect_state);
    2234           0 :         NTSTATUS status;
    2235           0 :         uint16_t max_xmit = 0;
    2236           0 :         uint16_t tid = 0;
    2237             : 
    2238           0 :         status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
    2239           0 :         if (tevent_req_nterror(req, status)) {
    2240           0 :                 return;
    2241             :         }
    2242             : 
    2243           0 :         smb1cli_tcon_set_values(state->cli->smb1.tcon,
    2244             :                                 tid,
    2245             :                                 0, /* optional_support */
    2246             :                                 0, /* maximal_access */
    2247             :                                 0, /* guest_maximal_access */
    2248             :                                 NULL, /* service */
    2249             :                                 NULL); /* fs_type */
    2250             : 
    2251           0 :         tevent_req_done(req);
    2252             : }
    2253             : 
    2254       38069 : static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
    2255             : {
    2256       38069 :         return tevent_req_simple_recv_ntstatus(req);
    2257             : }
    2258             : 
    2259       32362 : NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
    2260             :                           const char *dev, const char *pass)
    2261             : {
    2262           0 :         struct tevent_context *ev;
    2263           0 :         struct tevent_req *req;
    2264       32362 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    2265             : 
    2266       32362 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    2267           0 :                 return NT_STATUS_INVALID_PARAMETER;
    2268             :         }
    2269       32362 :         ev = samba_tevent_context_init(talloc_tos());
    2270       32362 :         if (ev == NULL) {
    2271           0 :                 goto fail;
    2272             :         }
    2273       32362 :         req = cli_tree_connect_send(ev, ev, cli, share, dev, pass);
    2274       32362 :         if (req == NULL) {
    2275           0 :                 goto fail;
    2276             :         }
    2277       32362 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    2278           0 :                 goto fail;
    2279             :         }
    2280       32362 :         status = cli_tree_connect_recv(req);
    2281       32362 : fail:
    2282       32362 :         TALLOC_FREE(ev);
    2283       32362 :         return status;
    2284             : }
    2285             : 
    2286       12022 : NTSTATUS cli_tree_connect_creds(struct cli_state *cli,
    2287             :                                 const char *share, const char *dev,
    2288             :                                 struct cli_credentials *creds)
    2289             : {
    2290       12022 :         bool need_pass = false;
    2291       12022 :         const char *pw = NULL;
    2292             : 
    2293             :         /*
    2294             :          * We should work out if the protocol
    2295             :          * will make use of a password for share level
    2296             :          * authentication before we may cause
    2297             :          * the password prompt to be called.
    2298             :          */
    2299       12022 :         if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
    2300        3445 :                 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
    2301             : 
    2302             :                 /* in user level security don't send a password now */
    2303        3445 :                 if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
    2304           0 :                         need_pass = true;
    2305             :                 }
    2306             :         }
    2307             : 
    2308       12022 :         if (need_pass && creds != NULL) {
    2309           0 :                 pw = cli_credentials_get_password(creds);
    2310             :         }
    2311             : 
    2312       12022 :         return cli_tree_connect(cli, share, dev, pw);
    2313             : }
    2314             : 
    2315             : /****************************************************************************
    2316             :  Send a tree disconnect.
    2317             : ****************************************************************************/
    2318             : 
    2319             : struct cli_tdis_state {
    2320             :         struct cli_state *cli;
    2321             : };
    2322             : 
    2323             : static void cli_tdis_done(struct tevent_req *subreq);
    2324             : 
    2325        7003 : static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
    2326             :                                  struct tevent_context *ev,
    2327             :                                  struct cli_state *cli)
    2328             : {
    2329           0 :         struct tevent_req *req, *subreq;
    2330           0 :         struct cli_tdis_state *state;
    2331             : 
    2332        7003 :         req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
    2333        7003 :         if (req == NULL) {
    2334           0 :                 return NULL;
    2335             :         }
    2336        7003 :         state->cli = cli;
    2337             : 
    2338        7003 :         subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
    2339        7003 :         if (tevent_req_nomem(subreq, req)) {
    2340           0 :                 return tevent_req_post(req, ev);
    2341             :         }
    2342        7003 :         tevent_req_set_callback(subreq, cli_tdis_done, req);
    2343        7003 :         return req;
    2344             : }
    2345             : 
    2346        7003 : static void cli_tdis_done(struct tevent_req *subreq)
    2347             : {
    2348        7003 :         struct tevent_req *req = tevent_req_callback_data(
    2349             :                 subreq, struct tevent_req);
    2350        7003 :         struct cli_tdis_state *state = tevent_req_data(
    2351             :                 req, struct cli_tdis_state);
    2352           0 :         NTSTATUS status;
    2353             : 
    2354        7003 :         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    2355        7003 :         TALLOC_FREE(subreq);
    2356        7003 :         if (tevent_req_nterror(req, status)) {
    2357          18 :                 return;
    2358             :         }
    2359        6985 :         TALLOC_FREE(state->cli->smb1.tcon);
    2360        6985 :         tevent_req_done(req);
    2361             : }
    2362             : 
    2363        7003 : static NTSTATUS cli_tdis_recv(struct tevent_req *req)
    2364             : {
    2365        7003 :         return tevent_req_simple_recv_ntstatus(req);
    2366             : }
    2367             : 
    2368       34303 : NTSTATUS cli_tdis(struct cli_state *cli)
    2369             : {
    2370           0 :         struct tevent_context *ev;
    2371           0 :         struct tevent_req *req;
    2372       34303 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    2373             : 
    2374       34303 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
    2375       27302 :                 status = smb2cli_tdis(cli->conn,
    2376       27302 :                                     cli->timeout,
    2377             :                                     cli->smb2.session,
    2378             :                                     cli->smb2.tcon);
    2379       27302 :                 if (NT_STATUS_IS_OK(status)) {
    2380       27201 :                         TALLOC_FREE(cli->smb2.tcon);
    2381             :                 }
    2382       27302 :                 return status;
    2383             :         }
    2384             : 
    2385        7001 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    2386           0 :                 return NT_STATUS_INVALID_PARAMETER;
    2387             :         }
    2388        7001 :         ev = samba_tevent_context_init(talloc_tos());
    2389        7001 :         if (ev == NULL) {
    2390           0 :                 goto fail;
    2391             :         }
    2392        7001 :         req = cli_tdis_send(ev, ev, cli);
    2393        7001 :         if (req == NULL) {
    2394           0 :                 goto fail;
    2395             :         }
    2396        7001 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    2397           0 :                 goto fail;
    2398             :         }
    2399        7001 :         status = cli_tdis_recv(req);
    2400        7001 : fail:
    2401        7001 :         TALLOC_FREE(ev);
    2402        7001 :         return status;
    2403             : }
    2404             : 
    2405             : struct cli_connect_sock_state {
    2406             :         const char **called_names;
    2407             :         const char **calling_names;
    2408             :         int *called_types;
    2409             :         int fd;
    2410             :         uint16_t port;
    2411             : };
    2412             : 
    2413             : static void cli_connect_sock_done(struct tevent_req *subreq);
    2414             : 
    2415             : /*
    2416             :  * Async only if we don't have to look up the name, i.e. "pss" is set with a
    2417             :  * nonzero address.
    2418             :  */
    2419             : 
    2420       18455 : static struct tevent_req *cli_connect_sock_send(
    2421             :         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
    2422             :         const char *host, int name_type, const struct sockaddr_storage *pss,
    2423             :         const char *myname, uint16_t port)
    2424             : {
    2425           0 :         struct tevent_req *req, *subreq;
    2426           0 :         struct cli_connect_sock_state *state;
    2427       18455 :         struct sockaddr_storage *addrs = NULL;
    2428           0 :         unsigned i;
    2429       18455 :         unsigned num_addrs = 0;
    2430           0 :         NTSTATUS status;
    2431             : 
    2432       18455 :         req = tevent_req_create(mem_ctx, &state,
    2433             :                                 struct cli_connect_sock_state);
    2434       18455 :         if (req == NULL) {
    2435           0 :                 return NULL;
    2436             :         }
    2437             : 
    2438       18455 :         if ((pss == NULL) || is_zero_addr(pss)) {
    2439             : 
    2440             :                 /*
    2441             :                  * Here we cheat. resolve_name_list is not async at all. So
    2442             :                  * this call will only be really async if the name lookup has
    2443             :                  * been done externally.
    2444             :                  */
    2445             : 
    2446       10325 :                 status = resolve_name_list(state, host, name_type,
    2447             :                                            &addrs, &num_addrs);
    2448       10325 :                 if (tevent_req_nterror(req, status)) {
    2449           2 :                         return tevent_req_post(req, ev);
    2450             :                 }
    2451             :         } else {
    2452        8130 :                 addrs = talloc_array(state, struct sockaddr_storage, 1);
    2453        8130 :                 if (tevent_req_nomem(addrs, req)) {
    2454           0 :                         return tevent_req_post(req, ev);
    2455             :                 }
    2456        8130 :                 addrs[0] = *pss;
    2457        8130 :                 num_addrs = 1;
    2458             :         }
    2459             : 
    2460       18453 :         state->called_names = talloc_array(state, const char *, num_addrs);
    2461       18453 :         if (tevent_req_nomem(state->called_names, req)) {
    2462           0 :                 return tevent_req_post(req, ev);
    2463             :         }
    2464       18453 :         state->called_types = talloc_array(state, int, num_addrs);
    2465       18453 :         if (tevent_req_nomem(state->called_types, req)) {
    2466           0 :                 return tevent_req_post(req, ev);
    2467             :         }
    2468       18453 :         state->calling_names = talloc_array(state, const char *, num_addrs);
    2469       18453 :         if (tevent_req_nomem(state->calling_names, req)) {
    2470           0 :                 return tevent_req_post(req, ev);
    2471             :         }
    2472       45504 :         for (i=0; i<num_addrs; i++) {
    2473       27051 :                 state->called_names[i] = host;
    2474       27051 :                 state->called_types[i] = name_type;
    2475       27051 :                 state->calling_names[i] = myname;
    2476             :         }
    2477             : 
    2478       18453 :         subreq = smbsock_any_connect_send(
    2479       18453 :                 state, ev, addrs, state->called_names, state->called_types,
    2480       18453 :                 state->calling_names, NULL, num_addrs, port);
    2481       18453 :         if (tevent_req_nomem(subreq, req)) {
    2482           0 :                 return tevent_req_post(req, ev);
    2483             :         }
    2484       18453 :         tevent_req_set_callback(subreq, cli_connect_sock_done, req);
    2485       18453 :         return req;
    2486             : }
    2487             : 
    2488       18453 : static void cli_connect_sock_done(struct tevent_req *subreq)
    2489             : {
    2490       18453 :         struct tevent_req *req = tevent_req_callback_data(
    2491             :                 subreq, struct tevent_req);
    2492       18453 :         struct cli_connect_sock_state *state = tevent_req_data(
    2493             :                 req, struct cli_connect_sock_state);
    2494           0 :         NTSTATUS status;
    2495             : 
    2496       18453 :         status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
    2497             :                                           &state->port);
    2498       18453 :         TALLOC_FREE(subreq);
    2499       18453 :         if (tevent_req_nterror(req, status)) {
    2500           2 :                 return;
    2501             :         }
    2502       18451 :         set_socket_options(state->fd, lp_socket_options());
    2503       18451 :         tevent_req_done(req);
    2504             : }
    2505             : 
    2506       18455 : static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
    2507             :                                       int *pfd, uint16_t *pport)
    2508             : {
    2509       18455 :         struct cli_connect_sock_state *state = tevent_req_data(
    2510             :                 req, struct cli_connect_sock_state);
    2511           0 :         NTSTATUS status;
    2512             : 
    2513       18455 :         if (tevent_req_is_nterror(req, &status)) {
    2514           4 :                 return status;
    2515             :         }
    2516       18451 :         *pfd = state->fd;
    2517       18451 :         *pport = state->port;
    2518       18451 :         return NT_STATUS_OK;
    2519             : }
    2520             : 
    2521             : struct cli_connect_nb_state {
    2522             :         const char *desthost;
    2523             :         enum smb_signing_setting signing_state;
    2524             :         int flags;
    2525             :         struct cli_state *cli;
    2526             : };
    2527             : 
    2528             : static void cli_connect_nb_done(struct tevent_req *subreq);
    2529             : 
    2530       18455 : static struct tevent_req *cli_connect_nb_send(
    2531             :         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
    2532             :         const char *host, const struct sockaddr_storage *dest_ss,
    2533             :         uint16_t port, int name_type, const char *myname,
    2534             :         enum smb_signing_setting signing_state, int flags)
    2535             : {
    2536           0 :         struct tevent_req *req, *subreq;
    2537           0 :         struct cli_connect_nb_state *state;
    2538             : 
    2539       18455 :         req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
    2540       18455 :         if (req == NULL) {
    2541           0 :                 return NULL;
    2542             :         }
    2543       18455 :         state->signing_state = signing_state;
    2544       18455 :         state->flags = flags;
    2545             : 
    2546       18455 :         if (host != NULL) {
    2547       18455 :                 char *p = strchr(host, '#');
    2548             : 
    2549       18455 :                 if (p != NULL) {
    2550           0 :                         name_type = strtol(p+1, NULL, 16);
    2551           0 :                         host = talloc_strndup(state, host, p - host);
    2552           0 :                         if (tevent_req_nomem(host, req)) {
    2553           0 :                                 return tevent_req_post(req, ev);
    2554             :                         }
    2555             :                 }
    2556             : 
    2557       18455 :                 state->desthost = host;
    2558           0 :         } else if (dest_ss != NULL) {
    2559           0 :                 state->desthost = print_canonical_sockaddr(state, dest_ss);
    2560           0 :                 if (tevent_req_nomem(state->desthost, req)) {
    2561           0 :                         return tevent_req_post(req, ev);
    2562             :                 }
    2563             :         } else {
    2564             :                 /* No host or dest_ss given. Error out. */
    2565           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
    2566           0 :                 return tevent_req_post(req, ev);
    2567             :         }
    2568             : 
    2569       18455 :         subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
    2570             :                                        myname, port);
    2571       18455 :         if (tevent_req_nomem(subreq, req)) {
    2572           0 :                 return tevent_req_post(req, ev);
    2573             :         }
    2574       18455 :         tevent_req_set_callback(subreq, cli_connect_nb_done, req);
    2575       18455 :         return req;
    2576             : }
    2577             : 
    2578       18455 : static void cli_connect_nb_done(struct tevent_req *subreq)
    2579             : {
    2580       18455 :         struct tevent_req *req = tevent_req_callback_data(
    2581             :                 subreq, struct tevent_req);
    2582       18455 :         struct cli_connect_nb_state *state = tevent_req_data(
    2583             :                 req, struct cli_connect_nb_state);
    2584           0 :         NTSTATUS status;
    2585       18455 :         int fd = 0;
    2586           0 :         uint16_t port;
    2587             : 
    2588       18455 :         status = cli_connect_sock_recv(subreq, &fd, &port);
    2589       18455 :         TALLOC_FREE(subreq);
    2590       18455 :         if (tevent_req_nterror(req, status)) {
    2591           4 :                 return;
    2592             :         }
    2593             : 
    2594       18451 :         state->cli = cli_state_create(state, fd, state->desthost,
    2595             :                                       state->signing_state, state->flags);
    2596       18451 :         if (tevent_req_nomem(state->cli, req)) {
    2597           0 :                 close(fd);
    2598           0 :                 return;
    2599             :         }
    2600       18451 :         tevent_req_done(req);
    2601             : }
    2602             : 
    2603       18455 : static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
    2604             :                                     TALLOC_CTX *mem_ctx,
    2605             :                                     struct cli_state **pcli)
    2606             : {
    2607       18455 :         struct cli_connect_nb_state *state = tevent_req_data(
    2608             :                 req, struct cli_connect_nb_state);
    2609           0 :         NTSTATUS status;
    2610             : 
    2611       18455 :         if (tevent_req_is_nterror(req, &status)) {
    2612           4 :                 return status;
    2613             :         }
    2614       18451 :         *pcli = talloc_move(mem_ctx, &state->cli);
    2615       18451 :         return NT_STATUS_OK;
    2616             : }
    2617             : 
    2618       12635 : NTSTATUS cli_connect_nb(TALLOC_CTX *mem_ctx,
    2619             :                         const char *host,
    2620             :                         const struct sockaddr_storage *dest_ss,
    2621             :                         uint16_t port,
    2622             :                         int name_type,
    2623             :                         const char *myname,
    2624             :                         enum smb_signing_setting signing_state,
    2625             :                         int flags,
    2626             :                         struct cli_state **pcli)
    2627             : {
    2628           0 :         struct tevent_context *ev;
    2629           0 :         struct tevent_req *req;
    2630       12635 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    2631             : 
    2632       12635 :         ev = samba_tevent_context_init(mem_ctx);
    2633       12635 :         if (ev == NULL) {
    2634           0 :                 goto fail;
    2635             :         }
    2636       12635 :         req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
    2637             :                                   myname, signing_state, flags);
    2638       12635 :         if (req == NULL) {
    2639           0 :                 goto fail;
    2640             :         }
    2641       12635 :         if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
    2642           0 :                 goto fail;
    2643             :         }
    2644       12635 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    2645           0 :                 goto fail;
    2646             :         }
    2647       12635 :         status = cli_connect_nb_recv(req, mem_ctx, pcli);
    2648       12635 : fail:
    2649       12635 :         TALLOC_FREE(ev);
    2650       12635 :         return status;
    2651             : }
    2652             : 
    2653             : struct cli_start_connection_state {
    2654             :         struct tevent_context *ev;
    2655             :         struct cli_state *cli;
    2656             :         int min_protocol;
    2657             :         int max_protocol;
    2658             :         struct smb2_negotiate_contexts *negotiate_contexts;
    2659             : };
    2660             : 
    2661             : static void cli_start_connection_connected(struct tevent_req *subreq);
    2662             : static void cli_start_connection_done(struct tevent_req *subreq);
    2663             : 
    2664             : /**
    2665             :    establishes a connection to after the negprot.
    2666             :    @param output_cli A fully initialised cli structure, non-null only on success
    2667             :    @param dest_host The netbios name of the remote host
    2668             :    @param dest_ss (optional) The destination IP, NULL for name based lookup
    2669             :    @param port (optional) The destination port (0 for default)
    2670             : */
    2671             : 
    2672        5820 : static struct tevent_req *cli_start_connection_send(
    2673             :         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
    2674             :         const char *my_name, const char *dest_host,
    2675             :         const struct sockaddr_storage *dest_ss, int port,
    2676             :         enum smb_signing_setting signing_state, int flags,
    2677             :         struct smb2_negotiate_contexts *negotiate_contexts)
    2678             : {
    2679           0 :         struct tevent_req *req, *subreq;
    2680           0 :         struct cli_start_connection_state *state;
    2681             : 
    2682        5820 :         req = tevent_req_create(mem_ctx, &state,
    2683             :                                 struct cli_start_connection_state);
    2684        5820 :         if (req == NULL) {
    2685           0 :                 return NULL;
    2686             :         }
    2687        5820 :         state->ev = ev;
    2688             : 
    2689        5820 :         if (flags & CLI_FULL_CONNECTION_IPC) {
    2690        1584 :                 state->min_protocol = lp_client_ipc_min_protocol();
    2691        1584 :                 state->max_protocol = lp_client_ipc_max_protocol();
    2692             :         } else {
    2693        4236 :                 state->min_protocol = lp_client_min_protocol();
    2694        4236 :                 state->max_protocol = lp_client_max_protocol();
    2695             :         }
    2696             : 
    2697        5820 :         if (flags & CLI_FULL_CONNECTION_FORCE_SMB1) {
    2698         540 :                 state->max_protocol = MIN(state->max_protocol,
    2699             :                                           PROTOCOL_NT1);
    2700         540 :                 state->min_protocol = MIN(state->min_protocol,
    2701             :                                           state->max_protocol);
    2702             :         }
    2703             : 
    2704        5820 :         if (flags & CLI_FULL_CONNECTION_DISABLE_SMB1) {
    2705           4 :                 state->min_protocol = MAX(state->min_protocol,
    2706             :                                           PROTOCOL_SMB2_02);
    2707           4 :                 state->max_protocol = MAX(state->max_protocol,
    2708             :                                           state->min_protocol);
    2709             :         }
    2710             : 
    2711        5820 :         state->negotiate_contexts = talloc_zero(
    2712             :                 state, struct smb2_negotiate_contexts);
    2713        5820 :         if (tevent_req_nomem(state->negotiate_contexts, req)) {
    2714           0 :                 return tevent_req_post(req, ev);
    2715             :         }
    2716             : 
    2717        5820 :         if (flags & CLI_FULL_CONNECTION_REQUEST_POSIX) {
    2718           0 :                 NTSTATUS status;
    2719             : 
    2720          24 :                 status = smb2_negotiate_context_add(
    2721          24 :                         state->negotiate_contexts,
    2722          24 :                         state->negotiate_contexts,
    2723             :                         SMB2_POSIX_EXTENSIONS_AVAILABLE,
    2724             :                         (const uint8_t *)SMB2_CREATE_TAG_POSIX,
    2725             :                         strlen(SMB2_CREATE_TAG_POSIX));
    2726          24 :                 if (tevent_req_nterror(req, status)) {
    2727           0 :                         return tevent_req_post(req, ev);
    2728             :                 }
    2729             :         }
    2730             : 
    2731        5820 :         if (negotiate_contexts != NULL) {
    2732             :                 uint16_t i;
    2733             : 
    2734           8 :                 for (i=0; i<negotiate_contexts->num_contexts; i++) {
    2735           4 :                         struct smb2_negotiate_context *ctx =
    2736           4 :                                 &negotiate_contexts->contexts[i];
    2737           0 :                         NTSTATUS status;
    2738             : 
    2739           4 :                         status = smb2_negotiate_context_add(
    2740           4 :                                 state->negotiate_contexts,
    2741           4 :                                 state->negotiate_contexts,
    2742           4 :                                 ctx->type,
    2743           4 :                                 ctx->data.data,
    2744             :                                 ctx->data.length);
    2745           4 :                         if (tevent_req_nterror(req, status)) {
    2746           0 :                                 return tevent_req_post(req, ev);
    2747             :                         }
    2748             :                 }
    2749             :         }
    2750             : 
    2751        5820 :         subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
    2752             :                                      0x20, my_name, signing_state, flags);
    2753        5820 :         if (tevent_req_nomem(subreq, req)) {
    2754           0 :                 return tevent_req_post(req, ev);
    2755             :         }
    2756        5820 :         tevent_req_set_callback(subreq, cli_start_connection_connected, req);
    2757        5820 :         return req;
    2758             : }
    2759             : 
    2760        5820 : static void cli_start_connection_connected(struct tevent_req *subreq)
    2761             : {
    2762        5820 :         struct tevent_req *req = tevent_req_callback_data(
    2763             :                 subreq, struct tevent_req);
    2764        5820 :         struct cli_start_connection_state *state = tevent_req_data(
    2765             :                 req, struct cli_start_connection_state);
    2766           0 :         NTSTATUS status;
    2767             : 
    2768        5820 :         status = cli_connect_nb_recv(subreq, state, &state->cli);
    2769        5820 :         TALLOC_FREE(subreq);
    2770        5820 :         if (tevent_req_nterror(req, status)) {
    2771           4 :                 return;
    2772             :         }
    2773             : 
    2774        5816 :         subreq = smbXcli_negprot_send(
    2775             :                 state,
    2776             :                 state->ev,
    2777        5816 :                 state->cli->conn,
    2778        5816 :                 state->cli->timeout,
    2779        5816 :                 state->min_protocol,
    2780        5816 :                 state->max_protocol,
    2781             :                 WINDOWS_CLIENT_PURE_SMB2_NEGPROT_INITIAL_CREDIT_ASK,
    2782             :                 state->negotiate_contexts);
    2783        5816 :         if (tevent_req_nomem(subreq, req)) {
    2784           0 :                 return;
    2785             :         }
    2786        5816 :         tevent_req_set_callback(subreq, cli_start_connection_done, req);
    2787             : }
    2788             : 
    2789        5816 : static void cli_start_connection_done(struct tevent_req *subreq)
    2790             : {
    2791        5816 :         struct tevent_req *req = tevent_req_callback_data(
    2792             :                 subreq, struct tevent_req);
    2793        5816 :         struct cli_start_connection_state *state = tevent_req_data(
    2794             :                 req, struct cli_start_connection_state);
    2795           0 :         NTSTATUS status;
    2796             : 
    2797        5816 :         status = smbXcli_negprot_recv(subreq, NULL, NULL);
    2798        5816 :         TALLOC_FREE(subreq);
    2799        5816 :         if (tevent_req_nterror(req, status)) {
    2800          26 :                 return;
    2801             :         }
    2802             : 
    2803        5790 :         if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
    2804             :                 /* Ensure we ask for some initial credits. */
    2805        5180 :                 smb2cli_conn_set_max_credits(state->cli->conn,
    2806             :                                              DEFAULT_SMB2_MAX_CREDITS);
    2807             :         }
    2808             : 
    2809        5790 :         tevent_req_done(req);
    2810             : }
    2811             : 
    2812        5820 : static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
    2813             :                                           TALLOC_CTX *mem_ctx,
    2814             :                                           struct cli_state **output_cli)
    2815             : {
    2816        5820 :         struct cli_start_connection_state *state = tevent_req_data(
    2817             :                 req, struct cli_start_connection_state);
    2818           0 :         NTSTATUS status;
    2819             : 
    2820        5820 :         if (tevent_req_is_nterror(req, &status)) {
    2821          30 :                 return status;
    2822             :         }
    2823        5790 :         *output_cli = talloc_move(mem_ctx, &state->cli);
    2824             : 
    2825        5790 :         return NT_STATUS_OK;
    2826             : }
    2827             : 
    2828          21 : NTSTATUS cli_start_connection(TALLOC_CTX *mem_ctx,
    2829             :                               struct cli_state **output_cli,
    2830             :                               const char *my_name,
    2831             :                               const char *dest_host,
    2832             :                               const struct sockaddr_storage *dest_ss, int port,
    2833             :                               enum smb_signing_setting signing_state, int flags)
    2834             : {
    2835           0 :         struct tevent_context *ev;
    2836           0 :         struct tevent_req *req;
    2837          21 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    2838             : 
    2839          21 :         ev = samba_tevent_context_init(mem_ctx);
    2840          21 :         if (ev == NULL) {
    2841           0 :                 goto fail;
    2842             :         }
    2843          21 :         req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
    2844             :                                         port, signing_state, flags, NULL);
    2845          21 :         if (req == NULL) {
    2846           0 :                 goto fail;
    2847             :         }
    2848          21 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    2849           0 :                 goto fail;
    2850             :         }
    2851          21 :         status = cli_start_connection_recv(req, mem_ctx, output_cli);
    2852          21 : fail:
    2853          21 :         TALLOC_FREE(ev);
    2854          21 :         return status;
    2855             : }
    2856             : 
    2857             : struct cli_smb1_setup_encryption_blob_state {
    2858             :         uint16_t setup[1];
    2859             :         uint8_t param[4];
    2860             :         NTSTATUS status;
    2861             :         DATA_BLOB out;
    2862             :         uint16_t enc_ctx_id;
    2863             : };
    2864             : 
    2865             : static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq);
    2866             : 
    2867         884 : static struct tevent_req *cli_smb1_setup_encryption_blob_send(TALLOC_CTX *mem_ctx,
    2868             :                                                         struct tevent_context *ev,
    2869             :                                                         struct cli_state *cli,
    2870             :                                                         const DATA_BLOB in)
    2871             : {
    2872         884 :         struct tevent_req *req = NULL;
    2873         884 :         struct cli_smb1_setup_encryption_blob_state *state = NULL;
    2874         884 :         struct tevent_req *subreq = NULL;
    2875             : 
    2876         884 :         req = tevent_req_create(mem_ctx, &state,
    2877             :                                 struct cli_smb1_setup_encryption_blob_state);
    2878         884 :         if (req == NULL) {
    2879           0 :                 return NULL;
    2880             :         }
    2881             : 
    2882         884 :         if (in.length > CLI_BUFFER_SIZE) {
    2883           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
    2884           0 :                 return tevent_req_post(req, ev);
    2885             :         }
    2886             : 
    2887         884 :         SSVAL(state->setup+0,  0, TRANSACT2_SETFSINFO);
    2888         884 :         SSVAL(state->param, 0, 0);
    2889         884 :         SSVAL(state->param, 2, SMB_REQUEST_TRANSPORT_ENCRYPTION);
    2890             : 
    2891         884 :         subreq = smb1cli_trans_send(state, ev, cli->conn,
    2892             :                                     SMBtrans2,
    2893             :                                     0, 0, /* _flags */
    2894             :                                     0, 0, /* _flags2 */
    2895         884 :                                     cli->timeout,
    2896             :                                     cli->smb1.pid,
    2897             :                                     cli->smb1.tcon,
    2898             :                                     cli->smb1.session,
    2899             :                                     NULL, /* pipe_name */
    2900             :                                     0, /* fid */
    2901             :                                     0, /* function */
    2902             :                                     0, /* flags */
    2903         884 :                                     state->setup, 1, 0,
    2904         884 :                                     state->param, 4, 2,
    2905         884 :                                     in.data, in.length, CLI_BUFFER_SIZE);
    2906         884 :         if (tevent_req_nomem(subreq, req)) {
    2907           0 :                 return tevent_req_post(req, ev);
    2908             :         }
    2909         884 :         tevent_req_set_callback(subreq,
    2910             :                                 cli_smb1_setup_encryption_blob_done,
    2911             :                                 req);
    2912             : 
    2913         884 :         return req;
    2914             : }
    2915             : 
    2916         884 : static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq)
    2917             : {
    2918           0 :         struct tevent_req *req =
    2919         884 :                 tevent_req_callback_data(subreq,
    2920             :                                 struct tevent_req);
    2921           0 :         struct cli_smb1_setup_encryption_blob_state *state =
    2922         884 :                 tevent_req_data(req,
    2923             :                 struct cli_smb1_setup_encryption_blob_state);
    2924         884 :         uint8_t *rparam=NULL, *rdata=NULL;
    2925           0 :         uint32_t num_rparam, num_rdata;
    2926           0 :         NTSTATUS status;
    2927             : 
    2928         884 :         status = smb1cli_trans_recv(subreq, state,
    2929             :                                     NULL, /* recv_flags */
    2930             :                                     NULL, 0, NULL, /* rsetup */
    2931             :                                     &rparam, 0, &num_rparam,
    2932             :                                     &rdata, 0, &num_rdata);
    2933         884 :         TALLOC_FREE(subreq);
    2934         884 :         state->status = status;
    2935         884 :         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    2936           0 :                 status = NT_STATUS_OK;
    2937             :         }
    2938         884 :         if (tevent_req_nterror(req, status)) {
    2939           0 :                 return;
    2940             :         }
    2941             : 
    2942         884 :         if (num_rparam == 2) {
    2943         442 :                 state->enc_ctx_id = SVAL(rparam, 0);
    2944             :         }
    2945         884 :         TALLOC_FREE(rparam);
    2946             : 
    2947         884 :         state->out = data_blob_const(rdata, num_rdata);
    2948             : 
    2949         884 :         tevent_req_done(req);
    2950             : }
    2951             : 
    2952         884 : static NTSTATUS cli_smb1_setup_encryption_blob_recv(struct tevent_req *req,
    2953             :                                                     TALLOC_CTX *mem_ctx,
    2954             :                                                     DATA_BLOB *out,
    2955             :                                                     uint16_t *enc_ctx_id)
    2956             : {
    2957           0 :         struct cli_smb1_setup_encryption_blob_state *state =
    2958         884 :                 tevent_req_data(req,
    2959             :                 struct cli_smb1_setup_encryption_blob_state);
    2960           0 :         NTSTATUS status;
    2961             : 
    2962         884 :         if (tevent_req_is_nterror(req, &status)) {
    2963           0 :                 tevent_req_received(req);
    2964           0 :                 return status;
    2965             :         }
    2966             : 
    2967         884 :         status = state->status;
    2968             : 
    2969         884 :         *out = state->out;
    2970         884 :         talloc_steal(mem_ctx, out->data);
    2971             : 
    2972         884 :         *enc_ctx_id = state->enc_ctx_id;
    2973             : 
    2974         884 :         tevent_req_received(req);
    2975         884 :         return status;
    2976             : }
    2977             : 
    2978             : struct cli_smb1_setup_encryption_state {
    2979             :         struct tevent_context *ev;
    2980             :         struct cli_state *cli;
    2981             :         struct smb_trans_enc_state *es;
    2982             :         DATA_BLOB blob_in;
    2983             :         DATA_BLOB blob_out;
    2984             :         bool local_ready;
    2985             :         bool remote_ready;
    2986             : };
    2987             : 
    2988             : static void cli_smb1_setup_encryption_local_next(struct tevent_req *req);
    2989             : static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq);
    2990             : static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req);
    2991             : static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq);
    2992             : static void cli_smb1_setup_encryption_ready(struct tevent_req *req);
    2993             : 
    2994         442 : static struct tevent_req *cli_smb1_setup_encryption_send(TALLOC_CTX *mem_ctx,
    2995             :                                                 struct tevent_context *ev,
    2996             :                                                 struct cli_state *cli,
    2997             :                                                 struct cli_credentials *creds)
    2998             : {
    2999         442 :         struct tevent_req *req = NULL;
    3000         442 :         struct cli_smb1_setup_encryption_state *state = NULL;
    3001         442 :         struct auth_generic_state *ags = NULL;
    3002         442 :         const DATA_BLOB *b = NULL;
    3003         442 :         bool auth_requested = false;
    3004         442 :         const char *target_service = NULL;
    3005         442 :         const char *target_hostname = NULL;
    3006           0 :         NTSTATUS status;
    3007             : 
    3008         442 :         req = tevent_req_create(mem_ctx, &state,
    3009             :                                 struct cli_smb1_setup_encryption_state);
    3010         442 :         if (req == NULL) {
    3011           0 :                 return NULL;
    3012             :         }
    3013         442 :         state->ev = ev;
    3014         442 :         state->cli = cli;
    3015             : 
    3016         442 :         auth_requested = cli_credentials_authentication_requested(creds);
    3017         442 :         if (!auth_requested) {
    3018           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
    3019           0 :                 return tevent_req_post(req, ev);
    3020             :         }
    3021             : 
    3022         442 :         target_service = "cifs";
    3023         442 :         target_hostname = smbXcli_conn_remote_name(cli->conn);
    3024             : 
    3025         442 :         state->es = talloc_zero(state, struct smb_trans_enc_state);
    3026         442 :         if (tevent_req_nomem(state->es, req)) {
    3027           0 :                 return tevent_req_post(req, ev);
    3028             :         }
    3029             : 
    3030         442 :         status = auth_generic_client_prepare(state->es, &ags);
    3031         442 :         if (tevent_req_nterror(req, status)) {
    3032           0 :                 return tevent_req_post(req, ev);
    3033             :         }
    3034             : 
    3035         442 :         gensec_want_feature(ags->gensec_security,
    3036             :                             GENSEC_FEATURE_SIGN);
    3037         442 :         gensec_want_feature(ags->gensec_security,
    3038             :                             GENSEC_FEATURE_SEAL);
    3039             : 
    3040         442 :         status = auth_generic_set_creds(ags, creds);
    3041         442 :         if (tevent_req_nterror(req, status)) {
    3042           0 :                 return tevent_req_post(req, ev);
    3043             :         }
    3044             : 
    3045         442 :         if (target_service != NULL) {
    3046         442 :                 status = gensec_set_target_service(ags->gensec_security,
    3047             :                                                    target_service);
    3048         442 :                 if (tevent_req_nterror(req, status)) {
    3049           0 :                         return tevent_req_post(req, ev);
    3050             :                 }
    3051             :         }
    3052             : 
    3053         442 :         if (target_hostname != NULL) {
    3054         442 :                 status = gensec_set_target_hostname(ags->gensec_security,
    3055             :                                                     target_hostname);
    3056         442 :                 if (tevent_req_nterror(req, status)) {
    3057           0 :                         return tevent_req_post(req, ev);
    3058             :                 }
    3059             :         }
    3060             : 
    3061         442 :         gensec_set_max_update_size(ags->gensec_security,
    3062             :                                    CLI_BUFFER_SIZE);
    3063             : 
    3064         442 :         b = smbXcli_conn_server_gss_blob(state->cli->conn);
    3065         442 :         if (b != NULL) {
    3066         442 :                 state->blob_in = *b;
    3067             :         }
    3068             : 
    3069         442 :         status = auth_generic_client_start(ags, GENSEC_OID_SPNEGO);
    3070         442 :         if (tevent_req_nterror(req, status)) {
    3071           0 :                 return tevent_req_post(req, ev);
    3072             :         }
    3073             : 
    3074             :         /*
    3075             :          * We only need the gensec_security part from here.
    3076             :          */
    3077         442 :         state->es->gensec_security = talloc_move(state->es,
    3078             :                                                  &ags->gensec_security);
    3079         442 :         TALLOC_FREE(ags);
    3080             : 
    3081         442 :         cli_smb1_setup_encryption_local_next(req);
    3082         442 :         if (!tevent_req_is_in_progress(req)) {
    3083           0 :                 return tevent_req_post(req, ev);
    3084             :         }
    3085             : 
    3086         442 :         return req;
    3087             : }
    3088             : 
    3089        1326 : static void cli_smb1_setup_encryption_local_next(struct tevent_req *req)
    3090             : {
    3091           0 :         struct cli_smb1_setup_encryption_state *state =
    3092        1326 :                 tevent_req_data(req,
    3093             :                 struct cli_smb1_setup_encryption_state);
    3094        1326 :         struct tevent_req *subreq = NULL;
    3095             : 
    3096        1326 :         if (state->local_ready) {
    3097           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
    3098           0 :                 return;
    3099             :         }
    3100             : 
    3101        1326 :         subreq = gensec_update_send(state, state->ev,
    3102        1326 :                         state->es->gensec_security,
    3103             :                         state->blob_in);
    3104        1326 :         if (tevent_req_nomem(subreq, req)) {
    3105           0 :                 return;
    3106             :         }
    3107        1326 :         tevent_req_set_callback(subreq, cli_smb1_setup_encryption_local_done, req);
    3108             : }
    3109             : 
    3110        1326 : static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq)
    3111             : {
    3112           0 :         struct tevent_req *req =
    3113        1326 :                 tevent_req_callback_data(subreq,
    3114             :                 struct tevent_req);
    3115           0 :         struct cli_smb1_setup_encryption_state *state =
    3116        1326 :                 tevent_req_data(req,
    3117             :                 struct cli_smb1_setup_encryption_state);
    3118           0 :         NTSTATUS status;
    3119             : 
    3120        1326 :         status = gensec_update_recv(subreq, state, &state->blob_out);
    3121        1326 :         TALLOC_FREE(subreq);
    3122        1326 :         state->blob_in = data_blob_null;
    3123        1326 :         if (!NT_STATUS_IS_OK(status) &&
    3124         884 :             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
    3125             :         {
    3126           0 :                 tevent_req_nterror(req, status);
    3127           0 :                 return;
    3128             :         }
    3129             : 
    3130        1326 :         if (NT_STATUS_IS_OK(status)) {
    3131         442 :                 state->local_ready = true;
    3132             :         }
    3133             : 
    3134             :         /*
    3135             :          * We always get NT_STATUS_OK from the server even if it is not ready.
    3136             :          * So guess the server is ready when we are ready and already sent
    3137             :          * our last blob to the server.
    3138             :          */
    3139        1326 :         if (state->local_ready && state->blob_out.length == 0) {
    3140         442 :                 state->remote_ready = true;
    3141             :         }
    3142             : 
    3143        1326 :         if (state->local_ready && state->remote_ready) {
    3144         442 :                 cli_smb1_setup_encryption_ready(req);
    3145         442 :                 return;
    3146             :         }
    3147             : 
    3148         884 :         cli_smb1_setup_encryption_remote_next(req);
    3149             : }
    3150             : 
    3151         884 : static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req)
    3152             : {
    3153           0 :         struct cli_smb1_setup_encryption_state *state =
    3154         884 :                 tevent_req_data(req,
    3155             :                 struct cli_smb1_setup_encryption_state);
    3156         884 :         struct tevent_req *subreq = NULL;
    3157             : 
    3158         884 :         if (state->remote_ready) {
    3159           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
    3160           0 :                 return;
    3161             :         }
    3162             : 
    3163         884 :         subreq = cli_smb1_setup_encryption_blob_send(state, state->ev,
    3164             :                                                      state->cli, state->blob_out);
    3165         884 :         if (tevent_req_nomem(subreq, req)) {
    3166           0 :                 return;
    3167             :         }
    3168         884 :         tevent_req_set_callback(subreq,
    3169             :                                 cli_smb1_setup_encryption_remote_done,
    3170             :                                 req);
    3171             : }
    3172             : 
    3173         884 : static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq)
    3174             : {
    3175           0 :         struct tevent_req *req =
    3176         884 :                 tevent_req_callback_data(subreq,
    3177             :                 struct tevent_req);
    3178           0 :         struct cli_smb1_setup_encryption_state *state =
    3179         884 :                 tevent_req_data(req,
    3180             :                 struct cli_smb1_setup_encryption_state);
    3181           0 :         NTSTATUS status;
    3182             : 
    3183         884 :         status = cli_smb1_setup_encryption_blob_recv(subreq, state,
    3184             :                                                      &state->blob_in,
    3185         884 :                                                      &state->es->enc_ctx_num);
    3186         884 :         TALLOC_FREE(subreq);
    3187         884 :         data_blob_free(&state->blob_out);
    3188         884 :         if (!NT_STATUS_IS_OK(status) &&
    3189           0 :             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
    3190             :         {
    3191           0 :                 tevent_req_nterror(req, status);
    3192           0 :                 return;
    3193             :         }
    3194             : 
    3195             :         /*
    3196             :          * We always get NT_STATUS_OK even if the server is not ready.
    3197             :          * So guess the server is ready when we are ready and sent
    3198             :          * our last blob to the server.
    3199             :          */
    3200         884 :         if (state->local_ready) {
    3201           0 :                 state->remote_ready = true;
    3202             :         }
    3203             : 
    3204         884 :         if (state->local_ready && state->remote_ready) {
    3205           0 :                 cli_smb1_setup_encryption_ready(req);
    3206           0 :                 return;
    3207             :         }
    3208             : 
    3209         884 :         cli_smb1_setup_encryption_local_next(req);
    3210             : }
    3211             : 
    3212         442 : static void cli_smb1_setup_encryption_ready(struct tevent_req *req)
    3213             : {
    3214           0 :         struct cli_smb1_setup_encryption_state *state =
    3215         442 :                 tevent_req_data(req,
    3216             :                 struct cli_smb1_setup_encryption_state);
    3217         442 :         struct smb_trans_enc_state *es = NULL;
    3218             : 
    3219         442 :         if (state->blob_in.length != 0) {
    3220           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
    3221           0 :                 return;
    3222             :         }
    3223             : 
    3224         442 :         if (state->blob_out.length != 0) {
    3225           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
    3226           0 :                 return;
    3227             :         }
    3228             : 
    3229         442 :         es = talloc_move(state->cli->conn, &state->es);
    3230         442 :         es->enc_on = true;
    3231         442 :         smb1cli_conn_set_encryption(state->cli->conn, es);
    3232         442 :         es = NULL;
    3233             : 
    3234         442 :         tevent_req_done(req);
    3235             : }
    3236             : 
    3237         442 : static NTSTATUS cli_smb1_setup_encryption_recv(struct tevent_req *req)
    3238             : {
    3239         442 :         return tevent_req_simple_recv_ntstatus(req);
    3240             : }
    3241             : 
    3242         440 : NTSTATUS cli_smb1_setup_encryption(struct cli_state *cli,
    3243             :                                    struct cli_credentials *creds)
    3244             : {
    3245         440 :         struct tevent_context *ev = NULL;
    3246         440 :         struct tevent_req *req = NULL;
    3247         440 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    3248             : 
    3249         440 :         ev = samba_tevent_context_init(talloc_tos());
    3250         440 :         if (ev == NULL) {
    3251           0 :                 goto fail;
    3252             :         }
    3253         440 :         req = cli_smb1_setup_encryption_send(ev, ev, cli, creds);
    3254         440 :         if (req == NULL) {
    3255           0 :                 goto fail;
    3256             :         }
    3257         440 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    3258           0 :                 goto fail;
    3259             :         }
    3260         440 :         status = cli_smb1_setup_encryption_recv(req);
    3261         440 :  fail:
    3262         440 :         TALLOC_FREE(ev);
    3263         440 :         return status;
    3264             : }
    3265             : 
    3266             : /**
    3267             :    establishes a connection right up to doing tconX, password specified.
    3268             :    @param output_cli A fully initialised cli structure, non-null only on success
    3269             :    @param dest_host The netbios name of the remote host
    3270             :    @param dest_ip (optional) The the destination IP, NULL for name based lookup
    3271             :    @param port (optional) The destination port (0 for default)
    3272             :    @param service (optional) The share to make the connection to.  Should be 'unqualified' in any way.
    3273             :    @param service_type The 'type' of service.
    3274             :    @param creds The used user credentials
    3275             : */
    3276             : 
    3277             : struct cli_full_connection_creds_state {
    3278             :         struct tevent_context *ev;
    3279             :         const char *service;
    3280             :         const char *service_type;
    3281             :         struct cli_credentials *creds;
    3282             :         int flags;
    3283             :         struct cli_state *cli;
    3284             : };
    3285             : 
    3286          89 : static int cli_full_connection_creds_state_destructor(
    3287             :         struct cli_full_connection_creds_state *s)
    3288             : {
    3289          89 :         if (s->cli != NULL) {
    3290          59 :                 cli_shutdown(s->cli);
    3291          59 :                 s->cli = NULL;
    3292             :         }
    3293          89 :         return 0;
    3294             : }
    3295             : 
    3296             : static void cli_full_connection_creds_conn_done(struct tevent_req *subreq);
    3297             : static void cli_full_connection_creds_sess_done(struct tevent_req *subreq);
    3298             : static void cli_full_connection_creds_enc_start(struct tevent_req *req);
    3299             : static void cli_full_connection_creds_enc_tcon(struct tevent_req *subreq);
    3300             : static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq);
    3301             : static void cli_full_connection_creds_enc_done(struct tevent_req *subreq);
    3302             : static void cli_full_connection_creds_enc_tdis(struct tevent_req *req);
    3303             : static void cli_full_connection_creds_enc_finished(struct tevent_req *subreq);
    3304             : static void cli_full_connection_creds_tcon_start(struct tevent_req *req);
    3305             : static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq);
    3306             : 
    3307        5799 : struct tevent_req *cli_full_connection_creds_send(
    3308             :         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
    3309             :         const char *my_name, const char *dest_host,
    3310             :         const struct sockaddr_storage *dest_ss, int port,
    3311             :         const char *service, const char *service_type,
    3312             :         struct cli_credentials *creds,
    3313             :         int flags,
    3314             :         struct smb2_negotiate_contexts *negotiate_contexts)
    3315             : {
    3316           0 :         struct tevent_req *req, *subreq;
    3317           0 :         struct cli_full_connection_creds_state *state;
    3318           0 :         enum smb_signing_setting signing_state;
    3319           0 :         enum smb_encryption_setting encryption_state =
    3320        5799 :                 cli_credentials_get_smb_encryption(creds);
    3321             : 
    3322        5799 :         req = tevent_req_create(mem_ctx, &state,
    3323             :                                 struct cli_full_connection_creds_state);
    3324        5799 :         if (req == NULL) {
    3325           0 :                 return NULL;
    3326             :         }
    3327        5799 :         talloc_set_destructor(state, cli_full_connection_creds_state_destructor);
    3328             : 
    3329        5799 :         state->ev = ev;
    3330        5799 :         state->service = service;
    3331        5799 :         state->service_type = service_type;
    3332        5799 :         state->creds = creds;
    3333        5799 :         state->flags = flags;
    3334             : 
    3335        5799 :         if (flags & CLI_FULL_CONNECTION_IPC) {
    3336        1584 :                 signing_state = cli_credentials_get_smb_ipc_signing(creds);
    3337             :         } else {
    3338        4215 :                 signing_state = cli_credentials_get_smb_signing(creds);
    3339             :         }
    3340             : 
    3341        5799 :         if (encryption_state == SMB_ENCRYPTION_REQUIRED) {
    3342           4 :                 if (flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK) {
    3343           0 :                         encryption_state = SMB_ENCRYPTION_DESIRED;
    3344             :                 }
    3345             :         }
    3346             : 
    3347        5799 :         if (encryption_state >= SMB_ENCRYPTION_DESIRED) {
    3348           4 :                 signing_state = SMB_SIGNING_REQUIRED;
    3349             :         }
    3350             : 
    3351        5799 :         subreq = cli_start_connection_send(
    3352             :                 state, ev, my_name, dest_host, dest_ss, port,
    3353             :                 signing_state, flags,
    3354             :                 negotiate_contexts);
    3355        5799 :         if (tevent_req_nomem(subreq, req)) {
    3356           0 :                 return tevent_req_post(req, ev);
    3357             :         }
    3358        5799 :         tevent_req_set_callback(subreq,
    3359             :                                 cli_full_connection_creds_conn_done,
    3360             :                                 req);
    3361        5799 :         return req;
    3362             : }
    3363             : 
    3364        5799 : static void cli_full_connection_creds_conn_done(struct tevent_req *subreq)
    3365             : {
    3366        5799 :         struct tevent_req *req = tevent_req_callback_data(
    3367             :                 subreq, struct tevent_req);
    3368        5799 :         struct cli_full_connection_creds_state *state = tevent_req_data(
    3369             :                 req, struct cli_full_connection_creds_state);
    3370           0 :         NTSTATUS status;
    3371             : 
    3372        5799 :         status = cli_start_connection_recv(subreq, state, &state->cli);
    3373        5799 :         TALLOC_FREE(subreq);
    3374        5799 :         if (tevent_req_nterror(req, status)) {
    3375          30 :                 return;
    3376             :         }
    3377             : 
    3378        5769 :         subreq = cli_session_setup_creds_send(
    3379             :                 state, state->ev, state->cli, state->creds);
    3380        5769 :         if (tevent_req_nomem(subreq, req)) {
    3381           0 :                 return;
    3382             :         }
    3383        5769 :         tevent_req_set_callback(subreq,
    3384             :                                 cli_full_connection_creds_sess_done,
    3385             :                                 req);
    3386             : }
    3387             : 
    3388        5770 : static void cli_full_connection_creds_sess_done(struct tevent_req *subreq)
    3389             : {
    3390        5770 :         struct tevent_req *req = tevent_req_callback_data(
    3391             :                 subreq, struct tevent_req);
    3392        5770 :         struct cli_full_connection_creds_state *state = tevent_req_data(
    3393             :                 req, struct cli_full_connection_creds_state);
    3394           0 :         NTSTATUS status;
    3395             : 
    3396        5770 :         status = cli_session_setup_creds_recv(subreq);
    3397        5770 :         TALLOC_FREE(subreq);
    3398             : 
    3399        5770 :         if (!NT_STATUS_IS_OK(status) &&
    3400          60 :             (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
    3401             : 
    3402           1 :                 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
    3403             : 
    3404           1 :                 state->creds = cli_credentials_init_anon(state);
    3405           1 :                 if (tevent_req_nomem(state->creds, req)) {
    3406          60 :                         return;
    3407             :                 }
    3408             : 
    3409           1 :                 subreq = cli_session_setup_creds_send(
    3410             :                         state, state->ev, state->cli, state->creds);
    3411           1 :                 if (tevent_req_nomem(subreq, req)) {
    3412           0 :                         return;
    3413             :                 }
    3414           1 :                 tevent_req_set_callback(subreq,
    3415             :                                         cli_full_connection_creds_sess_done,
    3416             :                                         req);
    3417           1 :                 return;
    3418             :         }
    3419             : 
    3420        5769 :         if (tevent_req_nterror(req, status)) {
    3421          59 :                 return;
    3422             :         }
    3423             : 
    3424        5710 :         cli_full_connection_creds_enc_start(req);
    3425             : }
    3426             : 
    3427        5710 : static void cli_full_connection_creds_enc_start(struct tevent_req *req)
    3428             : {
    3429        5710 :         struct cli_full_connection_creds_state *state = tevent_req_data(
    3430             :                 req, struct cli_full_connection_creds_state);
    3431           0 :         enum smb_encryption_setting encryption_state =
    3432        5710 :                 cli_credentials_get_smb_encryption(state->creds);
    3433        5710 :         struct tevent_req *subreq = NULL;
    3434           0 :         NTSTATUS status;
    3435             : 
    3436        5710 :         if (encryption_state < SMB_ENCRYPTION_DESIRED) {
    3437        5706 :                 cli_full_connection_creds_tcon_start(req);
    3438        5708 :                 return;
    3439             :         }
    3440             : 
    3441           4 :         if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
    3442           2 :                 status = smb2cli_session_encryption_on(state->cli->smb2.session);
    3443           2 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
    3444           0 :                         if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
    3445           0 :                                 cli_full_connection_creds_tcon_start(req);
    3446           0 :                                 return;
    3447             :                         }
    3448           0 :                         d_printf("Encryption required and "
    3449             :                                 "server doesn't support "
    3450             :                                 "SMB3 encryption - failing connect\n");
    3451           0 :                         tevent_req_nterror(req, status);
    3452           0 :                         return;
    3453           2 :                 } else if (!NT_STATUS_IS_OK(status)) {
    3454           0 :                         d_printf("Encryption required and "
    3455             :                                 "setup failed with error %s.\n",
    3456             :                                 nt_errstr(status));
    3457           0 :                         tevent_req_nterror(req, status);
    3458           0 :                         return;
    3459             :                 }
    3460             : 
    3461           2 :                 cli_full_connection_creds_tcon_start(req);
    3462           2 :                 return;
    3463             :         }
    3464             : 
    3465           2 :         if (!SERVER_HAS_UNIX_CIFS(state->cli)) {
    3466           0 :                 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
    3467           0 :                         cli_full_connection_creds_tcon_start(req);
    3468           0 :                         return;
    3469             :                 }
    3470             : 
    3471           0 :                 status = NT_STATUS_NOT_SUPPORTED;
    3472           0 :                 d_printf("Encryption required and "
    3473             :                         "server doesn't support "
    3474             :                         "SMB1 Unix Extensions - failing connect\n");
    3475           0 :                 tevent_req_nterror(req, status);
    3476           0 :                 return;
    3477             :         }
    3478             : 
    3479             :         /*
    3480             :          * We do a tcon on IPC$ just to setup the encryption,
    3481             :          * the real tcon will be encrypted then.
    3482             :          */
    3483           2 :         subreq = cli_tree_connect_send(state, state->ev, state->cli,
    3484             :                                        "IPC$", "IPC", NULL);
    3485           2 :         if (tevent_req_nomem(subreq, req)) {
    3486           0 :                 return;
    3487             :         }
    3488           2 :         tevent_req_set_callback(subreq, cli_full_connection_creds_enc_tcon, req);
    3489             : }
    3490             : 
    3491           2 : static void cli_full_connection_creds_enc_tcon(struct tevent_req *subreq)
    3492             : {
    3493           2 :         struct tevent_req *req = tevent_req_callback_data(
    3494             :                 subreq, struct tevent_req);
    3495           2 :         struct cli_full_connection_creds_state *state = tevent_req_data(
    3496             :                 req, struct cli_full_connection_creds_state);
    3497           0 :         NTSTATUS status;
    3498             : 
    3499           2 :         status = cli_tree_connect_recv(subreq);
    3500           2 :         TALLOC_FREE(subreq);
    3501           2 :         if (tevent_req_nterror(req, status)) {
    3502           0 :                 return;
    3503             :         }
    3504             : 
    3505           2 :         subreq = cli_unix_extensions_version_send(state, state->ev, state->cli);
    3506           2 :         if (tevent_req_nomem(subreq, req)) {
    3507           0 :                 return;
    3508             :         }
    3509           2 :         tevent_req_set_callback(subreq, cli_full_connection_creds_enc_ver, req);
    3510             : }
    3511             : 
    3512           2 : static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq)
    3513             : {
    3514           2 :         struct tevent_req *req = tevent_req_callback_data(
    3515             :                 subreq, struct tevent_req);
    3516           2 :         struct cli_full_connection_creds_state *state = tevent_req_data(
    3517             :                 req, struct cli_full_connection_creds_state);
    3518           0 :         enum smb_encryption_setting encryption_state =
    3519           2 :                 cli_credentials_get_smb_encryption(state->creds);
    3520           0 :         uint16_t major, minor;
    3521           0 :         uint32_t caplow, caphigh;
    3522           0 :         NTSTATUS status;
    3523             : 
    3524           2 :         status = cli_unix_extensions_version_recv(subreq,
    3525             :                                                   &major, &minor,
    3526             :                                                   &caplow,
    3527             :                                                   &caphigh);
    3528           2 :         TALLOC_FREE(subreq);
    3529           2 :         if (!NT_STATUS_IS_OK(status)) {
    3530           0 :                 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
    3531             :                         /* disconnect ipc$ followed by the real tree connect */
    3532           0 :                         cli_full_connection_creds_enc_tdis(req);
    3533           0 :                         return;
    3534             :                 }
    3535           0 :                 DEBUG(10, ("%s: cli_unix_extensions_version "
    3536             :                            "returned %s\n", __func__, nt_errstr(status)));
    3537           0 :                 tevent_req_nterror(req, NT_STATUS_UNKNOWN_REVISION);
    3538           0 :                 return;
    3539             :         }
    3540             : 
    3541           2 :         if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
    3542           0 :                 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
    3543             :                         /* disconnect ipc$ followed by the real tree connect */
    3544           0 :                         cli_full_connection_creds_enc_tdis(req);
    3545           0 :                         return;
    3546             :                 }
    3547           0 :                 DEBUG(10, ("%s: CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP "
    3548             :                            "not supported\n", __func__));
    3549           0 :                 tevent_req_nterror(req, NT_STATUS_UNSUPPORTED_COMPRESSION);
    3550           0 :                 return;
    3551             :         }
    3552             : 
    3553           2 :         subreq = cli_smb1_setup_encryption_send(state, state->ev,
    3554             :                                                 state->cli,
    3555             :                                                 state->creds);
    3556           2 :         if (tevent_req_nomem(subreq, req)) {
    3557           0 :                 return;
    3558             :         }
    3559           2 :         tevent_req_set_callback(subreq,
    3560             :                                 cli_full_connection_creds_enc_done,
    3561             :                                 req);
    3562             : }
    3563             : 
    3564           2 : static void cli_full_connection_creds_enc_done(struct tevent_req *subreq)
    3565             : {
    3566           2 :         struct tevent_req *req = tevent_req_callback_data(
    3567             :                 subreq, struct tevent_req);
    3568           0 :         NTSTATUS status;
    3569             : 
    3570           2 :         status = cli_smb1_setup_encryption_recv(subreq);
    3571           2 :         TALLOC_FREE(subreq);
    3572           2 :         if (tevent_req_nterror(req, status)) {
    3573           0 :                 return;
    3574             :         }
    3575             : 
    3576             :         /* disconnect ipc$ followed by the real tree connect */
    3577           2 :         cli_full_connection_creds_enc_tdis(req);
    3578             : }
    3579             : 
    3580           2 : static void cli_full_connection_creds_enc_tdis(struct tevent_req *req)
    3581             : {
    3582           2 :         struct cli_full_connection_creds_state *state = tevent_req_data(
    3583             :                 req, struct cli_full_connection_creds_state);
    3584           2 :         struct tevent_req *subreq = NULL;
    3585             : 
    3586           2 :         subreq = cli_tdis_send(state, state->ev, state->cli);
    3587           2 :         if (tevent_req_nomem(subreq, req)) {
    3588           0 :                 return;
    3589             :         }
    3590           2 :         tevent_req_set_callback(subreq,
    3591             :                                 cli_full_connection_creds_enc_finished,
    3592             :                                 req);
    3593             : }
    3594             : 
    3595           2 : static void cli_full_connection_creds_enc_finished(struct tevent_req *subreq)
    3596             : {
    3597           2 :         struct tevent_req *req = tevent_req_callback_data(
    3598             :                 subreq, struct tevent_req);
    3599           0 :         NTSTATUS status;
    3600             : 
    3601           2 :         status = cli_tdis_recv(subreq);
    3602           2 :         TALLOC_FREE(subreq);
    3603           2 :         if (tevent_req_nterror(req, status)) {
    3604           0 :                 return;
    3605             :         }
    3606             : 
    3607           2 :         cli_full_connection_creds_tcon_start(req);
    3608             : }
    3609             : 
    3610        5710 : static void cli_full_connection_creds_tcon_start(struct tevent_req *req)
    3611             : {
    3612        5710 :         struct cli_full_connection_creds_state *state = tevent_req_data(
    3613             :                 req, struct cli_full_connection_creds_state);
    3614        5710 :         struct tevent_req *subreq = NULL;
    3615        5710 :         const char *password = NULL;
    3616             : 
    3617        5710 :         if (state->service == NULL) {
    3618           5 :                 tevent_req_done(req);
    3619           5 :                 return;
    3620             :         }
    3621             : 
    3622        5705 :         password = cli_credentials_get_password(state->creds);
    3623             : 
    3624        5705 :         subreq = cli_tree_connect_send(state, state->ev,
    3625             :                                        state->cli,
    3626             :                                        state->service,
    3627             :                                        state->service_type,
    3628             :                                        password);
    3629        5705 :         if (tevent_req_nomem(subreq, req)) {
    3630           0 :                 return;
    3631             :         }
    3632        5705 :         tevent_req_set_callback(subreq,
    3633             :                                 cli_full_connection_creds_tcon_done,
    3634             :                                 req);
    3635             : }
    3636             : 
    3637        5705 : static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq)
    3638             : {
    3639        5705 :         struct tevent_req *req = tevent_req_callback_data(
    3640             :                 subreq, struct tevent_req);
    3641           0 :         NTSTATUS status;
    3642             : 
    3643        5705 :         status = cli_tree_connect_recv(subreq);
    3644        5705 :         TALLOC_FREE(subreq);
    3645        5705 :         if (tevent_req_nterror(req, status)) {
    3646           0 :                 return;
    3647             :         }
    3648             : 
    3649        5705 :         tevent_req_done(req);
    3650             : }
    3651             : 
    3652        5799 : NTSTATUS cli_full_connection_creds_recv(struct tevent_req *req,
    3653             :                                         TALLOC_CTX *mem_ctx,
    3654             :                                         struct cli_state **output_cli)
    3655             : {
    3656        5799 :         struct cli_full_connection_creds_state *state = tevent_req_data(
    3657             :                 req, struct cli_full_connection_creds_state);
    3658           0 :         NTSTATUS status;
    3659             : 
    3660        5799 :         if (tevent_req_is_nterror(req, &status)) {
    3661          89 :                 return status;
    3662             :         }
    3663        5710 :         *output_cli = talloc_move(mem_ctx, &state->cli);
    3664        5710 :         talloc_set_destructor(state, NULL);
    3665        5710 :         return NT_STATUS_OK;
    3666             : }
    3667             : 
    3668        4347 : NTSTATUS cli_full_connection_creds(TALLOC_CTX *mem_ctx,
    3669             :                                    struct cli_state **output_cli,
    3670             :                                    const char *my_name,
    3671             :                                    const char *dest_host,
    3672             :                                    const struct sockaddr_storage *dest_ss, int port,
    3673             :                                    const char *service, const char *service_type,
    3674             :                                    struct cli_credentials *creds,
    3675             :                                    int flags)
    3676             : {
    3677           0 :         struct tevent_context *ev;
    3678           0 :         struct tevent_req *req;
    3679        4347 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    3680             : 
    3681        4347 :         ev = samba_tevent_context_init(mem_ctx);
    3682        4347 :         if (ev == NULL) {
    3683           0 :                 goto fail;
    3684             :         }
    3685        4347 :         req = cli_full_connection_creds_send(
    3686             :                 ev, ev, my_name, dest_host, dest_ss, port, service,
    3687             :                 service_type, creds, flags,
    3688             :                 NULL);
    3689        4347 :         if (req == NULL) {
    3690           0 :                 goto fail;
    3691             :         }
    3692        4347 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    3693           0 :                 goto fail;
    3694             :         }
    3695        4347 :         status = cli_full_connection_creds_recv(req, mem_ctx, output_cli);
    3696        4347 :  fail:
    3697        4347 :         TALLOC_FREE(ev);
    3698        4347 :         return status;
    3699             : }
    3700             : 
    3701             : /****************************************************************************
    3702             :  Send an old style tcon.
    3703             : ****************************************************************************/
    3704             : struct cli_raw_tcon_state {
    3705             :         uint16_t *ret_vwv;
    3706             : };
    3707             : 
    3708             : static void cli_raw_tcon_done(struct tevent_req *subreq);
    3709             : 
    3710           7 : static struct tevent_req *cli_raw_tcon_send(
    3711             :         TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
    3712             :         const char *service, const char *pass, const char *dev)
    3713             : {
    3714           0 :         struct tevent_req *req, *subreq;
    3715           0 :         struct cli_raw_tcon_state *state;
    3716           0 :         uint8_t *bytes;
    3717             : 
    3718           7 :         req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
    3719           7 :         if (req == NULL) {
    3720           0 :                 return NULL;
    3721             :         }
    3722             : 
    3723           7 :         if (!lp_client_plaintext_auth() && (*pass)) {
    3724           5 :                 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
    3725             :                           " or 'client ntlmv2 auth = yes'\n"));
    3726           5 :                 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
    3727           5 :                 return tevent_req_post(req, ev);
    3728             :         }
    3729             : 
    3730           2 :         TALLOC_FREE(cli->smb1.tcon);
    3731           2 :         cli->smb1.tcon = smbXcli_tcon_create(cli);
    3732           2 :         if (tevent_req_nomem(cli->smb1.tcon, req)) {
    3733           0 :                 return tevent_req_post(req, ev);
    3734             :         }
    3735           2 :         smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
    3736             : 
    3737           2 :         bytes = talloc_array(state, uint8_t, 0);
    3738           2 :         bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
    3739           2 :         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
    3740           2 :                                    service, strlen(service)+1, NULL);
    3741           2 :         bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
    3742           2 :         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
    3743           2 :                                    pass, strlen(pass)+1, NULL);
    3744           2 :         bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
    3745           2 :         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
    3746           2 :                                    dev, strlen(dev)+1, NULL);
    3747             : 
    3748           2 :         if (tevent_req_nomem(bytes, req)) {
    3749           0 :                 return tevent_req_post(req, ev);
    3750             :         }
    3751             : 
    3752           2 :         subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
    3753           2 :                               talloc_get_size(bytes), bytes);
    3754           2 :         if (tevent_req_nomem(subreq, req)) {
    3755           0 :                 return tevent_req_post(req, ev);
    3756             :         }
    3757           2 :         tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
    3758           2 :         return req;
    3759             : }
    3760             : 
    3761           2 : static void cli_raw_tcon_done(struct tevent_req *subreq)
    3762             : {
    3763           2 :         struct tevent_req *req = tevent_req_callback_data(
    3764             :                 subreq, struct tevent_req);
    3765           2 :         struct cli_raw_tcon_state *state = tevent_req_data(
    3766             :                 req, struct cli_raw_tcon_state);
    3767           0 :         NTSTATUS status;
    3768             : 
    3769           2 :         status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
    3770             :                               NULL, NULL);
    3771           2 :         TALLOC_FREE(subreq);
    3772           2 :         if (tevent_req_nterror(req, status)) {
    3773           2 :                 return;
    3774             :         }
    3775           0 :         tevent_req_done(req);
    3776             : }
    3777             : 
    3778           7 : static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
    3779             :                                   uint16_t *max_xmit, uint16_t *tid)
    3780             : {
    3781           7 :         struct cli_raw_tcon_state *state = tevent_req_data(
    3782             :                 req, struct cli_raw_tcon_state);
    3783           0 :         NTSTATUS status;
    3784             : 
    3785           7 :         if (tevent_req_is_nterror(req, &status)) {
    3786           7 :                 return status;
    3787             :         }
    3788           0 :         *max_xmit = SVAL(state->ret_vwv + 0, 0);
    3789           0 :         *tid = SVAL(state->ret_vwv + 1, 0);
    3790           0 :         return NT_STATUS_OK;
    3791             : }
    3792             : 
    3793           7 : NTSTATUS cli_raw_tcon(struct cli_state *cli,
    3794             :                       const char *service, const char *pass, const char *dev,
    3795             :                       uint16_t *max_xmit, uint16_t *tid)
    3796             : {
    3797           0 :         struct tevent_context *ev;
    3798           0 :         struct tevent_req *req;
    3799           7 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    3800             : 
    3801           7 :         ev = samba_tevent_context_init(talloc_tos());
    3802           7 :         if (ev == NULL) {
    3803           0 :                 goto fail;
    3804             :         }
    3805           7 :         req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
    3806           7 :         if (req == NULL) {
    3807           0 :                 goto fail;
    3808             :         }
    3809           7 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    3810           0 :                 goto fail;
    3811             :         }
    3812           7 :         status = cli_raw_tcon_recv(req, max_xmit, tid);
    3813           7 : fail:
    3814           7 :         TALLOC_FREE(ev);
    3815           7 :         return status;
    3816             : }
    3817             : 
    3818             : /* Return a cli_state pointing at the IPC$ share for the given server */
    3819             : 
    3820          23 : static struct cli_state *get_ipc_connect(TALLOC_CTX *mem_ctx,
    3821             :                                          char *server,
    3822             :                                          struct sockaddr_storage *server_ss,
    3823             :                                          struct cli_credentials *creds)
    3824             : {
    3825           0 :         struct cli_state *cli;
    3826           0 :         NTSTATUS nt_status;
    3827          23 :         uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
    3828             : 
    3829          23 :         flags |= CLI_FULL_CONNECTION_FORCE_SMB1;
    3830          23 :         flags |= CLI_FULL_CONNECTION_IPC;
    3831             : 
    3832          23 :         nt_status = cli_full_connection_creds(mem_ctx,
    3833             :                                               &cli,
    3834             :                                               NULL,
    3835             :                                               server,
    3836             :                                               server_ss,
    3837             :                                               0,
    3838             :                                               "IPC$",
    3839             :                                               "IPC",
    3840             :                                               creds,
    3841             :                                               flags);
    3842             : 
    3843          23 :         if (NT_STATUS_IS_OK(nt_status)) {
    3844           1 :                 return cli;
    3845             :         }
    3846          22 :         if (is_ipaddress(server)) {
    3847             :             /* windows 9* needs a correct NMB name for connections */
    3848           0 :             fstring remote_name;
    3849             : 
    3850          11 :             if (name_status_find("*", 0, 0, server_ss, remote_name)) {
    3851          11 :                 cli = get_ipc_connect(mem_ctx, remote_name, server_ss, creds);
    3852          11 :                 if (cli)
    3853           0 :                     return cli;
    3854             :             }
    3855             :         }
    3856          22 :         return NULL;
    3857             : }
    3858             : 
    3859             : /*
    3860             :  * Given the IP address of a master browser on the network, return its
    3861             :  * workgroup and connect to it.
    3862             :  *
    3863             :  * This function is provided to allow additional processing beyond what
    3864             :  * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
    3865             :  * browsers and obtain each master browsers' list of domains (in case the
    3866             :  * first master browser is recently on the network and has not yet
    3867             :  * synchronized with other master browsers and therefore does not yet have the
    3868             :  * entire network browse list)
    3869             :  */
    3870             : 
    3871          12 : struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
    3872             :                                 struct sockaddr_storage *mb_ip,
    3873             :                                 struct cli_credentials *creds,
    3874             :                                 char **pp_workgroup_out)
    3875             : {
    3876           0 :         char addr[INET6_ADDRSTRLEN];
    3877           0 :         fstring name;
    3878           0 :         struct cli_state *cli;
    3879           0 :         struct sockaddr_storage server_ss;
    3880             : 
    3881          12 :         *pp_workgroup_out = NULL;
    3882             : 
    3883          12 :         print_sockaddr(addr, sizeof(addr), mb_ip);
    3884          12 :         DEBUG(99, ("Looking up name of master browser %s\n",
    3885             :                    addr));
    3886             : 
    3887             :         /*
    3888             :          * Do a name status query to find out the name of the master browser.
    3889             :          * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
    3890             :          * master browser will not respond to a wildcard query (or, at least,
    3891             :          * an NT4 server acting as the domain master browser will not).
    3892             :          *
    3893             :          * We might be able to use ONLY the query on MSBROWSE, but that's not
    3894             :          * yet been tested with all Windows versions, so until it is, leave
    3895             :          * the original wildcard query as the first choice and fall back to
    3896             :          * MSBROWSE if the wildcard query fails.
    3897             :          */
    3898          12 :         if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
    3899           0 :             !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
    3900             : 
    3901           0 :                 DEBUG(99, ("Could not retrieve name status for %s\n",
    3902             :                            addr));
    3903           0 :                 return NULL;
    3904             :         }
    3905             : 
    3906          12 :         if (!find_master_ip(name, &server_ss)) {
    3907           0 :                 DEBUG(99, ("Could not find master ip for %s\n", name));
    3908           0 :                 return NULL;
    3909             :         }
    3910             : 
    3911          12 :         *pp_workgroup_out = talloc_strdup(ctx, name);
    3912             : 
    3913          12 :         DEBUG(4, ("found master browser %s, %s\n", name, addr));
    3914             : 
    3915          12 :         print_sockaddr(addr, sizeof(addr), &server_ss);
    3916          12 :         cli = get_ipc_connect(ctx, addr, &server_ss, creds);
    3917             : 
    3918          12 :         return cli;
    3919             : }

Generated by: LCOV version 1.14