s4: ran minimal_includes.pl on source4/auth/ntlmssp
[ira/wip.git] / source4 / auth / ntlmssp / ntlmssp_client.c
index 7801e0208d2145c9c09fc13ead6fb3f696da279b..7aef086c1cd33a38e36536732100f88d8f3be2cf 100644 (file)
@@ -9,7 +9,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
-#include "auth/auth.h"
 #include "auth/ntlmssp/ntlmssp.h"
-#include "lib/crypto/crypto.h"
-#include "librpc/gen_ndr/ndr_samr.h" /* for struct samrPassword */
+#include "../lib/crypto/crypto.h"
+#include "../libcli/auth/libcli_auth.h"
+#include "auth/credentials/credentials.h"
+#include "auth/gensec/gensec.h"
+#include "param/param.h"
 
 /*********************************************************************
  Client side NTLMSSP
@@ -46,7 +47,18 @@ NTSTATUS ntlmssp_client_initial(struct gensec_security *gensec_security,
                                TALLOC_CTX *out_mem_ctx, 
                                DATA_BLOB in, DATA_BLOB *out) 
 {
-       struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
+       struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data;
+       const char *domain = gensec_ntlmssp_state->domain;
+       const char *workstation = cli_credentials_get_workstation(gensec_security->credentials);
+
+       /* These don't really matter in the initial packet, so don't panic if they are not set */
+       if (!domain) {
+               domain = "";
+       }
+
+       if (!workstation) {
+               workstation = "";
+       }
 
        if (gensec_ntlmssp_state->unicode) {
                gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE;
@@ -64,8 +76,8 @@ NTSTATUS ntlmssp_client_initial(struct gensec_security *gensec_security,
                  "NTLMSSP",
                  NTLMSSP_NEGOTIATE,
                  gensec_ntlmssp_state->neg_flags,
-                 gensec_ntlmssp_state->get_domain()
-                 cli_credentials_get_workstation(gensec_security->credentials));
+                 domain
+                 workstation);
 
        gensec_ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
 
@@ -86,26 +98,29 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
                                  TALLOC_CTX *out_mem_ctx,
                                  const DATA_BLOB in, DATA_BLOB *out) 
 {
-       struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
+       struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data;
        uint32_t chal_flags, ntlmssp_command, unkn1, unkn2;
        DATA_BLOB server_domain_blob;
        DATA_BLOB challenge_blob;
-       DATA_BLOB struct_blob = data_blob(NULL, 0);
+       DATA_BLOB target_info = data_blob(NULL, 0);
        char *server_domain;
        const char *chal_parse_string;
        const char *auth_gen_string;
-       uint8_t lm_hash[16];
        DATA_BLOB lm_response = data_blob(NULL, 0);
        DATA_BLOB nt_response = data_blob(NULL, 0);
        DATA_BLOB session_key = data_blob(NULL, 0);
        DATA_BLOB lm_session_key = data_blob(NULL, 0);
        DATA_BLOB encrypted_session_key = data_blob(NULL, 0);
        NTSTATUS nt_status;
+       int flags = 0;
+       const char *user, *domain;
 
-       const struct samr_Password *nt_hash;
-       const char *user, *domain, *password;
+       TALLOC_CTX *mem_ctx = talloc_new(out_mem_ctx);
+       if (!mem_ctx) {
+               return NT_STATUS_NO_MEMORY;
+       }
 
-       if (!msrpc_parse(out_mem_ctx,
+       if (!msrpc_parse(mem_ctx,
                         &in, "CdBd",
                         "NTLMSSP",
                         &ntlmssp_command, 
@@ -113,6 +128,7 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
                         &chal_flags)) {
                DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#1)\n"));
                dump_data(2, in.data, in.length);
+               talloc_free(mem_ctx);
 
                return NT_STATUS_INVALID_PARAMETER;
        }
@@ -125,14 +141,14 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
        ntlmssp_handle_neg_flags(gensec_ntlmssp_state, chal_flags, gensec_ntlmssp_state->allow_lm_key);
 
        if (gensec_ntlmssp_state->unicode) {
-               if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) {
+               if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) {
                        chal_parse_string = "CdUdbddB";
                } else {
                        chal_parse_string = "CdUdbdd";
                }
                auth_gen_string = "CdBBUUUBd";
        } else {
-               if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) {
+               if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) {
                        chal_parse_string = "CdAdbddB";
                } else {
                        chal_parse_string = "CdAdbdd";
@@ -141,10 +157,7 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
                auth_gen_string = "CdBBAAABd";
        }
 
-       DEBUG(3, ("NTLMSSP: Set final flags:\n"));
-       debug_ntlmssp_flags(gensec_ntlmssp_state->neg_flags);
-
-       if (!msrpc_parse(out_mem_ctx,
+       if (!msrpc_parse(mem_ctx,
                         &in, chal_parse_string,
                         "NTLMSSP",
                         &ntlmssp_command, 
@@ -152,143 +165,59 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
                         &chal_flags,
                         &challenge_blob, 8,
                         &unkn1, &unkn2,
-                        &struct_blob)) {
+                        &target_info)) {
                DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#2)\n"));
                dump_data(2, in.data, in.length);
+               talloc_free(mem_ctx);
                return NT_STATUS_INVALID_PARAMETER;
        }
 
        gensec_ntlmssp_state->server_domain = server_domain;
 
        if (challenge_blob.length != 8) {
+               talloc_free(mem_ctx);
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       cli_credentials_get_ntlm_username_domain(gensec_security->credentials, out_mem_ctx, 
+       cli_credentials_get_ntlm_username_domain(gensec_security->credentials, mem_ctx, 
                                                 &user, &domain);
 
-       nt_hash = cli_credentials_get_nt_hash(gensec_security->credentials, out_mem_ctx);
-
-       if (!nt_hash) {
-               static const uint8_t zeros[16];
-               /* do nothing - blobs are zero length */
-
-               /* session key is all zeros */
-               session_key = data_blob_talloc(gensec_ntlmssp_state, zeros, 16);
-               lm_session_key = data_blob_talloc(gensec_ntlmssp_state, zeros, 16);
-
-               lm_response = data_blob(NULL, 0);
-               nt_response = data_blob(NULL, 0);
-               
-               /* not doing NLTM2 without a password */
-               gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
-       } else if (gensec_ntlmssp_state->use_ntlmv2) {
-
-               if (!struct_blob.length) {
-                       /* be lazy, match win2k - we can't do NTLMv2 without it */
-                       DEBUG(1, ("Server did not provide 'target information', required for NTLMv2\n"));
-                       return NT_STATUS_INVALID_PARAMETER;
-               }
+       if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
+               flags |= CLI_CRED_NTLM2;
+       }
+       if (gensec_ntlmssp_state->use_ntlmv2) {
+               flags |= CLI_CRED_NTLMv2_AUTH;
+       }
+       if (gensec_ntlmssp_state->use_nt_response) {
+               flags |= CLI_CRED_NTLM_AUTH;
+       }
+       if (lp_client_lanman_auth(gensec_security->settings->lp_ctx)) {
+               flags |= CLI_CRED_LANMAN_AUTH;
+       }
 
-               /* TODO: if the remote server is standalone, then we should replace 'domain'
-                  with the server name as supplied above */
-               
-               if (!SMBNTLMv2encrypt_hash(gensec_ntlmssp_state,
-                                          user, 
-                                          domain, 
-                                          nt_hash->hash, &challenge_blob, 
-                                          &struct_blob, 
-                                          &lm_response, &nt_response, 
-                                          NULL, &session_key)) {
-                       data_blob_free(&challenge_blob);
-                       data_blob_free(&struct_blob);
-                       return NT_STATUS_NO_MEMORY;
-               }
+       nt_status = cli_credentials_get_ntlm_response(gensec_security->credentials, mem_ctx, 
+                                                     &flags, challenge_blob, target_info,
+                                                     &lm_response, &nt_response, 
+                                                     &lm_session_key, &session_key);
 
-               /* LM Key is incompatible... */
-               gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
-
-       } else if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
-               struct MD5Context md5_session_nonce_ctx;
-               uint8_t session_nonce[16];
-               uint8_t session_nonce_hash[16];
-               uint8_t user_session_key[16];
-               
-               lm_response = data_blob_talloc(gensec_ntlmssp_state, NULL, 24);
-               generate_random_buffer(lm_response.data, 8);
-               memset(lm_response.data+8, 0, 16);
-
-               memcpy(session_nonce, challenge_blob.data, 8);
-               memcpy(&session_nonce[8], lm_response.data, 8);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               return nt_status;
+       }
        
-               MD5Init(&md5_session_nonce_ctx);
-               MD5Update(&md5_session_nonce_ctx, challenge_blob.data, 8);
-               MD5Update(&md5_session_nonce_ctx, lm_response.data, 8);
-               MD5Final(session_nonce_hash, &md5_session_nonce_ctx);
-
-               DEBUG(5, ("NTLMSSP challenge set by NTLM2\n"));
-               DEBUG(5, ("challenge is: \n"));
-               dump_data(5, session_nonce_hash, 8);
-               
-               nt_response = data_blob_talloc(gensec_ntlmssp_state, NULL, 24);
-               SMBOWFencrypt(nt_hash->hash,
-                             session_nonce_hash,
-                             nt_response.data);
-               
-               session_key = data_blob_talloc(gensec_ntlmssp_state, NULL, 16);
-
-               SMBsesskeygen_ntv1(nt_hash->hash, user_session_key);
-               hmac_md5(user_session_key, session_nonce, sizeof(session_nonce), session_key.data);
-               dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);
-
-               /* LM Key is incompatible... */
-               gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
-       } else {
-               if (gensec_ntlmssp_state->use_nt_response) {
-                       nt_response = data_blob_talloc(gensec_ntlmssp_state, NULL, 24);
-                       SMBOWFencrypt(nt_hash->hash, challenge_blob.data,
-                                     nt_response.data);
-
-                       session_key = data_blob_talloc(gensec_ntlmssp_state, NULL, 16);
-                       SMBsesskeygen_ntv1(nt_hash->hash, session_key.data);
-                       dump_data_pw("NT session key:\n", session_key.data, session_key.length);
-               }
+       if (!(flags & CLI_CRED_LANMAN_AUTH)) {
+               /* LM Key is still possible, just silly.  Fortunetly
+                * we require command line options to end up here */
+               /* gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY; */
+       }
 
-               /* lanman auth is insecure, it may be disabled.  We may also not have a password */
-               if (lp_client_lanman_auth()) {
-                       password = cli_credentials_get_password(gensec_security->credentials);
-                       if (!password) {
-                               lm_response = nt_response;
-                       } else {
-                               lm_response = data_blob_talloc(gensec_ntlmssp_state, NULL, 24);
-                               if (!SMBencrypt(password,challenge_blob.data,
-                                               lm_response.data)) {
-                                       /* If the LM password was too long (and therefore the LM hash being
-                                          of the first 14 chars only), don't send it */
-                                       data_blob_free(&lm_response);
-                                       
-                                       /* LM Key is incompatible with 'long' passwords */
-                                       gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
-                               } else {
-                                       E_deshash(password, lm_hash);
-                                       lm_session_key = data_blob_talloc(gensec_ntlmssp_state, NULL, 16);
-                                       memcpy(lm_session_key.data, lm_hash, 8);
-                                       memset(&lm_session_key.data[8], '\0', 8);
-                                       
-                                       if (!gensec_ntlmssp_state->use_nt_response) {
-                                       session_key = lm_session_key;
-                                       }
-                               }
-                       }
-               } else {
-                       /* LM Key is incompatible... */
-                       gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
-               }
+       if (!(flags & CLI_CRED_NTLM2)) {
+               /* NTLM2 is incompatible... */
+               gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
        }
        
        if ((gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) 
-           && lp_client_lanman_auth() && lm_session_key.length == 16) {
-               DATA_BLOB new_session_key = data_blob_talloc(gensec_ntlmssp_state, NULL, 16);
+           && lp_client_lanman_auth(gensec_security->settings->lp_ctx) && lm_session_key.length == 16) {
+               DATA_BLOB new_session_key = data_blob_talloc(mem_ctx, NULL, 16);
                if (lm_response.length == 24) {
                        SMBsesskeygen_lm_sess_key(lm_session_key.data, lm_response.data, 
                                                  new_session_key.data);
@@ -297,7 +226,6 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
                        SMBsesskeygen_lm_sess_key(lm_session_key.data, zeros,
                                                  new_session_key.data);
                }
-               new_session_key.length = 16;
                session_key = new_session_key;
                dump_data_pw("LM session key\n", session_key.data, session_key.length);
        }
@@ -308,7 +236,7 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
        if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
                /* Make up a new session key */
                uint8_t client_session_key[16];
-               generate_random_buffer(client_session_key, sizeof(client_session_key));
+               generate_secret_buffer(client_session_key, sizeof(client_session_key));
 
                /* Encrypt the new session key with the old one */
                encrypted_session_key = data_blob_talloc(gensec_ntlmssp_state, 
@@ -318,11 +246,14 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
                dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length);
 
                /* Mark the new session key as the 'real' session key */
-               session_key = data_blob_talloc(gensec_ntlmssp_state, client_session_key, sizeof(client_session_key));
+               session_key = data_blob_talloc(mem_ctx, client_session_key, sizeof(client_session_key));
        }
 
+       DEBUG(3, ("NTLMSSP: Set final flags:\n"));
+       debug_ntlmssp_flags(gensec_ntlmssp_state->neg_flags);
+
        /* this generates the actual auth packet */
-       if (!msrpc_gen(out_mem_ctx, 
+       if (!msrpc_gen(mem_ctx, 
                       out, auth_gen_string, 
                       "NTLMSSP", 
                       NTLMSSP_AUTH, 
@@ -333,18 +264,20 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
                       cli_credentials_get_workstation(gensec_security->credentials),
                       encrypted_session_key.data, encrypted_session_key.length,
                       gensec_ntlmssp_state->neg_flags)) {
-               
+               talloc_free(mem_ctx);
                return NT_STATUS_NO_MEMORY;
        }
 
        gensec_ntlmssp_state->session_key = session_key;
+       talloc_steal(gensec_ntlmssp_state, session_key.data);
 
-       /* The client might be using 56 or 40 bit weakened keys */
-       ntlmssp_weaken_keys(gensec_ntlmssp_state);
+       talloc_steal(out_mem_ctx, out->data);
 
        gensec_ntlmssp_state->chal = challenge_blob;
        gensec_ntlmssp_state->lm_resp = lm_response;
+       talloc_steal(gensec_ntlmssp_state->lm_resp.data, lm_response.data);
        gensec_ntlmssp_state->nt_resp = nt_response;
+       talloc_steal(gensec_ntlmssp_state->nt_resp.data, nt_response.data);
 
        gensec_ntlmssp_state->expected_state = NTLMSSP_DONE;
 
@@ -353,10 +286,12 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
                if (!NT_STATUS_IS_OK(nt_status)) {
                        DEBUG(1, ("Could not setup NTLMSSP signing/sealing system (error was: %s)\n", 
                                  nt_errstr(nt_status)));
+                       talloc_free(mem_ctx);
                        return nt_status;
                }
        }
 
+       talloc_free(mem_ctx);
        return NT_STATUS_OK;
 }
 
@@ -368,20 +303,21 @@ NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
        nt_status = gensec_ntlmssp_start(gensec_security);
        NT_STATUS_NOT_OK_RETURN(nt_status);
 
-       gensec_ntlmssp_state = gensec_security->private_data;
+       gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data;
 
        gensec_ntlmssp_state->role = NTLMSSP_CLIENT;
 
-       gensec_ntlmssp_state->get_domain = lp_workgroup;
+       gensec_ntlmssp_state->domain = lp_workgroup(gensec_security->settings->lp_ctx);
 
-       gensec_ntlmssp_state->unicode = lp_parm_bool(-1, "ntlmssp_client", "unicode", True);
+       gensec_ntlmssp_state->unicode = gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "unicode", true);
 
-       gensec_ntlmssp_state->use_nt_response = lp_parm_bool(-1, "ntlmssp_client", "send_nt_reponse", True);
+       gensec_ntlmssp_state->use_nt_response = gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "send_nt_reponse", true);
 
-       gensec_ntlmssp_state->allow_lm_key = (lp_lanman_auth() 
-                                         && lp_parm_bool(-1, "ntlmssp_client", "allow_lm_key", False));
+       gensec_ntlmssp_state->allow_lm_key = (lp_client_lanman_auth(gensec_security->settings->lp_ctx) 
+                                             && (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "allow_lm_key", false)
+                                                 || gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "lm_key", false)));
 
-       gensec_ntlmssp_state->use_ntlmv2 = lp_client_ntlmv2_auth();
+       gensec_ntlmssp_state->use_ntlmv2 = lp_client_ntlmv2_auth(gensec_security->settings->lp_ctx);
 
        gensec_ntlmssp_state->expected_state = NTLMSSP_INITIAL;
 
@@ -389,19 +325,31 @@ NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
                NTLMSSP_NEGOTIATE_NTLM |
                NTLMSSP_REQUEST_TARGET;
 
-       if (lp_parm_bool(-1, "ntlmssp_client", "128bit", True)) {
+       if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "128bit", true)) {
                gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_128;               
        }
 
-       if (lp_parm_bool(-1, "ntlmssp_client", "keyexchange", True)) {
+       if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "56bit", false)) {
+               gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_56;                
+       }
+
+       if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "lm_key", false)) {
+               gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY;
+       }
+
+       if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "keyexchange", true)) {
                gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_KEY_EXCH;          
        }
 
-       if (lp_parm_bool(-1, "ntlmssp_client", "ntlm2", True)) {
+       if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "alwayssign", true)) {
+               gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;               
+       }
+
+       if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "ntlm2", true)) {
                gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;             
        } else {
                /* apparently we can't do ntlmv2 if we don't do ntlm2 */
-               gensec_ntlmssp_state->use_ntlmv2 = False;
+               gensec_ntlmssp_state->use_ntlmv2 = false;
        }
 
        if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {