s4/libcli: do not use netbios name in NTLMv2 blobs w/o spnego
[mat/samba.git] / source4 / libcli / smb_composite / sesssetup.c
index 92b49dc3d4028839dd77ddb4ab4b3aa986116e7b..ebc35983d213a00ca3b1134a39ee0d9f660494ac 100644 (file)
@@ -80,13 +80,15 @@ static void set_user_session_key(struct smbcli_session *session,
 */
 static void request_handler(struct smbcli_request *req)
 {
-       struct composite_context *c = (struct composite_context *)req->async.private;
+       struct composite_context *c = (struct composite_context *)req->async.private_data;
        struct sesssetup_state *state = talloc_get_type(c->private_data, struct sesssetup_state);
        struct smbcli_session *session = req->session;
        DATA_BLOB session_key = data_blob(NULL, 0);
        DATA_BLOB null_data_blob = data_blob(NULL, 0);
        NTSTATUS session_key_err, nt_status;
        struct smbcli_request *check_req = NULL;
+       const char *os = NULL;
+       const char *lanman = NULL;
 
        if (req->sign_caller_checks) {
                req->do_not_free = true;
@@ -97,6 +99,15 @@ static void request_handler(struct smbcli_request *req)
        c->status = state->remote_status;
        state->req = NULL;
 
+       /*
+        * we only need to check the signature if the
+        * NT_STATUS_OK is returned
+        */
+       if (!NT_STATUS_IS_OK(state->remote_status)) {
+               talloc_free(check_req);
+               check_req = NULL;
+       }
+
        switch (state->setup.old.level) {
        case RAW_SESSSETUP_OLD:
                state->io->out.vuid = state->setup.old.out.vuid;
@@ -117,6 +128,8 @@ static void request_handler(struct smbcli_request *req)
                                }
                        }
                }
+               os = state->setup.old.out.os;
+               lanman = state->setup.old.out.lanman;
                break;
 
        case RAW_SESSSETUP_NT1:
@@ -136,6 +149,8 @@ static void request_handler(struct smbcli_request *req)
                                }
                        }
                }
+               os = state->setup.nt1.out.os;
+               lanman = state->setup.nt1.out.lanman;
                break;
 
        case RAW_SESSSETUP_SPNEGO:
@@ -207,6 +222,8 @@ static void request_handler(struct smbcli_request *req)
                        composite_continue_smb(c, state->req, request_handler, c);
                        return;
                }
+               os = state->setup.spnego.out.os;
+               lanman = state->setup.spnego.out.lanman;
                break;
 
        case RAW_SESSSETUP_SMB2:
@@ -237,6 +254,19 @@ static void request_handler(struct smbcli_request *req)
                return;
        }
 
+       if (os) {
+               session->os = talloc_strdup(session, os);
+               if (composite_nomem(session->os, c)) return;
+       } else {
+               session->os = NULL;
+       }
+       if (lanman) {
+               session->lanman = talloc_strdup(session, lanman);
+               if (composite_nomem(session->lanman, c)) return;
+       } else {
+               session->lanman = NULL;
+       }
+
        composite_done(c);
 }
 
@@ -250,8 +280,17 @@ static NTSTATUS session_setup_nt1(struct composite_context *c,
                                  struct smbcli_request **req) 
 {
        NTSTATUS nt_status = NT_STATUS_INTERNAL_ERROR;
-       struct sesssetup_state *state = talloc_get_type(c->private_data, struct sesssetup_state);
-       DATA_BLOB names_blob = NTLMv2_generate_names_blob(state, lp_iconv_convenience(global_loadparm), session->transport->socket->hostname, lp_workgroup(global_loadparm));
+       struct sesssetup_state *state = talloc_get_type(c->private_data,
+                                                       struct sesssetup_state);
+       const char *domain = cli_credentials_get_domain(io->in.credentials);
+
+       /*
+        * domain controllers tend to reject the NTLM v2 blob
+        * if the netbiosname is not valid (e.g. IP address or FQDN)
+        * so just leave it away (as Windows client do)
+        */
+       DATA_BLOB names_blob = NTLMv2_generate_names_blob(state, NULL, domain);
+
        DATA_BLOB session_key = data_blob(NULL, 0);
        int flags = CLI_CRED_NTLM_AUTH;
 
@@ -323,9 +362,18 @@ static NTSTATUS session_setup_old(struct composite_context *c,
                                  struct smbcli_request **req) 
 {
        NTSTATUS nt_status;
-       struct sesssetup_state *state = talloc_get_type(c->private_data, struct sesssetup_state);
+       struct sesssetup_state *state = talloc_get_type(c->private_data,
+                                                       struct sesssetup_state);
        const char *password = cli_credentials_get_password(io->in.credentials);
-       DATA_BLOB names_blob = NTLMv2_generate_names_blob(state, lp_iconv_convenience(global_loadparm), session->transport->socket->hostname, lp_workgroup(global_loadparm));
+       const char *domain = cli_credentials_get_domain(io->in.credentials);
+
+       /*
+        * domain controllers tend to reject the NTLM v2 blob
+        * if the netbiosname is not valid (e.g. IP address or FQDN)
+        * so just leave it away (as Windows client do)
+        */
+       DATA_BLOB names_blob = NTLMv2_generate_names_blob(state, NULL, domain);
+
        DATA_BLOB session_key;
        int flags = 0;
        if (session->options.lanman_auth) {
@@ -399,7 +447,7 @@ static NTSTATUS session_setup_spnego(struct composite_context *c,
        smbcli_temp_set_signing(session->transport);
 
        status = gensec_client_start(session, &session->gensec, c->event_ctx,
-                                    global_loadparm);
+                                    io->in.gensec_settings);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(1, ("Failed to start GENSEC client mode: %s\n", nt_errstr(status)));
                return status;
@@ -433,12 +481,13 @@ static NTSTATUS session_setup_spnego(struct composite_context *c,
                status = gensec_start_mech_by_oid(session->gensec, chosen_oid);
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(1, ("Failed to start set GENSEC client mechanism %s: %s\n",
-                                 gensec_get_name_by_oid(chosen_oid), nt_errstr(status)));
+                                 gensec_get_name_by_oid(session->gensec, chosen_oid), nt_errstr(status)));
                        chosen_oid = GENSEC_OID_NTLMSSP;
                        status = gensec_start_mech_by_oid(session->gensec, chosen_oid);
                        if (!NT_STATUS_IS_OK(status)) {
                                DEBUG(1, ("Failed to start set (fallback) GENSEC client mechanism %s: %s\n",
-                                         gensec_get_name_by_oid(chosen_oid), nt_errstr(status)));
+                                         gensec_get_name_by_oid(session->gensec, chosen_oid), 
+                                         nt_errstr(status)));
                        return status;
                        }
                }
@@ -448,7 +497,7 @@ static NTSTATUS session_setup_spnego(struct composite_context *c,
                status = gensec_start_mech_by_oid(session->gensec, chosen_oid);
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(1, ("Failed to start set GENSEC client mechanism %s: %s\n",
-                                 gensec_get_name_by_oid(chosen_oid), nt_errstr(status)));
+                                 gensec_get_name_by_oid(session->gensec, chosen_oid), nt_errstr(status)));
                }
        }
 
@@ -466,7 +515,8 @@ static NTSTATUS session_setup_spnego(struct composite_context *c,
        if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && 
            !NT_STATUS_IS_OK(status)) {
                DEBUG(1, ("Failed initial gensec_update with mechanism %s: %s\n",
-                         gensec_get_name_by_oid(chosen_oid), nt_errstr(status)));
+                         gensec_get_name_by_oid(session->gensec, chosen_oid), 
+                         nt_errstr(status)));
                return status;
        }
        state->gensec_status = status;