r7757: Add NTLMv2 support to the NT1 Session setup (ie, not SPNEGO/NTLMSSP)
authorAndrew Bartlett <abartlet@samba.org>
Sun, 19 Jun 2005 13:26:32 +0000 (13:26 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:18:32 +0000 (13:18 -0500)
Session Setup code.

Add a mem_ctx argument to a few of the NTLMv2 support functions, and
add smb.conf options to control client NTLMv2 behaviour.

Andrew Bartlett
(This used to be commit 3f35cdb218a3dae08a05e77452ca9f73716ceb28)

source4/auth/ntlmssp/ntlmssp_client.c
source4/libcli/auth/smbencrypt.c
source4/libcli/composite/sesssetup.c
source4/param/loadparm.c
source4/torture/rpc/samlogon.c

index 23fe8f5cc962dd0491a8d2e90252d3ec13708e2e..726885c82fb42fa9feeab75ea3dbb4bcdcbbb164 100644 (file)
@@ -203,7 +203,8 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
                /* TODO: if the remote server is standalone, then we should replace 'domain'
                   with the server name as supplied above */
                
-               if (!SMBNTLMv2encrypt_hash(user, 
+               if (!SMBNTLMv2encrypt_hash(gensec_ntlmssp_state,
+                                          user, 
                                           domain, 
                                           nt_hash->hash, &challenge_blob, 
                                           &struct_blob, 
index 3a4a724789f37c1dc60d734651ce4bef10195920..a9a7bb99032eb0b6d1726a0339784b4d94a81caa 100644 (file)
@@ -324,7 +324,8 @@ static DATA_BLOB NTLMv2_generate_client_data(TALLOC_CTX *mem_ctx, const DATA_BLO
        return response;
 }
 
-static DATA_BLOB NTLMv2_generate_response(const uint8_t ntlm_v2_hash[16],
+static DATA_BLOB NTLMv2_generate_response(TALLOC_CTX *out_mem_ctx, 
+                                         const uint8_t ntlm_v2_hash[16],
                                          const DATA_BLOB *server_chal,
                                          const DATA_BLOB *names_blob)
 {
@@ -332,7 +333,8 @@ static DATA_BLOB NTLMv2_generate_response(const uint8_t ntlm_v2_hash[16],
        DATA_BLOB ntlmv2_client_data;
        DATA_BLOB final_response;
        
-       TALLOC_CTX *mem_ctx = talloc_init("NTLMv2_generate_response internal context");
+       TALLOC_CTX *mem_ctx = talloc_named(out_mem_ctx, 0, 
+                                          "NTLMv2_generate_response internal context");
 
        if (!mem_ctx) {
                return data_blob(NULL, 0);
@@ -346,7 +348,7 @@ static DATA_BLOB NTLMv2_generate_response(const uint8_t ntlm_v2_hash[16],
        /* Given that data, and the challenge from the server, generate a response */
        SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, &ntlmv2_client_data, ntlmv2_response);
        
-       final_response = data_blob(NULL, sizeof(ntlmv2_response) + ntlmv2_client_data.length);
+       final_response = data_blob(out_mem_ctx, sizeof(ntlmv2_response) + ntlmv2_client_data.length);
 
        memcpy(final_response.data, ntlmv2_response, sizeof(ntlmv2_response));
 
@@ -358,12 +360,13 @@ static DATA_BLOB NTLMv2_generate_response(const uint8_t ntlm_v2_hash[16],
        return final_response;
 }
 
-static DATA_BLOB LMv2_generate_response(const uint8_t ntlm_v2_hash[16],
+static DATA_BLOB LMv2_generate_response(TALLOC_CTX *mem_ctx, 
+                                       const uint8_t ntlm_v2_hash[16],
                                        const DATA_BLOB *server_chal)
 {
        uint8_t lmv2_response[16];
-       DATA_BLOB lmv2_client_data = data_blob(NULL, 8);
-       DATA_BLOB final_response = data_blob(NULL, 24);
+       DATA_BLOB lmv2_client_data = data_blob(mem_ctx, 8);
+       DATA_BLOB final_response = data_blob(mem_ctx, 24);
        
        /* LMv2 */
        /* client-supplied random data */
@@ -383,7 +386,8 @@ static DATA_BLOB LMv2_generate_response(const uint8_t ntlm_v2_hash[16],
        return final_response;
 }
 
-BOOL SMBNTLMv2encrypt_hash(const char *user, const char *domain, const uint8_t nt_hash[16],
+BOOL SMBNTLMv2encrypt_hash(TALLOC_CTX *mem_ctx, 
+                          const char *user, const char *domain, const uint8_t nt_hash[16],
                           const DATA_BLOB *server_chal, 
                           const DATA_BLOB *names_blob,
                           DATA_BLOB *lm_response, DATA_BLOB *nt_response, 
@@ -400,10 +404,11 @@ BOOL SMBNTLMv2encrypt_hash(const char *user, const char *domain, const uint8_t n
        }
        
        if (nt_response) {
-               *nt_response = NTLMv2_generate_response(ntlm_v2_hash, server_chal,
+               *nt_response = NTLMv2_generate_response(mem_ctx, 
+                                                       ntlm_v2_hash, server_chal,
                                                        names_blob); 
                if (user_session_key) {
-                       *user_session_key = data_blob(NULL, 16);
+                       *user_session_key = data_blob(mem_ctx, 16);
                        
                        /* The NTLMv2 calculations also provide a session key, for signing etc later */
                        /* use only the first 16 bytes of nt_response for session key */
@@ -414,9 +419,10 @@ BOOL SMBNTLMv2encrypt_hash(const char *user, const char *domain, const uint8_t n
        /* LMv2 */
        
        if (lm_response) {
-               *lm_response = LMv2_generate_response(ntlm_v2_hash, server_chal);
+               *lm_response = LMv2_generate_response(mem_ctx, 
+                                                     ntlm_v2_hash, server_chal);
                if (lm_session_key) {
-                       *lm_session_key = data_blob(NULL, 16);
+                       *lm_session_key = data_blob(mem_ctx, 16);
                        
                        /* The NTLMv2 calculations also provide a session key, for signing etc later */
                        /* use only the first 16 bytes of lm_response for session key */
@@ -427,7 +433,9 @@ BOOL SMBNTLMv2encrypt_hash(const char *user, const char *domain, const uint8_t n
        return True;
 }
 
-BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password, 
+BOOL SMBNTLMv2encrypt(TALLOC_CTX *mem_ctx, 
+                     const char *user, const char *domain, 
+                     const char *password, 
                      const DATA_BLOB *server_chal, 
                      const DATA_BLOB *names_blob,
                      DATA_BLOB *lm_response, DATA_BLOB *nt_response, 
@@ -436,7 +444,8 @@ BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password
        uint8_t nt_hash[16];
        E_md4hash(password, nt_hash);
 
-       return SMBNTLMv2encrypt_hash(user, domain, nt_hash, server_chal, names_blob,
+       return SMBNTLMv2encrypt_hash(mem_ctx, 
+                                    user, domain, nt_hash, server_chal, names_blob,
                                     lm_response, nt_response, lm_session_key, user_session_key);
 }
 
index 2736d91262feabd992c54ee450a55a08b8569f09..2a75fb4e203132dff627c69353d93d3d72c442dc 100644 (file)
@@ -25,7 +25,7 @@
 #include "libcli/raw/libcliraw.h"
 #include "libcli/composite/composite.h"
 #include "auth/auth.h"
-
+#include "version.h"
 
 struct sesssetup_state {
        union smb_sesssetup setup;
@@ -50,10 +50,10 @@ static DATA_BLOB lanman_blob(TALLOC_CTX *mem_ctx, const char *pass, DATA_BLOB ch
   form an encrypted NT password from a plaintext password
   and the server supplied challenge
 */
-static DATA_BLOB nt_blob(TALLOC_CTX *mem_ctx, const char *pass, DATA_BLOB challenge)
+static DATA_BLOB nt_blob(TALLOC_CTX *mem_ctx, const struct samr_Password *nt_hash, DATA_BLOB challenge)
 {
        DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, 24);
-       SMBNTencrypt(pass, challenge.data, blob.data);
+       SMBOWFencrypt(nt_hash->hash, challenge.data, blob.data);
        return blob;
 }
 
@@ -68,26 +68,6 @@ static void set_user_session_key(struct smbcli_session *session,
                                                     session_key->length);
 }
 
-/*
-  setup signing for a NT1 style session setup
-*/
-static void use_nt1_session_keys(struct smbcli_session *session, 
-                                const char *password, const DATA_BLOB *nt_response)
-{
-       struct smbcli_transport *transport = session->transport; 
-       uint8_t nt_hash[16];
-       DATA_BLOB session_key = data_blob_talloc(session, NULL, 16);
-
-       E_md4hash(password, nt_hash);
-       SMBsesskeygen_ntv1(nt_hash, session_key.data);
-
-       smbcli_transport_simple_set_signing(transport, session_key, *nt_response);
-
-       set_user_session_key(session, &session_key);
-       data_blob_free(&session_key);
-}
-
-
 /*
   handler for completion of a smbcli_request sub-request
 */
@@ -169,6 +149,7 @@ static struct smbcli_request *session_setup_nt1(struct composite_context *c,
                                                struct smb_composite_sesssetup *io) 
 {
        struct sesssetup_state *state = talloc_get_type(c->private, struct sesssetup_state);
+       const struct samr_Password *nt_hash = cli_credentials_get_nt_hash(io->in.credentials, state);
        const char *password = cli_credentials_get_password(io->in.credentials);
 
        state->setup.nt1.level           = RAW_SESSSETUP_NT1;
@@ -178,7 +159,7 @@ static struct smbcli_request *session_setup_nt1(struct composite_context *c,
        state->setup.nt1.in.sesskey      = io->in.sesskey;
        state->setup.nt1.in.capabilities = io->in.capabilities;
        state->setup.nt1.in.os           = "Unix";
-       state->setup.nt1.in.lanman       = "Samba";
+       state->setup.nt1.in.lanman       = talloc_asprintf(state, "Samba %s", SAMBA_VERSION_STRING);
        state->setup.nt1.in.user         = cli_credentials_get_username(io->in.credentials);
        state->setup.nt1.in.domain       = cli_credentials_get_domain(io->in.credentials);
 
@@ -187,14 +168,59 @@ static struct smbcli_request *session_setup_nt1(struct composite_context *c,
                state->setup.nt1.in.password2 = data_blob(NULL, 0);
        } else if (session->transport->negotiate.sec_mode & 
                   NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) {
-               state->setup.nt1.in.password1 = lanman_blob(state, password, 
-                                                           session->transport->negotiate.secblob);
-               state->setup.nt1.in.password2 = nt_blob(state, password, 
-                                                       session->transport->negotiate.secblob);
-               use_nt1_session_keys(session, password, &state->setup.nt1.in.password2);
-       } else {
+               DATA_BLOB session_key;
+               /* TODO: NTLMv2 in the client session setup */
+               if (lp_client_ntlmv2_auth()) {
+                       DATA_BLOB names_blob = NTLMv2_generate_names_blob(state, lp_netbios_name(), lp_workgroup());
+                       DATA_BLOB lmv2_response, ntlmv2_response, lmv2_session_key;
+                       
+                       /* TODO - test with various domain cases, and without domain */
+                       if (!SMBNTLMv2encrypt_hash(state, 
+                                                  state->setup.nt1.in.user, state->setup.nt1.in.domain, 
+                                                  nt_hash->hash, &session->transport->negotiate.secblob,
+                                                  &names_blob,
+                                                  &lmv2_response, &ntlmv2_response, 
+                                                  &lmv2_session_key, &session_key)) {
+                               data_blob_free(&names_blob);
+                               return NULL;
+                       }
+                       data_blob_free(&names_blob);
+                       state->setup.nt1.in.password1 = lmv2_response;
+                       state->setup.nt1.in.password2 = ntlmv2_response;
+                       
+                       smbcli_transport_simple_set_signing(session->transport, session_key, 
+                                                           state->setup.nt1.in.password2);
+                       set_user_session_key(session, &session_key);
+                       
+                       data_blob_free(&lmv2_session_key);
+                       data_blob_free(&session_key);
+               } else {
+
+                       state->setup.nt1.in.password2 = nt_blob(state, nt_hash,
+                                                               session->transport->negotiate.secblob);
+                       if (lp_client_lanman_auth()) {
+                               state->setup.nt1.in.password1 = lanman_blob(state, password, 
+                                                                           session->transport->negotiate.secblob);
+                       } else {
+                               /* if not sending the LM password, send the NT password twice */
+                               state->setup.nt1.in.password1 = state->setup.nt1.in.password2;
+                       }
+
+                       session_key = data_blob_talloc(session, NULL, 16);
+                       SMBsesskeygen_ntv1(nt_hash->hash, session_key.data);
+                       smbcli_transport_simple_set_signing(session->transport, session_key, 
+                                                           state->setup.nt1.in.password2);
+                       set_user_session_key(session, &session_key);
+                       
+                       data_blob_free(&session_key);
+               }
+
+       } else if (lp_client_plaintext_auth()) {
                state->setup.nt1.in.password1 = data_blob_talloc(state, password, strlen(password));
                state->setup.nt1.in.password2 = data_blob(NULL, 0);
+       } else {
+               /* could match windows client and return 'cannot logon from this workstation', but it just confuses everybody */
+               return NULL;
        }
 
        return smb_raw_session_setup_send(session, &state->setup);
@@ -219,7 +245,7 @@ static struct smbcli_request *session_setup_old(struct composite_context *c,
        state->setup.old.in.domain  = cli_credentials_get_domain(io->in.credentials);
        state->setup.old.in.user    = cli_credentials_get_username(io->in.credentials);
        state->setup.old.in.os      = "Unix";
-       state->setup.old.in.lanman  = "Samba";
+       state->setup.old.in.lanman  = talloc_asprintf(state, "Samba %s", SAMBA_VERSION_STRING);
        
        if (!password) {
                state->setup.old.in.password = data_blob(NULL, 0);
@@ -256,7 +282,7 @@ static struct smbcli_request *session_setup_spnego(struct composite_context *c,
        state->setup.spnego.in.sesskey      = io->in.sesskey;
        state->setup.spnego.in.capabilities = io->in.capabilities;
        state->setup.spnego.in.os           = "Unix";
-       state->setup.spnego.in.lanman       = "Samba";
+       state->setup.spnego.in.lanman       = talloc_asprintf(state, "Samba %s", SAMBA_VERSION_STRING);
        state->setup.spnego.in.workgroup    = io->in.workgroup;
 
        state->setup.spnego.out.vuid        = session->vuid;
index 26466797adf808715871a66f51b288185c82ecb2..49bb52230e47cbb1719dc0224d02b873d70e0e32 100644 (file)
@@ -235,11 +235,13 @@ typedef struct
        BOOL bNTSmbSupport;
        BOOL bNTStatusSupport;
        BOOL bAllowTrustedDomains;
+       BOOL bPlaintextAuth;
        BOOL bLanmanAuth;
        BOOL bNTLMAuth;
        BOOL bUseSpnego;
        int  server_signing;
        int  client_signing;
+       BOOL bClientPlaintextAuth;
        BOOL bClientLanManAuth;
        BOOL bClientNTLMv2Auth;
        BOOL bHostMSDfs;
@@ -561,10 +563,12 @@ static struct parm_struct parm_table[] = {
        {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"username level", P_INTEGER, P_GLOBAL, &Globals.unamelevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"restrict anonymous", P_INTEGER, P_GLOBAL, &Globals.restrict_anonymous, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"plaintext auth", P_BOOL, P_GLOBAL, &Globals.bPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        
        {"username", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
        {"user", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_HIDE},
@@ -1242,8 +1246,10 @@ FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
 FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
 FN_GLOBAL_BOOL(lp_allow_trusted_domains, &Globals.bAllowTrustedDomains)
 FN_GLOBAL_INTEGER(lp_restrict_anonymous, &Globals.restrict_anonymous)
+FN_GLOBAL_BOOL(lp_plaintext_auth, &Globals.bPlaintextAuth)
 FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
 FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
+FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
 FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
 FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
 FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
index 37b9025194550ca3102e2403228162d8bc84b075..a7d57899aaef640f0516defb5245655cc936edb0 100644 (file)
@@ -551,7 +551,8 @@ static BOOL test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, enum
        ZERO_STRUCT(user_session_key);
        
        /* TODO - test with various domain cases, and without domain */
-       if (!SMBNTLMv2encrypt(samlogon_state->account_name, samlogon_state->account_domain, 
+       if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx, 
+                             samlogon_state->account_name, samlogon_state->account_domain, 
                              samlogon_state->password, &samlogon_state->chall,
                              &names_blob,
                              &lmv2_response, &ntlmv2_response, 
@@ -681,7 +682,8 @@ static BOOL test_lmv2_ntlm_broken(struct samlogon_state *samlogon_state, enum nt
        ZERO_STRUCT(user_session_key);
        
        /* TODO - test with various domain cases, and without domain */
-       if (!SMBNTLMv2encrypt(samlogon_state->account_name, samlogon_state->account_domain, 
+       if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx, 
+                             samlogon_state->account_name, samlogon_state->account_domain, 
                              samlogon_state->password, &samlogon_state->chall,
                              &names_blob,
                              &lmv2_response, &ntlmv2_response,