]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3:libsmb: provide generic cli_session_setup_gensec_send/recv() pair
authorStefan Metzmacher <metze@samba.org>
Tue, 1 Mar 2016 14:47:11 +0000 (15:47 +0100)
committerStefan Metzmacher <metze@samba.org>
Thu, 10 Mar 2016 05:52:30 +0000 (06:52 +0100)
It will be possible to use this for more than just NTLMSSP in future.

This prepares a fix for https://bugzilla.samba.org/show_bug.cgi?id=10288

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Günther Deschner <gd@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source3/libsmb/cliconnect.c

index 9f75b897fe01e57615faeb0bab5bb6855a4875e9..bb8d018c4683c65e9f9f24d0ac51058c7177634d 100644 (file)
@@ -1414,7 +1414,7 @@ static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
  Do a spnego/NTLMSSP encrypted session setup.
 ****************************************************************************/
 
-struct cli_session_setup_ntlmssp_state {
+struct cli_session_setup_gensec_state {
        struct tevent_context *ev;
        struct cli_state *cli;
        struct auth_generic_state *auth_generic;
@@ -1428,30 +1428,35 @@ struct cli_session_setup_ntlmssp_state {
        DATA_BLOB session_key;
 };
 
-static int cli_session_setup_ntlmssp_state_destructor(
-       struct cli_session_setup_ntlmssp_state *state)
+static int cli_session_setup_gensec_state_destructor(
+       struct cli_session_setup_gensec_state *state)
 {
        TALLOC_FREE(state->auth_generic);
        data_blob_clear_free(&state->session_key);
        return 0;
 }
 
-static void cli_session_setup_ntlmssp_local_next(struct tevent_req *req);
-static void cli_session_setup_ntlmssp_local_done(struct tevent_req *subreq);
-static void cli_session_setup_ntlmssp_remote_next(struct tevent_req *req);
-static void cli_session_setup_ntlmssp_remote_done(struct tevent_req *subreq);
-static void cli_session_setup_ntlmssp_ready(struct tevent_req *req);
+static void cli_session_setup_gensec_local_next(struct tevent_req *req);
+static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
+static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
+static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
+static void cli_session_setup_gensec_ready(struct tevent_req *req);
 
-static struct tevent_req *cli_session_setup_ntlmssp_send(
+static struct tevent_req *cli_session_setup_gensec_send(
        TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
-       const char *user, const char *pass, const char *domain)
+       const char *user, const char *pass, const char *domain,
+       enum credentials_use_kerberos krb5_state,
+       const char *target_service,
+       const char *target_hostname,
+       const char *target_principal)
 {
        struct tevent_req *req;
-       struct cli_session_setup_ntlmssp_state *state;
+       struct cli_session_setup_gensec_state *state;
        NTSTATUS status;
+       bool use_spnego_principal = lp_client_use_spnego_principal();
 
        req = tevent_req_create(mem_ctx, &state,
-                               struct cli_session_setup_ntlmssp_state);
+                               struct cli_session_setup_gensec_state);
        if (req == NULL) {
                return NULL;
        }
@@ -1459,7 +1464,7 @@ static struct tevent_req *cli_session_setup_ntlmssp_send(
        state->cli = cli;
 
        talloc_set_destructor(
-               state, cli_session_setup_ntlmssp_state_destructor);
+               state, cli_session_setup_gensec_state_destructor);
 
        status = auth_generic_client_prepare(state, &state->auth_generic);
        if (tevent_req_nterror(req, status)) {
@@ -1519,7 +1524,49 @@ static struct tevent_req *cli_session_setup_ntlmssp_send(
        }
 
        cli_credentials_set_kerberos_state(state->auth_generic->credentials,
-                                          CRED_DONT_USE_KERBEROS);
+                                          krb5_state);
+
+       if (krb5_state == CRED_DONT_USE_KERBEROS) {
+               use_spnego_principal = false;
+       }
+
+       if (target_service != NULL) {
+               status = gensec_set_target_service(
+                               state->auth_generic->gensec_security,
+                               target_service);
+               if (tevent_req_nterror(req, status)) {
+                       return tevent_req_post(req, ev);
+               }
+       }
+
+       if (target_hostname != NULL) {
+               status = gensec_set_target_hostname(
+                               state->auth_generic->gensec_security,
+                               target_hostname);
+               if (tevent_req_nterror(req, status)) {
+                       return tevent_req_post(req, ev);
+               }
+       }
+
+       if (target_principal != NULL) {
+               status = gensec_set_target_principal(
+                               state->auth_generic->gensec_security,
+                               target_principal);
+               if (tevent_req_nterror(req, status)) {
+                       return tevent_req_post(req, ev);
+               }
+               use_spnego_principal = false;
+       } else if (target_service != NULL && target_hostname != NULL) {
+               use_spnego_principal = false;
+       }
+
+       if (use_spnego_principal) {
+               const DATA_BLOB *b;
+               b = smbXcli_conn_server_gss_blob(cli->conn);
+               if (b != NULL) {
+                       state->blob_in = *b;
+               }
+       }
 
        state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
 
@@ -1537,7 +1584,7 @@ static struct tevent_req *cli_session_setup_ntlmssp_send(
                }
        }
 
-       cli_session_setup_ntlmssp_local_next(req);
+       cli_session_setup_gensec_local_next(req);
        if (!tevent_req_is_in_progress(req)) {
                return tevent_req_post(req, ev);
        }
@@ -1545,11 +1592,11 @@ static struct tevent_req *cli_session_setup_ntlmssp_send(
        return req;
 }
 
-static void cli_session_setup_ntlmssp_local_next(struct tevent_req *req)
+static void cli_session_setup_gensec_local_next(struct tevent_req *req)
 {
-       struct cli_session_setup_ntlmssp_state *state =
+       struct cli_session_setup_gensec_state *state =
                tevent_req_data(req,
-               struct cli_session_setup_ntlmssp_state);
+               struct cli_session_setup_gensec_state);
        struct tevent_req *subreq = NULL;
 
        if (state->local_ready) {
@@ -1563,17 +1610,17 @@ static void cli_session_setup_ntlmssp_local_next(struct tevent_req *req)
        if (tevent_req_nomem(subreq, req)) {
                return;
        }
-       tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_local_done, req);
+       tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
 }
 
-static void cli_session_setup_ntlmssp_local_done(struct tevent_req *subreq)
+static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
 {
        struct tevent_req *req =
                tevent_req_callback_data(subreq,
                struct tevent_req);
-       struct cli_session_setup_ntlmssp_state *state =
+       struct cli_session_setup_gensec_state *state =
                tevent_req_data(req,
-               struct cli_session_setup_ntlmssp_state);
+               struct cli_session_setup_gensec_state);
        NTSTATUS status;
 
        status = gensec_update_recv(subreq, state, &state->blob_out);
@@ -1591,18 +1638,18 @@ static void cli_session_setup_ntlmssp_local_done(struct tevent_req *subreq)
        }
 
        if (state->local_ready && state->remote_ready) {
-               cli_session_setup_ntlmssp_ready(req);
+               cli_session_setup_gensec_ready(req);
                return;
        }
 
-       cli_session_setup_ntlmssp_remote_next(req);
+       cli_session_setup_gensec_remote_next(req);
 }
 
-static void cli_session_setup_ntlmssp_remote_next(struct tevent_req *req)
+static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
 {
-       struct cli_session_setup_ntlmssp_state *state =
+       struct cli_session_setup_gensec_state *state =
                tevent_req_data(req,
-               struct cli_session_setup_ntlmssp_state);
+               struct cli_session_setup_gensec_state);
        struct tevent_req *subreq = NULL;
 
        if (state->remote_ready) {
@@ -1616,18 +1663,18 @@ static void cli_session_setup_ntlmssp_remote_next(struct tevent_req *req)
                return;
        }
        tevent_req_set_callback(subreq,
-                               cli_session_setup_ntlmssp_remote_done,
+                               cli_session_setup_gensec_remote_done,
                                req);
 }
 
-static void cli_session_setup_ntlmssp_remote_done(struct tevent_req *subreq)
+static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
 {
        struct tevent_req *req =
                tevent_req_callback_data(subreq,
                struct tevent_req);
-       struct cli_session_setup_ntlmssp_state *state =
+       struct cli_session_setup_gensec_state *state =
                tevent_req_data(req,
-               struct cli_session_setup_ntlmssp_state);
+               struct cli_session_setup_gensec_state);
        NTSTATUS status;
 
        TALLOC_FREE(state->inbuf);
@@ -1649,18 +1696,18 @@ static void cli_session_setup_ntlmssp_remote_done(struct tevent_req *subreq)
        }
 
        if (state->local_ready && state->remote_ready) {
-               cli_session_setup_ntlmssp_ready(req);
+               cli_session_setup_gensec_ready(req);
                return;
        }
 
-       cli_session_setup_ntlmssp_local_next(req);
+       cli_session_setup_gensec_local_next(req);
 }
 
-static void cli_session_setup_ntlmssp_ready(struct tevent_req *req)
+static void cli_session_setup_gensec_ready(struct tevent_req *req)
 {
-       struct cli_session_setup_ntlmssp_state *state =
+       struct cli_session_setup_gensec_state *state =
                tevent_req_data(req,
-               struct cli_session_setup_ntlmssp_state);
+               struct cli_session_setup_gensec_state);
        const char *server_domain = NULL;
        NTSTATUS status;
 
@@ -1675,6 +1722,9 @@ static void cli_session_setup_ntlmssp_ready(struct tevent_req *req)
        }
 
        /*
+        * 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.
@@ -1749,11 +1799,11 @@ static void cli_session_setup_ntlmssp_ready(struct tevent_req *req)
        tevent_req_done(req);
 }
 
-static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
+static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
 {
-       struct cli_session_setup_ntlmssp_state *state =
+       struct cli_session_setup_gensec_state *state =
                tevent_req_data(req,
-               struct cli_session_setup_ntlmssp_state);
+               struct cli_session_setup_gensec_state);
        NTSTATUS status;
 
        if (tevent_req_is_nterror(req, &status)) {
@@ -1833,6 +1883,7 @@ static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
 struct cli_session_setup_spnego_state {
        struct tevent_context *ev;
        struct cli_state *cli;
+       const char *target_hostname;
        const char *user;
        const char *account;
        const char *pass;
@@ -1876,6 +1927,7 @@ static struct tevent_req *cli_session_setup_spnego_send(
                return tevent_req_post(req, ev);
        }
 
+       state->target_hostname = smbXcli_conn_remote_name(cli->conn);
        server_blob = smbXcli_conn_server_gss_blob(cli->conn);
 
        DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
@@ -1923,12 +1975,10 @@ static struct tevent_req *cli_session_setup_spnego_send(
         * and do not store results */
 
        if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
-               const char *remote_name = smbXcli_conn_remote_name(cli->conn);
                char *tmp;
 
-
                tmp = cli_session_setup_get_principal(
-                       talloc_tos(), principal, remote_name, dest_realm);
+                       talloc_tos(), principal, state->target_hostname, dest_realm);
                TALLOC_FREE(principal);
                principal = tmp;
 
@@ -1964,8 +2014,11 @@ static struct tevent_req *cli_session_setup_spnego_send(
 #endif
 
 ntlmssp:
-       subreq = cli_session_setup_ntlmssp_send(
-               state, ev, cli, state->account, pass, user_domain);
+       subreq = cli_session_setup_gensec_send(
+               state, state->ev, state->cli,
+               state->account, state->pass, state->user_domain,
+               CRED_DONT_USE_KERBEROS,
+               "cifs", state->target_hostname, NULL);
        if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
        }
@@ -1991,9 +2044,11 @@ static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq)
                return;
        }
 
-       subreq = cli_session_setup_ntlmssp_send(
-               state, state->ev, state->cli, state->account, state->pass,
-               state->user_domain);
+       subreq = cli_session_setup_gensec_send(
+               state, state->ev, state->cli,
+               state->account, state->pass, state->user_domain,
+               CRED_DONT_USE_KERBEROS,
+               "cifs", state->target_hostname, NULL);
        if (tevent_req_nomem(subreq, req)) {
                return;
        }
@@ -2010,7 +2065,7 @@ static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq)
                req, struct cli_session_setup_spnego_state);
        NTSTATUS status;
 
-       status = cli_session_setup_ntlmssp_recv(subreq);
+       status = cli_session_setup_gensec_recv(subreq);
        TALLOC_FREE(subreq);
        state->result = ADS_ERROR_NT(status);
        tevent_req_done(req);