diff options
author | Andreas Schneider <asn@samba.org> | 2021-07-26 10:18:05 +0200 |
---|---|---|
committer | Andreas Schneider <asn@cryptomilk.org> | 2021-08-03 10:18:26 +0000 |
commit | 23e5b7cc79b006ae9260d3723e6c44ad66589382 (patch) | |
tree | 764764e56b6c78a873324edad27a1bf324b55ed4 | |
parent | f1df0c4d0ad43ed1726ba961810078059b990be3 (diff) | |
download | samba-23e5b7cc79b006ae9260d3723e6c44ad66589382.tar.gz |
s4:torture: Add rpc netlogon fips test
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Autobuild-User(master): Andreas Schneider <asn@cryptomilk.org>
Autobuild-Date(master): Tue Aug 3 10:18:26 UTC 2021 on sn-devel-184
-rwxr-xr-x | source4/selftest/tests.py | 16 | ||||
-rw-r--r-- | source4/torture/rpc/netlogon_crypto.c | 274 | ||||
-rw-r--r-- | source4/torture/rpc/rpc.c | 1 | ||||
-rw-r--r-- | source4/torture/wscript_build | 1 |
4 files changed, 291 insertions, 1 deletions
diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index acf2cf95d35..01c190704a0 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -201,7 +201,11 @@ all_rpc_tests = ncalrpc_tests + ncacn_np_tests + ncacn_ip_tcp_tests + slow_ncacn rpc_s3only = [ "rpc.mdssvc", ] -rpc_tests = [x for x in smbtorture4_testsuites("rpc.") if x not in rpc_s3only] +rpc_fipsonly = [ + "rpc.fips.netlogon.crypto", +] +rpc_exclude = rpc_s3only + rpc_fipsonly +rpc_tests = [x for x in smbtorture4_testsuites("rpc.") if x not in rpc_exclude] auto_rpc_tests = list(filter(lambda t: t not in all_rpc_tests, rpc_tests)) for bindoptions in ["seal,padcheck"] + validate_list + ["bigendian"]: @@ -636,6 +640,16 @@ if have_gnutls_fips_mode_support: environ={'GNUTLS_FORCE_FIPS_MODE': '1', 'OPENSSL_FORCE_FIPS_MODE': '1'}) + plansmbtorture4testsuite('rpc.fips.netlogon.crypto', + 'ad_dc_fips', + ['ncacn_np:$SERVER[krb5]', + '-U$USERNAME%$PASSWORD', + '--workgroup=$DOMAIN', + '--client-protection=encrypt'], + 'samba4.rpc.fips.netlogon.crypto', + environ={'GNUTLS_FORCE_FIPS_MODE': '1', + 'OPENSSL_FORCE_FIPS_MODE': '1'}) + plansmbtorture4testsuite('rpc.echo', "ad_dc_ntvfs", ['ncacn_np:$NETBIOSALIAS', '-U$DOMAIN/$USERNAME%$PASSWORD'], "samba4.rpc.echo against NetBIOS alias") # Test wbinfo trust auth diff --git a/source4/torture/rpc/netlogon_crypto.c b/source4/torture/rpc/netlogon_crypto.c new file mode 100644 index 00000000000..05beb2b77b3 --- /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_ACCESS_DENIED, + "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; +} diff --git a/source4/torture/rpc/rpc.c b/source4/torture/rpc/rpc.c index ba10b169902..b172732409b 100644 --- a/source4/torture/rpc/rpc.c +++ b/source4/torture/rpc/rpc.c @@ -606,6 +606,7 @@ NTSTATUS torture_rpc_init(TALLOC_CTX *ctx) torture_suite_add_suite(suite, torture_rpc_netlogon_s3(suite)); torture_suite_add_suite(suite, torture_rpc_netlogon_admin(suite)); torture_suite_add_suite(suite, torture_rpc_netlogon_zerologon(suite)); + torture_suite_add_suite(suite, torture_rpc_netlogon_crypto_fips(suite)); torture_suite_add_suite(suite, torture_rpc_remote_pac(suite)); torture_suite_add_simple_test(suite, "samlogon", torture_rpc_samlogon); torture_suite_add_simple_test(suite, "samsync", torture_rpc_samsync); diff --git a/source4/torture/wscript_build b/source4/torture/wscript_build index 3afe3b558ed..b6014f9c462 100644 --- a/source4/torture/wscript_build +++ b/source4/torture/wscript_build @@ -121,6 +121,7 @@ bld.SAMBA_MODULE('torture_rpc', rpc/testjoin.c rpc/schannel.c rpc/netlogon.c + rpc/netlogon_crypto.c rpc/remote_pac.c rpc/samlogon.c rpc/samsync.c |