]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
auth/ntlmssp: provide a "ntlmssp_resume_ccache" backend
authorStefan Metzmacher <metze@samba.org>
Wed, 25 Nov 2015 20:41:23 +0000 (21:41 +0100)
committerStefan Metzmacher <metze@samba.org>
Thu, 10 Mar 2016 05:52:28 +0000 (06:52 +0100)
These can be used to implement the winbindd side of
the WINBINDD_CCACHE_NTLMAUTH call.

It can properly get the initial NEGOTIATE messages
injected if available.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Günther Deschner <gd@samba.org>
auth/ntlmssp/ntlmssp.c
auth/ntlmssp/ntlmssp.h
auth/ntlmssp/ntlmssp_client.c
auth/ntlmssp/ntlmssp_private.h

index 0b7667c5e20e3aa27ba17e0b479e667eccbefb26..091fdab9e4a8cdd99b468104ad720e6a062106d7 100644 (file)
@@ -47,6 +47,10 @@ static const struct ntlmssp_callbacks {
                .role           = NTLMSSP_CLIENT,
                .command        = NTLMSSP_INITIAL,
                .sync_fn        = ntlmssp_client_initial,
+       },{
+               .role           = NTLMSSP_CLIENT,
+               .command        = NTLMSSP_NEGOTIATE,
+               .sync_fn        = gensec_ntlmssp_resume_ccache,
        },{
                .role           = NTLMSSP_SERVER,
                .command        = NTLMSSP_NEGOTIATE,
@@ -82,6 +86,15 @@ static NTSTATUS gensec_ntlmssp_update_find(struct gensec_security *gensec_securi
        if (!input.length) {
                switch (gensec_ntlmssp->ntlmssp_state->role) {
                case NTLMSSP_CLIENT:
+                       if (gensec_ntlmssp->ntlmssp_state->resume_ccache) {
+                               /*
+                                * make sure gensec_ntlmssp_resume_ccache()
+                                * will be called
+                                */
+                               ntlmssp_command = NTLMSSP_NEGOTIATE;
+                               break;
+                       }
+
                        ntlmssp_command = NTLMSSP_INITIAL;
                        break;
                case NTLMSSP_SERVER:
@@ -194,6 +207,15 @@ static const struct gensec_security_ops gensec_ntlmssp_security_ops = {
        .priority       = GENSEC_NTLMSSP
 };
 
+static const struct gensec_security_ops gensec_ntlmssp_resume_ccache_ops = {
+       .name           = "ntlmssp_resume_ccache",
+       .client_start   = gensec_ntlmssp_resume_ccache_start,
+       .update         = gensec_ntlmssp_update,
+       .session_key    = gensec_ntlmssp_session_key,
+       .have_feature   = gensec_ntlmssp_have_feature,
+       .enabled        = true,
+       .priority       = GENSEC_NTLMSSP
+};
 
 _PUBLIC_ NTSTATUS gensec_ntlmssp_init(void)
 {
@@ -206,6 +228,13 @@ _PUBLIC_ NTSTATUS gensec_ntlmssp_init(void)
                return ret;
        }
 
+       ret = gensec_register(&gensec_ntlmssp_resume_ccache_ops);
+       if (!NT_STATUS_IS_OK(ret)) {
+               DEBUG(0,("Failed to register '%s' gensec backend!\n",
+                       gensec_ntlmssp_resume_ccache_ops.name));
+               return ret;
+       }
+
        return ret;
 }
 
index b357e42d362a3a63ca6b2790cececc40c81dfb50..4d2ddf9c12e9b49d6065bbc74f96fc6337706222 100644 (file)
@@ -62,6 +62,7 @@ struct ntlmssp_state
        bool unicode;
        bool use_ntlmv2;
        bool use_ccache;
+       bool resume_ccache;
        bool use_nt_response;  /* Set to 'False' to debug what happens when the NT response is omited */
        bool allow_lm_key;     /* The LM_KEY code is not very secure... */
 
index 1ac09960724267ad3d0aa61403a4e946967cac07..df29aa22552eac6181d405c2e752d3c2e8cb9f70 100644 (file)
@@ -114,6 +114,98 @@ NTSTATUS ntlmssp_client_initial(struct gensec_security *gensec_security,
        return NT_STATUS_MORE_PROCESSING_REQUIRED;
 }
 
+NTSTATUS gensec_ntlmssp_resume_ccache(struct gensec_security *gensec_security,
+                               TALLOC_CTX *out_mem_ctx,
+                               DATA_BLOB in, DATA_BLOB *out)
+{
+       struct gensec_ntlmssp_context *gensec_ntlmssp =
+               talloc_get_type_abort(gensec_security->private_data,
+                                     struct gensec_ntlmssp_context);
+       struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
+       uint32_t neg_flags = 0;
+       uint32_t ntlmssp_command;
+       NTSTATUS status;
+       bool ok;
+
+       *out = data_blob_null;
+
+       if (in.length == 0) {
+               /*
+                * This is compat code for older callers
+                * which were missing the "initial_blob"
+                */
+               ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
+               return NT_STATUS_MORE_PROCESSING_REQUIRED;
+       }
+
+       /* parse the NTLMSSP packet */
+
+       if (in.length > UINT16_MAX) {
+               DEBUG(1, ("%s: reject large request of length %u\n",
+                       __func__, (unsigned int)in.length));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       ok = msrpc_parse(ntlmssp_state, &in, "Cdd",
+                        "NTLMSSP",
+                        &ntlmssp_command,
+                        &neg_flags);
+       if (!ok) {
+               DEBUG(1, ("%s: failed to parse NTLMSSP Negotiate of length %u\n",
+                       __func__, (unsigned int)in.length));
+               dump_data(2, in.data, in.length);
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (ntlmssp_command != NTLMSSP_NEGOTIATE) {
+               DEBUG(1, ("%s: no NTLMSSP Negotiate message (length %u)\n",
+                       __func__, (unsigned int)in.length));
+               dump_data(2, in.data, in.length);
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       ntlmssp_state->neg_flags = neg_flags;
+       DEBUG(3, ("Imported Negotiate flags:\n"));
+       debug_ntlmssp_flags(neg_flags);
+
+       if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_UNICODE) {
+               ntlmssp_state->unicode = true;
+       } else {
+               ntlmssp_state->unicode = false;
+       }
+
+       if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) {
+               gensec_security->want_features |= GENSEC_FEATURE_SIGN;
+
+               ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
+       }
+
+       if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
+               gensec_security->want_features |= GENSEC_FEATURE_SEAL;
+
+               ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
+               ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
+       }
+
+       if (DEBUGLEVEL >= 10) {
+               struct NEGOTIATE_MESSAGE *negotiate = talloc(
+                       ntlmssp_state, struct NEGOTIATE_MESSAGE);
+               if (negotiate != NULL) {
+                       status = ntlmssp_pull_NEGOTIATE_MESSAGE(
+                               &in, negotiate, negotiate);
+                       if (NT_STATUS_IS_OK(status)) {
+                               NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE,
+                                               negotiate);
+                       }
+                       TALLOC_FREE(negotiate);
+               }
+       }
+
+       ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
+
+       return NT_STATUS_MORE_PROCESSING_REQUIRED;
+}
+
 /**
  * Next state function for the Challenge Packet.  Generate an auth packet.
  *
@@ -476,3 +568,22 @@ NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
 
        return NT_STATUS_OK;
 }
+
+NTSTATUS gensec_ntlmssp_resume_ccache_start(struct gensec_security *gensec_security)
+{
+       struct gensec_ntlmssp_context *gensec_ntlmssp = NULL;
+       NTSTATUS status;
+
+       status = gensec_ntlmssp_client_start(gensec_security);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       gensec_ntlmssp = talloc_get_type_abort(gensec_security->private_data,
+                                              struct gensec_ntlmssp_context);
+       gensec_ntlmssp->ntlmssp_state->use_ccache = false;
+       gensec_ntlmssp->ntlmssp_state->resume_ccache = true;
+       gensec_ntlmssp->ntlmssp_state->expected_state = NTLMSSP_NEGOTIATE;
+
+       return NT_STATUS_OK;
+}
index 778d638b2ad2c842e4a178f5f31ddb765e297521..ea5703ffeeae4c60aa891c7c1f869b5f71355d22 100644 (file)
@@ -88,6 +88,10 @@ NTSTATUS ntlmssp_client_initial(struct gensec_security *gensec_security,
                                TALLOC_CTX *out_mem_ctx,
                                DATA_BLOB in, DATA_BLOB *out) ;
 
+NTSTATUS gensec_ntlmssp_resume_ccache(struct gensec_security *gensec_security,
+                               TALLOC_CTX *out_mem_ctx,
+                               DATA_BLOB in, DATA_BLOB *out);
+
 /**
  * Next state function for the Challenge Packet.  Generate an auth packet.
  *
@@ -101,6 +105,7 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
                                  TALLOC_CTX *out_mem_ctx,
                                  const DATA_BLOB in, DATA_BLOB *out) ;
 NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security);
+NTSTATUS gensec_ntlmssp_resume_ccache_start(struct gensec_security *gensec_security);
 
 /* The following definitions come from auth/ntlmssp/gensec_ntlmssp_server.c  */