Fix most of bug #169.
authorAndrew Bartlett <abartlet@samba.org>
Sat, 3 Apr 2004 15:41:32 +0000 (15:41 +0000)
committerAndrew Bartlett <abartlet@samba.org>
Sat, 3 Apr 2004 15:41:32 +0000 (15:41 +0000)
For a (very) long time, we have had a bug in Samba were an NTLMv2-only
PDC would fail, because it converted the password into NTLM format for
checking.

This patch performs the direct comparison required for interactive
logons to function in this situation.  It also removes the 'auth flags', which
simply where not ever used.

Natrually, this plays with the size of structures, so rebuild, rebuild
rebuild...

Andrew Bartlett

source/auth/auth_ntlmssp.c
source/auth/auth_sam.c
source/auth/auth_util.c
source/include/auth.h
source/libsmb/ntlm_check.c
source/utils/ntlm_auth.c

index a5ce101e5e7360b46e458918f0e6dacd549ad2ff..498a7b1a39aa8e8e2df7b1ac9034fd2b4ed8f37a 100644 (file)
@@ -78,21 +78,9 @@ static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state,
 static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *nt_session_key, DATA_BLOB *lm_session_key) 
 {
        AUTH_NTLMSSP_STATE *auth_ntlmssp_state = ntlmssp_state->auth_context;
-       uint32 auth_flags = AUTH_FLAG_NONE;
        auth_usersupplied_info *user_info = NULL;
-       DATA_BLOB plaintext_password = data_blob(NULL, 0);
        NTSTATUS nt_status;
 
-       if (auth_ntlmssp_state->ntlmssp_state->lm_resp.length) {
-               auth_flags |= AUTH_FLAG_LM_RESP;
-       }
-
-       if (auth_ntlmssp_state->ntlmssp_state->nt_resp.length == 24) {
-               auth_flags |= AUTH_FLAG_NTLM_RESP;
-       } else  if (auth_ntlmssp_state->ntlmssp_state->nt_resp.length > 24) {
-               auth_flags |= AUTH_FLAG_NTLMv2_RESP;
-       }
-
        /* the client has given us its machine name (which we otherwise would not get on port 445).
           we need to possibly reload smb.conf if smb.conf includes depend on the machine name */
 
@@ -108,10 +96,10 @@ static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state,
                                       auth_ntlmssp_state->ntlmssp_state->user, 
                                       auth_ntlmssp_state->ntlmssp_state->domain, 
                                       auth_ntlmssp_state->ntlmssp_state->workstation, 
-                                      auth_ntlmssp_state->ntlmssp_state->lm_resp, 
-                                      auth_ntlmssp_state->ntlmssp_state->nt_resp, 
-                                      plaintext_password, 
-                                      auth_flags, True);
+                                      auth_ntlmssp_state->ntlmssp_state->lm_resp.data ? &auth_ntlmssp_state->ntlmssp_state->lm_resp : NULL
+                                      auth_ntlmssp_state->ntlmssp_state->nt_resp.data ? &auth_ntlmssp_state->ntlmssp_state->nt_resp : NULL
+                                      NULL, NULL, NULL,
+                                      True);
 
        if (!NT_STATUS_IS_OK(nt_status)) {
                return nt_status;
index b35cc78d6b282ac21f4e180f8e0e2e2e4b1275f3..5efc51b21ae4634c9f7716596f507b43436ab896 100644 (file)
@@ -57,7 +57,8 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context,
        nt_pw = pdb_get_nt_passwd(sampass);
 
        return ntlm_password_check(mem_ctx, &auth_context->challenge, 
-                                  &user_info->lm_resp, &user_info->nt_resp,  
+                                  &user_info->lm_resp, &user_info->nt_resp, 
+                                  &user_info->lm_interactive_pwd, &user_info->nt_interactive_pwd,
                                   username, 
                                   user_info->smb_name.str, 
                                   user_info->client_domain.str, 
index f62cc2fb9e06a8b577eb0e3027837286d862168c..9df587398378f15a48bd5640c13224d923c7ff7a 100644 (file)
@@ -124,9 +124,10 @@ static NTSTATUS make_user_info(auth_usersupplied_info **user_info,
                                const char *client_domain, 
                                const char *domain,
                                const char *wksta_name, 
-                               DATA_BLOB lm_pwd, DATA_BLOB nt_pwd,
-                               DATA_BLOB plaintext, 
-                               uint32 auth_flags, BOOL encrypted)
+                               DATA_BLOB *lm_pwd, DATA_BLOB *nt_pwd,
+                               DATA_BLOB *lm_interactive_pwd, DATA_BLOB *nt_interactive_pwd,
+                               DATA_BLOB *plaintext, 
+                               BOOL encrypted)
 {
 
        DEBUG(5,("attempting to make a user_info for %s (%s)\n", internal_username, smb_name));
@@ -183,12 +184,19 @@ static NTSTATUS make_user_info(auth_usersupplied_info **user_info,
 
        DEBUG(5,("making blobs for %s's user_info struct\n", internal_username));
 
-       (*user_info)->lm_resp = data_blob(lm_pwd.data, lm_pwd.length);
-       (*user_info)->nt_resp = data_blob(nt_pwd.data, nt_pwd.length);
-       (*user_info)->plaintext_password = data_blob(plaintext.data, plaintext.length);
+       if (lm_pwd)
+               (*user_info)->lm_resp = data_blob(lm_pwd->data, lm_pwd->length);
+       if (nt_pwd)
+               (*user_info)->nt_resp = data_blob(nt_pwd->data, nt_pwd->length);
+       if (lm_interactive_pwd)
+               (*user_info)->lm_interactive_pwd = data_blob(lm_interactive_pwd->data, lm_interactive_pwd->length);
+       if (nt_interactive_pwd)
+               (*user_info)->nt_interactive_pwd = data_blob(nt_interactive_pwd->data, nt_interactive_pwd->length);
+
+       if (plaintext)
+               (*user_info)->plaintext_password = data_blob(plaintext->data, plaintext->length);
 
        (*user_info)->encrypted = encrypted;
-       (*user_info)->auth_flags = auth_flags;
 
        DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted ? "":"un" , internal_username, smb_name));
 
@@ -203,9 +211,10 @@ NTSTATUS make_user_info_map(auth_usersupplied_info **user_info,
                            const char *smb_name, 
                            const char *client_domain, 
                            const char *wksta_name, 
-                           DATA_BLOB lm_pwd, DATA_BLOB nt_pwd,
-                           DATA_BLOB plaintext, 
-                           uint32 ntlmssp_flags, BOOL encrypted)
+                           DATA_BLOB *lm_pwd, DATA_BLOB *nt_pwd,
+                           DATA_BLOB *lm_interactive_pwd, DATA_BLOB *nt_interactive_pwd,
+                           DATA_BLOB *plaintext, 
+                           BOOL encrypted)
 {
        const char *domain;
        fstring internal_username;
@@ -233,8 +242,10 @@ NTSTATUS make_user_info_map(auth_usersupplied_info **user_info,
        /* we know that it is a trusted domain (and we are allowing them) or it is our domain */
        
        return make_user_info(user_info, smb_name, internal_username, 
-               client_domain, domain, wksta_name, lm_pwd, nt_pwd,
-               plaintext, ntlmssp_flags, encrypted);
+                             client_domain, domain, wksta_name, 
+                             lm_pwd, nt_pwd,
+                             lm_interactive_pwd, nt_interactive_pwd,
+                             plaintext, encrypted);
 }
 
 /****************************************************************************
@@ -253,23 +264,14 @@ BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info,
        NTSTATUS nt_status;
        DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
        DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
-       DATA_BLOB plaintext_blob = data_blob(NULL, 0);
-       uint32 auth_flags = AUTH_FLAG_NONE;
-
-       if (lm_pwd_len)
-               auth_flags |= AUTH_FLAG_LM_RESP;
-       if (nt_pwd_len == 24) {
-               auth_flags |= AUTH_FLAG_NTLM_RESP; 
-       } else if (nt_pwd_len != 0) {
-               auth_flags |= AUTH_FLAG_NTLMv2_RESP; 
-       }
 
        nt_status = make_user_info_map(user_info,
-                                     smb_name, client_domain, 
-                                  wksta_name, 
-                                     lm_blob, nt_blob,
-                                     plaintext_blob, 
-                                     auth_flags, True);
+                                      smb_name, client_domain, 
+                                      wksta_name, 
+                                      lm_pwd_len ? &lm_blob : NULL, 
+                                      nt_pwd_len ? &nt_blob : NULL,
+                                      NULL, NULL, NULL,
+                                      True);
        
        ret = NT_STATUS_IS_OK(nt_status) ? True : False;
                
@@ -297,7 +299,6 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info,
        unsigned char local_lm_response[24];
        unsigned char local_nt_response[24];
        unsigned char key[16];
-       uint32 auth_flags = AUTH_FLAG_NONE;
        
        ZERO_STRUCT(key);
        memcpy(key, dc_sess_key, 8);
@@ -316,8 +317,11 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info,
        dump_data(100, nt_pwd, sizeof(nt_pwd));
 #endif
        
-       SamOEMhash((uchar *)lm_pwd, key, sizeof(lm_pwd));
-       SamOEMhash((uchar *)nt_pwd, key, sizeof(nt_pwd));
+       if (lm_interactive_pwd)
+               SamOEMhash((uchar *)lm_pwd, key, sizeof(lm_pwd));
+       
+       if (nt_interactive_pwd)
+               SamOEMhash((uchar *)nt_pwd, key, sizeof(nt_pwd));
        
 #ifdef DEBUG_PASSWORD
        DEBUG(100,("decrypt of lm owf password:"));
@@ -327,37 +331,51 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info,
        dump_data(100, nt_pwd, sizeof(nt_pwd));
 #endif
        
-       SMBOWFencrypt((const unsigned char *)lm_pwd, chal, local_lm_response);
-       SMBOWFencrypt((const unsigned char *)nt_pwd, chal, local_nt_response);
+       if (lm_interactive_pwd)
+               SMBOWFencrypt((const unsigned char *)lm_pwd, chal, local_lm_response);
+
+       if (nt_interactive_pwd)
+               SMBOWFencrypt((const unsigned char *)nt_pwd, chal, local_nt_response);
        
        /* Password info paranoia */
-       ZERO_STRUCT(lm_pwd);
-       ZERO_STRUCT(nt_pwd);
        ZERO_STRUCT(key);
 
        {
                BOOL ret;
                NTSTATUS nt_status;
-               DATA_BLOB local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response));
-               DATA_BLOB local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response));
-               DATA_BLOB plaintext_blob = data_blob(NULL, 0);
+               DATA_BLOB local_lm_blob;
+               DATA_BLOB local_nt_blob;
 
-               if (lm_interactive_pwd)
-                       auth_flags |= AUTH_FLAG_LM_RESP;
-               if (nt_interactive_pwd)
-                       auth_flags |= AUTH_FLAG_NTLM_RESP; 
+               DATA_BLOB lm_interactive_blob;
+               DATA_BLOB nt_interactive_blob;
+               
+               if (lm_interactive_pwd) {
+                       local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response));
+                       lm_interactive_blob = data_blob(lm_pwd, sizeof(lm_pwd));
+                       ZERO_STRUCT(lm_pwd);
+               }
+               
+               if (nt_interactive_pwd) {
+                       local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response));
+                       nt_interactive_blob = data_blob(nt_pwd, sizeof(nt_pwd));
+                       ZERO_STRUCT(nt_pwd);
+               }
 
                nt_status = make_user_info_map(user_info, 
                                               smb_name, client_domain, 
                                               wksta_name, 
-                                              local_lm_blob,
-                                              local_nt_blob,
-                                              plaintext_blob, 
-                                              auth_flags, True);
-               
+                                              lm_interactive_pwd ? &local_lm_blob : NULL,
+                                              nt_interactive_pwd ? &local_nt_blob : NULL,
+                                              lm_interactive_pwd ? &lm_interactive_blob : NULL,
+                                              nt_interactive_pwd ? &nt_interactive_blob : NULL,
+                                              NULL,
+                                              True);
+
                ret = NT_STATUS_IS_OK(nt_status) ? True : False;
                data_blob_free(&local_lm_blob);
                data_blob_free(&local_nt_blob);
+               data_blob_free(&lm_interactive_blob);
+               data_blob_free(&nt_interactive_blob);
                return ret;
        }
 }
@@ -377,7 +395,6 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info,
        DATA_BLOB local_lm_blob;
        DATA_BLOB local_nt_blob;
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-       uint32 auth_flags = AUTH_FLAG_NONE;
                        
        /*
         * Not encrypted - do so.
@@ -400,7 +417,6 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info,
                   case insensitive */
                local_nt_blob = data_blob(NULL, 0); 
                
-               auth_flags = (AUTH_FLAG_PLAINTEXT | AUTH_FLAG_LM_RESP);
        } else {
                local_lm_blob = data_blob(NULL, 0); 
                local_nt_blob = data_blob(NULL, 0); 
@@ -409,10 +425,11 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info,
        ret = make_user_info_map(user_info, smb_name,
                                 client_domain, 
                                 get_remote_machine_name(),
-                                local_lm_blob,
-                                local_nt_blob,
-                                plaintext_password, 
-                                auth_flags, False);
+                                local_lm_blob.data ? &local_lm_blob : NULL,
+                                local_nt_blob.data ? &local_nt_blob : NULL,
+                                NULL, NULL,
+                                plaintext_password.data ? &plaintext_password : NULL, 
+                                False);
        
        data_blob_free(&local_lm_blob);
        return NT_STATUS_IS_OK(ret) ? True : False;
@@ -427,27 +444,13 @@ NTSTATUS make_user_info_for_reply_enc(auth_usersupplied_info **user_info,
                                       const char *client_domain, 
                                       DATA_BLOB lm_resp, DATA_BLOB nt_resp)
 {
-       uint32 auth_flags = AUTH_FLAG_NONE;
-
-       DATA_BLOB no_plaintext_blob = data_blob(NULL, 0); 
-       
-       if (lm_resp.length == 24) {
-               auth_flags |= AUTH_FLAG_LM_RESP;
-       }
-       if (nt_resp.length == 0) {
-       } else if (nt_resp.length == 24) {
-               auth_flags |= AUTH_FLAG_NTLM_RESP;
-       } else {
-               auth_flags |= AUTH_FLAG_NTLMv2_RESP;
-       }
-
        return make_user_info_map(user_info, smb_name, 
-                                client_domain, 
-                                get_remote_machine_name(), 
-                                lm_resp
-                                nt_resp
-                                no_plaintext_blob, 
-                                auth_flags, True);
+                                 client_domain, 
+                                 get_remote_machine_name(), 
+                                 lm_resp.data ? &lm_resp : NULL
+                                 nt_resp.data ? &nt_resp : NULL
+                                 NULL, NULL, NULL,
+                                 True);
 }
 
 /****************************************************************************
@@ -456,19 +459,16 @@ NTSTATUS make_user_info_for_reply_enc(auth_usersupplied_info **user_info,
 
 BOOL make_user_info_guest(auth_usersupplied_info **user_info) 
 {
-       DATA_BLOB lm_blob = data_blob(NULL, 0);
-       DATA_BLOB nt_blob = data_blob(NULL, 0);
-       DATA_BLOB plaintext_blob = data_blob(NULL, 0);
-       uint32 auth_flags = AUTH_FLAG_NONE;
        NTSTATUS nt_status;
 
        nt_status = make_user_info(user_info, 
-                             "","", 
-                             "","", 
-                             "", 
-                             nt_blob, lm_blob,
-                             plaintext_blob, 
-                             auth_flags, True);
+                                  "","", 
+                                  "","", 
+                                  "", 
+                                  NULL, NULL, 
+                                  NULL, NULL, 
+                                  NULL,
+                                  True);
                              
        return NT_STATUS_IS_OK(nt_status) ? True : False;
 }
@@ -1307,7 +1307,8 @@ void free_user_info(auth_usersupplied_info **user_info)
                SAFE_FREE((*user_info)->wksta_name.str);
                data_blob_free(&(*user_info)->lm_resp);
                data_blob_free(&(*user_info)->nt_resp);
-               SAFE_FREE((*user_info)->interactive_password);
+               data_blob_clear_free(&(*user_info)->lm_interactive_pwd);
+               data_blob_clear_free(&(*user_info)->nt_interactive_pwd);
                data_blob_clear_free(&(*user_info)->plaintext_password);
                ZERO_STRUCT(**user_info);
        }
index ecf4d539d8c032826fc14c0eb4f07742a9eb3f00..8f52512e6a05dd37ba154962b91fdc289833d231 100644 (file)
@@ -27,37 +27,17 @@ typedef struct normal_string
        char *str;
 } AUTH_STR;
 
-/* AUTH_UNISTR - unicode string or buffer */
-typedef struct unicode_string
-{
-       int len;
-       uchar *unistr;
-} AUTH_UNISTR;
-
-typedef struct interactive_password
-{
-       OWF_INFO          lm_owf;              /* LM OWF Password */
-       OWF_INFO          nt_owf;              /* NT OWF Password */
-} auth_interactive_password;
-
-#define AUTH_FLAG_NONE        0x000000
-#define AUTH_FLAG_PLAINTEXT   0x000001
-#define AUTH_FLAG_LM_RESP     0x000002
-#define AUTH_FLAG_NTLM_RESP   0x000004
-#define AUTH_FLAG_NTLMv2_RESP 0x000008
-
 typedef struct auth_usersupplied_info
 {
        
        DATA_BLOB lm_resp;
        DATA_BLOB nt_resp;
-       auth_interactive_password * interactive_password;
+       DATA_BLOB lm_interactive_pwd;
+       DATA_BLOB nt_interactive_pwd;
        DATA_BLOB plaintext_password;
        
        BOOL encrypted;
        
-       uint32 auth_flags;
-
        AUTH_STR           client_domain;          /* domain name string */
        AUTH_STR           domain;               /* domain name after mapping */
        AUTH_STR           internal_username;    /* username after mapping */
index bc291b512863f139462328598b45e04b289ea670..a7764f9e98639945a1af6a952cd56cd39e03c369 100644 (file)
@@ -170,6 +170,8 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
                             const DATA_BLOB *challenge,
                             const DATA_BLOB *lm_response,
                             const DATA_BLOB *nt_response,
+                            const DATA_BLOB *lm_interactive_pwd,
+                            const DATA_BLOB *nt_interactive_pwd,
                             const char *username, 
                             const char *client_username, 
                             const char *client_domain,
@@ -183,6 +185,47 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
                         username));
        }
 
+       if (nt_interactive_pwd && nt_interactive_pwd->length && nt_pw) { 
+               if (nt_interactive_pwd->length != 16) {
+                       DEBUG(3,("ntlm_password_check: Interactive logon: Invalid NT password length (%d) supplied for user %s\n", (int)nt_interactive_pwd->length,
+                                username));
+                       return NT_STATUS_WRONG_PASSWORD;
+               }
+
+               if (memcmp(nt_interactive_pwd->data, nt_pw, 16) == 0) {
+                       if (user_sess_key) {
+                               *user_sess_key = data_blob(NULL, 16);
+                               SMBsesskeygen_ntv1(nt_pw, NULL, user_sess_key->data);
+                       }
+                       return NT_STATUS_OK;
+               } else {
+                       DEBUG(3,("ntlm_password_check: Interactive logon: NT password check failed for user %s\n",
+                                username));
+                       return NT_STATUS_WRONG_PASSWORD;
+               }
+
+       } else if (lm_interactive_pwd && lm_interactive_pwd->length && lm_pw) { 
+               if (lm_interactive_pwd->length != 16) {
+                       DEBUG(3,("ntlm_password_check: Interactive logon: Invalid LANMAN password length (%d) supplied for user %s\n", (int)lm_interactive_pwd->length,
+                                username));
+                       return NT_STATUS_WRONG_PASSWORD;
+               }
+
+               if (!lp_lanman_auth()) {
+                       DEBUG(3,("ntlm_password_check: Interactive logon: only LANMAN password supplied for user %s, and LM passwords are disabled!\n",
+                                username));
+                       return NT_STATUS_WRONG_PASSWORD;
+               }
+
+               if (memcmp(lm_interactive_pwd->data, lm_pw, 16) == 0) {
+                       return NT_STATUS_OK;
+               } else {
+                       DEBUG(3,("ntlm_password_check: Interactive logon: LANMAN password check failed for user %s\n",
+                                username));
+                       return NT_STATUS_WRONG_PASSWORD;
+               }
+       }
+
        /* Check for cleartext netlogon. Used by Exchange 5.5. */
        if (challenge->length == sizeof(zeros) && 
            (memcmp(challenge->data, zeros, challenge->length) == 0 )) {
index 2213a9bae37ae52a4a425b5b0b19b0960982f734..e33bca363bf1a5712ff9c815d3475eeef88060de 100644 (file)
@@ -366,6 +366,7 @@ static NTSTATUS local_pw_check(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *n
                                        &ntlmssp_state->chal,
                                        &ntlmssp_state->lm_resp,
                                        &ntlmssp_state->nt_resp, 
+                                       NULL, NULL,
                                        ntlmssp_state->user, 
                                        ntlmssp_state->user, 
                                        ntlmssp_state->domain,