2 # Unix SMB/CIFS implementation.
3 # Copyright (C) Stefan Metzmacher 2020
4 # Copyright (C) 2020 Catalyst.Net Ltd
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
23 sys.path.insert(0, "bin/python")
24 os.environ["PYTHONUNBUFFERED"] = "1"
26 from samba.tests.krb5.kdc_base_test import KDCBaseTest
27 from samba.tests.krb5.rfc4120_constants import (
28 AES256_CTS_HMAC_SHA1_96,
36 global_asn1_print = False
37 global_hexdump = False
40 class KdcTgsTests(KDCBaseTest):
44 self.do_asn1_print = global_asn1_print
45 self.do_hexdump = global_hexdump
47 def test_tgs_req_cname_does_not_not_match_authenticator_cname(self):
48 ''' Try and obtain a ticket from the TGS, but supply a cname
49 that differs from that provided to the krbtgt
51 # Create the user account
52 samdb = self.get_samdb()
53 user_name = "tsttktusr"
54 (uc, _) = self.create_account(samdb, user_name)
55 realm = uc.get_realm().lower()
57 # Do the initial AS-REQ, should get a pre-authentication required
59 etype = (AES256_CTS_HMAC_SHA1_96,)
60 cname = self.PrincipalName_create(
61 name_type=NT_PRINCIPAL, names=[user_name])
62 sname = self.PrincipalName_create(
63 name_type=NT_SRV_INST, names=["krbtgt", realm])
65 rep = self.as_req(cname, sname, realm, etype)
66 self.check_pre_authentication(rep)
69 padata = self.get_enc_timestamp_pa_data(uc, rep)
70 key = self.get_as_rep_key(uc, rep)
71 rep = self.as_req(cname, sname, realm, etype, padata=[padata])
72 self.check_as_reply(rep)
74 # Request a service ticket, but use a cname that does not match
75 # that in the original AS-REQ
76 enc_part2 = self.get_as_rep_enc_data(key, rep)
77 key = self.EncryptionKey_import(enc_part2['key'])
78 ticket = rep['ticket']
80 cname = self.PrincipalName_create(
81 name_type=NT_PRINCIPAL,
82 names=["Administrator"])
83 sname = self.PrincipalName_create(
84 name_type=NT_PRINCIPAL,
85 names=["host", samdb.host_dns_name()])
87 (rep, enc_part) = self.tgs_req(cname, sname, realm, ticket, key, etype,
88 expected_error_mode=KDC_ERR_BADMATCH)
92 "rep = {%s}, enc_part = {%s}" % (rep, enc_part))
93 self.assertEqual(KRB_ERROR, rep['msg-type'], "rep = {%s}" % rep)
99 def test_ldap_service_ticket(self):
100 '''Get a ticket to the ldap service
102 # Create the user account
103 samdb = self.get_samdb()
104 user_name = "tsttktusr"
105 (uc, _) = self.create_account(samdb, user_name)
106 realm = uc.get_realm().lower()
108 # Do the initial AS-REQ, should get a pre-authentication required
110 etype = (AES256_CTS_HMAC_SHA1_96,)
111 cname = self.PrincipalName_create(
112 name_type=NT_PRINCIPAL, names=[user_name])
113 sname = self.PrincipalName_create(
114 name_type=NT_SRV_INST, names=["krbtgt", realm])
116 rep = self.as_req(cname, sname, realm, etype)
117 self.check_pre_authentication(rep)
120 padata = self.get_enc_timestamp_pa_data(uc, rep)
121 key = self.get_as_rep_key(uc, rep)
122 rep = self.as_req(cname, sname, realm, etype, padata=[padata])
123 self.check_as_reply(rep)
125 enc_part2 = self.get_as_rep_enc_data(key, rep)
126 key = self.EncryptionKey_import(enc_part2['key'])
127 ticket = rep['ticket']
129 # Request a ticket to the ldap service
130 sname = self.PrincipalName_create(
131 name_type=NT_SRV_INST,
132 names=["ldap", samdb.host_dns_name()])
134 (rep, _) = self.tgs_req(
135 cname, sname, uc.get_realm(), ticket, key, etype,
136 service_creds=self.get_dc_creds())
138 self.check_tgs_reply(rep)
140 def test_get_ticket_for_host_service_of_machine_account(self):
142 # Create a user and machine account for the test.
144 samdb = self.get_samdb()
145 user_name = "tsttktusr"
146 (uc, dn) = self.create_account(samdb, user_name)
147 (mc, _) = self.create_account(samdb, "tsttktmac", machine_account=True)
148 realm = uc.get_realm().lower()
150 # Do the initial AS-REQ, should get a pre-authentication required
152 etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5)
153 cname = self.PrincipalName_create(
154 name_type=NT_PRINCIPAL, names=[user_name])
155 sname = self.PrincipalName_create(
156 name_type=NT_SRV_INST, names=["krbtgt", realm])
158 rep = self.as_req(cname, sname, realm, etype)
159 self.check_pre_authentication(rep)
162 padata = self.get_enc_timestamp_pa_data(uc, rep)
163 key = self.get_as_rep_key(uc, rep)
164 rep = self.as_req(cname, sname, realm, etype, padata=[padata])
165 self.check_as_reply(rep)
167 # Request a ticket to the host service on the machine account
168 ticket = rep['ticket']
169 enc_part2 = self.get_as_rep_enc_data(key, rep)
170 key = self.EncryptionKey_import(enc_part2['key'])
171 cname = self.PrincipalName_create(
172 name_type=NT_PRINCIPAL,
174 sname = self.PrincipalName_create(
175 name_type=NT_PRINCIPAL,
176 names=[mc.get_username()])
178 (rep, enc_part) = self.tgs_req(
179 cname, sname, uc.get_realm(), ticket, key, etype,
181 self.check_tgs_reply(rep)
183 # Check the contents of the service ticket
184 ticket = rep['ticket']
185 enc_part = self.decode_service_ticket(mc, ticket)
187 pac_data = self.get_pac_data(enc_part['authorization-data'])
188 sid = self.get_objectSid(samdb, dn)
189 upn = "%s@%s" % (uc.get_username(), realm)
192 str(pac_data.account_name),
193 "rep = {%s},%s" % (rep, pac_data))
197 "rep = {%s},%s" % (rep, pac_data))
200 pac_data.domain_name,
201 "rep = {%s},%s" % (rep, pac_data))
205 "rep = {%s},%s" % (rep, pac_data))
208 pac_data.account_sid,
209 "rep = {%s},%s" % (rep, pac_data))
212 if __name__ == "__main__":
213 global_asn1_print = True
214 global_hexdump = True