LCOV - code coverage report
Current view: top level - source3/libsmb - cliconnect.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 1343 1952 68.8 %
Date: 2024-04-21 15:09:00 Functions: 93 97 95.9 %

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

Generated by: LCOV version 1.14