]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s4:torture/rpc: add test for invalid av_pair content in LogonSamLogonEx
authorStefan Metzmacher <metze@samba.org>
Fri, 17 Dec 2021 21:28:51 +0000 (22:28 +0100)
committerJeremy Allison <jra@samba.org>
Tue, 4 Jan 2022 20:07:28 +0000 (20:07 +0000)
A netapp diag tool uses a NTLMv2_CLIENT_CHALLENGE with invalid bytes
as av_pair blob. Which is supposed to be ignored by DCs.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14932

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
selftest/knownfail.d/rpc.schannel [new file with mode: 0644]
source4/torture/rpc/schannel.c

diff --git a/selftest/knownfail.d/rpc.schannel b/selftest/knownfail.d/rpc.schannel
new file mode 100644 (file)
index 0000000..f0be92f
--- /dev/null
@@ -0,0 +1,14 @@
+^samba3.rpc.schannel.schannel.nt4_dc
+^samba3.rpc.schannel.schannel.ad_dc
+^samba4.rpc.schannel.on.ncalrpc.with.seal,padcheck.schannel.ad_dc_default:local
+^samba4.rpc.schannel.on.ncacn_np.with.seal,padcheck.schannel.ad_dc_default
+^samba4.rpc.schannel.on.ncacn_ip_tcp.with.seal,padcheck.schannel.ad_dc_default
+^samba4.rpc.schannel.on.ncalrpc.with.validate.schannel.ad_dc_default:local
+^samba4.rpc.schannel.on.ncacn_np.with.validate.schannel.ad_dc_default
+^samba4.rpc.schannel.on.ncacn_ip_tcp.with.validate.schannel.ad_dc_default
+^samba4.rpc.schannel.on.ncalrpc.with.bigendian.schannel.ad_dc_default:local
+^samba4.rpc.schannel.on.ncacn_np.with.bigendian.schannel.ad_dc_default
+^samba4.rpc.schannel.on.ncacn_ip_tcp.with.bigendian.schannel.ad_dc_default
+^samba4.rpc.schannel.with.seal,padcheck.schannel.ad_dc
+^samba4.rpc.schannel.with.validate.schannel.ad_dc
+^samba4.rpc.schannel.with.bigendian.schannel.ad_dc
index 85807e6aeaba8e7bc4b00ff59cd6d1f2e3857ace..ed94c912251a0af906c5aefd6b4ebd99ed62a5fc 100644 (file)
@@ -241,6 +241,211 @@ bool test_netlogon_ex_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
        return true;
 }
 
+static bool test_netlogon_ex_bug14932(struct dcerpc_pipe *p,
+                                     struct torture_context *tctx,
+                                     struct cli_credentials *credentials,
+                                     struct netlogon_creds_CredentialState *creds)
+{
+       NTSTATUS status;
+       struct netr_LogonSamLogonEx r;
+       struct netr_NetworkInfo ninfo;
+       union netr_LogonLevel logon;
+       union netr_Validation validation;
+       uint8_t authoritative = 1;
+       uint32_t _flags = 0;
+       static const char *netapp_magic =
+               "\x01\x01\x00\x00\x00\x00\x00\x00"
+               "\x3f\x3f\x3f\x3f\x3f\x3f\x3f\x3f"
+               "\xb8\x82\x3a\xf1\xb3\xdd\x08\x15"
+               "\x00\x00\x00\x00\x11\xa2\x08\x81"
+               "\x50\x38\x22\x78\x2b\x94\x47\xfe"
+               "\x54\x94\x7b\xff\x17\x27\x5a\xb4"
+               "\xf4\x18\xba\xdc\x2c\x38\xfd\x5b"
+               "\xfb\x0e\xc1\x85\x1e\xcc\x92\xbb"
+               "\x9b\xb1\xc4\xd5\x53\x14\xff\x8c"
+               "\x76\x49\xf5\x45\x90\x19\xa2";
+       NTTIME timestamp = BVAL(netapp_magic, 8);
+       DATA_BLOB names_blob = data_blob_string_const(netapp_magic + 28);
+       DATA_BLOB chal, lm_resp, nt_resp;
+       int i;
+       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 = NULL;
+       const char *crypto_alg = "";
+       bool can_do_validation_6 = true;
+       enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
+
+       flags |= CLI_CRED_NTLMv2_AUTH;
+
+       cli_credentials_get_ntlm_username_domain(samba_cmdline_get_creds(),
+                               tctx,
+                               &ninfo.identity_info.account_name.string,
+                               &ninfo.identity_info.domain_name.string);
+
+       generate_random_buffer(ninfo.challenge,
+                              sizeof(ninfo.challenge));
+
+       chal = data_blob_const(ninfo.challenge,
+                              sizeof(ninfo.challenge));
+
+       status = cli_credentials_get_ntlm_response(
+                       samba_cmdline_get_creds(),
+                       tctx,
+                       &flags,
+                       chal,
+                       &timestamp,
+                       names_blob,
+                       &lm_resp, &nt_resp,
+                       NULL, NULL);
+       torture_assert_ntstatus_ok(tctx, status,
+                                  "cli_credentials_get_ntlm_response failed");
+
+       ninfo.lm.data = lm_resp.data;
+       ninfo.lm.length = lm_resp.length;
+
+       ninfo.nt.data = nt_resp.data;
+       ninfo.nt.length = nt_resp.length;
+
+       ninfo.identity_info.parameter_control = 0;
+       ninfo.identity_info.logon_id = 0;
+       ninfo.identity_info.workstation.string = cli_credentials_get_workstation(credentials);
+
+       logon.network = &ninfo;
+
+       r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
+       r.in.computer_name = cli_credentials_get_workstation(credentials);
+       r.in.logon_level = NetlogonNetworkInformation;
+       r.in.logon= &logon;
+       r.in.flags = &_flags;
+       r.out.validation = &validation;
+       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 != NULL) {
+               if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
+                       crypto_alg = "AES";
+               } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
+                       crypto_alg = "ARCFOUR";
+               }
+       }
+
+       dcerpc_binding_handle_auth_info(b, NULL, &auth_level);
+       if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
+               r.in.validation_level = 6;
+
+               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");
+       } else {
+               torture_comment(tctx,
+                               "Skip auth_level[%u] Testing LogonSamLogonEx with name %s using %s and validation_level: %d\n",
+                               auth_level, ninfo.identity_info.account_name.string, crypto_alg,
+                               r.in.validation_level);
+               r.out.result = NT_STATUS_INVALID_INFO_CLASS;
+       }
+
+       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++) {
+
+               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_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;
+}
+
 /*
   do some samr ops using the schannel connection
  */
@@ -436,6 +641,10 @@ static bool test_schannel(struct torture_context *tctx,
        torture_assert(tctx, test_netlogon_ex_ops(p_netlogon, tctx, credentials, creds),
                "Failed to process schannel secured NETLOGON EX ops");
 
+       /* regression test for https://bugzilla.samba.org/show_bug.cgi?id=14932 */
+       torture_assert(tctx, test_netlogon_ex_bug14932(p_netlogon, tctx, credentials, creds),
+                      "Failed to process schannel secured NETLOGON EX for BUG 14932");
+
        /* we *MUST* use ncacn_np for openpolicy etc. */
        transport = dcerpc_binding_get_transport(b);
        status = dcerpc_binding_set_transport(b, NCACN_NP);