]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
initial FAST tests
authorGary Lockyer <gary@catalyst.net.nz>
Wed, 9 Jun 2021 21:56:58 +0000 (09:56 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 18 Aug 2021 22:28:34 +0000 (22:28 +0000)
Currently incomplete, and tested only against MIT Kerberos.

[abartlet@samba.org
 Originally "WIP inital FAST tests"

 Samba's general policy that we don't push WIP patches, we polish
 into a 'perfect' patch stream.

 However, I think there are good reasons to keep this patch distinct
 in this particular case.

 Gary is being modest in titling this WIP (now removed from the title
 to avoid confusion). They are not WIP in the normal sense of
 partially or untested code or random unfinished thoughts. The primary
 issue is that at that point where Gary had to finish up he had
 trouble getting FAST support enabled on Windows, so couldn't test
 against our standard reference. They are instead good, working
 initial tests written against the RFC and tested against Samba's AD DC
 in the mode backed by MIT Kerberos.

 This preserves clear authorship for the two distinct bodies of work,
 as in the next patch Joseph was able to extend and improve the tests
 significantly. ]

Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
python/samba/tests/krb5/fast_tests.py [new file with mode: 0755]
python/samba/tests/usage.py
selftest/knownfail_heimdal_kdc
source4/selftest/tests.py

diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py
new file mode 100755 (executable)
index 0000000..c4d1c2c
--- /dev/null
@@ -0,0 +1,245 @@
+#!/usr/bin/env python3
+# Unix SMB/CIFS implementation.
+# Copyright (C) Stefan Metzmacher 2020
+# Copyright (C) 2020 Catalyst.Net Ltd
+#
+# 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/>.
+#
+
+import sys
+import os
+
+sys.path.insert(0, "bin/python")
+os.environ["PYTHONUNBUFFERED"] = "1"
+
+from samba.tests.krb5.kdc_base_test import KDCBaseTest
+from samba.tests.krb5.rfc4120_constants import (
+    AES256_CTS_HMAC_SHA1_96,
+    ARCFOUR_HMAC_MD5,
+    NT_PRINCIPAL,
+    NT_SRV_INST,
+    PADATA_FX_COOKIE,
+    PADATA_FX_FAST,
+)
+import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1
+
+global_asn1_print = False
+global_hexdump = False
+
+
+class FAST_Tests(KDCBaseTest):
+    '''
+    '''
+
+    def setUp(self):
+        super().setUp()
+        self.do_asn1_print = global_asn1_print
+        self.do_hexdump = global_hexdump
+
+    def get_padata_element(self, rep, padata_type):
+        rep_padata = self.der_decode(
+            rep['e-data'], asn1Spec=krb5_asn1.METHOD_DATA())
+        for pa in rep_padata:
+            if pa['padata-type'] == padata_type:
+                return pa['padata-value']
+        return None
+
+    def test_fast_supported(self):
+        '''Confirm that the kdc supports FAST
+           The KDC SHOULD return an empty PA-FX-FAST in a
+               PREAUTH_REQUIRED error if FAST is supported
+
+
+        '''
+
+        # Create a user account for the test.
+        #
+        samdb = self.get_samdb()
+        user_name = "krb5fastusr"
+        (uc, dn) = self.create_account(samdb, user_name)
+        realm = uc.get_realm().lower()
+
+        # Do the initial AS-REQ, should get a pre-authentication required
+        # response
+        etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5)
+        cname = self.PrincipalName_create(
+            name_type=NT_PRINCIPAL, names=[user_name])
+        sname = self.PrincipalName_create(
+            name_type=NT_SRV_INST, names=["krbtgt", realm])
+
+        rep = self.as_req(cname, sname, realm, etype)
+        self.assertIsNotNone(rep)
+        self.assertEqual(rep['msg-type'], 30)
+        self.assertEqual(rep['error-code'], 25)
+
+        fx_fast = self.get_padata_element(rep, PADATA_FX_FAST)
+        self.assertIsNotNone(fx_fast, "No PADATA_FX_FAST element")
+
+    def test_explicit_PA_FX_FAST_in_as_req(self):
+        '''
+           Add an empty PA-FX-FAST in the initial AS-REQ
+           This should get rejected with a Generic error.
+
+        '''
+
+        # Create a user account for the test.
+        #
+        samdb = self.get_samdb()
+        user_name = "krb5fastusr"
+        (uc, dn) = self.create_account(samdb, user_name)
+        realm = uc.get_realm().lower()
+
+        # Do the initial AS-REQ, should get a generic error response
+        # response
+        etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5)
+        cname = self.PrincipalName_create(
+            name_type=NT_PRINCIPAL, names=[user_name])
+        sname = self.PrincipalName_create(
+            name_type=NT_SRV_INST, names=["krbtgt", realm])
+
+        x = self.PA_DATA_create(PADATA_FX_FAST, b'')
+        padata = [x]
+        rep = self.as_req(cname, sname, realm, etype, padata)
+
+        self.assertIsNotNone(rep)
+        self.assertEqual(rep['msg-type'], 30)
+        self.assertEqual(rep['error-code'], 60)
+
+    def test_fast_cookie_retured_in_pre_auth(self):
+        '''Confirm that the kdc returns PA-FX-COOKIE
+        '''
+
+        # Create a user account for the test.
+        #
+        samdb = self.get_samdb()
+        user_name = "krb5fastusr"
+        (uc, dn) = self.create_account(samdb, user_name)
+        realm = uc.get_realm().lower()
+
+        # Do the initial AS-REQ, should get a pre-authentication required
+        # response
+        etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5)
+        cname = self.PrincipalName_create(
+            name_type=NT_PRINCIPAL, names=[user_name])
+        sname = self.PrincipalName_create(
+            name_type=NT_SRV_INST, names=["krbtgt", realm])
+
+        rep = self.as_req(cname, sname, realm, etype)
+        self.assertIsNotNone(rep)
+        self.assertEqual(rep['msg-type'], 30)
+        self.assertEqual(rep['error-code'], 25)
+
+        fx_fast = self.get_padata_element(rep, PADATA_FX_FAST)
+        self.assertIsNotNone(fx_fast, "No PADATA_FX_FAST element")
+
+        fx_cookie = self.get_padata_element(rep, PADATA_FX_COOKIE)
+        self.assertIsNotNone(fx_cookie, "No PADATA_FX_COOKIE element")
+
+    def test_ignore_fast(self):
+        '''
+            TODO reword this
+            Attempt to authenticate with out FAST, i.e. ignoring the
+            FAST advertised in the pre-auth
+        '''
+
+        # Create a user account for the test.
+        #
+        samdb = self.get_samdb()
+        user_name = "krb5fastusr"
+        (uc, dn) = self.create_account(samdb, user_name)
+        realm = uc.get_realm().lower()
+
+        # Do the initial AS-REQ, should get a pre-authentication required
+        # response
+        etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5)
+        cname = self.PrincipalName_create(
+            name_type=NT_PRINCIPAL, names=[user_name])
+        sname = self.PrincipalName_create(
+            name_type=NT_SRV_INST, names=["krbtgt", realm])
+
+        rep = self.as_req(cname, sname, realm, etype)
+        self.assertIsNotNone(rep)
+        self.assertEqual(rep['msg-type'], 30)
+        self.assertEqual(rep['error-code'], 25)
+
+        fx_fast = self.get_padata_element(rep, PADATA_FX_FAST)
+        self.assertIsNotNone(fx_fast, "No PADATA_FX_FAST element")
+
+        fx_cookie = self.get_padata_element(rep, PADATA_FX_COOKIE)
+        self.assertIsNotNone(fx_cookie, "No PADATA_FX_COOKIE element")
+
+        # Do the next AS-REQ
+        padata = [self.get_enc_timestamp_pa_data(uc, rep)]
+        rep = self.as_req(cname, sname, realm, etype, padata=padata)
+        self.check_as_reply(rep)
+
+    def test_fast(self):
+        '''
+            Attempt to authenticate with
+        '''
+
+        # Create a user account for the test.
+        #
+        samdb = self.get_samdb()
+        user_name = "krb5fastusr"
+        (uc, dn) = self.create_account(samdb, user_name)
+        realm = uc.get_realm().lower()
+
+        # Do the initial AS-REQ, should get a pre-authentication required
+        # response
+        etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5)
+        cname = self.PrincipalName_create(
+            name_type=NT_PRINCIPAL, names=[user_name])
+        sname = self.PrincipalName_create(
+            name_type=NT_SRV_INST, names=["krbtgt", realm])
+
+        rep = self.as_req(cname, sname, realm, etype)
+        self.assertIsNotNone(rep)
+        self.assertEqual(rep['msg-type'], 30)
+        self.assertEqual(rep['error-code'], 25)
+
+        fx_fast = self.get_padata_element(rep, PADATA_FX_FAST)
+        self.assertIsNotNone(fx_fast, "No PADATA_FX_FAST element")
+
+        fx_cookie = self.get_padata_element(rep, PADATA_FX_COOKIE)
+        self.assertIsNotNone(fx_cookie, "No PADATA_FX_COOKIE element")
+
+        cookie = self.PA_DATA_create(PADATA_FX_COOKIE, fx_cookie)
+
+        # Do the next AS-REQ
+        padata = [self.get_enc_timestamp_pa_data(uc, rep)]
+        padata.append(cookie)
+        # req = self.AS_REQ_create(padata=padata,
+        #                         kdc_options=str(kdc_options),
+        #                         cname=cname,
+        #                         realm=realm,
+        #                         sname=sname,
+        #                         from_time=None,
+        #                         till_time=till,
+        #                         renew_time=None,
+        #                         nonce=0x7fffffff,
+        #                         etypes=etypes,
+        #                         addresses=None,
+        #                         EncAuthorizationData=None,
+        #                         EncAuthorizationData_key=None,
+        #                         additional_tickets=None)
+        # rep = self.as_req(cname, sname, realm, etype, padata=padata)
+        # self.check_as_reply(rep)
+
+
+if __name__ == "__main__":
+    global_asn1_print = False
+    global_hexdump = False
+    import unittest
+    unittest.main()
index 2cc9e520d295f7c21625d6daf60c1fbad877bbfd..e97be071a5d012d5d8a5322abb6f4c17a1009a98 100644 (file)
@@ -102,6 +102,7 @@ EXCLUDE_USAGE = {
     'python/samba/tests/krb5/test_smb.py',
     'python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py',
     'python/samba/tests/krb5/as_req_tests.py',
+    'python/samba/tests/krb5/fast_tests.py',
 }
 
 EXCLUDE_HELP = {
index 4e6ee93ce9641bee5a706fc9dea1b4d97f720cd2..66f07cebc144fdb4026f789def9bcb8669a3432e 100644 (file)
 ^samba.tests.krb5.ms_kile_client_principal_lookup_tests.samba.tests.krb5.ms_kile_client_principal_lookup_tests.MS_Kile_Client_Principal_Lookup_Tests.test_nt_principal_step_4_b
 ^samba.tests.krb5.ms_kile_client_principal_lookup_tests.samba.tests.krb5.ms_kile_client_principal_lookup_tests.MS_Kile_Client_Principal_Lookup_Tests.test_nt_principal_step_4_c
 ^samba.tests.krb5.ms_kile_client_principal_lookup_tests.samba.tests.krb5.ms_kile_client_principal_lookup_tests.MS_Kile_Client_Principal_Lookup_Tests.test_nt_principal_step_6_c
+#
+# MIT specific FAST tests,
+#
+^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_explicit_PA_FX_FAST_in_as_req\(ad_dc\)
+^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast\(ad_dc\)
+^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_cookie_retured_in_pre_auth\(ad_dc\)
+^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_supported\(ad_dc\)
+^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_ignore_fast\(ad_dc\)
index 01c190704a0f5b83c857f877a85e5aa580e31a6a..a47037c0ecc4d72b7d3634876cc6b7fd7dfdecbd 100755 (executable)
@@ -1533,6 +1533,14 @@ planpythontestsuite(
         'ADMIN_USERNAME': '$USERNAME',
         'ADMIN_PASSWORD': '$PASSWORD'
     })
+planpythontestsuite(
+    "ad_dc",
+    "samba.tests.krb5.fast_tests",
+    environ={
+        'ADMIN_USERNAME': '$USERNAME',
+        'ADMIN_PASSWORD': '$PASSWORD',
+        'SERVICE_USERNAME': '$SERVER'
+    })
 planpythontestsuite(
     "ad_dc",
     "samba.tests.krb5.ms_kile_client_principal_lookup_tests",