#include "idl_types.h" import "drsuapi.idl", "misc.idl", "samr.idl", "lsa.idl", "security.idl"; [ uuid("12345778-1234-abcd-0001-00000001"), version(0.0), pointer_default(unique), helper("../librpc/ndr/ndr_drsblobs.h"), helpstring("Active Directory Replication LDAP Blobs") ] interface drsblobs { typedef bitmap drsuapi_DrsOptions drsuapi_DrsOptions; typedef [v1_enum] enum drsuapi_DsAttributeId drsuapi_DsAttributeId; typedef [v1_enum] enum lsa_TrustAuthType lsa_TrustAuthType; /* * replPropertyMetaData * w2k uses version 1 * w2k3 uses version 1 * * Also equivalent to * MS-DRSR 4.1.10.2.22 PROPERTY_META_DATA */ typedef [public] struct { drsuapi_DsAttributeId attid; uint32 version; NTTIME_1sec originating_change_time; GUID originating_invocation_id; hyper originating_usn; hyper local_usn; } replPropertyMetaData1; void decode_replPropertyMetaData1( [in] replPropertyMetaData1 blob ); typedef struct { uint32 count; [value(0)] uint32 reserved; replPropertyMetaData1 array[count]; } replPropertyMetaDataCtr1; typedef [nodiscriminant] union { [case(1)] replPropertyMetaDataCtr1 ctr1; } replPropertyMetaDataCtr; typedef [public] struct { uint32 version; [value(0)] uint32 reserved; [switch_is(version)] replPropertyMetaDataCtr ctr; } replPropertyMetaDataBlob; void decode_replPropertyMetaData( [in] replPropertyMetaDataBlob blob ); /* * replUpToDateVector * w2k uses version 1 * w2k3 uses version 2 */ typedef struct { uint32 count; [value(0)] uint32 reserved; drsuapi_DsReplicaCursor cursors[count]; } replUpToDateVectorCtr1; typedef struct { uint32 count; [value(0)] uint32 reserved; drsuapi_DsReplicaCursor2 cursors[count]; } replUpToDateVectorCtr2; typedef [nodiscriminant] union { [case(1)] replUpToDateVectorCtr1 ctr1; [case(2)] replUpToDateVectorCtr2 ctr2; } replUpToDateVectorCtr; typedef [public] struct { uint32 version; [value(0)] uint32 reserved; [switch_is(version)] replUpToDateVectorCtr ctr; } replUpToDateVectorBlob; void decode_replUpToDateVector( [in] replUpToDateVectorBlob blob ); /* * repsFrom/repsTo * w2k uses version 1 * w2k3 uses version 1 * w2k8 uses version 2 */ typedef [public,gensize] struct { [value(strlen(dns_name)+1)] uint32 __dns_name_size; [charset(DOS)] uint8 dns_name[__dns_name_size]; } repsFromTo1OtherInfo; typedef [public,gensize,flag(NDR_PAHEX)] struct { /* this includes the 8 bytes of the repsFromToBlob header */ [value(ndr_size_repsFromTo1(this, ndr->flags)+8)] uint32 blobsize; uint32 consecutive_sync_failures; NTTIME_1sec last_success; NTTIME_1sec last_attempt; WERROR result_last_attempt; [relative] repsFromTo1OtherInfo *other_info; [value(ndr_size_repsFromTo1OtherInfo(other_info, ndr->flags))] uint32 other_info_length; drsuapi_DrsOptions replica_flags; uint8 schedule[84]; [value(0)] uint32 reserved; drsuapi_DsReplicaHighWaterMark highwatermark; GUID source_dsa_obj_guid; /* the 'objectGuid' field of the CN=NTDS Settings object */ GUID source_dsa_invocation_id; /* the 'invocationId' field of the CN=NTDS Settings object */ GUID transport_guid; } repsFromTo1; typedef [public,relative_base,gensize] struct { [value(ndr_size_repsFromTo2OtherInfo(this,ndr->flags))] uint32 __ndr_size; [relative] nstring *dns_name1; uint32 unknown1; [relative] nstring *dns_name2; hyper unknown2; } repsFromTo2OtherInfo; typedef [public,gensize,flag(NDR_PAHEX)] struct { /* this includes the 8 bytes of the repsFromToBlob header */ [value(ndr_size_repsFromTo2(this, ndr->flags)+8)] uint32 blobsize; uint32 consecutive_sync_failures; NTTIME_1sec last_success; NTTIME_1sec last_attempt; WERROR result_last_attempt; [relative] repsFromTo2OtherInfo *other_info; [value(ndr_size_repsFromTo2OtherInfo(other_info, ndr->flags))] uint32 other_info_length; drsuapi_DrsOptions replica_flags; uint8 schedule[84]; [value(0)] uint32 reserved; drsuapi_DsReplicaHighWaterMark highwatermark; GUID source_dsa_obj_guid; /* the 'objectGuid' field of the CN=NTDS Settings object */ GUID source_dsa_invocation_id; /* the 'invocationId' field of the CN=NTDS Settings object */ GUID transport_guid; hyper unknown1; } repsFromTo2; typedef [nodiscriminant] union { [case(1)] repsFromTo1 ctr1; [case(2)] repsFromTo2 ctr2; } repsFromTo; typedef [public] struct { uint32 version; [value(0)] uint32 reserved; [switch_is(version)] repsFromTo ctr; } repsFromToBlob; void decode_repsFromTo( [in] repsFromToBlob blob ); /* Replication schedule structures as defined in MS-ADTS 7.1.4.5 * Appears as attribute of NTDSConnection object */ typedef [public] struct { [value(0)] uint32 type; /* always 0 */ uint32 offset; } scheduleHeader; typedef [public] struct { uint8 slots[168]; } scheduleSlots; typedef [public] struct { uint32 size; [value(0)] uint32 bandwidth; /* ignored */ [value(1)] uint32 numberOfSchedules; /* always 1 */ scheduleHeader headerArray[numberOfSchedules]; scheduleSlots dataArray[numberOfSchedules]; } schedule; /* * partialAttributeSet * w2k uses version 1 * w2k3 uses version 1 */ typedef struct { uint32 count; drsuapi_DsAttributeId array[count]; } partialAttributeSetCtr1; typedef [nodiscriminant] union { [case(1)] partialAttributeSetCtr1 ctr1; } partialAttributeSetCtr; typedef [public] struct { uint32 version; [value(0)] uint32 reserved; [switch_is(version)] partialAttributeSetCtr ctr; } partialAttributeSetBlob; void decode_partialAttributeSet( [in] partialAttributeSetBlob blob ); /* * schemaInfo attribute * * Used as an attribute on Schema. * Also during replication as part of * prefixMap to identify what revision * of Schema source DC has */ typedef [public,flag(NDR_NOALIGN)] struct { [value(0xFF)] uint8 marker; [flag(NDR_BIG_ENDIAN)] uint32 revision; GUID invocation_id; } schemaInfoBlob; /* * MS w2k3 and w2k8 prefixMap format * There is no version number. Format is: * uint32 - number of entries in the map * uint32 - total bytes that structure occupies * ENTRIES: * uint16 - prefix ID (OID's last sub-id encoded. see prefixMap) * uint16 - number of bytes in prefix N * uint8[N] - BER encoded prefix */ typedef [noprint,flag(NDR_NOALIGN)] struct { uint16 entryID; uint16 length; uint8 binary_oid[length]; } drsuapi_MSPrefixMap_Entry; typedef [public,gensize] struct { uint32 num_entries; [value(ndr_size_drsuapi_MSPrefixMap_Ctr(r, ndr->flags))] uint32 __ndr_size; drsuapi_MSPrefixMap_Entry entries[num_entries]; } drsuapi_MSPrefixMap_Ctr; /* * prefixMap * w2k unknown * w2k3 unknown * samba4 uses 0x44534442 'DSDB' * * as we windows don't return the prefixMap attribute when you ask for * we don't know the format, but the attribute is not replicated * so that we can choose our own format... */ typedef [v1_enum] enum { PREFIX_MAP_VERSION_DSDB = 0x44534442 } prefixMapVersion; typedef [nodiscriminant] union { [case(PREFIX_MAP_VERSION_DSDB)] drsuapi_DsReplicaOIDMapping_Ctr dsdb; } prefixMapCtr; typedef [public] struct { prefixMapVersion version; [value(0)] uint32 reserved; [switch_is(version)] prefixMapCtr ctr; } prefixMapBlob; void decode_prefixMap( [in] prefixMapBlob blob ); /* * the cookie for the LDAP dirsync control */ typedef [nodiscriminant,gensize] union { [case(0)]; [default] replUpToDateVectorBlob uptodateness_vector; } ldapControlDirSyncExtra; typedef struct { [value(3)] uint32 u1; NTTIME time; uint32 u2; uint32 u3; [value(ndr_size_ldapControlDirSyncExtra(&extra, extra.uptodateness_vector.version, 0))] uint32 extra_length; drsuapi_DsReplicaHighWaterMark highwatermark; GUID guid1; [switch_is(extra_length)] ldapControlDirSyncExtra extra; } ldapControlDirSyncBlob; typedef [public,relative_base] struct { [charset(DOS),value("MSDS")] uint8 msds[4]; [subcontext(0)] ldapControlDirSyncBlob blob; } ldapControlDirSyncCookie; void decode_ldapControlDirSync( [in] ldapControlDirSyncCookie cookie ); typedef [public] struct { [value(2*strlen_m(name))] uint16 name_len; [value(strlen(data))] uint16 data_len; uint16 reserved; /* 2 for 'Packages', 1 for 'Primary:*', but should be ignored */ [charset(UTF16)] uint8 name[name_len]; /* * the data field contains data as HEX strings * * 'Packages': * data contains the list of packages * as non termiated UTF16 strings with * a UTF16 NULL byte as separator * * 'Primary:Kerberos-Newer-Keys': * ... * * 'Primary:Kerberos': * ... * * 'Primary:WDigest': * ... * * 'Primary:CLEARTEXT': * data contains the cleartext password * as UTF16 string encoded as HEX string * * 'Primary:userPassword': * ... * * 'Primary:SambaGPG': * ... * * 'Primary:NTLM-Strong-NTOWF': * ... Not yet implemented. * */ [charset(DOS)] uint8 data[data_len]; } supplementalCredentialsPackage; /* this are 0x30 (48) whitespaces (0x20) */ const string SUPPLEMENTAL_CREDENTIALS_PREFIX = " "; typedef [flag(NDR_PAHEX),public] enum { SUPPLEMENTAL_CREDENTIALS_SIGNATURE = 0x0050 } supplementalCredentialsSignature; typedef [gensize,nopush,nopull] struct { [value(SUPPLEMENTAL_CREDENTIALS_PREFIX),charset(UTF16)] uint16 prefix[0x30]; [value(SUPPLEMENTAL_CREDENTIALS_SIGNATURE)] supplementalCredentialsSignature signature; uint16 num_packages; supplementalCredentialsPackage packages[num_packages]; } supplementalCredentialsSubBlob; typedef [public] struct { [value(0)] uint32 unknown1; [value(ndr_size_supplementalCredentialsSubBlob(&sub, ndr->flags))] uint32 __ndr_size; [value(0)] uint32 unknown2; [subcontext(0),subcontext_size(__ndr_size)] supplementalCredentialsSubBlob sub; [value(0)] uint8 unknown3; } supplementalCredentialsBlob; void decode_supplementalCredentials( [in] supplementalCredentialsBlob blob ); typedef [public] struct { [flag(STR_NOTERM|NDR_REMAINING)] string_array names; } package_PackagesBlob; void decode_Packages( [in] package_PackagesBlob blob ); typedef struct { [value(2*strlen_m(string))] uint16 length; [value(2*strlen_m(string))] uint16 size; [relative,subcontext(0),subcontext_size(size),flag(STR_NOTERM|NDR_REMAINING)] string *string; } package_PrimaryKerberosString; typedef struct { [value(0)] uint16 reserved1; [value(0)] uint16 reserved2; [value(0)] uint32 reserved3; uint32 keytype; [value((value?value->length:0))] uint32 value_len; [relative,subcontext(0),subcontext_size(value_len),flag(NDR_REMAINING)] DATA_BLOB *value; } package_PrimaryKerberosKey3; typedef struct { uint16 num_keys; uint16 num_old_keys; package_PrimaryKerberosString salt; package_PrimaryKerberosKey3 keys[num_keys]; package_PrimaryKerberosKey3 old_keys[num_old_keys]; [value(0)] uint32 padding1; [value(0)] uint32 padding2; [value(0)] uint32 padding3; [value(0)] uint32 padding4; [value(0)] uint32 padding5; } package_PrimaryKerberosCtr3; typedef struct { [value(0)] uint16 reserved1; [value(0)] uint16 reserved2; [value(0)] uint32 reserved3; uint32 iteration_count; uint32 keytype; [value((value?value->length:0))] uint32 value_len; [relative,subcontext(0),subcontext_size(value_len),flag(NDR_REMAINING)] DATA_BLOB *value; } package_PrimaryKerberosKey4; typedef struct { uint16 num_keys; [value(0)] uint16 num_service_keys; uint16 num_old_keys; uint16 num_older_keys; package_PrimaryKerberosString salt; uint32 default_iteration_count; package_PrimaryKerberosKey4 keys[num_keys]; package_PrimaryKerberosKey4 service_keys[num_service_keys]; package_PrimaryKerberosKey4 old_keys[num_old_keys]; package_PrimaryKerberosKey4 older_keys[num_older_keys]; } package_PrimaryKerberosCtr4; typedef [nodiscriminant] union { [case(3)] package_PrimaryKerberosCtr3 ctr3; [case(4)] package_PrimaryKerberosCtr4 ctr4; } package_PrimaryKerberosCtr; typedef [public] struct { uint16 version; [value(0)] uint16 flags; [switch_is(version)] package_PrimaryKerberosCtr ctr; } package_PrimaryKerberosBlob; void decode_PrimaryKerberos( [in] package_PrimaryKerberosBlob blob ); typedef [public] struct { [flag(NDR_REMAINING)] DATA_BLOB cleartext; } package_PrimaryCLEARTEXTBlob; void decode_PrimaryCLEARTEXT( [in] package_PrimaryCLEARTEXTBlob blob ); typedef [flag(NDR_PAHEX)] struct { uint8 hash[16]; } package_PrimaryWDigestHash; typedef [public] struct { [value(0x31)] uint16 unknown1; [value(0x01)] uint8 unknown2; uint8 num_hashes; [value(0)] uint32 unknown3; [value(0)] udlong uuknown4; package_PrimaryWDigestHash hashes[num_hashes]; } package_PrimaryWDigestBlob; void decode_PrimaryWDigest( [in] package_PrimaryWDigestBlob blob ); typedef [public] struct { [flag(NDR_REMAINING)] DATA_BLOB gpg_blob; } package_PrimarySambaGPGBlob; void decode_PrimarySambaGPG( [in] package_PrimarySambaGPGBlob blob ); /* * Password hashes stored in a scheme compatible with * OpenLDAP's userPassword attribute. The Package is named * Primary:userPassword each calculated hash, * which is typically caclulated via crypt(), the scheme is stored. * The scheme name and the {scheme} format is re-used from OpenLDAP's * use for userPassword to aid interopability when exported. * * The currently supported scheme so far is {CRYPT}, which may * be specified multiple times if both CryptSHA256 ($5$) and * CryptSHA512 ($6$) are in use. * * current_nt_hash is either the unicodePwd or the * NTLM-Strong-NTOWF, to allow us to prove this password is * a valid element. */ typedef struct { [value(2*strlen_m(scheme))] uint16 scheme_len; [charset(UTF16)] uint8 scheme[scheme_len]; [value((value?value->length:0))] uint32 value_len; [relative,subcontext(0),subcontext_size(value_len), flag(NDR_REMAINING)] DATA_BLOB *value; } package_PrimaryUserPasswordValue; typedef [public] struct { samr_Password current_nt_hash; uint16 num_hashes; package_PrimaryUserPasswordValue hashes[num_hashes]; } package_PrimaryUserPasswordBlob; void decode_PrimaryUserPasswordBlob( [in] package_PrimaryUserPasswordBlob blob ); typedef struct { [value(0)] uint32 size; } AuthInfoNone; typedef struct { [value(16)] uint32 size; samr_Password password; } AuthInfoNT4Owf; /* * the secret value is encoded as UTF16 if it's a string * but depending the AuthType, it might also be krb5 trusts have random bytes here, so converting to UTF16 * mayfail... * * TODO: We should try handle the case of a random buffer in all places * we deal with cleartext passwords from windows * * so we don't use this: * * uint32 value_len; * [charset(UTF16)] uint8 value[value_len]; */ typedef struct { uint32 size; uint8 password[size]; } AuthInfoClear; typedef struct { [value(4)] uint32 size; uint32 version; } AuthInfoVersion; typedef [nodiscriminant] union { [case(TRUST_AUTH_TYPE_NONE)] AuthInfoNone none; [case(TRUST_AUTH_TYPE_NT4OWF)] AuthInfoNT4Owf nt4owf; [case(TRUST_AUTH_TYPE_CLEAR)] AuthInfoClear clear; [case(TRUST_AUTH_TYPE_VERSION)] AuthInfoVersion version; } AuthInfo; typedef [public] struct { NTTIME LastUpdateTime; lsa_TrustAuthType AuthType; [switch_is(AuthType)] AuthInfo AuthInfo; [flag(NDR_ALIGN4)] DATA_BLOB _pad; } AuthenticationInformation; /* count is not on the wire */ typedef [public,nopull,nopush,gensize] struct { uint32 count; AuthenticationInformation array[count]; } AuthenticationInformationArray; /* we cannot use [relative] pointers here because Windows expects the * previous_offset to match the total size of the struct in case * the previous array is empty, see MS-LSAD 2.2.7.16 - gd */ typedef [public,gensize,nopush] struct { uint32 count; [value((count > 0) ? 12 : 0)] uint32 current_offset; [value((count > 0) ? 12 + ndr_size_AuthenticationInformationArray(¤t, ndr->flags) : 0)] uint32 previous_offset; [subcontext(0),subcontext_size((previous_offset)-(current_offset))] AuthenticationInformationArray current; [subcontext(0)] [flag(NDR_REMAINING)] AuthenticationInformationArray previous; } trustAuthInOutBlob; [nopython] void decode_trustAuthInOut( [in] trustAuthInOutBlob blob ); typedef [public,nopull] struct { uint8 confounder[512]; [subcontext(0),subcontext_size(outgoing_size)] trustAuthInOutBlob outgoing; [subcontext(0),subcontext_size(incoming_size)] trustAuthInOutBlob incoming; [value(ndr_size_trustAuthInOutBlob(&outgoing, ndr->flags))] uint32 outgoing_size; [value(ndr_size_trustAuthInOutBlob(&incoming, ndr->flags))] uint32 incoming_size; } trustDomainPasswords; [nopython] void decode_trustDomainPasswords( [in] trustDomainPasswords blob ); typedef [public] struct { uint32 marker; DATA_BLOB data; } DsCompressedChunk; typedef struct { uint16 __size; [size_is(__size),charset(DOS)] uint8 *string; } ExtendedErrorAString; typedef struct { uint16 __size; [size_is(__size),charset(UTF16)] uint16 *string; } ExtendedErrorUString; typedef struct { uint16 length; [size_is(length)] uint8 *data; } ExtendedErrorBlob; typedef enum { EXTENDED_ERROR_COMPUTER_NAME_PRESENT = 1, EXTENDED_ERROR_COMPUTER_NAME_NOT_PRESENT= 2 } ExtendedErrorComputerNamePresent; typedef [switch_type(ExtendedErrorComputerNamePresent)] union { [case(EXTENDED_ERROR_COMPUTER_NAME_PRESENT)] ExtendedErrorUString name; [case(EXTENDED_ERROR_COMPUTER_NAME_NOT_PRESENT)]; } ExtendedErrorComputerNameU; typedef struct { ExtendedErrorComputerNamePresent present; [switch_is(present)] ExtendedErrorComputerNameU n; } ExtendedErrorComputerName; typedef enum { EXTENDED_ERROR_PARAM_TYPE_ASCII_STRING = 1, EXTENDED_ERROR_PARAM_TYPE_UNICODE_STRING = 2, EXTENDED_ERROR_PARAM_TYPE_UINT32 = 3, EXTENDED_ERROR_PARAM_TYPE_UINT16 = 4, EXTENDED_ERROR_PARAM_TYPE_UINT64 = 5, EXTENDED_ERROR_PARAM_TYPE_NONE = 6, EXTENDED_ERROR_PARAM_TYPE_BLOB = 7 } ExtendedErrorParamType; typedef [switch_type(ExtendedErrorParamType)] union { [case(EXTENDED_ERROR_PARAM_TYPE_ASCII_STRING)] ExtendedErrorAString a_string; [case(EXTENDED_ERROR_PARAM_TYPE_UNICODE_STRING)] ExtendedErrorUString u_string; [case(EXTENDED_ERROR_PARAM_TYPE_UINT32)] uint32 uint32; [case(EXTENDED_ERROR_PARAM_TYPE_UINT16)] uint16 uint16; [case(EXTENDED_ERROR_PARAM_TYPE_UINT64)] hyper uint64; [case(EXTENDED_ERROR_PARAM_TYPE_NONE)]; [case(EXTENDED_ERROR_PARAM_TYPE_BLOB)] ExtendedErrorBlob blob; } ExtendedErrorParamU; typedef struct { ExtendedErrorParamType type; [switch_is(type)] ExtendedErrorParamU p; } ExtendedErrorParam; typedef [public] struct { ExtendedErrorInfo *next; ExtendedErrorComputerName computer_name; hyper pid; NTTIME time; uint32 generating_component; WERROR status; uint16 detection_location; uint16 flags; uint16 num_params; [size_is(num_params)] ExtendedErrorParam params[]; } ExtendedErrorInfo; typedef struct { [unique] ExtendedErrorInfo *info; } ExtendedErrorInfoPtr; [nopython] void decode_ExtendedErrorInfo ( [in,subcontext(0xFFFFFC01)] ExtendedErrorInfoPtr ptr ); /* MS-ADTS 7.1.6.9.3 msDS-TrustForestTrustInfo Attribute */ typedef struct { [value(strlen_m(string))] uint32 size; [charset(UTF8)] uint8 string[size]; } ForestTrustString; typedef [flag(NDR_NOALIGN)] struct { [value(ndr_size_dom_sid0(&sid, ndr->flags))] uint32 sid_size; [subcontext(0),subcontext_size(sid_size)] dom_sid sid; ForestTrustString dns_name; ForestTrustString netbios_name; } ForestTrustDataDomainInfo; typedef [flag(NDR_NOALIGN)] struct { uint32 size; uint8 data[size]; } ForestTrustDataBinaryData; typedef [nodiscriminant] union { [case(FOREST_TRUST_TOP_LEVEL_NAME)] ForestTrustString name; [case(FOREST_TRUST_TOP_LEVEL_NAME_EX)] ForestTrustString name; [case(FOREST_TRUST_DOMAIN_INFO)] ForestTrustDataDomainInfo info; [default] ForestTrustDataBinaryData data; } ForestTrustData; /* same as lsa_ForestTrustRecordType, but only 8 bit */ typedef [enum8bit] enum { FOREST_TRUST_TOP_LEVEL_NAME = LSA_FOREST_TRUST_TOP_LEVEL_NAME, FOREST_TRUST_TOP_LEVEL_NAME_EX = LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX, FOREST_TRUST_DOMAIN_INFO = LSA_FOREST_TRUST_DOMAIN_INFO } ForestTrustInfoRecordType; /* meaning of flags depends on record type and values are the same as in lsa.idl, see collision record types */ typedef [public,gensize,flag(NDR_NOALIGN)] struct { lsa_ForestTrustRecordFlags flags; NTTIME timestamp; ForestTrustInfoRecordType type; [switch_is(type)] ForestTrustData data; } ForestTrustInfoRecord; typedef [flag(NDR_NOALIGN)] struct { [value(ndr_size_ForestTrustInfoRecord(&record, ndr->flags))] uint32 record_size; ForestTrustInfoRecord record; } ForestTrustInfoRecordArmor; typedef [public,flag(NDR_NOALIGN)] struct { uint32 version; uint32 count; ForestTrustInfoRecordArmor records[count]; } ForestTrustInfo; [nopython] void decode_ForestTrustInfo( [in] ForestTrustInfo blob ); }