r4499: Almost make our Samba4 server pass the RPC-SAMLOGON torture test.
authorAndrew Bartlett <abartlet@samba.org>
Mon, 3 Jan 2005 06:23:02 +0000 (06:23 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:08:15 +0000 (13:08 -0500)
I just need to fix a couple of NTLMv2 issues before we can fully pass,
and put this in test_rpc.sh, as a 'should pass' test.

Andrew Bartlett
(This used to be commit 4b52409e385366d87724bb79f4fad4803e8ecfec)

source4/auth/ntlm_check.c
source4/libcli/auth/credentials.c
source4/rpc_server/netlogon/dcerpc_netlogon.c
source4/rpc_server/netlogon/schannel_state.c
source4/torture/rpc/netlogon.c
source4/torture/rpc/samlogon.c

index e6a8ce681fae833342944a4954b8cdc4197b55ad..474742bee0bbdcc210714bdbd4dfa3b44cd3edc1 100644 (file)
@@ -285,48 +285,57 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
                         (unsigned long)nt_response->length, username));                
        }
        
-       if (nt_response->length >= 24 && nt_pw) {
-               if (nt_response->length > 24) {
-                       /* We have the NT MD4 hash challenge available - see if we can
-                          use it 
-                       */
-                       DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with domain [%s]\n", client_domain));
-                       if (smb_pwd_check_ntlmv2(mem_ctx,
-                                                nt_response, 
-                                                nt_pw, challenge, 
-                                                client_username, 
-                                                client_domain,
-                                                False,
-                                                user_sess_key)) {
-                               return NT_STATUS_OK;
+       if (nt_response->length > 24 && nt_pw) {
+               /* We have the NT MD4 hash challenge available - see if we can
+                  use it 
+               */
+               DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with domain [%s]\n", client_domain));
+               if (smb_pwd_check_ntlmv2(mem_ctx,
+                                        nt_response, 
+                                        nt_pw, challenge, 
+                                        client_username, 
+                                        client_domain,
+                                        False,
+                                        user_sess_key)) {
+                       if (lm_sess_key) {
+                               *lm_sess_key = *user_sess_key;
+                               lm_sess_key->length = 8;
                        }
-                       
-                       DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with uppercased version of domain [%s]\n", client_domain));
-                       if (smb_pwd_check_ntlmv2(mem_ctx,
-                                                nt_response, 
-                                                nt_pw, challenge, 
-                                                client_username, 
-                                                client_domain,
-                                                True,
-                                                user_sess_key)) {
-                               return NT_STATUS_OK;
+                       return NT_STATUS_OK;
+               }
+               
+               DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with uppercased version of domain [%s]\n", client_domain));
+               if (smb_pwd_check_ntlmv2(mem_ctx,
+                                        nt_response, 
+                                        nt_pw, challenge, 
+                                        client_username, 
+                                        client_domain,
+                                        True,
+                                        user_sess_key)) {
+                       if (lm_sess_key) {
+                               *lm_sess_key = *user_sess_key;
+                               lm_sess_key->length = 8;
                        }
-                       
-                       DEBUG(4,("ntlm_password_check: Checking NTLMv2 password without a domain\n"));
-                       if (smb_pwd_check_ntlmv2(mem_ctx,
-                                                nt_response, 
-                                                nt_pw, challenge, 
-                                                client_username, 
-                                                "",
-                                                False,
-                                                user_sess_key)) {
-                               return NT_STATUS_OK;
-                       } else {
-                               DEBUG(3,("ntlm_password_check: NTLMv2 password check failed\n"));
-                               return NT_STATUS_WRONG_PASSWORD;
+                       return NT_STATUS_OK;
+               }
+               
+               DEBUG(4,("ntlm_password_check: Checking NTLMv2 password without a domain\n"));
+               if (smb_pwd_check_ntlmv2(mem_ctx,
+                                        nt_response, 
+                                        nt_pw, challenge, 
+                                        client_username, 
+                                        "",
+                                        False,
+                                        user_sess_key)) {
+                       if (lm_sess_key) {
+                               *lm_sess_key = *user_sess_key;
+                               lm_sess_key->length = 8;
                        }
+                       return NT_STATUS_OK;
+               } else {
+                       DEBUG(3,("ntlm_password_check: NTLMv2 password check failed\n"));
                }
-
+       } else if (nt_response->length == 24 && nt_pw) {
                if (lp_ntlm_auth()) {           
                        /* We have the NT MD4 hash challenge available - see if we can
                           use it (ie. does it exist in the smbpasswd file).
@@ -338,7 +347,7 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
                                                 user_sess_key)) {
                                /* The LM session key for this response is not very secure, 
                                   so use it only if we otherwise allow LM authentication */
-
+                               
                                if (lp_lanman_auth() && lm_pw) {
                                        *lm_sess_key = data_blob_talloc(mem_ctx, lm_pw, 8);
                                }
@@ -409,7 +418,11 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
                                 client_username,
                                 client_domain,
                                 False,
-                                NULL)) {
+                                user_sess_key)) {
+               if (lm_sess_key) {
+                       *lm_sess_key = *user_sess_key;
+                       lm_sess_key->length = 8;
+               }
                return NT_STATUS_OK;
        }
        
@@ -420,7 +433,11 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
                                 client_username,
                                 client_domain,
                                 True,
-                                NULL)) {
+                                user_sess_key)) {
+               if (lm_sess_key) {
+                       *lm_sess_key = *user_sess_key;
+                       lm_sess_key->length = 8;
+               }
                return NT_STATUS_OK;
        }
        
@@ -431,7 +448,11 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
                                 client_username,
                                 "",
                                 False,
-                                NULL)) {
+                                user_sess_key)) {
+               if (lm_sess_key) {
+                       *lm_sess_key = *user_sess_key;
+                       lm_sess_key->length = 8;
+               }
                return NT_STATUS_OK;
        }
 
index a61660d7765184d025e9a72af8cb09cb107c05be..8cae71180cd669776bc647cc971ac7bb2da05406 100644 (file)
@@ -273,6 +273,7 @@ void creds_server_init(struct creds_CredentialState *creds,
        }
 
        *initial_credential = creds->server;
+       creds->negotiate_flags = negotiate_flags;
 }
 
 /*
@@ -290,10 +291,14 @@ BOOL creds_server_check(const struct creds_CredentialState *creds,
        return True;
 }
 
-BOOL creds_server_step_check(struct creds_CredentialState *creds,
+NTSTATUS creds_server_step_check(struct creds_CredentialState *creds,
                             struct netr_Authenticator *received_authenticator,
                             struct netr_Authenticator *return_authenticator) 
 {
+       if (!received_authenticator || !return_authenticator) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
        /* TODO: this may allow the a replay attack on a non-signed
           connection. Should we check that this is increasing? */
        creds->sequence = received_authenticator->timestamp;
@@ -301,9 +306,9 @@ BOOL creds_server_step_check(struct creds_CredentialState *creds,
        if (creds_server_check(creds, &received_authenticator->cred)) {
                return_authenticator->cred = creds->server;
                return_authenticator->timestamp = creds->sequence;
-               return True;
+               return NT_STATUS_OK;
        } else {
                ZERO_STRUCTP(return_authenticator);
-               return False;
+               return NT_STATUS_ACCESS_DENIED;
        }
 }
index 422aa626ede2f0a2f89dbf916f8d8a7c4e0e1584..167c4e8ceb533ea85b9d0548a271a0d81148b698 100644 (file)
@@ -317,12 +317,17 @@ static NTSTATUS netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TAL
 }
 
 
-static BOOL netr_creds_server_step_check(struct server_pipe_state *pipe_state,
-                                        struct netr_Authenticator *received_authenticator,
-                                        struct netr_Authenticator *return_authenticator) 
+static NTSTATUS netr_creds_server_step_check(struct server_pipe_state *pipe_state,
+                                            struct netr_Authenticator *received_authenticator,
+                                            struct netr_Authenticator *return_authenticator) 
 {
+       if (!pipe_state) {
+               DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
        if (!pipe_state->authenticated) {
-               return False;
+               return NT_STATUS_ACCESS_DENIED;
        }
        return creds_server_step_check(pipe_state->creds, 
                                       received_authenticator, 
@@ -351,13 +356,9 @@ static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLO
        const char **domain_attrs = attrs;
        ZERO_STRUCT(mod);
 
-       if (!pipe_state) {
-               DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
-       if (!netr_creds_server_step_check(pipe_state, &r->in.credential, &r->out.return_authenticator)) {
-               return NT_STATUS_ACCESS_DENIED;
+       nt_status = netr_creds_server_step_check(pipe_state, &r->in.credential, &r->out.return_authenticator);
+       if (NT_STATUS_IS_OK(nt_status)) {
+               return nt_status;
        }
 
        sam_ctx = samdb_connect(mem_ctx);
@@ -461,9 +462,10 @@ static WERROR netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX
 /* 
   netr_LogonSamLogonWithFlags
 
+  This version of the function allows other wrappers to say 'do not check the credentials'
 */
-static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                                           struct netr_LogonSamLogonWithFlags *r)
+static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                    struct netr_LogonSamLogonEx *r)
 {
        struct server_pipe_state *pipe_state = dce_call->conn->private;
 
@@ -478,30 +480,21 @@ static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call,
        struct netr_SamInfo3 *sam3;
        struct netr_SamInfo6 *sam6;
        
-       if (!pipe_state) {
-               DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
-       r->out.return_authenticator = talloc_p(mem_ctx, struct netr_Authenticator);
-       if (!r->out.return_authenticator) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       if (!netr_creds_server_step_check(pipe_state, r->in.credential, r->out.return_authenticator)) {
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
        switch (r->in.logon_level) {
        case 1:
        case 3:
        case 5:
-               creds_arcfour_crypt(pipe_state->creds, 
-                                   r->in.logon.password->lmpassword.hash, 
-                                   sizeof(r->in.logon.password->lmpassword.hash));
-               creds_arcfour_crypt(pipe_state->creds, 
-                                   r->in.logon.password->ntpassword.hash, 
-                                   sizeof(r->in.logon.password->ntpassword.hash));
+               if (pipe_state->creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
+                       creds_arcfour_crypt(pipe_state->creds, 
+                                           r->in.logon.password->lmpassword.hash, 
+                                           sizeof(r->in.logon.password->lmpassword.hash));
+                       creds_arcfour_crypt(pipe_state->creds, 
+                                           r->in.logon.password->ntpassword.hash, 
+                                           sizeof(r->in.logon.password->ntpassword.hash));
+               } else {
+                       creds_des_decrypt(pipe_state->creds, &r->in.logon.password->lmpassword);
+                       creds_des_decrypt(pipe_state->creds, &r->in.logon.password->ntpassword);
+               }
 
                nt_status = make_auth_context_subsystem(pipe_state, &auth_context);
                if (!NT_STATUS_IS_OK(nt_status)) {
@@ -600,9 +593,13 @@ static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call,
        if ((r->in.validation_level != 6) 
            && memcmp(sam->key.key, zeros,  
                      sizeof(sam->key.key)) != 0) {
-               creds_arcfour_crypt(pipe_state->creds, 
-                                   sam->key.key, 
-                                   sizeof(sam->key.key));
+
+               /* This key is sent unencrypted without the ARCFOUR flag set */
+               if (pipe_state->creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
+                       creds_arcfour_crypt(pipe_state->creds, 
+                                           sam->key.key, 
+                                           sizeof(sam->key.key));
+               }
        }
        
        if (server_info->lm_session_key.length == sizeof(sam->LMSessKey.key)) {
@@ -617,9 +614,14 @@ static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call,
        if ((r->in.validation_level != 6) 
            && memcmp(sam->LMSessKey.key, zeros,  
                      sizeof(sam->LMSessKey.key)) != 0) {
-               creds_arcfour_crypt(pipe_state->creds, 
-                                   sam->LMSessKey.key, 
-                                   sizeof(sam->LMSessKey.key));
+               if (pipe_state->creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
+                       creds_arcfour_crypt(pipe_state->creds, 
+                                           sam->LMSessKey.key, 
+                                           sizeof(sam->LMSessKey.key));
+               } else {
+                       creds_des_encrypt_LMKey(pipe_state->creds, 
+                                               &sam->LMSessKey);
+               }
        }
 
        switch (r->in.validation_level) {
@@ -656,6 +658,45 @@ static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call,
        return NT_STATUS_OK;
 }
 
+/* 
+  netr_LogonSamLogonWithFlags
+
+*/
+static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                           struct netr_LogonSamLogonWithFlags *r)
+{
+       NTSTATUS nt_status;
+       struct netr_LogonSamLogonEx r2;
+
+       struct server_pipe_state *pipe_state = dce_call->conn->private;
+
+       r->out.return_authenticator = talloc_p(mem_ctx, struct netr_Authenticator);
+       if (!r->out.return_authenticator) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       nt_status = netr_creds_server_step_check(pipe_state, r->in.credential, r->out.return_authenticator);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               return nt_status;
+       }
+
+       ZERO_STRUCT(r2);
+
+       r2.in.server_name = r->in.server_name;
+       r2.in.workstation = r->in.workstation;
+       r2.in.logon_level = r->in.logon_level;
+       r2.in.logon = r->in.logon;
+       r2.in.validation_level = r->in.validation_level;
+       r2.in.flags = r->in.flags;
+
+       nt_status = netr_LogonSamLogonEx(dce_call, mem_ctx, &r2);
+
+       r->out.validation = r2.out.validation;
+       r->out.authoritative = r2.out.authoritative;
+
+       return nt_status;
+}
+
 /* 
   netr_LogonSamLogon
 */
@@ -940,13 +981,10 @@ static NTSTATUS netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALL
        int ret1, ret2, i;
        NTSTATUS status;
 
-       if (!pipe_state) {
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
-       if (!netr_creds_server_step_check(pipe_state, 
-                                         r->in.credential, r->out.credential)) {
-               return NT_STATUS_ACCESS_DENIED;
+       status = netr_creds_server_step_check(pipe_state, 
+                                             r->in.credential, r->out.credential);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
        sam_ctx = samdb_connect(mem_ctx);
@@ -1133,16 +1171,6 @@ static WERROR netr_DSRGETDCSITECOVERAGEW(struct dcesrv_call_state *dce_call, TAL
 }
 
 
-/* 
-  netr_LogonSamLogonEx
-*/
-static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct netr_LogonSamLogonEx *r)
-{
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
-
 /* 
   netr_DsrEnumerateDomainTrusts 
 */
index 564564e8c21c7a1efd480687ff2edaf36001963a..7dc60a161781b6fb5c943cfd721017021904ca87 100644 (file)
@@ -61,7 +61,8 @@ NTSTATUS schannel_store_session_key(TALLOC_CTX *mem_ctx,
        struct ldb_wrap *ldb;
        struct ldb_message *msg;
        struct ldb_val val, seed;
-       char *s = NULL;
+       char *s;
+       char *f;
        time_t expiry = time(NULL) + SCHANNEL_CREDENTIALS_EXPIRY;
        int ret;
 
@@ -77,6 +78,13 @@ NTSTATUS schannel_store_session_key(TALLOC_CTX *mem_ctx,
                return NT_STATUS_NO_MEMORY;
        }
 
+       f = talloc_asprintf(mem_ctx, "%u", (unsigned int)creds->negotiate_flags);
+
+       if (f == NULL) {
+               talloc_free(ldb);
+               return NT_STATUS_NO_MEMORY;
+       }
+
        msg = ldb_msg_new(mem_ctx);
        if (msg == NULL) {
                talloc_free(ldb);
@@ -99,6 +107,7 @@ NTSTATUS schannel_store_session_key(TALLOC_CTX *mem_ctx,
        ldb_msg_add_value(ldb->ldb, msg, "sessionKey", &val);
        ldb_msg_add_value(ldb->ldb, msg, "seed", &seed);
        ldb_msg_add_string(ldb->ldb, msg, "expiry", s);
+       ldb_msg_add_string(ldb->ldb, msg, "negotiateFlags", f);
 
        ldb_delete(ldb->ldb, msg->dn);
 
@@ -180,6 +189,8 @@ NTSTATUS schannel_fetch_session_key(TALLOC_CTX *mem_ctx,
 
        memcpy((*creds)->seed.data, val->data, 8);
 
+       (*creds)->negotiate_flags = ldb_msg_find_int(res[0], "negotiateFlags", 0);
+
        talloc_free(ldb);
 
        return NT_STATUS_OK;
index a23cdb8b0c552519dac1a177463fe843e2b0fa64..35f64933a9d6b54d5b86004a3585038f7f5e9776 100644 (file)
@@ -378,6 +378,22 @@ static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
                }
        }
 
+       r.in.credential = NULL;
+
+       for (i=2;i<=3;i++) {
+
+               r.in.validation_level = i;
+
+               printf("Testing SamLogon with validation level %d\n", i);
+
+               status = dcerpc_netr_LogonSamLogon(p, mem_ctx, &r);
+               if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
+                       printf("LogonSamLogon expected INVALID_PARAMETER, got: %s\n", nt_errstr(status));
+                       ret = False;
+               }
+
+       }
+
        return ret;
 }
 
index 821a8235950f438279abd2fc25d21d9008731eac..29a87f9804e550ae7f5ce613e733fb1b44b274a5 100644 (file)
@@ -220,7 +220,11 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state,
                /* we cannot check the session key, if the logon failed... */
                return status;
        }
-               
+
+       if (!base) {
+               printf("No user info returned from 'successful' SamLogon*() call!\n");
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
        /* find and decyrpt the session keys, return in parameters above */
        if (validation_level == 6) {
@@ -1043,11 +1047,12 @@ BOOL torture_rpc_samlogon(void)
        int i;
        
        unsigned int credential_flags[] = {
-               0, 
                NETLOGON_NEG_AUTH2_FLAGS,
                NETLOGON_NEG_ARCFOUR,
                NETLOGON_NEG_ARCFOUR | NETLOGON_NEG_128BIT,
-               NETLOGON_NEG_AUTH2_ADS_FLAGS};
+               NETLOGON_NEG_AUTH2_ADS_FLAGS, 
+               0 /* yes, this is a valid flag, causes the use of DES */ 
+       };
 
        struct creds_CredentialState *creds;