def encode(self): package_names = [] kerberos = [] kerberos_newer_keys = [] cred_List = [] # Order matters for key_id in (3, 1): if key_id in self.keys: kerberos.append(self.keys[key_id]) for key_id in (18, 17): if key_id in self.keys: kerberos_newer_keys.append(self.keys[key_id]) if kerberos_newer_keys and kerberos: logger.debug("compute Primary:Kerberos-Newer-Keys") creddata_Primary_Kerberos_Newer = KerberosNewerKeysProperty(kerberos_newer_keys + kerberos).encode() credname_Primary_Kerberos_Newer = "Primary:Kerberos-Newer-Keys" cred_Primary_Kerberos_Newer = drsblobs.supplementalCredentialsPackage() cred_Primary_Kerberos_Newer.name = credname_Primary_Kerberos_Newer cred_Primary_Kerberos_Newer.name_len = len(credname_Primary_Kerberos_Newer) cred_Primary_Kerberos_Newer.data = creddata_Primary_Kerberos_Newer cred_Primary_Kerberos_Newer.data_len = len(creddata_Primary_Kerberos_Newer) cred_Primary_Kerberos_Newer.reserved = 1 cred_List.append(cred_Primary_Kerberos_Newer) package_names.append('Kerberos-Newer-Keys') if kerberos: logger.debug("compute Primary:Kerberos") creddata_Primary_Kerberos = KerberosProperty(kerberos).encode() credname_Primary_Kerberos = "Primary:Kerberos" cred_Primary_Kerberos = drsblobs.supplementalCredentialsPackage() cred_Primary_Kerberos.name = credname_Primary_Kerberos cred_Primary_Kerberos.name_len = len(credname_Primary_Kerberos) cred_Primary_Kerberos.data = creddata_Primary_Kerberos cred_Primary_Kerberos.data_len = len(creddata_Primary_Kerberos) cred_Primary_Kerberos.reserved = 1 cred_List.append(cred_Primary_Kerberos) package_names.append('Kerberos') if package_names: krb_blob_Packages = '\0'.join(package_names).encode('utf-16-le') cred_PackagesBlob_data = binascii.hexlify(krb_blob_Packages).upper() cred_PackagesBlob_name = "Packages" cred_PackagesBlob = drsblobs.supplementalCredentialsPackage() cred_PackagesBlob.name = cred_PackagesBlob_name cred_PackagesBlob.name_len = len(cred_PackagesBlob_name) cred_PackagesBlob.data = cred_PackagesBlob_data cred_PackagesBlob.data_len = len(cred_PackagesBlob_data) cred_PackagesBlob.reserved = 2 cred_List.append(cred_PackagesBlob) else: raise Exception("Can't buid credentials, no keys provided") sub = drsblobs.supplementalCredentialsSubBlob() sub.num_packages = len(cred_List) sub.packages = cred_List sub.signature = drsblobs.SUPPLEMENTAL_CREDENTIALS_SIGNATURE sub.prefix = drsblobs.SUPPLEMENTAL_CREDENTIALS_PREFIX sc = drsblobs.supplementalCredentialsBlob() sc.sub = sub sc_blob = ndr_pack(sc) return sc_blob
def encode(self): package_names = [] kerberos = [] kerberos_newer_keys = [] cred_List = [] # Order matters for key_id in (3, 1): if key_id in self.keys: kerberos.append(self.keys[key_id]) for key_id in (18, 17): if key_id in self.keys: kerberos_newer_keys.append(self.keys[key_id]) if kerberos_newer_keys and kerberos: logger.debug("compute Primary:Kerberos-Newer-Keys") creddata_Primary_Kerberos_Newer = KerberosNewerKeysProperty( kerberos_newer_keys + kerberos).encode() credname_Primary_Kerberos_Newer = "Primary:Kerberos-Newer-Keys" cred_Primary_Kerberos_Newer = drsblobs.supplementalCredentialsPackage( ) cred_Primary_Kerberos_Newer.name = credname_Primary_Kerberos_Newer cred_Primary_Kerberos_Newer.name_len = len( credname_Primary_Kerberos_Newer) cred_Primary_Kerberos_Newer.data = creddata_Primary_Kerberos_Newer cred_Primary_Kerberos_Newer.data_len = len( creddata_Primary_Kerberos_Newer) cred_Primary_Kerberos_Newer.reserved = 1 cred_List.append(cred_Primary_Kerberos_Newer) package_names.append('Kerberos-Newer-Keys') if kerberos: logger.debug("compute Primary:Kerberos") creddata_Primary_Kerberos = KerberosProperty(kerberos).encode() credname_Primary_Kerberos = "Primary:Kerberos" cred_Primary_Kerberos = drsblobs.supplementalCredentialsPackage() cred_Primary_Kerberos.name = credname_Primary_Kerberos cred_Primary_Kerberos.name_len = len(credname_Primary_Kerberos) cred_Primary_Kerberos.data = creddata_Primary_Kerberos cred_Primary_Kerberos.data_len = len(creddata_Primary_Kerberos) cred_Primary_Kerberos.reserved = 1 cred_List.append(cred_Primary_Kerberos) package_names.append('Kerberos') if package_names: krb_blob_Packages = '\0'.join(package_names).encode('utf-16-le') cred_PackagesBlob_data = binascii.hexlify( krb_blob_Packages).upper() cred_PackagesBlob_name = "Packages" cred_PackagesBlob = drsblobs.supplementalCredentialsPackage() cred_PackagesBlob.name = cred_PackagesBlob_name cred_PackagesBlob.name_len = len(cred_PackagesBlob_name) cred_PackagesBlob.data = cred_PackagesBlob_data cred_PackagesBlob.data_len = len(cred_PackagesBlob_data) cred_PackagesBlob.reserved = 2 cred_List.append(cred_PackagesBlob) else: raise Exception("Can't buid credentials, no keys provided") sub = drsblobs.supplementalCredentialsSubBlob() sub.num_packages = len(cred_List) sub.packages = cred_List sub.signature = drsblobs.SUPPLEMENTAL_CREDENTIALS_SIGNATURE sub.prefix = drsblobs.SUPPLEMENTAL_CREDENTIALS_PREFIX sc = drsblobs.supplementalCredentialsBlob() sc.sub = sub sc_blob = ndr_pack(sc) return sc_blob
def calculate_supplementalCredentials(ucs_krb5key, old_supplementalCredentials): old_krb = {} if old_supplementalCredentials: sc = ndr_unpack(drsblobs.supplementalCredentialsBlob, old_supplementalCredentials) for p in sc.sub.packages: ud.debug(ud.LDAP, ud.INFO, "calculate_supplementalCredentials: parsing %s blob" % p.name) if p.name == "Primary:Kerberos": krb_blob = binascii.unhexlify(p.data) try: krb = ndr_unpack(drsblobs.package_PrimaryKerberosBlob, krb_blob) assert krb.version == 3 old_krb['ctr3'] = krb.ctr for k in krb.ctr.keys: ud.debug(ud.LDAP, ud.INFO, "calculate_supplementalCredentials: ctr3.key.keytype: %s" % k.keytype) except: ud.debug(ud.LDAP, ud.ERROR, "calculate_supplementalCredentials: ndr_unpack of S4 Primary:Kerberos blob failed. Traceback:") traceback.print_exc() ud.debug(ud.LDAP, ud.ERROR, "calculate_supplementalCredentials: Continuing anyway, Primary:Kerberos (DES keys) blob will be missing in supplementalCredentials ctr3.old_keys.") elif p.name == "Primary:Kerberos-Newer-Keys": krb_blob = binascii.unhexlify(p.data) try: krb = ndr_unpack(drsblobs.package_PrimaryKerberosBlob, krb_blob) assert krb.version == 4 old_krb['ctr4'] = krb.ctr for k in krb.ctr.keys: ud.debug(ud.LDAP, ud.INFO, "calculate_supplementalCredentials: ctr4.key.keytype: %s" % k.keytype) except: ud.debug(ud.LDAP, ud.ERROR, "calculate_supplementalCredentials: ndr_unpack of S4 Primary:Kerberos-Newer-Keys blob failed. Traceback:") traceback.print_exc() ud.debug(ud.LDAP, ud.ERROR, "calculate_supplementalCredentials: Continuing anyway, Primary:Kerberos-Newer-Keys (AES and DES keys) blob will be missing in supplementalCredentials ctr4.old_keys.") krb5_aes256 = '' krb5_aes128 = '' krb5_des_md5 = '' krb5_des_crc = '' krb_ctr3_salt = '' krb_ctr4_salt = '' for k in ucs_krb5key: (keyblock, salt, kvno) = heimdal.asn1_decode_key(k) key_data = keyblock.keyvalue() saltstring = salt.saltvalue() enctype = keyblock.keytype() enctype_id = enctype.toint() ud.debug(ud.LDAP, ud.INFO, "calculate_supplementalCredentials: krb5_keytype: %s (%d)" % (enctype, enctype_id)) if enctype_id == 18: krb5_aes256 = key_data if not krb_ctr4_salt: krb_ctr4_salt = saltstring elif enctype_id == 17: krb5_aes128 = key_data if not krb_ctr4_salt: krb_ctr4_salt = saltstring elif enctype_id == 3: krb5_des_md5 = key_data if not krb_ctr3_salt: krb_ctr3_salt = saltstring elif enctype_id == 1: krb5_des_crc = key_data if not krb_ctr3_salt: krb_ctr3_salt = saltstring ## build new drsblobs.supplementalCredentialsBlob sc_blob = None cred_List = [] package_names = [] ## Primary:Kerberos-Newer-Keys : AES keys if krb5_aes256 or krb5_aes128: ud.debug(ud.LDAP, ud.INFO, "calculate_supplementalCredentials: building Primary:Kerberos-Newer-Keys blob") kerberosKey4list = [] if krb5_aes256: assert len(krb5_aes256) == 32 next_key = drsblobs.package_PrimaryKerberosKey4() next_key.keytype = 18 next_key.value = krb5_aes256 next_key.value_len = len(krb5_aes256) kerberosKey4list.append(next_key) if krb5_aes128: assert len(krb5_aes128) == 16 next_key = drsblobs.package_PrimaryKerberosKey4() next_key.keytype = 17 next_key.value = krb5_aes128 next_key.value_len = len(krb5_aes128) kerberosKey4list.append(next_key) if krb5_des_md5: assert len(krb5_des_md5) == 8 next_key = drsblobs.package_PrimaryKerberosKey4() next_key.keytype = 3 next_key.value = krb5_des_md5 next_key.value_len = len(krb5_des_md5) kerberosKey4list.append(next_key) if krb5_des_crc: assert len(krb5_des_crc) == 8 next_key = drsblobs.package_PrimaryKerberosKey4() next_key.keytype = 1 next_key.value = krb5_des_crc next_key.value_len = len(krb5_des_crc) kerberosKey4list.append(next_key) salt4 = drsblobs.package_PrimaryKerberosString() salt4.string = krb_ctr4_salt ctr4 = drsblobs.package_PrimaryKerberosCtr4() ctr4.salt = salt4 ctr4.num_keys = len(kerberosKey4list) ctr4.keys = kerberosKey4list if old_krb.get('ctr4'): ## Backup old_keys to s4_old_keys s4_num_old_keys = old_krb['ctr4'].num_old_keys s4_old_keys = [] for key in old_krb['ctr4'].old_keys: s4_old_keys.append(key) ## keys -> old_keys if len(old_krb['ctr4'].keys) != ctr4.num_keys: cleaned_old_keys = [] for key in old_krb['ctr4'].keys: if key.keytype == 4294967156: ## in all known cases W2k8 AD uses keytype 4294967156 (=-140L) to include the arc4 hash ud.debug(ud.LDAP, ud.INFO, "calculate_supplementalCredentials: Primary:Kerberos-Newer-Keys filtering keytype %s from old_keys" % key.keytype) continue else: # TODO: can we do something better at this point to make old_keys == num_keys ? cleaned_old_keys.append(key) ctr4.old_keys = cleaned_old_keys ctr4.num_old_keys = len(cleaned_old_keys) else: ctr4.old_keys = old_krb['ctr4'].keys ctr4.num_old_keys = old_krb['ctr4'].num_keys ## s4_old_keys -> older_keys if ctr4.num_old_keys != ctr4.num_older_keys: cleaned_older_keys = [] for key in s4_old_keys: if key.keytype == 4294967156: ## in all known cases W2k8 AD uses keytype 4294967156 (=-140L) to include the arc4 hash ud.debug(ud.LDAP, ud.INFO, "calculate_supplementalCredentials: Primary:Kerberos-Newer-Keys filtering keytype %s from older_keys" % key.keytype) continue else: # TODO: can we do something better at this point to make old_keys == num_keys ? cleaned_older_keys.append(key) ctr4.older_keys = cleaned_older_keys ctr4.num_older_keys = len(cleaned_older_keys) else: ctr4.older_keys = s4_old_keys ctr4.num_older_keys = s4_num_old_keys if ctr4.num_old_keys != 0 and ctr4.num_old_keys != ctr4.num_keys: # TODO: Recommended policy is to fill up old_keys to match num_keys, this will result in a traceback, can we do something better? ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: Primary:Kerberos-Newer-Keys num_keys = %s" % ctr4.num_keys) for k in ctr4.keys: ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: ctr4.key.keytype: %s" % k.keytype) ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: Primary:Kerberos-Newer-Keys num_old_keys = %s" % ctr4.num_old_keys) for k in ctr4.old_keys: ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: ctr4.old_key.keytype: %s" % k.keytype) if ctr4.num_older_keys != 0 and ctr4.num_older_keys != ctr4.num_old_keys: # TODO: Recommended policy is to fill up old_keys to match num_keys, this will result in a traceback, can we do something better? ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: Primary:Kerberos-Newer-Keys num_old_keys = %s" % ctr4.num_old_keys) for k in ctr4.old_keys: ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: ctr4.old_key.keytype: %s" % k.keytype) ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: Primary:Kerberos-Newer-Keys num_older_keys = %s" % ctr4.num_older_keys) for k in ctr4.older_keys: ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: ctr4.older_key.keytype: %s" % k.keytype) krb_Primary_Kerberos_Newer = drsblobs.package_PrimaryKerberosBlob() krb_Primary_Kerberos_Newer.version = 4 krb_Primary_Kerberos_Newer.ctr = ctr4 krb_blob_Primary_Kerberos_Newer = ndr_pack(krb_Primary_Kerberos_Newer) creddata_Primary_Kerberos_Newer = binascii.hexlify(krb_blob_Primary_Kerberos_Newer) credname_Primary_Kerberos_Newer = "Primary:Kerberos-Newer-Keys" cred_Primary_Kerberos_Newer = drsblobs.supplementalCredentialsPackage() cred_Primary_Kerberos_Newer.name = credname_Primary_Kerberos_Newer cred_Primary_Kerberos_Newer.name_len = len(credname_Primary_Kerberos_Newer) cred_Primary_Kerberos_Newer.data = creddata_Primary_Kerberos_Newer cred_Primary_Kerberos_Newer.data_len = len(creddata_Primary_Kerberos_Newer) cred_Primary_Kerberos_Newer.reserved = 1 cred_List.append(cred_Primary_Kerberos_Newer) package_names.append('Kerberos-Newer-Keys') ## Primary:Kerberos : MD5 and CRC keys if krb5_des_md5 or krb5_des_crc: ud.debug(ud.LDAP, ud.INFO, "calculate_supplementalCredentials: building Primary:Kerberos blob") kerberosKey3list = [] if krb5_des_md5: next_key = drsblobs.package_PrimaryKerberosKey3() next_key.keytype = 3 next_key.value = krb5_des_md5 next_key.value_len = len(krb5_des_md5) kerberosKey3list.append(next_key) if krb5_des_crc: next_key = drsblobs.package_PrimaryKerberosKey3() next_key.keytype = 1 next_key.value = krb5_des_crc next_key.value_len = len(krb5_des_crc) kerberosKey3list.append(next_key) salt = drsblobs.package_PrimaryKerberosString() salt.string = krb_ctr3_salt ctr3 = drsblobs.package_PrimaryKerberosCtr3() ctr3.salt = salt ctr3.num_keys = len(kerberosKey3list) ctr3.keys = kerberosKey3list if old_krb.get('ctr3'): ## keys -> old_keys if len(old_krb['ctr3'].keys) != ctr3.num_keys: cleaned_ctr3_old_keys = [] for key in old_krb['ctr3'].keys: if key.keytype == 4294967156: ## in all known cases W2k8 AD uses keytype 4294967156 (=-140L) to include the arc4 hash ud.debug(ud.LDAP, ud.INFO, "calculate_supplementalCredentials: Primary:Kerberos filtering keytype %s from old_keys" % key.keytype) continue else: # TODO: can we do something better at this point to make old_keys == num_keys ? cleaned_ctr3_old_keys.append(key) ctr3.old_keys = cleaned_ctr3_old_keys ctr3.num_old_keys = len(cleaned_ctr3_old_keys) else: ctr3.old_keys = old_krb['ctr3'].keys ctr3.num_old_keys = old_krb['ctr3'].num_keys if ctr3.num_old_keys != 0 and ctr3.num_old_keys != ctr3.num_keys: # TODO: Recommended policy is to fill up old_keys to match num_keys, this will result in a traceback, can we do something better? ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: Primary:Kerberos num_keys = %s" % ctr3.num_keys) for k in ctr4.keys: ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: ctr3.key.keytype: %s" % k.keytype) ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: Primary:Kerberos num_old_keys = %s" % ctr3.num_old_keys) for k in ctr4.old_keys: ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: ctr3.old_key.keytype: %s" % k.keytype) krb = drsblobs.package_PrimaryKerberosBlob() krb.version = 3 krb.ctr = ctr3 krb3_blob = ndr_pack(krb) creddata_Primary_Kerberos = binascii.hexlify(krb3_blob) credname_Primary_Kerberos = "Primary:Kerberos" cred_Primary_Kerberos = drsblobs.supplementalCredentialsPackage() cred_Primary_Kerberos.name = credname_Primary_Kerberos cred_Primary_Kerberos.name_len = len(credname_Primary_Kerberos) cred_Primary_Kerberos.data = creddata_Primary_Kerberos cred_Primary_Kerberos.data_len = len(creddata_Primary_Kerberos) cred_Primary_Kerberos.reserved = 1 cred_List.append(cred_Primary_Kerberos) package_names.append('Kerberos') if package_names: package_names_carray = (ctypes.c_char_p * len(package_names))(*package_names) package_names_PyCObject = _PyCObject_FromVoidPtr(ctypes.cast(package_names_carray, ctypes.POINTER(ctypes.c_char_p)), None) krb_Packages = drsblobs.package_PackagesBlob() krb_Packages.names = package_names_PyCObject krb_blob_Packages = ndr_pack(krb_Packages) # krb_blob_Packages = '\0'.join(package_names).encode('utf-16le') # this pretty much simulates it cred_PackagesBlob_data = binascii.hexlify(krb_blob_Packages).upper() cred_PackagesBlob_name = "Packages" cred_PackagesBlob = drsblobs.supplementalCredentialsPackage() cred_PackagesBlob.name = cred_PackagesBlob_name cred_PackagesBlob.name_len = len(cred_PackagesBlob_name) cred_PackagesBlob.data = cred_PackagesBlob_data cred_PackagesBlob.data_len = len(cred_PackagesBlob_data) cred_PackagesBlob.reserved = 2 cred_List.insert(-1, cred_PackagesBlob) sub = drsblobs.supplementalCredentialsSubBlob() sub.num_packages = len(cred_List) sub.packages = cred_List sub.signature = drsblobs.SUPPLEMENTAL_CREDENTIALS_SIGNATURE sub.prefix = drsblobs.SUPPLEMENTAL_CREDENTIALS_PREFIX sc = drsblobs.supplementalCredentialsBlob() sc.sub = sub sc_blob = ndr_pack(sc) return sc_blob
propertydata.append(package) packages_listblob = "\0".join(propertynames).encode("utf-16le") packages_blob = drsblobs.supplementalCredentialsPackage() packages_blob.name = "Packages" packages_blob.name_len = len(packages_blob.name) packages_blob.data = binascii.hexlify(packages_listblob).upper() packages_blob.data_len = len(packages_blob.data) packages_blob.reserved = 2 # see note about this property above # Build supplementalCredentials blob # https://msdn.microsoft.com/en-us/library/cc245500.aspx supcred_sections = [packages_blob] supcred_sections.extend(propertydata) supcred_subblock = drsblobs.supplementalCredentialsSubBlob() supcred_subblock.packages = supcred_sections supcred_subblock.num_packages = len(supcred_sections) supcred_subblock.prefix = drsblobs.SUPPLEMENTAL_CREDENTIALS_PREFIX supcred_subblock.signature = drsblobs.SUPPLEMENTAL_CREDENTIALS_SIGNATURE supcred_blob_unpacked = drsblobs.supplementalCredentialsBlob() supcred_blob_unpacked.sub = supcred_subblock supcred_blob = ndr_pack(supcred_blob_unpacked) if args.base64: print(binascii.b2a_base64(supcred_blob)) else: print(supcred_blob)
def calculate_supplementalCredentials(ucs_krb5key, old_supplementalCredentials): old_krb = {} if old_supplementalCredentials: sc = ndr_unpack(drsblobs.supplementalCredentialsBlob, old_supplementalCredentials) for p in sc.sub.packages: ud.debug(ud.LDAP, ud.INFO, "calculate_supplementalCredentials: parsing %s blob" % p.name) if p.name == "Primary:Kerberos": krb_blob = binascii.unhexlify(p.data) try: krb = ndr_unpack(drsblobs.package_PrimaryKerberosBlob, krb_blob) assert krb.version == 3 old_krb['ctr3'] = krb.ctr for k in krb.ctr.keys: ud.debug(ud.LDAP, ud.INFO, "calculate_supplementalCredentials: ctr3.key.keytype: %s" % k.keytype) except: ud.debug(ud.LDAP, ud.ERROR, "calculate_supplementalCredentials: ndr_unpack of S4 Primary:Kerberos blob failed. Traceback:") traceback.print_exc() ud.debug(ud.LDAP, ud.ERROR, "calculate_supplementalCredentials: Continuing anyway, Primary:Kerberos (DES keys) blob will be missing in supplementalCredentials ctr3.old_keys.") elif p.name == "Primary:Kerberos-Newer-Keys": krb_blob = binascii.unhexlify(p.data) try: krb = ndr_unpack(drsblobs.package_PrimaryKerberosBlob, krb_blob) assert krb.version == 4 old_krb['ctr4'] = krb.ctr for k in krb.ctr.keys: ud.debug(ud.LDAP, ud.INFO, "calculate_supplementalCredentials: ctr4.key.keytype: %s" % k.keytype) except: ud.debug(ud.LDAP, ud.ERROR, "calculate_supplementalCredentials: ndr_unpack of S4 Primary:Kerberos-Newer-Keys blob failed. Traceback:") traceback.print_exc() ud.debug(ud.LDAP, ud.ERROR, "calculate_supplementalCredentials: Continuing anyway, Primary:Kerberos-Newer-Keys (AES and DES keys) blob will be missing in supplementalCredentials ctr4.old_keys.") krb5_aes256 = '' krb5_aes128 = '' krb5_des_md5 = '' krb5_des_crc = '' krb_ctr3_salt = '' krb_ctr4_salt = '' for k in ucs_krb5key: (keyblock, salt, kvno) = heimdal.asn1_decode_key(k) key_data = keyblock.keyvalue() saltstring = salt.saltvalue() enctype = keyblock.keytype() enctype_id = enctype.toint() if enctype_id not in krb5_context.etype_ids: ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: ignoring unsupported krb5_keytype: (%d)" % (enctype_id,)) continue ud.debug(ud.LDAP, ud.INFO, "calculate_supplementalCredentials: krb5_keytype: %s (%d)" % (enctype, enctype_id)) if enctype_id == 18: krb5_aes256 = key_data if not krb_ctr4_salt: krb_ctr4_salt = saltstring elif enctype_id == 17: krb5_aes128 = key_data if not krb_ctr4_salt: krb_ctr4_salt = saltstring elif enctype_id == 3: krb5_des_md5 = key_data if not krb_ctr3_salt: krb_ctr3_salt = saltstring elif enctype_id == 1: krb5_des_crc = key_data if not krb_ctr3_salt: krb_ctr3_salt = saltstring # build new drsblobs.supplementalCredentialsBlob sc_blob = None cred_List = [] package_names = [] # Primary:Kerberos-Newer-Keys : AES keys if krb5_aes256 or krb5_aes128: ud.debug(ud.LDAP, ud.INFO, "calculate_supplementalCredentials: building Primary:Kerberos-Newer-Keys blob") kerberosKey4list = [] if krb5_aes256: assert len(krb5_aes256) == 32 next_key = drsblobs.package_PrimaryKerberosKey4() next_key.keytype = 18 next_key.value = krb5_aes256 next_key.value_len = len(krb5_aes256) kerberosKey4list.append(next_key) if krb5_aes128: assert len(krb5_aes128) == 16 next_key = drsblobs.package_PrimaryKerberosKey4() next_key.keytype = 17 next_key.value = krb5_aes128 next_key.value_len = len(krb5_aes128) kerberosKey4list.append(next_key) if krb5_des_md5: assert len(krb5_des_md5) == 8 next_key = drsblobs.package_PrimaryKerberosKey4() next_key.keytype = 3 next_key.value = krb5_des_md5 next_key.value_len = len(krb5_des_md5) kerberosKey4list.append(next_key) if krb5_des_crc: assert len(krb5_des_crc) == 8 next_key = drsblobs.package_PrimaryKerberosKey4() next_key.keytype = 1 next_key.value = krb5_des_crc next_key.value_len = len(krb5_des_crc) kerberosKey4list.append(next_key) salt4 = drsblobs.package_PrimaryKerberosString() salt4.string = krb_ctr4_salt ctr4 = drsblobs.package_PrimaryKerberosCtr4() ctr4.salt = salt4 ctr4.num_keys = len(kerberosKey4list) ctr4.keys = kerberosKey4list if old_krb.get('ctr4'): # Backup old_keys to s4_old_keys s4_num_old_keys = old_krb['ctr4'].num_old_keys s4_old_keys = [] for key in old_krb['ctr4'].old_keys: s4_old_keys.append(key) # keys -> old_keys if len(old_krb['ctr4'].keys) != ctr4.num_keys: cleaned_old_keys = [] for key in old_krb['ctr4'].keys: if key.keytype == 4294967156: # in all known cases W2k8 AD uses keytype 4294967156 (=-140L) to include the arc4 hash ud.debug(ud.LDAP, ud.INFO, "calculate_supplementalCredentials: Primary:Kerberos-Newer-Keys filtering keytype %s from old_keys" % key.keytype) continue else: # TODO: can we do something better at this point to make old_keys == num_keys ? cleaned_old_keys.append(key) ctr4.old_keys = cleaned_old_keys ctr4.num_old_keys = len(cleaned_old_keys) else: ctr4.old_keys = old_krb['ctr4'].keys ctr4.num_old_keys = old_krb['ctr4'].num_keys # s4_old_keys -> older_keys if ctr4.num_old_keys != ctr4.num_older_keys: cleaned_older_keys = [] for key in s4_old_keys: if key.keytype == 4294967156: # in all known cases W2k8 AD uses keytype 4294967156 (=-140L) to include the arc4 hash ud.debug(ud.LDAP, ud.INFO, "calculate_supplementalCredentials: Primary:Kerberos-Newer-Keys filtering keytype %s from older_keys" % key.keytype) continue else: # TODO: can we do something better at this point to make old_keys == num_keys ? cleaned_older_keys.append(key) ctr4.older_keys = cleaned_older_keys ctr4.num_older_keys = len(cleaned_older_keys) else: ctr4.older_keys = s4_old_keys ctr4.num_older_keys = s4_num_old_keys if ctr4.num_old_keys != 0 and ctr4.num_old_keys != ctr4.num_keys: # TODO: Recommended policy is to fill up old_keys to match num_keys, this will result in a traceback, can we do something better? ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: Primary:Kerberos-Newer-Keys num_keys = %s" % ctr4.num_keys) for k in ctr4.keys: ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: ctr4.key.keytype: %s" % k.keytype) ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: Primary:Kerberos-Newer-Keys num_old_keys = %s" % ctr4.num_old_keys) for k in ctr4.old_keys: ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: ctr4.old_key.keytype: %s" % k.keytype) if ctr4.num_older_keys != 0 and ctr4.num_older_keys != ctr4.num_old_keys: # TODO: Recommended policy is to fill up old_keys to match num_keys, this will result in a traceback, can we do something better? ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: Primary:Kerberos-Newer-Keys num_old_keys = %s" % ctr4.num_old_keys) for k in ctr4.old_keys: ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: ctr4.old_key.keytype: %s" % k.keytype) ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: Primary:Kerberos-Newer-Keys num_older_keys = %s" % ctr4.num_older_keys) for k in ctr4.older_keys: ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: ctr4.older_key.keytype: %s" % k.keytype) krb_Primary_Kerberos_Newer = drsblobs.package_PrimaryKerberosBlob() krb_Primary_Kerberos_Newer.version = 4 krb_Primary_Kerberos_Newer.ctr = ctr4 krb_blob_Primary_Kerberos_Newer = ndr_pack(krb_Primary_Kerberos_Newer) creddata_Primary_Kerberos_Newer = binascii.hexlify(krb_blob_Primary_Kerberos_Newer) credname_Primary_Kerberos_Newer = "Primary:Kerberos-Newer-Keys" cred_Primary_Kerberos_Newer = drsblobs.supplementalCredentialsPackage() cred_Primary_Kerberos_Newer.name = credname_Primary_Kerberos_Newer cred_Primary_Kerberos_Newer.name_len = len(credname_Primary_Kerberos_Newer) cred_Primary_Kerberos_Newer.data = creddata_Primary_Kerberos_Newer cred_Primary_Kerberos_Newer.data_len = len(creddata_Primary_Kerberos_Newer) cred_Primary_Kerberos_Newer.reserved = 1 cred_List.append(cred_Primary_Kerberos_Newer) package_names.append('Kerberos-Newer-Keys') # Primary:Kerberos : MD5 and CRC keys if krb5_des_md5 or krb5_des_crc: ud.debug(ud.LDAP, ud.INFO, "calculate_supplementalCredentials: building Primary:Kerberos blob") kerberosKey3list = [] if krb5_des_md5: next_key = drsblobs.package_PrimaryKerberosKey3() next_key.keytype = 3 next_key.value = krb5_des_md5 next_key.value_len = len(krb5_des_md5) kerberosKey3list.append(next_key) if krb5_des_crc: next_key = drsblobs.package_PrimaryKerberosKey3() next_key.keytype = 1 next_key.value = krb5_des_crc next_key.value_len = len(krb5_des_crc) kerberosKey3list.append(next_key) salt = drsblobs.package_PrimaryKerberosString() salt.string = krb_ctr3_salt ctr3 = drsblobs.package_PrimaryKerberosCtr3() ctr3.salt = salt ctr3.num_keys = len(kerberosKey3list) ctr3.keys = kerberosKey3list if old_krb.get('ctr3'): # keys -> old_keys if len(old_krb['ctr3'].keys) != ctr3.num_keys: cleaned_ctr3_old_keys = [] for key in old_krb['ctr3'].keys: if key.keytype == 4294967156: # in all known cases W2k8 AD uses keytype 4294967156 (=-140L) to include the arc4 hash ud.debug(ud.LDAP, ud.INFO, "calculate_supplementalCredentials: Primary:Kerberos filtering keytype %s from old_keys" % key.keytype) continue else: # TODO: can we do something better at this point to make old_keys == num_keys ? cleaned_ctr3_old_keys.append(key) ctr3.old_keys = cleaned_ctr3_old_keys ctr3.num_old_keys = len(cleaned_ctr3_old_keys) else: ctr3.old_keys = old_krb['ctr3'].keys ctr3.num_old_keys = old_krb['ctr3'].num_keys if ctr3.num_old_keys != 0 and ctr3.num_old_keys != ctr3.num_keys: # TODO: Recommended policy is to fill up old_keys to match num_keys, this will result in a traceback, can we do something better? ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: Primary:Kerberos num_keys = %s" % ctr3.num_keys) for k in ctr3.keys: ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: ctr3.key.keytype: %s" % k.keytype) ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: Primary:Kerberos num_old_keys = %s" % ctr3.num_old_keys) for k in ctr3.old_keys: ud.debug(ud.LDAP, ud.WARN, "calculate_supplementalCredentials: ctr3.old_key.keytype: %s" % k.keytype) krb = drsblobs.package_PrimaryKerberosBlob() krb.version = 3 krb.ctr = ctr3 krb3_blob = ndr_pack(krb) creddata_Primary_Kerberos = binascii.hexlify(krb3_blob) credname_Primary_Kerberos = "Primary:Kerberos" cred_Primary_Kerberos = drsblobs.supplementalCredentialsPackage() cred_Primary_Kerberos.name = credname_Primary_Kerberos cred_Primary_Kerberos.name_len = len(credname_Primary_Kerberos) cred_Primary_Kerberos.data = creddata_Primary_Kerberos cred_Primary_Kerberos.data_len = len(creddata_Primary_Kerberos) cred_Primary_Kerberos.reserved = 1 cred_List.append(cred_Primary_Kerberos) package_names.append('Kerberos') if package_names: krb_blob_Packages = '\0'.join(package_names).encode('utf-16le') cred_PackagesBlob_data = binascii.hexlify(krb_blob_Packages).upper() cred_PackagesBlob_name = "Packages" cred_PackagesBlob = drsblobs.supplementalCredentialsPackage() cred_PackagesBlob.name = cred_PackagesBlob_name cred_PackagesBlob.name_len = len(cred_PackagesBlob_name) cred_PackagesBlob.data = cred_PackagesBlob_data cred_PackagesBlob.data_len = len(cred_PackagesBlob_data) cred_PackagesBlob.reserved = 2 cred_List.insert(-1, cred_PackagesBlob) sub = drsblobs.supplementalCredentialsSubBlob() sub.num_packages = len(cred_List) sub.packages = cred_List sub.signature = drsblobs.SUPPLEMENTAL_CREDENTIALS_SIGNATURE sub.prefix = drsblobs.SUPPLEMENTAL_CREDENTIALS_PREFIX sc = drsblobs.supplementalCredentialsBlob() sc.sub = sub sc_blob = ndr_pack(sc) ud.debug(ud.LDAP, ud.ALL, "calculate_supplementalCredentials: sc:\n%s" % ndr_print(sc)) return sc_blob