CVE-2016-2110: winbindd: add new_spnego to the WINBINDD_CCACHE_NTLMAUTH response
authorStefan Metzmacher <metze@samba.org>
Fri, 20 Nov 2015 13:06:18 +0000 (14:06 +0100)
committerStefan Metzmacher <metze@samba.org>
Tue, 12 Apr 2016 17:25:22 +0000 (19:25 +0200)
We don't need to change the protocol version because:

1. An old client may provide the "initial_blob"
   (which was and is still ignored when going
   via the wbcCredentialCache() function)
   and the new winbindd won't use new_spnego.

2. A new client will just get a zero byte
   from an old winbindd. As it uses talloc_zero() to
   create struct winbindd_response.

3. Changing the version number would introduce problems
   with backports to older Samba versions.

New clients which are capable of using the new_spnego field
will use "negotiate_blob" instead of "initial_blob".

BUG: https://bugzilla.samba.org/show_bug.cgi?id=11644

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: G√ľnther Deschner <gd@samba.org>
nsswitch/libwbclient/wbc_pam.c
nsswitch/winbind_struct_protocol.h
source3/winbindd/winbindd_ccache_access.c

index 672cf3733420bea827fff8965cba49d09d08075f..0d1b90c75fd6af7f75138389c083e8eb327754da 100644 (file)
@@ -1286,7 +1286,17 @@ wbcErr wbcCtxCredentialCache(struct wbcContext *ctx,
        }
 
        for (i=0; i<params->num_blobs; i++) {
        }
 
        for (i=0; i<params->num_blobs; i++) {
-               if (strcasecmp(params->blobs[i].name, "initial_blob") == 0) {
+               /*
+                * Older callers may used to provide the NEGOTIATE request
+                * as "initial_blob", but it was completely ignored by winbindd.
+                *
+                * So we keep ignoring it.
+                *
+                * A new callers that is capable to support "new_spnego",
+                * will provide the NEGOTIATE request as "negotiate_blob"
+                * instead.
+                */
+               if (strcasecmp(params->blobs[i].name, "negotiate_blob") == 0) {
                        if (initial_blob != NULL) {
                                status = WBC_ERR_INVALID_PARAM;
                                goto fail;
                        if (initial_blob != NULL) {
                                status = WBC_ERR_INVALID_PARAM;
                                goto fail;
@@ -1384,6 +1394,15 @@ wbcErr wbcCtxCredentialCache(struct wbcContext *ctx,
        if (!WBC_ERROR_IS_OK(status)) {
                goto fail;
        }
        if (!WBC_ERROR_IS_OK(status)) {
                goto fail;
        }
+       if (response.data.ccache_ntlm_auth.new_spnego) {
+               status = wbcAddNamedBlob(
+                       &result->num_blobs, &result->blobs, "new_spnego", 0,
+                       &response.data.ccache_ntlm_auth.new_spnego,
+                       sizeof(response.data.ccache_ntlm_auth.new_spnego));
+               if (!WBC_ERROR_IS_OK(status)) {
+                       goto fail;
+               }
+       }
 
        *info = result;
        result = NULL;
 
        *info = result;
        result = NULL;
index 622dcfef23204a1374201e9a9e6d5bb366f4cd2e..84829d2da74286bc7bd08e071c5a2d6ab6604098 100644 (file)
@@ -488,6 +488,7 @@ struct winbindd_response {
                struct {
                        uint8_t session_key[16];
                        uint32_t auth_blob_len; /* blob in extra_data */
                struct {
                        uint8_t session_key[16];
                        uint32_t auth_blob_len; /* blob in extra_data */
+                       uint8_t new_spnego;
                } ccache_ntlm_auth;
                struct {
                        fstring dc_unc;
                } ccache_ntlm_auth;
                struct {
                        fstring dc_unc;
index ddedf6a020802c3d78c022f268370280999d0e16..039e653401322dc21809f83846de7420277982ae 100644 (file)
@@ -50,7 +50,8 @@ static NTSTATUS do_ntlm_auth_with_stored_pw(const char *username,
                                            const DATA_BLOB challenge_msg,
                                            TALLOC_CTX *mem_ctx,
                                            DATA_BLOB *auth_msg,
                                            const DATA_BLOB challenge_msg,
                                            TALLOC_CTX *mem_ctx,
                                            DATA_BLOB *auth_msg,
-                                           uint8_t session_key[16])
+                                           uint8_t session_key[16],
+                                           uint8_t *new_spnego)
 {
        NTSTATUS status;
        struct auth_generic_state *auth_generic_state = NULL;
 {
        NTSTATUS status;
        struct auth_generic_state *auth_generic_state = NULL;
@@ -144,6 +145,8 @@ static NTSTATUS do_ntlm_auth_with_stored_pw(const char *username,
        memcpy(session_key, session_key_blob.data, 16);
        data_blob_free(&session_key_blob);
        *auth_msg = reply;
        memcpy(session_key, session_key_blob.data, 16);
        data_blob_free(&session_key_blob);
        *auth_msg = reply;
+       *new_spnego = gensec_have_feature(auth_generic_state->gensec_security,
+                                         GENSEC_FEATURE_NEW_SPNEGO);
        status = NT_STATUS_OK;
 
 done:
        status = NT_STATUS_OK;
 
 done:
@@ -272,7 +275,8 @@ void winbindd_ccache_ntlm_auth(struct winbindd_cli_state *state)
        result = do_ntlm_auth_with_stored_pw(
                name_user, name_domain, entry->pass,
                initial, challenge, talloc_tos(), &auth,
        result = do_ntlm_auth_with_stored_pw(
                name_user, name_domain, entry->pass,
                initial, challenge, talloc_tos(), &auth,
-               state->response->data.ccache_ntlm_auth.session_key);
+               state->response->data.ccache_ntlm_auth.session_key,
+               &state->response->data.ccache_ntlm_auth.new_spnego);
 
        if (!NT_STATUS_IS_OK(result)) {
                goto process_result;
 
        if (!NT_STATUS_IS_OK(result)) {
                goto process_result;