lib/crypto: move gnutls error wrapper to own subsystem
[samba.git] / auth / ntlmssp / ntlmssp_client.c
index 5edd5f4fce64cd6f40d1d2c1a295640c1304b020..df891f8d93306a10878bf2ce0cf78d106a2dfaae 100644 (file)
@@ -25,7 +25,6 @@ struct auth_session_info;
 
 #include "includes.h"
 #include "auth/ntlmssp/ntlmssp.h"
-#include "../lib/crypto/crypto.h"
 #include "../libcli/auth/libcli_auth.h"
 #include "auth/credentials/credentials.h"
 #include "auth/gensec/gensec.h"
@@ -36,6 +35,13 @@ struct auth_session_info;
 #include "../auth/ntlmssp/ntlmssp_ndr.h"
 #include "../nsswitch/libwbclient/wbclient.h"
 
+#include "lib/crypto/gnutls_helpers.h"
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_AUTH
+
 /*********************************************************************
  Client side NTLMSSP
 *********************************************************************/
@@ -245,7 +251,8 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
        const NTTIME *server_timestamp = NULL;
        uint8_t mic_buffer[NTLMSSP_MIC_SIZE] = { 0, };
        DATA_BLOB mic_blob = data_blob_const(mic_buffer, sizeof(mic_buffer));
-       HMACMD5Context ctx;
+       gnutls_hmac_hd_t hmac_hnd = NULL;
+       int rc;
 
        TALLOC_CTX *mem_ctx = talloc_new(out_mem_ctx);
        if (!mem_ctx) {
@@ -339,6 +346,22 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
                }
        }
 
+       if (DEBUGLEVEL >= 10) {
+               struct CHALLENGE_MESSAGE *challenge =
+                       talloc(ntlmssp_state, struct CHALLENGE_MESSAGE);
+               if (challenge != NULL) {
+                       NTSTATUS status;
+                       challenge->NegotiateFlags = chal_flags;
+                       status = ntlmssp_pull_CHALLENGE_MESSAGE(
+                                       &in, challenge, challenge);
+                       if (NT_STATUS_IS_OK(status)) {
+                               NDR_PRINT_DEBUG(CHALLENGE_MESSAGE,
+                                               challenge);
+                       }
+                       TALLOC_FREE(challenge);
+               }
+       }
+
        if (chal_flags & NTLMSSP_TARGET_TYPE_SERVER) {
                ntlmssp_state->server.is_standalone = true;
        } else {
@@ -699,6 +722,22 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
                return nt_status;
        }
 
+       if (DEBUGLEVEL >= 10) {
+               struct AUTHENTICATE_MESSAGE *authenticate =
+                       talloc(ntlmssp_state, struct AUTHENTICATE_MESSAGE);
+               if (authenticate != NULL) {
+                       NTSTATUS status;
+                       authenticate->NegotiateFlags = ntlmssp_state->neg_flags;
+                       status = ntlmssp_pull_AUTHENTICATE_MESSAGE(
+                               out, authenticate, authenticate);
+                       if (NT_STATUS_IS_OK(status)) {
+                               NDR_PRINT_DEBUG(AUTHENTICATE_MESSAGE,
+                                               authenticate);
+                       }
+                       TALLOC_FREE(authenticate);
+               }
+       }
+
        /*
         * We always include the MIC, even without:
         * av_flags->Value.AvFlags |= NTLMSSP_AVFLAG_MIC_IN_AUTHENTICATE_MESSAGE;
@@ -706,18 +745,45 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
         *
         * This matches a Windows client.
         */
-       hmac_md5_init_limK_to_64(session_key.data,
-                                session_key.length,
-                                &ctx);
-       hmac_md5_update(ntlmssp_state->negotiate_blob.data,
-                       ntlmssp_state->negotiate_blob.length,
-                       &ctx);
-       hmac_md5_update(in.data, in.length, &ctx);
-       hmac_md5_update(out->data, out->length, &ctx);
-       hmac_md5_final(mic_buffer, &ctx);
+       rc = gnutls_hmac_init(&hmac_hnd,
+                             GNUTLS_MAC_MD5,
+                        session_key.data,
+                        MIN(session_key.length, 64));
+       if (rc < 0) {
+               nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED);
+               goto done;
+       }
+
+       rc = gnutls_hmac(hmac_hnd,
+                        ntlmssp_state->negotiate_blob.data,
+                        ntlmssp_state->negotiate_blob.length);
+       if (rc < 0) {
+               gnutls_hmac_deinit(hmac_hnd, NULL);
+               nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED);
+               goto done;
+       }
+       rc = gnutls_hmac(hmac_hnd, in.data, in.length);
+       if (rc < 0) {
+               gnutls_hmac_deinit(hmac_hnd, NULL);
+               nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED);
+               goto done;
+       }
+       rc = gnutls_hmac(hmac_hnd, out->data, out->length);
+       if (rc < 0) {
+               gnutls_hmac_deinit(hmac_hnd, NULL);
+               nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED);
+               goto done;
+       }
+
+       gnutls_hmac_deinit(hmac_hnd, mic_buffer);
+
        memcpy(out->data + NTLMSSP_MIC_OFFSET, mic_buffer, NTLMSSP_MIC_SIZE);
+       ZERO_ARRAY(mic_buffer);
 
+       nt_status = NT_STATUS_OK;
 done:
+       ZERO_ARRAY_LEN(ntlmssp_state->negotiate_blob.data,
+                      ntlmssp_state->negotiate_blob.length);
        data_blob_free(&ntlmssp_state->negotiate_blob);
 
        ntlmssp_state->session_key = session_key;
@@ -741,7 +807,7 @@ done:
        }
 
        talloc_free(mem_ctx);
-       return NT_STATUS_OK;
+       return nt_status;
 }
 
 NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
@@ -774,7 +840,11 @@ NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
 
        ntlmssp_state->unicode = gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "unicode", true);
 
-       ntlmssp_state->use_nt_response = gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "send_nt_reponse", true);
+       ntlmssp_state->use_nt_response = \
+               gensec_setting_bool(gensec_security->settings,
+                                   "ntlmssp_client",
+                                   "send_nt_response",
+                                   true);
 
        ntlmssp_state->allow_lm_response = lpcfg_client_lanman_auth(gensec_security->settings->lp_ctx);
 
@@ -862,13 +932,23 @@ NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
                         * is requested.
                         */
                        ntlmssp_state->force_wrap_seal = true;
-                       /*
-                        * We want also work against old Samba servers
-                        * which didn't had GENSEC_FEATURE_LDAP_STYLE
-                        * we negotiate SEAL too. We may remove this
-                        * in a few years. As all servers should have
-                        * GENSEC_FEATURE_LDAP_STYLE by then.
-                        */
+               }
+       }
+       if (ntlmssp_state->force_wrap_seal) {
+               bool ret;
+
+               /*
+                * We want also work against old Samba servers
+                * which didn't had GENSEC_FEATURE_LDAP_STYLE
+                * we negotiate SEAL too. We may remove this
+                * in a few years. As all servers should have
+                * GENSEC_FEATURE_LDAP_STYLE by then.
+                */
+               ret = gensec_setting_bool(gensec_security->settings,
+                                         "ntlmssp_client",
+                                         "ldap_style_send_seal",
+                                         true);
+               if (ret) {
                        ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SEAL;
                }
        }