hack.. don't handle @
[metze/samba/wip.git] / source3 / libsmb / cliconnect.c
index 4116bae0402287a2a5e0b2d84e8d623858c2f3b2..445ed685a5d60f6ce54fae2b81fc75c5b9216ffa 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "includes.h"
 #include "libsmb/libsmb.h"
+#include "libsmb/namequery.h"
 #include "auth_info.h"
 #include "../libcli/auth/libcli_auth.h"
 #include "../libcli/auth/spnego.h"
@@ -39,6 +40,8 @@
 #include "../libcli/smb/smbXcli_base.h"
 #include "../libcli/smb/smb_seal.h"
 #include "lib/param/param.h"
+#include "../libcli/smb/smb2_negotiate_context.h"
+#include "libads/krb5_errs.h"
 
 #define STAR_SMBSERVER "*SMBSERVER"
 
@@ -228,6 +231,7 @@ NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli,
        const char *pass = NULL;
        const char *target_hostname = NULL;
        const DATA_BLOB *server_blob = NULL;
+       bool got_kerberos_mechanism = false;
        enum credentials_use_kerberos krb5_state;
        bool try_kerberos = false;
        bool need_kinit = false;
@@ -235,9 +239,7 @@ NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli,
        int ret;
 
        target_hostname = smbXcli_conn_remote_name(cli->conn);
-       if (!cli->got_kerberos_mechanism) {
-               server_blob = smbXcli_conn_server_gss_blob(cli->conn);
-       }
+       server_blob = smbXcli_conn_server_gss_blob(cli->conn);
 
        /* the server might not even do spnego */
        if (server_blob != NULL && server_blob->length != 0) {
@@ -275,7 +277,7 @@ NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli,
 
                        if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
                            strcmp(OIDs[i], OID_KERBEROS5) == 0) {
-                               cli->got_kerberos_mechanism = true;
+                               got_kerberos_mechanism = true;
                                break;
                        }
                }
@@ -283,8 +285,9 @@ NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli,
 
        auth_requested = cli_credentials_authentication_requested(creds);
        if (auth_requested) {
+               errno = 0;
                user_principal = cli_credentials_get_principal(creds, frame);
-               if (user_principal == NULL) {
+               if (errno != 0) {
                        TALLOC_FREE(frame);
                        return NT_STATUS_NO_MEMORY;
                }
@@ -299,6 +302,10 @@ NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli,
                try_kerberos = true;
        }
 
+       if (user_principal == NULL) {
+               try_kerberos = false;
+       }
+
        if (target_hostname == NULL) {
                try_kerberos = false;
        } else if (is_ipaddress(target_hostname)) {
@@ -324,7 +331,7 @@ NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli,
                need_kinit = false;
        } else if (krb5_state == CRED_MUST_USE_KERBEROS) {
                need_kinit = try_kerberos;
-       } else if (!cli->got_kerberos_mechanism) {
+       } else if (!got_kerberos_mechanism) {
                /*
                 * Most likely the server doesn't support
                 * Kerberos, don't waste time doing a kinit
@@ -349,9 +356,15 @@ NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli,
                                0 /* no time correction for now */,
                                NULL);
        if (ret != 0) {
-               DEBUG(0, ("Kinit for %s to access %s failed: %s\n",
-                         user_principal, target_hostname,
-                         error_message(ret)));
+               int dbglvl = DBGLVL_NOTICE;
+
+               if (krb5_state == CRED_MUST_USE_KERBEROS) {
+                       dbglvl = DBGLVL_ERR;
+               }
+
+               DEBUG(dbglvl, ("Kinit for %s to access %s failed: %s\n",
+                              user_principal, target_hostname,
+                              error_message(ret)));
                if (krb5_state == CRED_MUST_USE_KERBEROS) {
                        TALLOC_FREE(frame);
                        return krb5_to_nt_status(ret);
@@ -366,6 +379,91 @@ NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli,
        return NT_STATUS_OK;
 }
 
+NTSTATUS cli_state_update_after_negprot(struct cli_state *cli)
+{
+       static const struct {
+               enum protocol_types proto;
+               const char *name;
+       } protos[] = {
+       {PROTOCOL_SMB3_11, "SMB3_11"},
+       {PROTOCOL_SMB3_10, "SMB3_10"},
+       {PROTOCOL_SMB3_02, "SMB3_02"},
+       {PROTOCOL_SMB3_00, "SMB3_00"},
+       {PROTOCOL_SMB2_24, "SMB2_24"},
+       {PROTOCOL_SMB2_22, "SMB2_22"},
+       {PROTOCOL_SMB2_10, "SMB2_10"},
+       {PROTOCOL_SMB2_02, "SMB2_02"},
+       {PROTOCOL_NT1, "NT1"},
+       {PROTOCOL_LANMAN2, "LANMAN2"},
+       {PROTOCOL_LANMAN1, "LANMAN1"},
+       {PROTOCOL_CORE, "CORE"},
+       {PROTOCOL_COREPLUS, "COREPLUS"},
+       {PROTOCOL_NONE, "NONE"},
+       {PROTOCOL_DEFAULT, "DEFAULT"},
+       };
+       enum protocol_types protocol;
+       const char *proto_name = NULL;
+       size_t i;
+
+       protocol = smbXcli_conn_protocol(cli->conn);
+
+       if (protocol >= PROTOCOL_SMB2_02) {
+               /* Ensure we ask for some initial credits. */
+               smb2cli_conn_set_max_credits(cli->conn, DEFAULT_SMB2_MAX_CREDITS);
+       }
+
+       for (i=0; i < ARRAY_SIZE(protos); i++) {
+               if (protos[i].proto == protocol) {
+                       proto_name = protos[i].name;
+                       break;
+               }
+       }
+
+       cli->server_os = talloc_asprintf(cli, "%s Server", proto_name);
+       if (cli->server_os == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       cli->server_type = talloc_asprintf(cli, "%s",
+                               smbXcli_conn_remote_name(cli->conn));
+       if (cli->server_type == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS cli_state_update_after_sesssetup(struct cli_state *cli,
+                                                const char *native_os,
+                                                const char *native_lm,
+                                                const char *primary_domain)
+{
+#define _VALID_STR(p) ((p) != NULL && (p)[0] != '\0')
+
+       if (_VALID_STR(native_os)) {
+               cli->server_os = talloc_strdup(cli, native_os);
+               if (cli->server_os == NULL) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+       }
+
+       if (_VALID_STR(native_lm)) {
+               cli->server_type = talloc_strdup(cli, native_lm);
+               if (cli->server_type == NULL) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+       }
+
+       if (_VALID_STR(primary_domain)) {
+               cli->server_domain = talloc_strdup(cli, primary_domain);
+               if (cli->server_domain == NULL) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+       }
+
+#undef _VALID_STRING
+       return NT_STATUS_OK;
+}
+
 /********************************************************
  Utility function to ensure we always return at least
  a valid char * pointer to an empty string for the
@@ -756,7 +854,6 @@ static void cli_sesssetup_blob_done(struct tevent_req *subreq)
                subreq, struct tevent_req);
        struct cli_sesssetup_blob_state *state = tevent_req_data(
                req, struct cli_sesssetup_blob_state);
-       struct cli_state *cli = state->cli;
        NTSTATUS status;
 
        if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
@@ -778,15 +875,16 @@ static void cli_sesssetup_blob_done(struct tevent_req *subreq)
                return;
        }
 
-       if (cli->server_os == NULL) {
-               cli->server_os = talloc_move(cli, &state->out_native_os);
-       }
-       if (cli->server_type == NULL) {
-               cli->server_type = talloc_move(cli, &state->out_native_lm);
-       }
-
        state->status = status;
 
+       status = cli_state_update_after_sesssetup(state->cli,
+                                                 state->out_native_os,
+                                                 state->out_native_lm,
+                                                 NULL);
+       if (tevent_req_nterror(req, status)) {
+               return;
+       }
+
        if (state->blob.length != 0) {
                /*
                 * More to send
@@ -1064,13 +1162,16 @@ static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
                         * We can't finish the gensec handshake, we don't
                         * have a negotiated session key.
                         *
-                        * So just pretend we are completely done.
+                        * So just pretend we are completely done,
+                        * we need to continue as anonymous from this point,
+                        * as we can't get a session key.
                         *
                         * Note that smbXcli_session_is_guest()
                         * always returns false if we require signing.
                         */
                        state->blob_in = data_blob_null;
                        state->local_ready = true;
+                       state->is_anonymous = true;
                }
 
                state->remote_ready = true;
@@ -1084,12 +1185,63 @@ static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
        cli_session_setup_gensec_local_next(req);
 }
 
+static void cli_session_dump_keys(TALLOC_CTX *mem_ctx,
+                                 struct smbXcli_session *session,
+                                 DATA_BLOB session_key)
+{
+       NTSTATUS status;
+       DATA_BLOB sig = data_blob_null;
+       DATA_BLOB app = data_blob_null;
+       DATA_BLOB enc = data_blob_null;
+       DATA_BLOB dec = data_blob_null;
+       uint64_t sid = smb2cli_session_current_id(session);
+
+       status = smb2cli_session_signing_key(session, mem_ctx, &sig);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto out;
+       }
+       status = smbXcli_session_application_key(session, mem_ctx, &app);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto out;
+       }
+       status = smb2cli_session_encryption_key(session, mem_ctx, &enc);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto out;
+       }
+       status = smb2cli_session_decryption_key(session, mem_ctx, &dec);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto out;
+       }
+
+       DEBUG(0, ("debug encryption: dumping generated session keys\n"));
+       DEBUGADD(0, ("Session Id    "));
+       dump_data(0, (uint8_t*)&sid, sizeof(sid));
+       DEBUGADD(0, ("Session Key   "));
+       dump_data(0, session_key.data, session_key.length);
+       DEBUGADD(0, ("Signing Key   "));
+       dump_data(0, sig.data, sig.length);
+       DEBUGADD(0, ("App Key       "));
+       dump_data(0, app.data, app.length);
+
+       /* In client code, ServerIn is the encryption key */
+
+       DEBUGADD(0, ("ServerIn Key  "));
+       dump_data(0, enc.data, enc.length);
+       DEBUGADD(0, ("ServerOut Key "));
+       dump_data(0, dec.data, dec.length);
+
+out:
+       data_blob_clear_free(&sig);
+       data_blob_clear_free(&app);
+       data_blob_clear_free(&enc);
+       data_blob_clear_free(&dec);
+}
+
 static void cli_session_setup_gensec_ready(struct tevent_req *req)
 {
        struct cli_session_setup_gensec_state *state =
                tevent_req_data(req,
                struct cli_session_setup_gensec_state);
-       const char *server_domain = NULL;
        NTSTATUS status;
 
        if (state->blob_in.length != 0) {
@@ -1102,27 +1254,6 @@ static void cli_session_setup_gensec_ready(struct tevent_req *req)
                return;
        }
 
-       /*
-        * gensec_ntlmssp_server_domain() returns NULL
-        * if NTLMSSP is not used.
-        *
-        * We can remove this later
-        * and leave the server domain empty for SMB2 and above
-        * in future releases.
-        */
-       server_domain = gensec_ntlmssp_server_domain(
-                               state->auth_generic->gensec_security);
-
-       if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
-               TALLOC_FREE(state->cli->server_domain);
-               state->cli->server_domain = talloc_strdup(state->cli,
-                                       server_domain);
-               if (state->cli->server_domain == NULL) {
-                       tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
-                       return;
-               }
-       }
-
        if (state->is_anonymous) {
                /*
                 * Windows server does not set the
@@ -1151,6 +1282,11 @@ static void cli_session_setup_gensec_ready(struct tevent_req *req)
                if (tevent_req_nterror(req, status)) {
                        return;
                }
+               if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB3_00
+                   && lp_debug_encryption())
+               {
+                       cli_session_dump_keys(state, session, state->session_key);
+               }
        } else {
                struct smbXcli_session *session = state->cli->smb1.session;
                bool active;
@@ -1203,7 +1339,7 @@ static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
                return NULL;
        }
        p = strchr_m(account, '@');
-       if (p != NULL) {
+       if (0 && p != NULL) {
                *p = '\0';
        }
        return account;
@@ -1243,7 +1379,7 @@ static struct tevent_req *cli_session_setup_spnego_send(
 
        status = cli_session_creds_prepare_krb5(cli, creds);
        if (tevent_req_nterror(req, status)) {
-               return tevent_req_post(req, ev);;
+               return tevent_req_post(req, ev);
        }
 
        subreq = cli_session_setup_gensec_send(state, ev, cli, creds,
@@ -1661,14 +1797,12 @@ static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq)
                return;
        }
 
-       if (cli->server_os == NULL) {
-               cli->server_os = talloc_move(cli, &state->out_native_os);
-       }
-       if (cli->server_type == NULL) {
-               cli->server_type = talloc_move(cli, &state->out_native_lm);
-       }
-       if (cli->server_domain == NULL) {
-               cli->server_domain = talloc_move(cli, &state->out_primary_domain);
+       status = cli_state_update_after_sesssetup(state->cli,
+                                                 state->out_native_os,
+                                                 state->out_native_lm,
+                                                 state->out_primary_domain);
+       if (tevent_req_nterror(req, status)) {
+               return;
        }
 
        ok = smb1cli_conn_activate_signing(cli->conn,
@@ -1701,7 +1835,6 @@ static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq)
                subreq, struct tevent_req);
        struct cli_session_setup_creds_state *state = tevent_req_data(
                req, struct cli_session_setup_creds_state);
-       struct cli_state *cli = state->cli;
        NTSTATUS status;
 
        status = smb1cli_session_setup_lm21_recv(subreq, state,
@@ -1714,11 +1847,12 @@ static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq)
                return;
        }
 
-       if (cli->server_os == NULL) {
-               cli->server_os = talloc_move(cli, &state->out_native_os);
-       }
-       if (cli->server_type == NULL) {
-               cli->server_type = talloc_move(cli, &state->out_native_lm);
+       status = cli_state_update_after_sesssetup(state->cli,
+                                                 state->out_native_os,
+                                                 state->out_native_lm,
+                                                 NULL);
+       if (tevent_req_nterror(req, status)) {
+               return;
        }
 
        tevent_req_done(req);
@@ -1775,43 +1909,6 @@ NTSTATUS cli_session_setup_anon(struct cli_state *cli)
        return NT_STATUS_OK;
 }
 
-NTSTATUS cli_session_setup(struct cli_state *cli,
-                          const char *user,
-                          const char *pass,
-                          const char *workgroup)
-{
-       NTSTATUS status = NT_STATUS_NO_MEMORY;
-       const char *dest_realm = NULL;
-       struct cli_credentials *creds = NULL;
-
-       /*
-        * dest_realm is only valid in the winbindd use case,
-        * where we also have the account in that realm.
-        */
-       dest_realm = cli_state_remote_realm(cli);
-
-       creds = cli_session_creds_init(cli,
-                                      user,
-                                      workgroup,
-                                      dest_realm,
-                                      pass,
-                                      cli->use_kerberos,
-                                      cli->fallback_after_kerberos,
-                                      cli->use_ccache,
-                                      cli->pw_nt_hash);
-       if (creds == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       status = cli_session_setup_creds(cli, creds);
-       TALLOC_FREE(creds);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-
-       return NT_STATUS_OK;
-}
-
 /****************************************************************************
  Send a uloggoff.
 *****************************************************************************/
@@ -1946,6 +2043,13 @@ struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
        state->cli = cli;
        vwv = state->vwv;
 
+       TALLOC_FREE(cli->smb1.tcon);
+       cli->smb1.tcon = smbXcli_tcon_create(cli);
+       if (tevent_req_nomem(cli->smb1.tcon, req)) {
+               return tevent_req_post(req, ev);
+       }
+       smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
+
        cli->share = talloc_strdup(cli, share);
        if (!cli->share) {
                return NULL;
@@ -2255,6 +2359,7 @@ static struct tevent_req *cli_tree_connect_send(
        if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
                char *unc;
 
+               TALLOC_FREE(cli->smb2.tcon);
                cli->smb2.tcon = smbXcli_tcon_create(cli);
                if (tevent_req_nomem(cli->smb2.tcon, req)) {
                        return tevent_req_post(req, ev);
@@ -2427,7 +2532,7 @@ static void cli_tdis_done(struct tevent_req *subreq)
                tevent_req_nterror(req, status);
                return;
        }
-       cli_state_set_tid(state->cli, UINT16_MAX);
+       TALLOC_FREE(state->cli->smb1.tcon);
        tevent_req_done(req);
 }
 
@@ -2443,10 +2548,14 @@ NTSTATUS cli_tdis(struct cli_state *cli)
        NTSTATUS status = NT_STATUS_NO_MEMORY;
 
        if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
-               return smb2cli_tdis(cli->conn,
+               status = smb2cli_tdis(cli->conn,
                                    cli->timeout,
                                    cli->smb2.session,
                                    cli->smb2.tcon);
+               if (NT_STATUS_IS_OK(status)) {
+                       TALLOC_FREE(cli->smb2.tcon);
+               }
+               return status;
        }
 
        if (smbXcli_conn_has_async_calls(cli->conn)) {
@@ -2491,7 +2600,6 @@ static struct tevent_req *cli_connect_sock_send(
 {
        struct tevent_req *req, *subreq;
        struct cli_connect_sock_state *state;
-       const char *prog;
        struct sockaddr_storage *addrs;
        unsigned i, num_addrs;
        NTSTATUS status;
@@ -2502,19 +2610,6 @@ static struct tevent_req *cli_connect_sock_send(
                return NULL;
        }
 
-       prog = getenv("LIBSMB_PROG");
-       if (prog != NULL) {
-               state->fd = sock_exec(prog);
-               if (state->fd == -1) {
-                       status = map_nt_error_from_unix(errno);
-                       tevent_req_nterror(req, status);
-               } else {
-                       state->port = 0;
-                       tevent_req_done(req);
-               }
-               return tevent_req_post(req, ev);
-       }
-
        if ((pss == NULL) || is_zero_addr(pss)) {
 
                /*
@@ -2672,7 +2767,7 @@ static void cli_connect_nb_done(struct tevent_req *subreq)
                return;
        }
 
-       state->cli = cli_state_create(state, fd, state->desthost, NULL,
+       state->cli = cli_state_create(state, fd, state->desthost,
                                      state->signing_state, state->flags);
        if (tevent_req_nomem(state->cli, req)) {
                close(fd);
@@ -2766,6 +2861,15 @@ static struct tevent_req *cli_start_connection_send(
                state->max_protocol = lp_client_max_protocol();
        }
 
+       if (flags & CLI_FULL_CONNECTION_FORCE_SMB1) {
+               state->max_protocol = MIN(state->max_protocol, PROTOCOL_NT1);
+       }
+
+       if (flags & CLI_FULL_CONNECTION_DISABLE_SMB1) {
+               state->min_protocol = MAX(state->max_protocol, PROTOCOL_SMB2_02);
+               state->max_protocol = MAX(state->max_protocol, PROTOCOL_LATEST);
+       }
+
        subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
                                     0x20, my_name, signing_state, flags);
        if (tevent_req_nomem(subreq, req)) {
@@ -2792,7 +2896,8 @@ static void cli_start_connection_connected(struct tevent_req *subreq)
        subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
                                      state->cli->timeout,
                                      state->min_protocol,
-                                     state->max_protocol);
+                                     state->max_protocol,
+                                     WINDOWS_CLIENT_PURE_SMB2_NEGPROT_INITIAL_CREDIT_ASK);
        if (tevent_req_nomem(subreq, req)) {
                return;
        }
@@ -2813,10 +2918,9 @@ static void cli_start_connection_done(struct tevent_req *subreq)
                return;
        }
 
-       if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
-               /* Ensure we ask for some initial credits. */
-               smb2cli_conn_set_max_credits(state->cli->conn,
-                                            DEFAULT_SMB2_MAX_CREDITS);
+       status = cli_state_update_after_negprot(state->cli);
+       if (tevent_req_nterror(req, status)) {
+               return;
        }
 
        tevent_req_done(req);
@@ -3012,8 +3116,6 @@ static struct tevent_req *cli_smb1_setup_encryption_send(TALLOC_CTX *mem_ctx,
        struct auth_generic_state *ags = NULL;
        const DATA_BLOB *b = NULL;
        bool auth_requested = false;
-       enum credentials_use_kerberos krb5_state;
-       const char *mech_oid = NULL;
        const char *target_service = NULL;
        const char *target_hostname = NULL;
        NTSTATUS status;
@@ -3035,30 +3137,9 @@ static struct tevent_req *cli_smb1_setup_encryption_send(TALLOC_CTX *mem_ctx,
        target_service = "cifs";
        target_hostname = smbXcli_conn_remote_name(cli->conn);
 
-       krb5_state = cli_credentials_get_kerberos_state(creds);
-       if (krb5_state == CRED_MUST_USE_KERBEROS) {
-               mech_oid = GENSEC_OID_SPNEGO;
-
-               b = smbXcli_conn_server_gss_blob(state->cli->conn);
-               if (b != NULL) {
-                       state->blob_in = *b;
-               }
-
-               status = cli_session_creds_prepare_krb5(cli, creds);
-               if (tevent_req_nterror(req, status)) {
-                       return tevent_req_post(req, ev);
-               }
-       } else {
-               /*
-                * Be compatible with the <= 4.5 client code,
-                * which used raw NTLMSSP unless kerberos
-                * was forced.
-                *
-                * We need to check with the oldest server implementation
-                * if we can remove this and always use
-                * GENSEC_OID_SPNEGO.
-                */
-               mech_oid = GENSEC_OID_NTLMSSP;
+       status = cli_session_creds_prepare_krb5(cli, creds);
+       if (tevent_req_nterror(req, status)) {
+               return tevent_req_post(req, ev);
        }
 
        state->es = talloc_zero(state, struct smb_trans_enc_state);
@@ -3100,7 +3181,12 @@ static struct tevent_req *cli_smb1_setup_encryption_send(TALLOC_CTX *mem_ctx,
        gensec_set_max_update_size(ags->gensec_security,
                                   CLI_BUFFER_SIZE);
 
-       status = auth_generic_client_start(ags, mech_oid);
+       b = smbXcli_conn_server_gss_blob(state->cli->conn);
+       if (b != NULL) {
+               state->blob_in = *b;
+       }
+
+       status = auth_generic_client_start(ags, GENSEC_OID_SPNEGO);
        if (tevent_req_nterror(req, status)) {
                return tevent_req_post(req, ev);
        }
@@ -3638,6 +3724,13 @@ static struct tevent_req *cli_raw_tcon_send(
                return tevent_req_post(req, ev);
        }
 
+       TALLOC_FREE(cli->smb1.tcon);
+       cli->smb1.tcon = smbXcli_tcon_create(cli);
+       if (tevent_req_nomem(cli->smb1.tcon, req)) {
+               return tevent_req_post(req, ev);
+       }
+       smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
+
        bytes = talloc_array(state, uint8_t, 0);
        bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
        bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
@@ -3733,6 +3826,8 @@ struct cli_state *get_ipc_connect(char *server,
                flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
        }
 
+       flags |= CLI_FULL_CONNECTION_FORCE_SMB1;
+
        nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC", 
                                        get_cmdline_auth_info_username(user_info),
                                        lp_workgroup(),