summaryrefslogtreecommitdiffstats
path: root/source4/torture/rpc/netlogon_crypto.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/torture/rpc/netlogon_crypto.c')
-rw-r--r--source4/torture/rpc/netlogon_crypto.c274
1 files changed, 274 insertions, 0 deletions
diff --git a/source4/torture/rpc/netlogon_crypto.c b/source4/torture/rpc/netlogon_crypto.c
new file mode 100644
index 0000000..8584460
--- /dev/null
+++ b/source4/torture/rpc/netlogon_crypto.c
@@ -0,0 +1,274 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ test suite for netlogon rpc operations
+
+ Copyright (C) Andrew Tridgell 2003
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003-2004
+ Copyright (C) Tim Potter 2003
+ Copyright (C) Matthias Dieter Wallnöfer 2009-2010
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "lib/replace/system/network.h"
+#include "lib/cmdline/cmdline.h"
+#include "torture/rpc/torture_rpc.h"
+#include "libcli/auth/libcli_auth.h"
+#include "librpc/gen_ndr/ndr_netlogon_c.h"
+#include "param/param.h"
+#include "lib/param/loadparm.h"
+#include "libcli/security/security.h"
+
+#undef strcasecmp
+
+#define TEST_MACHINE_NAME "torturetest"
+
+static bool test_ServerAuth3Crypto(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
+ uint32_t negotiate_flags,
+ struct cli_credentials *machine_credentials,
+ bool force_client_rc4)
+{
+ struct netr_ServerReqChallenge r;
+ struct netr_ServerAuthenticate3 a;
+ struct netr_Credential netr_creds1 = {
+ .data = {0},
+ };
+ struct netr_Credential netr_creds2 = {
+ .data = {0},
+ };
+ struct netr_Credential netr_creds3 = {
+ .data = {0},
+ };
+ struct netlogon_creds_CredentialState *creds_state = NULL;
+ struct samr_Password machine_password = {
+ .hash = {0},
+ };
+ const char *machine_name = NULL;
+ const char *plain_pass = NULL;
+ struct dcerpc_binding_handle *b = NULL;
+ uint32_t rid = 0;
+ NTSTATUS status;
+ bool weak_crypto_allowed =
+ (lpcfg_weak_crypto(tctx->lp_ctx) ==
+ SAMBA_WEAK_CRYPTO_ALLOWED);
+
+ if (p == NULL) {
+ return false;
+ }
+ b = p->binding_handle;
+
+ ZERO_STRUCT(r);
+ ZERO_STRUCT(a);
+
+ torture_comment(tctx, "client negotiate_flags=0x%08x\n", negotiate_flags);
+
+ machine_name = cli_credentials_get_workstation(machine_credentials);
+ torture_assert_not_null(tctx, machine_name, "machine name is not set");
+
+ plain_pass = cli_credentials_get_password(machine_credentials);
+ torture_assert_not_null(tctx, plain_pass, "plain_pass is not set");
+
+
+ torture_comment(tctx, "Testing ServerReqChallenge\n");
+
+ r.in.server_name = NULL;
+ r.in.computer_name = machine_name;
+ r.in.credentials = &netr_creds1;
+ r.out.return_credentials = &netr_creds2;
+
+ netlogon_creds_random_challenge(&netr_creds1);
+
+ status = dcerpc_netr_ServerReqChallenge_r(b, tctx, &r);
+ torture_assert_ntstatus_ok(tctx,
+ status,
+ "ServerReqChallenge failed");
+ torture_assert_ntstatus_ok(tctx,
+ r.out.result,
+ "ServerReqChallenge failed");
+
+ E_md4hash(plain_pass, machine_password.hash);
+
+ a.in.server_name = NULL;
+ a.in.account_name = talloc_asprintf(tctx, "%s$", machine_name);
+ a.in.secure_channel_type =
+ cli_credentials_get_secure_channel_type(machine_credentials);
+ a.in.computer_name = machine_name;
+ a.in.negotiate_flags = &negotiate_flags;
+ a.in.credentials = &netr_creds3;
+ a.out.return_credentials = &netr_creds3;
+ a.out.negotiate_flags = &negotiate_flags;
+ a.out.rid = &rid;
+
+ if (force_client_rc4) {
+ GNUTLS_FIPS140_SET_LAX_MODE();
+ }
+ creds_state = netlogon_creds_client_init(tctx,
+ a.in.account_name,
+ a.in.computer_name,
+ a.in.secure_channel_type,
+ &netr_creds1,
+ &netr_creds2,
+ &machine_password,
+ &netr_creds3,
+ negotiate_flags);
+ GNUTLS_FIPS140_SET_STRICT_MODE();
+ /* Test that we fail to encrypt with RC4 */
+ if (creds_state == NULL &&
+ !weak_crypto_allowed && !force_client_rc4 &&
+ (negotiate_flags & NETLOGON_NEG_ARCFOUR)) {
+ return false;
+ }
+ torture_assert_not_null(tctx,
+ creds_state,
+ "Failed init netlogon client creds");
+
+
+ torture_comment(tctx, "Testing ServerAuthenticate3\n");
+
+ status = dcerpc_netr_ServerAuthenticate3_r(b, tctx, &a);
+ torture_assert_ntstatus_ok(tctx,
+ status,
+ "ServerAuthenticate3 failed");
+
+ /* Check that the server denies RC4 */
+ if (!NT_STATUS_IS_OK(a.out.result) &&
+ !weak_crypto_allowed &&
+ force_client_rc4) {
+ torture_assert_ntstatus_equal(tctx,
+ a.out.result,
+ NT_STATUS_DOWNGRADE_DETECTED,
+ "Unexpected status code");
+ return false;
+ }
+ torture_assert_ntstatus_ok(tctx,
+ a.out.result,
+ "ServerAuthenticate3 failed");
+ torture_assert(tctx,
+ netlogon_creds_client_check(creds_state, &netr_creds3),
+ "Credential chaining failed");
+
+ torture_comment(tctx,
+ "server negotiate_flags=0x%08x\n",
+ negotiate_flags);
+
+ if (!weak_crypto_allowed) {
+ torture_assert(tctx,
+ (negotiate_flags & NETLOGON_NEG_ARCFOUR) == 0,
+ "Server should not announce RC4 support");
+ }
+
+ /* Prove that requesting a challenge again won't break it */
+ torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b, tctx, &r),
+ "ServerReqChallenge failed");
+ torture_assert_ntstatus_ok(tctx, r.out.result, "ServerReqChallenge failed");
+
+ return true;
+}
+
+
+/* Test that we can successfully authenticate using AES. */
+static bool test_AES_Crypto(struct torture_context *tctx,
+ struct dcerpc_pipe *p,
+ struct cli_credentials *machine_credentials)
+{
+ uint32_t negotiate_flags =
+ NETLOGON_NEG_AUTH2_ADS_FLAGS|
+ NETLOGON_NEG_SUPPORTS_AES;
+ bool ok;
+
+ ok = test_ServerAuth3Crypto(p,
+ tctx,
+ negotiate_flags,
+ machine_credentials,
+ false);
+ if (!ok) {
+ return false;
+ }
+
+ return true;
+}
+
+/* If we try to use RC4, the client code should fail to encrypt. */
+static bool test_RC4_Crypto_Fail(struct torture_context *tctx,
+ struct dcerpc_pipe *p,
+ struct cli_credentials *machine_credentials)
+{
+ uint32_t negotiate_flags =
+ NETLOGON_NEG_AUTH2_ADS_FLAGS|
+ NETLOGON_NEG_ARCFOUR;
+ bool ok;
+
+ ok = test_ServerAuth3Crypto(p,
+ tctx,
+ negotiate_flags,
+ machine_credentials,
+ false);
+ if (!ok) {
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * Enforce the use of RC4 and try to authenticate. The server should fail
+ * in this case as it doesn't allow RC4
+ */
+static bool test_RC4_Crypto_Force(struct torture_context *tctx,
+ struct dcerpc_pipe *p,
+ struct cli_credentials *machine_credentials)
+{
+ uint32_t negotiate_flags =
+ NETLOGON_NEG_AUTH2_ADS_FLAGS|
+ NETLOGON_NEG_ARCFOUR;
+ bool ok;
+
+ ok = test_ServerAuth3Crypto(p,
+ tctx,
+ negotiate_flags,
+ machine_credentials,
+ true);
+ if (!ok) {
+ return true;
+ }
+
+ return false;
+}
+
+struct torture_suite *torture_rpc_netlogon_crypto_fips(TALLOC_CTX *mem_ctx)
+{
+ struct torture_suite *suite = torture_suite_create(mem_ctx,
+ "fips.netlogon.crypto");
+ struct torture_rpc_tcase *tcase = NULL;
+
+ tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite,
+ "netlogon",
+ &ndr_table_netlogon,
+ TEST_MACHINE_NAME);
+
+ torture_rpc_tcase_add_test_creds(tcase,
+ "test_AES_Crytpo",
+ test_AES_Crypto);
+ torture_rpc_tcase_add_test_creds(tcase,
+ "test_RC4_Crytpo_Fail",
+ test_RC4_Crypto_Fail);
+ torture_rpc_tcase_add_test_creds(tcase,
+ "test_RC4_Crytpo_Force",
+ test_RC4_Crypto_Force);
+
+ return suite;
+}