s4-torture: precalculate expected session keys from samlogon in schannel test.
authorGünther Deschner <gd@samba.org>
Fri, 7 Dec 2012 11:57:18 +0000 (12:57 +0100)
committerStefan Metzmacher <metze@samba.org>
Sun, 9 Dec 2012 18:39:08 +0000 (19:39 +0100)
Guenther

Signed-off-by: Günther Deschner <gd@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
source4/torture/rpc/schannel.c

index 7e3e6aad64ac85b487d2d24555ab7c59387dd3ec..e0862d246764191f211dab47f93447e45a43382e 100644 (file)
@@ -58,6 +58,13 @@ bool test_netlogon_ex_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
        int flags = CLI_CRED_NTLM_AUTH;
        struct dcerpc_binding_handle *b = p->binding_handle;
 
+       struct netr_UserSessionKey key;
+       struct netr_LMSessionKey LMSessKey;
+       uint32_t validation_levels[] = { 2, 3 };
+       struct netr_SamBaseInfo *base;
+       const char *crypto_alg = "";
+       bool can_do_validation_6 = true;
+
        if (lpcfg_client_lanman_auth(tctx->lp_ctx)) {
                flags |= CLI_CRED_LANMAN_AUTH;
        }
@@ -109,16 +116,113 @@ bool test_netlogon_ex_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
        r.out.authoritative = &authoritative;
        r.out.flags = &_flags;
 
+       /*
+       - retrieve level6
+       - save usrsession and lmsession key
+       - retrieve level 2
+       - calculate, compare
+       - retrieve level 3
+       - calculate, compare
+       */
+
+       if (creds) {
+               if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
+                       crypto_alg = "AES";
+               } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
+                       crypto_alg = "ARCFOUR";
+               }
+       }
+
+       r.in.validation_level = 6;
+
        torture_comment(tctx,
-                       "Testing LogonSamLogonEx with name %s\n",
-                       ninfo.identity_info.account_name.string);
+                       "Testing LogonSamLogonEx with name %s using %s and validation_level: %d\n",
+                       ninfo.identity_info.account_name.string, crypto_alg,
+                       r.in.validation_level);
+
+       torture_assert_ntstatus_ok(tctx,
+               dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
+               "LogonSamLogonEx failed");
+       if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_INFO_CLASS)) {
+               can_do_validation_6 = false;
+       } else {
+               torture_assert_ntstatus_ok(tctx, r.out.result,
+                       "LogonSamLogonEx failed");
+
+               key = r.out.validation->sam6->base.key;
+               LMSessKey = r.out.validation->sam6->base.LMSessKey;
+
+               DEBUG(1,("unencrypted session keys from validation_level 6:\n"));
+               dump_data(1, r.out.validation->sam6->base.key.key, 16);
+               dump_data(1, r.out.validation->sam6->base.LMSessKey.key, 8);
+       }
+
+       for (i=0; i < ARRAY_SIZE(validation_levels); i++) {
 
-       for (i=2;i<3;i++) {
-               r.in.validation_level = i;
+               r.in.validation_level = validation_levels[i];
+
+               torture_comment(tctx,
+                       "Testing LogonSamLogonEx with name %s using %s and validation_level: %d\n",
+                       ninfo.identity_info.account_name.string, crypto_alg,
+                       r.in.validation_level);
+
+               torture_assert_ntstatus_ok(tctx,
+                       dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
+                       "LogonSamLogonEx failed");
+               torture_assert_ntstatus_ok(tctx, r.out.result,
+                       "LogonSamLogonEx failed");
+
+               if (creds == NULL) {
+                       /* when this test is called without creds no point in
+                        * testing the session keys */
+                       continue;
+               }
+
+               switch (validation_levels[i]) {
+               case 2:
+                       base = &r.out.validation->sam2->base;
+                       break;
+               case 3:
+                       base = &r.out.validation->sam3->base;
+                       break;
+               default:
+                       break;
+               }
+
+               DEBUG(1,("encrypted keys validation_level %d:\n",
+                       validation_levels[i]));
+               dump_data(1, base->key.key, 16);
+               dump_data(1, base->LMSessKey.key, 8);
+
+               if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
+                       netlogon_creds_aes_decrypt(creds, base->key.key, 16);
+                       netlogon_creds_aes_decrypt(creds, base->LMSessKey.key, 8);
+               } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
+                       netlogon_creds_arcfour_crypt(creds, base->key.key, 16);
+                       netlogon_creds_arcfour_crypt(creds, base->LMSessKey.key, 8);
+               }
+
+               DEBUG(1,("decryped keys validation_level %d\n",
+                       validation_levels[i]));
+
+               dump_data(1, base->key.key, 16);
+               dump_data(1, base->LMSessKey.key, 8);
+
+               if (!can_do_validation_6) {
+                       /* we cant compare against unencrypted keys */
+                       continue;
+               }
 
-               torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
-                       "LogonSamLogon failed");
-               torture_assert_ntstatus_ok(tctx, r.out.result, "LogonSamLogon failed");
+               torture_assert_mem_equal(tctx,
+                                        base->key.key,
+                                        key.key,
+                                        16,
+                                        "unexpected user session key\n");
+               torture_assert_mem_equal(tctx,
+                                        base->LMSessKey.key,
+                                        LMSessKey.key,
+                                        8,
+                                        "unexpected LM session key\n");
        }
 
        return true;