NT_PRINCIPAL,
PADATA_AS_FRESHNESS,
PADATA_ENC_TIMESTAMP,
+ PADATA_PK_AS_REP_19,
PADATA_PK_AS_REQ,
)
import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1
self._pkinit_req(client_creds, target_creds,
using_pkinit=PkInit.DIFFIE_HELLMAN)
+ def test_pkinit_win2k(self):
+ """Test public-key Windows 2000 PK-INIT."""
+ client_creds = self._get_creds()
+ target_creds = self.get_service_creds()
+
+ self._pkinit_req(client_creds, target_creds, win2k_variant=True)
+
def test_pkinit_no_des3(self):
"""Test public-key PK-INIT without specifying the DES3 encryption
type. It should fail."""
self._pkinit_req(client_creds, target_creds,
using_pkinit=PkInit.DIFFIE_HELLMAN)
+ def test_pkinit_computer_win2k(self):
+ """Test public-key Windows 2000 PK-INIT with a computer account."""
+ client_creds = self._get_creds(self.AccountType.COMPUTER)
+ target_creds = self.get_service_creds()
+
+ self._pkinit_req(client_creds, target_creds, win2k_variant=True)
+
def test_pkinit_service(self):
"""Test public-key PK-INIT with a service account."""
client_creds = self._get_creds(self.AccountType.MANAGED_SERVICE)
self._pkinit_req(client_creds, target_creds,
using_pkinit=PkInit.DIFFIE_HELLMAN)
+ def test_pkinit_service_win2k(self):
+ """Test public-key Windows 2000 PK-INIT with a service account."""
+ client_creds = self._get_creds(self.AccountType.MANAGED_SERVICE)
+ target_creds = self.get_service_creds()
+
+ self._pkinit_req(client_creds, target_creds, win2k_variant=True)
+
def test_pkinit_no_supported_cms_types(self):
"""Test public-key PK-INIT, excluding the supportedCmsTypes field. This
causes Windows to reply with differently-encoded ASN.1."""
using_pkinit=PkInit.DIFFIE_HELLMAN,
signature_algorithm=krb5_asn1.id_pkcs1_sha256WithRSAEncryption)
+ def test_pkinit_sha256_signature_win2k(self):
+ """Test public-key Windows 2000 PK-INIT with a SHA256 signature."""
+ client_creds = self._get_creds()
+ target_creds = self.get_service_creds()
+
+ self._pkinit_req(
+ client_creds, target_creds,
+ signature_algorithm=krb5_asn1.id_pkcs1_sha256WithRSAEncryption,
+ win2k_variant=True)
+
def test_pkinit_sha256_certificate_signature(self):
"""Test public-key PK-INIT with a SHA256 certificate signature."""
client_creds = self._get_creds()
using_pkinit=PkInit.DIFFIE_HELLMAN,
certificate_signature=hashes.SHA256)
+ def test_pkinit_sha256_certificate_signature_win2k(self):
+ """Test public-key Windows 2000 PK-INIT with a SHA256 certificate
+ signature."""
+ client_creds = self._get_creds()
+ target_creds = self.get_service_creds()
+
+ self._pkinit_req(
+ client_creds, target_creds,
+ certificate_signature=hashes.SHA256,
+ win2k_variant=True)
+
def test_pkinit_freshness(self):
"""Test public-key PK-INIT with the PKINIT Freshness Extension."""
client_creds = self._get_creds()
signature_algorithm=None,
certificate_signature=None,
freshness_token=None,
+ win2k_variant=False,
):
self.assertIsNot(using_pkinit, PkInit.NOT_USED)
def generate_pk_padata(_kdc_exchange_dict,
_callback_dict,
req_body):
- checksum_blob = self.der_encode(
- req_body,
- asn1Spec=krb5_asn1.KDC_REQ_BODY())
+ if win2k_variant:
+ digest = None
+ else:
+ checksum_blob = self.der_encode(
+ req_body,
+ asn1Spec=krb5_asn1.KDC_REQ_BODY())
- # Calculate the SHA1 checksum over the KDC-REQ-BODY. This checksum
- # is required to be present in the authenticator, and must be SHA1.
- digest = hashes.Hash(hashes.SHA1(), default_backend())
- digest.update(checksum_blob)
- digest = digest.finalize()
+ # Calculate the SHA1 checksum over the KDC-REQ-BODY. This checksum
+ # is required to be present in the authenticator, and must be SHA1.
+ digest = hashes.Hash(hashes.SHA1(), default_backend())
+ digest.update(checksum_blob)
+ digest = digest.finalize()
ctime, cusec = self.get_KerberosTimeWithUsec()
+ if win2k_variant:
+ krbtgt_sname = self.get_krbtgt_sname()
+ krbtgt_realm = self.get_krbtgt_creds().get_realm()
+ else:
+ krbtgt_sname = None
+ krbtgt_realm = None
+
# Create the authenticator, which shows that we had possession of
# the private key at some point.
authenticator_obj = self.PKAuthenticator_create(
ctime,
pk_nonce,
pa_checksum=digest,
- freshness_token=freshness_token)
+ freshness_token=freshness_token,
+ kdc_name=krbtgt_sname,
+ kdc_realm=krbtgt_realm,
+ win2k_variant=win2k_variant)
if using_pkinit is PkInit.DIFFIE_HELLMAN:
dh_public_key = dh_private_key.public_key()
# differently encoded ReplyKeyPack, wrapping it first in a
# ContentInfo structure.
nonlocal supported_cms_types
- if supported_cms_types is False:
+ if win2k_variant:
+ self.assertIsNone(supported_cms_types)
+ elif supported_cms_types is False:
# Exclude this field.
supported_cms_types = None
elif supported_cms_types is None:
authenticator_obj,
client_public_value=client_public_value,
supported_cms_types=supported_cms_types,
- client_dh_nonce=client_dh_nonce)
+ client_dh_nonce=client_dh_nonce,
+ win2k_variant=win2k_variant)
- auth_pack = self.der_encode(auth_pack_obj,
- asn1Spec=krb5_asn1.AuthPack())
+ asn1_spec = (krb5_asn1.AuthPack_Win2k
+ if win2k_variant
+ else krb5_asn1.AuthPack)
+ auth_pack = self.der_encode(auth_pack_obj, asn1Spec=asn1_spec())
signature_hash = self.hash_from_algorithm(signature_algorithm)
# trusted by the client, that can
# be used to certify the KDC.
trusted_certifiers=None,
- kdc_pk_id=None)
+ kdc_pk_id=None,
+ win2k_variant=win2k_variant)
- padata = [self.PA_DATA_create(PADATA_PK_AS_REQ, pk_as_req)]
+ pa_type = (PADATA_PK_AS_REP_19
+ if win2k_variant
+ else PADATA_PK_AS_REQ)
+ padata = [self.PA_DATA_create(pa_type, pk_as_req)]
return padata, req_body
nonce,
*,
pa_checksum=None,
- freshness_token=None):
+ freshness_token=None,
+ kdc_name=None,
+ kdc_realm=None,
+ win2k_variant=False):
+ if win2k_variant:
+ self.assertIsNone(pa_checksum)
+ self.assertIsNone(freshness_token)
+ self.assertIsNotNone(kdc_name)
+ self.assertIsNotNone(kdc_realm)
+ else:
+ self.assertIsNone(kdc_name)
+ self.assertIsNone(kdc_realm)
+
pk_authenticator_obj = {
'cusec': cusec,
'ctime': ctime,
pk_authenticator_obj['paChecksum'] = pa_checksum
if freshness_token is not None:
pk_authenticator_obj['freshnessToken'] = freshness_token
+ if kdc_name is not None:
+ pk_authenticator_obj['kdcName'] = kdc_name
+ if kdc_realm is not None:
+ pk_authenticator_obj['kdcRealm'] = kdc_realm
return pk_authenticator_obj
*,
client_public_value=None,
supported_cms_types=None,
- client_dh_nonce=None):
+ client_dh_nonce=None,
+ win2k_variant=False):
+ if win2k_variant:
+ self.assertIsNone(supported_cms_types)
+ self.assertIsNone(client_dh_nonce)
+
auth_pack_obj = {
'pkAuthenticator': pk_authenticator,
}
signed_auth_pack,
*,
trusted_certifiers=None,
- kdc_pk_id=None):
+ kdc_pk_id=None,
+ kdc_cert=None,
+ encryption_cert=None,
+ win2k_variant=False):
+ if win2k_variant:
+ self.assertIsNone(kdc_pk_id)
+ asn1_spec = krb5_asn1.PA_PK_AS_REQ_Win2k
+ else:
+ self.assertIsNone(kdc_cert)
+ self.assertIsNone(encryption_cert)
+ asn1_spec = krb5_asn1.PA_PK_AS_REQ
+
content_info_obj = self.ContentInfo_create(
krb5_asn1.id_signedData, signed_auth_pack)
content_info = self.der_encode(content_info_obj,
pk_as_req_obj['trustedCertifiers'] = trusted_certifiers
if kdc_pk_id is not None:
pk_as_req_obj['kdcPkId'] = kdc_pk_id
+ if kdc_cert is not None:
+ pk_as_req_obj['kdcCert'] = kdc_cert
+ if encryption_cert is not None:
+ pk_as_req_obj['encryptionCert'] = encryption_cert
- return self.der_encode(pk_as_req_obj,
- asn1Spec=krb5_asn1.PA_PK_AS_REQ())
+ return self.der_encode(pk_as_req_obj, asn1Spec=asn1_spec())
def SignerInfo_create(self,
signer_id,
pa_dict = self.get_pa_dict(padata)
- if PADATA_PK_AS_REP in pa_dict:
- pk_as_rep = pa_dict[PADATA_PK_AS_REP]
+ pk_as_rep = pa_dict.get(PADATA_PK_AS_REP)
+ if pk_as_rep is not None:
+ pk_as_rep_asn1_spec = krb5_asn1.PA_PK_AS_REP
+ reply_key_pack_asn1_spec = krb5_asn1.ReplyKeyPack
+ pk_win2k = False
+ else:
+ pk_as_rep = pa_dict.get(PADATA_PK_AS_REP_19)
+ pk_as_rep_asn1_spec = krb5_asn1.PA_PK_AS_REP_Win2k
+ reply_key_pack_asn1_spec = krb5_asn1.ReplyKeyPack_Win2k
+ pk_win2k = True
+ if pk_as_rep is not None:
pk_as_rep = self.der_decode(pk_as_rep,
- asn1Spec=krb5_asn1.PA_PK_AS_REP())
+ asn1Spec=pk_as_rep_asn1_spec())
using_pkinit = kdc_exchange_dict['using_pkinit']
if using_pkinit is PkInit.PUBLIC_KEY:
self.assertEqual(str(krb5_asn1.id_pkinit_rkeyData),
content_type)
reply_key_pack = self.der_decode(
- content, asn1Spec=krb5_asn1.ReplyKeyPack())
-
- as_checksum = reply_key_pack['asChecksum']
+ content, asn1Spec=reply_key_pack_asn1_spec())
req_obj = kdc_exchange_dict['req_obj']
req_asn1Spec = kdc_exchange_dict['req_asn1Spec']
contents=reply_key['keyvalue'],
kvno=None)
- # Verify the checksum over the AS request body.
- kcrypto.verify_checksum(as_checksum['cksumtype'],
- encpart_decryption_key.key,
- KU_PKINIT_AS_REQ,
- req_obj,
- as_checksum['checksum'])
+ if not pk_win2k:
+ as_checksum = reply_key_pack['asChecksum']
+
+ # Verify the checksum over the AS request body.
+ kcrypto.verify_checksum(as_checksum['cksumtype'],
+ encpart_decryption_key.key,
+ KU_PKINIT_AS_REQ,
+ req_obj,
+ as_checksum['checksum'])
elif using_pkinit is PkInit.DIFFIE_HELLMAN:
content_info = self.der_decode(
pk_as_rep['dhInfo']['dhSignedData'],
if expect_requester_sid:
expected_types.append(krb5pac.PAC_TYPE_REQUESTER_SID)
- sent_pk_as_req = self.sent_pk_as_req(kdc_exchange_dict)
+ sent_pk_as_req = self.sent_pk_as_req(kdc_exchange_dict) or (
+ self.sent_pk_as_req_win2k(kdc_exchange_dict))
if sent_pk_as_req:
expected_types.append(krb5pac.PAC_TYPE_CREDENTIAL_INFO)
expected_patypes = ()
sent_fast = self.sent_fast(kdc_exchange_dict)
- using_pkinit = kdc_exchange_dict.get('using_pkinit', PkInit.NOT_USED)
rep_msg_type = kdc_exchange_dict['rep_msg_type']
if sent_fast:
expected_patypes += (PADATA_FX_FAST,)
elif rep_msg_type == KRB_AS_REP:
- if using_pkinit is PkInit.NOT_USED:
+ if self.sent_pk_as_req(kdc_exchange_dict):
+ expected_patypes += PADATA_PK_AS_REP,
+ elif self.sent_pk_as_req_win2k(kdc_exchange_dict):
+ expected_patypes += PADATA_PK_AS_REP_19,
+ else:
chosen_etype = self.getElementValue(encpart, 'etype')
self.assertIsNotNone(chosen_etype)
self.assertIsInstance(preauth_key, Krb5EncryptionKey)
if preauth_key.etype == kcrypto.Enctype.RC4 and rep_padata is None:
rep_padata = ()
- else:
- expected_patypes += PADATA_PK_AS_REP,
elif rep_msg_type == KRB_TGS_REP:
if expected_patypes == () and rep_padata is None:
rep_padata = ()
return PADATA_PK_AS_REQ in fast_pa_dict
+ def sent_pk_as_req_win2k(self, kdc_exchange_dict):
+ fast_pa_dict = self.get_fast_pa_dict(kdc_exchange_dict)
+
+ return PADATA_PK_AS_REP_19 in fast_pa_dict
+
def sent_freshness(self, kdc_exchange_dict):
fast_pa_dict = self.get_fast_pa_dict(kdc_exchange_dict)
^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_freshness_rodc_ts.ad_dc
^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_freshness_wrong_header.ad_dc
^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_freshness_wrong_header_dh.ad_dc
+#
+# Windows 2000 PK-INIT tests
+#
+^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_computer_win2k.ad_dc
+^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_service_win2k.ad_dc
+^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_sha256_certificate_signature_win2k.ad_dc
+^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_sha256_signature_win2k.ad_dc
+^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_win2k.ad_dc
^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_freshness_with_enc_ts.ad_dc
^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_freshness_wrong_header.ad_dc
^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_freshness_wrong_header_dh.ad_dc
+#
+# Windows 2000 PK-INIT tests
+#
+^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_computer_win2k.ad_dc
+^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_service_win2k.ad_dc
+^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_sha256_certificate_signature_win2k.ad_dc
+^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_sha256_signature_win2k.ad_dc
+^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_win2k.ad_dc