diff options
Diffstat (limited to 'source4/librpc')
-rw-r--r-- | source4/librpc/config.mk | 5 | ||||
-rw-r--r-- | source4/librpc/idl/dcerpc.idl | 3 | ||||
-rw-r--r-- | source4/librpc/idl/drsblobs.idl | 33 | ||||
-rw-r--r-- | source4/librpc/idl/drsuapi.idl | 24 | ||||
-rw-r--r-- | source4/librpc/idl/krb5pac.idl | 12 | ||||
-rw-r--r-- | source4/librpc/idl/lsa.idl | 111 | ||||
-rw-r--r-- | source4/librpc/idl/nbt.idl | 8 | ||||
-rw-r--r-- | source4/librpc/idl/security.idl | 8 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr.c | 115 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr_compression.c | 377 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr_drsuapi.c | 173 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc.c | 17 |
12 files changed, 695 insertions, 191 deletions
diff --git a/source4/librpc/config.mk b/source4/librpc/config.mk index d87683dd6f..b68d5e6a69 100644 --- a/source4/librpc/config.mk +++ b/source4/librpc/config.mk @@ -43,7 +43,8 @@ MANPAGES += $(librpcsrcdir)/tools/ndrdump.1 ################################################ # Start SUBSYSTEM NDR_COMPRESSION [SUBSYSTEM::NDR_COMPRESSION] -PUBLIC_DEPENDENCIES = LIBCOMPRESSION LIBSAMBA-ERRORS LIBNDR +PRIVATE_DEPENDENCIES = ZLIB LZXPRESS +PUBLIC_DEPENDENCIES = LIBSAMBA-ERRORS LIBNDR # End SUBSYSTEM NDR_COMPRESSION ################################################ @@ -133,7 +134,7 @@ PUBLIC_DEPENDENCIES = LIBNDR NDR_COMPRESSION NDR_SECURITY NDR_SAMR ASN1_UTIL NDR_DRSUAPI_OBJ_FILES = $(gen_ndrsrcdir)/ndr_drsuapi.o $(ndrsrcdir)/ndr_drsuapi.o [SUBSYSTEM::NDR_DRSBLOBS] -PUBLIC_DEPENDENCIES = LIBNDR NDR_MISC NDR_DRSUAPI +PUBLIC_DEPENDENCIES = LIBNDR NDR_MISC NDR_DRSUAPI LIBCLI_DRSBLOBS NDR_DRSBLOBS_OBJ_FILES = $(gen_ndrsrcdir)/ndr_drsblobs.o diff --git a/source4/librpc/idl/dcerpc.idl b/source4/librpc/idl/dcerpc.idl index e54bc2c29f..1c6574b11b 100644 --- a/source4/librpc/idl/dcerpc.idl +++ b/source4/librpc/idl/dcerpc.idl @@ -30,7 +30,6 @@ interface dcerpc } dcerpc_bind; const uint8 DCERPC_REQUEST_LENGTH = 24; - const uint8 DCERPC_MAX_SIGN_SIZE = 64; typedef struct { } dcerpc_empty; @@ -154,6 +153,8 @@ interface dcerpc [flag(NDR_REMAINING)] DATA_BLOB credentials; } dcerpc_auth; + const uint8 DCERPC_AUTH_TRAILER_LENGTH = 8; + typedef [public] struct { uint32 _pad; [flag(NDR_REMAINING)] DATA_BLOB auth_info; diff --git a/source4/librpc/idl/drsblobs.idl b/source4/librpc/idl/drsblobs.idl index b0cddfcdf9..eb85989eda 100644 --- a/source4/librpc/idl/drsblobs.idl +++ b/source4/librpc/idl/drsblobs.idl @@ -401,7 +401,7 @@ interface drsblobs { [case(TRUST_AUTH_TYPE_VERSION)] AuthInfoVersion version; } AuthInfo; - typedef struct { + typedef [public] struct { NTTIME LastUpdateTime; trustAuthType AuthType; @@ -422,32 +422,15 @@ interface drsblobs { [flag(NDR_ALIGN4)] DATA_BLOB _pad; } AuthenticationInformation; - typedef struct { - AuthenticationInformation info[1]; - } AuthenticationInformation1; - - typedef struct { - AuthenticationInformation info[2]; - } AuthenticationInformation2; - - typedef struct { - [relative] AuthenticationInformation1 *current; - [relative] AuthenticationInformation1 *previous; - } AuthenticationInformationCtr1; - - typedef struct { - [relative] AuthenticationInformation2 *current; - [relative] AuthenticationInformation2 *previous; - } AuthenticationInformationCtr2; + typedef [nopull,nopush,noprint] struct { + /* sizeis here is bogus, but this is here just for the structure */ + [size_is(1)] AuthenticationInformation array[]; + } AuthenticationInformationArray; - typedef [nodiscriminant] union { - [case(1)] AuthenticationInformationCtr1 info1; - [case(2)] AuthenticationInformationCtr2 info2; - } AuthenticationInformationCtr; - - typedef [public] struct { + typedef [public,nopull,nopush,noprint] struct { uint32 count; - [switch_is(count)] AuthenticationInformationCtr auth; + [relative] AuthenticationInformationArray *current; + [relative] AuthenticationInformationArray *previous; } trustAuthInOutBlob; void decode_trustAuthInOut( diff --git a/source4/librpc/idl/drsuapi.idl b/source4/librpc/idl/drsuapi.idl index 88d2126d0b..cc76599be6 100644 --- a/source4/librpc/idl/drsuapi.idl +++ b/source4/librpc/idl/drsuapi.idl @@ -617,36 +617,44 @@ interface drsuapi WERROR drs_error; } drsuapi_DsGetNCChangesCtr6; - typedef struct { + typedef [public] struct { + [subcontext(0xFFFFFC01)] drsuapi_DsGetNCChangesCtr1 ctr1; + } drsuapi_DsGetNCChangesCtr1TS; + + typedef [public] struct { + [subcontext(0xFFFFFC01)] drsuapi_DsGetNCChangesCtr6 ctr6; + } drsuapi_DsGetNCChangesCtr6TS; + + typedef [nopush] struct { uint32 decompressed_length; uint32 compressed_length; [subcontext(4),subcontext_size(compressed_length), compression(NDR_COMPRESSION_MSZIP,compressed_length,decompressed_length)] - drsuapi_DsGetNCChangesCtr1 *ctr1; + drsuapi_DsGetNCChangesCtr1TS *ts; } drsuapi_DsGetNCChangesMSZIPCtr1; - typedef struct { + typedef [nopush] struct { uint32 decompressed_length; uint32 compressed_length; [subcontext(4),subcontext_size(compressed_length), compression(NDR_COMPRESSION_MSZIP,compressed_length,decompressed_length)] - drsuapi_DsGetNCChangesCtr6 *ctr6; + drsuapi_DsGetNCChangesCtr6TS *ts; } drsuapi_DsGetNCChangesMSZIPCtr6; - typedef struct { + typedef [nopush] struct { uint32 decompressed_length; uint32 compressed_length; [subcontext(4),subcontext_size(compressed_length), compression(NDR_COMPRESSION_XPRESS,compressed_length,decompressed_length)] - drsuapi_DsGetNCChangesCtr1 *ctr1; + drsuapi_DsGetNCChangesCtr1TS *ts; } drsuapi_DsGetNCChangesXPRESSCtr1; - typedef struct { + typedef [nopush] struct { uint32 decompressed_length; uint32 compressed_length; [subcontext(4),subcontext_size(compressed_length), compression(NDR_COMPRESSION_XPRESS,compressed_length,decompressed_length)] - drsuapi_DsGetNCChangesCtr6 *ctr6; + drsuapi_DsGetNCChangesCtr6TS *ts; } drsuapi_DsGetNCChangesXPRESSCtr6; typedef [enum16bit] enum { diff --git a/source4/librpc/idl/krb5pac.idl b/source4/librpc/idl/krb5pac.idl index 3505fc895c..ca0efaed3e 100644 --- a/source4/librpc/idl/krb5pac.idl +++ b/source4/librpc/idl/krb5pac.idl @@ -45,10 +45,6 @@ interface krb5pac } PAC_UNKNOWN_12; typedef [public] struct { - [value(0x00081001)] uint32 unknown1; - [value(0xCCCCCCCC)] uint32 unknown2; - [value(NDR_ROUND(ndr_size_PAC_LOGON_INFO(info, ndr->flags)+4,8))] uint32 _ndr_size; - [value(0x00000000)] uint32 unknown3; PAC_LOGON_INFO *info; } PAC_LOGON_INFO_CTR; @@ -66,11 +62,15 @@ interface krb5pac } DATA_BLOB_REM; typedef [public,nodiscriminant,gensize] union { - [case(PAC_TYPE_LOGON_INFO)] PAC_LOGON_INFO_CTR logon_info; + [case(PAC_TYPE_LOGON_INFO)][subcontext(0xFFFFFC01)] PAC_LOGON_INFO_CTR logon_info; [case(PAC_TYPE_SRV_CHECKSUM)] PAC_SIGNATURE_DATA srv_cksum; [case(PAC_TYPE_KDC_CHECKSUM)] PAC_SIGNATURE_DATA kdc_cksum; [case(PAC_TYPE_LOGON_NAME)] PAC_LOGON_NAME logon_name; - [case(PAC_TYPE_UNKNOWN_12)] [subcontext(0)] DATA_BLOB_REM unknown; + /* when new PAC info types are added they are supposed to be done + in such a way that they are backwards compatible with existing + servers. This makes it safe to just use a [default] for + unknown types, which lets us ignore the data */ + [default] [subcontext(0)] DATA_BLOB_REM unknown; /* [case(PAC_TYPE_UNKNOWN_12)] PAC_UNKNOWN_12 unknown; */ } PAC_INFO; diff --git a/source4/librpc/idl/lsa.idl b/source4/librpc/idl/lsa.idl index 93cfdee201..408956b3fa 100644 --- a/source4/librpc/idl/lsa.idl +++ b/source4/librpc/idl/lsa.idl @@ -14,6 +14,7 @@ import "misc.idl", "security.idl"; ] interface lsarpc { typedef bitmap security_secinfo security_secinfo; + typedef bitmap kerb_EncTypes kerb_EncTypes; typedef [public,noejs] struct { [value(2*strlen_m(string))] uint16 length; @@ -507,22 +508,53 @@ import "misc.idl", "security.idl"; } lsa_DATA_BUF2; typedef enum { - LSA_TRUSTED_DOMAIN_INFO_NAME = 1, - LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS_INFO = 2, - LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET = 3, - LSA_TRUSTED_DOMAIN_INFO_PASSWORD = 4, - LSA_TRUSTED_DOMAIN_INFO_BASIC = 5, - LSA_TRUSTED_DOMAIN_INFO_INFO_EX = 6, - LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO = 7, - LSA_TRUSTED_DOMAIN_INFO_FULL_INFO = 8, - LSA_TRUSTED_DOMAIN_INFO_11 = 11, - LSA_TRUSTED_DOMAIN_INFO_INFO_ALL = 12 + LSA_TRUSTED_DOMAIN_INFO_NAME = 1, + LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS = 2, + LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET = 3, + LSA_TRUSTED_DOMAIN_INFO_PASSWORD = 4, + LSA_TRUSTED_DOMAIN_INFO_BASIC = 5, + LSA_TRUSTED_DOMAIN_INFO_INFO_EX = 6, + LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO = 7, + LSA_TRUSTED_DOMAIN_INFO_FULL_INFO = 8, + LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL = 9, + LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL = 10, + LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL = 11, + LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL = 12, + LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRTYPION_TYPES = 13 } lsa_TrustDomInfoEnum; + typedef [public,bitmap32bit] bitmap { + LSA_TRUST_DIRECTION_INBOUND = 0x00000001, + LSA_TRUST_DIRECTION_OUTBOUND = 0x00000002 + } lsa_TrustDirection; + + typedef [v1_enum] enum { + LSA_TRUST_TYPE_DOWNLEVEL = 0x00000001, + LSA_TRUST_TYPE_UPLEVEL = 0x00000002, + LSA_TRUST_TYPE_MIT = 0x00000003 + } lsa_TrustType; + + typedef [public,bitmap32bit] bitmap { + LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE = 0x00000001, + LSA_TRUST_ATTRIBUTE_UPLEVEL_ONLY = 0x00000002, + LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN = 0x00000004, + LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE = 0x00000008, + LSA_TRUST_ATTRIBUTE_CROSS_ORGANIZATION = 0x00000010, + LSA_TRUST_ATTRIBUTE_WITHIN_FOREST = 0x00000020, + LSA_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL = 0x00000040, + LSA_TRUST_ATTRIBUTE_USES_RC4_ENCRYPTION = 0x00000080 + } lsa_TrustAttributes; + typedef struct { lsa_StringLarge netbios_name; } lsa_TrustDomainInfoName; + + typedef struct { + uint32 entries; + [size_is(entries)] lsa_StringLarge *netbios_names; + } lsa_TrustDomainInfoControllers; + typedef struct { uint32 posix_offset; } lsa_TrustDomainInfoPosixOffset; @@ -540,10 +572,10 @@ import "misc.idl", "security.idl"; typedef struct { lsa_StringLarge domain_name; lsa_StringLarge netbios_name; - dom_sid2 *sid; - uint32 trust_direction; - uint32 trust_type; - uint32 trust_attributes; + dom_sid2 *sid; + lsa_TrustDirection trust_direction; + lsa_TrustType trust_type; + lsa_TrustAttributes trust_attributes; } lsa_TrustDomainInfoInfoEx; typedef struct { @@ -570,25 +602,46 @@ import "misc.idl", "security.idl"; typedef struct { lsa_TrustDomainInfoInfoEx info_ex; lsa_DATA_BUF2 data1; - } lsa_TrustDomainInfo11; + } lsa_TrustDomainInfoInfoEx2Internal; typedef struct { lsa_TrustDomainInfoInfoEx info_ex; lsa_DATA_BUF2 data1; lsa_TrustDomainInfoPosixOffset posix_offset; lsa_TrustDomainInfoAuthInfo auth_info; - } lsa_TrustDomainInfoInfoAll; + } lsa_TrustDomainInfoInfo2Internal; + + typedef struct { + kerb_EncTypes enc_types; + } lsa_TrustDomainInfoSupportedEncTypes; typedef [switch_type(lsa_TrustDomInfoEnum)] union { - [case(LSA_TRUSTED_DOMAIN_INFO_NAME)] lsa_TrustDomainInfoName name; - [case(LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET)] lsa_TrustDomainInfoPosixOffset posix_offset; - [case(LSA_TRUSTED_DOMAIN_INFO_PASSWORD)] lsa_TrustDomainInfoPassword password; - [case(LSA_TRUSTED_DOMAIN_INFO_BASIC)] lsa_TrustDomainInfoBasic info_basic; - [case(LSA_TRUSTED_DOMAIN_INFO_INFO_EX)] lsa_TrustDomainInfoInfoEx info_ex; - [case(LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO)] lsa_TrustDomainInfoAuthInfo auth_info; - [case(LSA_TRUSTED_DOMAIN_INFO_FULL_INFO)] lsa_TrustDomainInfoFullInfo full_info; - [case(LSA_TRUSTED_DOMAIN_INFO_11)] lsa_TrustDomainInfo11 info11; - [case(LSA_TRUSTED_DOMAIN_INFO_INFO_ALL)] lsa_TrustDomainInfoInfoAll info_all; + [case(LSA_TRUSTED_DOMAIN_INFO_NAME)] + lsa_TrustDomainInfoName name; + [case(LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS)] + lsa_TrustDomainInfoControllers controllers; + [case(LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET)] + lsa_TrustDomainInfoPosixOffset posix_offset; + [case(LSA_TRUSTED_DOMAIN_INFO_PASSWORD)] + lsa_TrustDomainInfoPassword password; + [case(LSA_TRUSTED_DOMAIN_INFO_BASIC)] + lsa_TrustDomainInfoBasic info_basic; + [case(LSA_TRUSTED_DOMAIN_INFO_INFO_EX)] + lsa_TrustDomainInfoInfoEx info_ex; + [case(LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO)] + lsa_TrustDomainInfoAuthInfo auth_info; + [case(LSA_TRUSTED_DOMAIN_INFO_FULL_INFO)] + lsa_TrustDomainInfoFullInfo full_info; + [case(LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL)] + lsa_TrustDomainInfoAuthInfo auth_info_internal; + [case(LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL)] + lsa_TrustDomainInfoFullInfo full_info_internal; + [case(LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL)] + lsa_TrustDomainInfoInfoEx2Internal info_ex2_internal; + [case(LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL)] + lsa_TrustDomainInfoInfo2Internal info2_internal; + [case(LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRTYPION_TYPES)] + lsa_TrustDomainInfoSupportedEncTypes enc_types; } lsa_TrustedDomainInfo; /* Function: 0x1a */ @@ -658,8 +711,12 @@ import "misc.idl", "security.idl"; [in] uint16 unknown ); - /* Function: 0x22 */ - [todo] NTSTATUS lsa_DeleteObject(); + /*******************/ + /* Function: 0x22 */ + NTSTATUS lsa_DeleteObject ( + [in,out] policy_handle *handle + ); + /*******************/ diff --git a/source4/librpc/idl/nbt.idl b/source4/librpc/idl/nbt.idl index a6d0245455..63be489e0d 100644 --- a/source4/librpc/idl/nbt.idl +++ b/source4/librpc/idl/nbt.idl @@ -353,7 +353,13 @@ interface nbt NBT_SERVER_TIMESERV = 0x00000040, NBT_SERVER_CLOSEST = 0x00000080, NBT_SERVER_WRITABLE = 0x00000100, - NBT_SERVER_GOOD_TIMESERV = 0x00000200 + NBT_SERVER_GOOD_TIMESERV = 0x00000200, + NBT_SERVER_NDNC = 0x00000400, + NBT_SERVER_SEL_SEC_DOM_6 = 0x00000800, + NBT_SERVER_FUL_SEC_DOM_6 = 0x00001000, + NBT_SERVER_DS_DNS_CONTR = 0x04000000, + NBT_SERVER_DS_DNS_DOMAIN = 0x02000000, + NBT_SERVER_DS_DNS_FOREST = 0x01000000 } nbt_server_type; typedef [bitmap32bit,public] bitmap { diff --git a/source4/librpc/idl/security.idl b/source4/librpc/idl/security.idl index f8e9e9e110..80efe46453 100644 --- a/source4/librpc/idl/security.idl +++ b/source4/librpc/idl/security.idl @@ -386,4 +386,12 @@ interface security SECINFO_PROTECTED_SACL = 0x40000000, SECINFO_PROTECTED_DACL = 0x80000000 } security_secinfo; + + typedef [public,bitmap32bit] bitmap { + KERB_ENCTYPE_DES_CBC_CRC = 0x00000001, + KERB_ENCTYPE_DES_CBC_MD5 = 0x00000002, + KERB_ENCTYPE_RC4_HMAC_MD5 = 0x00000004, + KERB_ENCTYPE_AES128_CTS_HMAC_SHA1_96 = 0x00000008, + KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96 = 0x00000010 + } kerb_EncTypes; } diff --git a/source4/librpc/ndr/ndr.c b/source4/librpc/ndr/ndr.c index 40852456bc..c5e4c44794 100644 --- a/source4/librpc/ndr/ndr.c +++ b/source4/librpc/ndr/ndr.c @@ -394,6 +394,8 @@ _PUBLIC_ enum ndr_err_code ndr_pull_subcontext_start(struct ndr_pull *ndr, { struct ndr_pull *subndr; uint32_t r_content_size; + bool force_le = false; + bool force_be = false; switch (header_size) { case 0: { @@ -426,6 +428,74 @@ _PUBLIC_ enum ndr_err_code ndr_pull_subcontext_start(struct ndr_pull *ndr, r_content_size = content_size; break; } + case 0xFFFFFC01: { + /* + * Common Type Header for the Serialization Stream + * See [MS-RPCE] 2.2.6 Type Serialization Version 1 + */ + uint8_t version; + uint8_t drep; + uint16_t hdrlen; + uint32_t filler; + uint32_t content_size; + uint32_t reserved; + + /* version */ + NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &version)); + + if (version != 1) { + return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, + "Bad subcontext (PULL) Common Type Header version %d != 1", + (int)version); + } + + /* + * 0x10 little endian + * 0x00 big endian + */ + NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &drep)); + if (drep == 0x10) { + force_le = true; + } else if (drep == 0x00) { + force_be = true; + } else { + return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, + "Bad subcontext (PULL) Common Type Header invalid drep 0x%02X", + (unsigned int)drep); + } + + /* length of the "Private Header for Constructed Type" */ + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &hdrlen)); + if (hdrlen != 8) { + return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, + "Bad subcontext (PULL) Common Type Header length %d != 8", + (int)hdrlen); + } + + /* filler should be ignored */ + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &filler)); + + /* + * Private Header for Constructed Type + */ + /* length - will be updated latter */ + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &content_size)); + if (size_is >= 0 && size_is != content_size) { + return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d", + (int)size_is, (int)content_size); + } + /* the content size must be a multiple of 8 */ + if ((content_size % 8) != 0) { + return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, + "Bad subcontext (PULL) size_is(%d) not padded to 8 content_size %d", + (int)size_is, (int)content_size); + } + r_content_size = content_size; + + /* reserved */ + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &reserved)); + break; + } default: return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) header_size %d", (int)header_size); @@ -443,6 +513,12 @@ _PUBLIC_ enum ndr_err_code ndr_pull_subcontext_start(struct ndr_pull *ndr, subndr->data_size = r_content_size; subndr->iconv_convenience = talloc_reference(subndr, ndr->iconv_convenience); + if (force_le) { + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_LITTLE_ENDIAN); + } else if (force_be) { + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_BIGENDIAN); + } + *_subndr = subndr; return NDR_ERR_SUCCESS; } @@ -487,8 +563,10 @@ _PUBLIC_ enum ndr_err_code ndr_push_subcontext_end(struct ndr_push *ndr, size_t header_size, ssize_t size_is) { + ssize_t padding_len; + if (size_is >= 0) { - ssize_t padding_len = size_is - subndr->offset; + padding_len = size_is - subndr->offset; if (padding_len > 0) { NDR_CHECK(ndr_push_zero(subndr, padding_len)); } else if (padding_len < 0) { @@ -509,6 +587,41 @@ _PUBLIC_ enum ndr_err_code ndr_push_subcontext_end(struct ndr_push *ndr, NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, subndr->offset)); break; + case 0xFFFFFC01: + /* + * Common Type Header for the Serialization Stream + * See [MS-RPCE] 2.2.6 Type Serialization Version 1 + */ + padding_len = NDR_ROUND(subndr->offset, 8) - subndr->offset; + if (padding_len > 0) { + NDR_CHECK(ndr_push_zero(subndr, padding_len)); + } + + /* version */ + NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, 1)); + + /* + * 0x10 little endian + * 0x00 big endian + */ + NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, NDR_BE(ndr)?0x00:0x10)); + + /* length of the "Private Header for Constructed Type" */ + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, 8)); + + /* filler */ + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0xCCCCCCCC)); + + /* + * Private Header for Constructed Type + */ + /* length - will be updated latter */ + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, subndr->offset)); + + /* reserved */ + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0)); + break; + default: return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext header size %d", (int)header_size); diff --git a/source4/librpc/ndr/ndr_compression.c b/source4/librpc/ndr/ndr_compression.c index 86a5a2560e..37f95bb1b6 100644 --- a/source4/librpc/ndr/ndr_compression.c +++ b/source4/librpc/ndr/ndr_compression.c @@ -4,6 +4,7 @@ libndr compression support Copyright (C) Stefan Metzmacher 2005 + Copyright (C) Matthieu Suiche 2008 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 @@ -20,13 +21,24 @@ */ #include "includes.h" -#include "lib/compression/mszip.h" +#include "lib/compression/lzxpress.h" #include "librpc/ndr/libndr.h" #include "librpc/ndr/ndr_compression.h" +#include <zlib.h> + +static voidpf ndr_zlib_alloc(voidpf opaque, uInt items, uInt size) +{ + return talloc_zero_size(opaque, items * size); +} + +static void ndr_zlib_free(voidpf opaque, voidpf address) +{ + talloc_free(address); +} static enum ndr_err_code ndr_pull_compression_mszip_chunk(struct ndr_pull *ndrpull, struct ndr_push *ndrpush, - struct decomp_state *decomp_state, + z_stream *z, bool *last) { DATA_BLOB comp_chunk; @@ -35,7 +47,7 @@ static enum ndr_err_code ndr_pull_compression_mszip_chunk(struct ndr_pull *ndrpu DATA_BLOB plain_chunk; uint32_t plain_chunk_offset; uint32_t plain_chunk_size; - int ret; + int z_ret; NDR_CHECK(ndr_pull_uint32(ndrpull, NDR_SCALARS, &plain_chunk_size)); if (plain_chunk_size > 0x00008000) { @@ -58,10 +70,71 @@ static enum ndr_err_code ndr_pull_compression_mszip_chunk(struct ndr_pull *ndrpu plain_chunk.length = plain_chunk_size; plain_chunk.data = ndrpush->data + plain_chunk_offset; - ret = ZIPdecompress(decomp_state, &comp_chunk, &plain_chunk); - if (ret != DECR_OK) { - return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, "Bad ZIPdecompress() error %d (PULL)", - ret); + if (comp_chunk.length < 2) { + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, + "Bad MSZIP comp chunk size %u < 2 (PULL)", + (unsigned int)comp_chunk.length); + } + /* CK = Chris Kirmse, official Microsoft purloiner */ + if (comp_chunk.data[0] != 'C' || + comp_chunk.data[1] != 'K') { + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, + "Bad MSZIP invalid prefix [%c%c] != [CK]", + comp_chunk.data[0], comp_chunk.data[1]); + } + + z->next_in = comp_chunk.data + 2; + z->avail_in = comp_chunk.length -2; + z->total_in = 0; + + z->next_out = plain_chunk.data; + z->avail_out = plain_chunk.length; + z->total_out = 0; + + if (!z->opaque) { + /* the first time we need to intialize completely */ + z->zalloc = ndr_zlib_alloc; + z->zfree = ndr_zlib_free; + z->opaque = ndrpull; + + z_ret = inflateInit2(z, -15); + if (z_ret != Z_OK) { + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, + "Bad inflateInit2 error %s(%d) (PULL)", + zError(z_ret), z_ret); + + } + } else { + z_ret = inflateReset2(z, Z_RESET_KEEP_WINDOW); + if (z_ret != Z_OK) { + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, + "Bad inflateReset2 error %s(%d) (PULL)", + zError(z_ret), z_ret); + } + } + + /* call inflate untill we get Z_STREAM_END or an error */ + while (true) { + z_ret = inflate(z, Z_BLOCK); + if (z_ret != Z_OK) break; + } + + if (z_ret != Z_STREAM_END) { + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, + "Bad inflate(Z_BLOCK) error %s(%d) (PULL)", + zError(z_ret), z_ret); + } + + if (z->avail_in) { + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, + "MSZIP not all avail_in[%u] bytes consumed (PULL)", + z->avail_in); + } + + if (z->avail_out) { + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, + "MSZIP not all avail_out[%u] bytes consumed (PULL)", + z->avail_out); } if ((plain_chunk_size < 0x00008000) || (ndrpull->offset+4 >= ndrpull->data_size)) { @@ -72,98 +145,122 @@ static enum ndr_err_code ndr_pull_compression_mszip_chunk(struct ndr_pull *ndrpu return NDR_ERR_SUCCESS; } -static enum ndr_err_code ndr_pull_compression_mszip(struct ndr_pull *subndr, - struct ndr_pull **_comndr, - ssize_t decompressed_len) +static enum ndr_err_code ndr_push_compression_mszip_chunk(struct ndr_push *ndrpush, + struct ndr_pull *ndrpull, + z_stream *z, + bool *last) { - struct ndr_push *ndrpush; - struct ndr_pull *comndr; - DATA_BLOB uncompressed; - uint32_t payload_header[4]; - uint32_t payload_size; - uint32_t payload_offset; - uint8_t *payload; - struct decomp_state *decomp_state; - bool last = false; + DATA_BLOB comp_chunk; + uint32_t comp_chunk_size; + uint32_t comp_chunk_size_offset; + DATA_BLOB plain_chunk; + uint32_t plain_chunk_size; + uint32_t plain_chunk_offset; + uint32_t max_plain_size = 0x00008000; + uint32_t max_comp_size = 0x00008000 + 2 + 12 /*TODO: what value do we really need here?*/; + uint32_t tmp_offset; + int z_ret; - ndrpush = ndr_push_init_ctx(subndr, subndr->iconv_convenience); - NDR_ERR_HAVE_NO_MEMORY(ndrpush); + plain_chunk_size = MIN(max_plain_size, ndrpull->data_size - ndrpull->offset); + plain_chunk_offset = ndrpull->offset; + NDR_CHECK(ndr_pull_advance(ndrpull, plain_chunk_size)); - decomp_state = ZIPdecomp_state(subndr); - NDR_ERR_HAVE_NO_MEMORY(decomp_state); + plain_chunk.data = ndrpull->data + plain_chunk_offset; + plain_chunk.length = plain_chunk_size; - while (!last) { - NDR_CHECK(ndr_pull_compression_mszip_chunk(subndr, ndrpush, decomp_state, &last)); + if (plain_chunk_size < max_plain_size) { + *last = true; } - uncompressed = ndr_push_blob(ndrpush); - - if (uncompressed.length != decompressed_len) { - return ndr_pull_error(subndr, NDR_ERR_COMPRESSION, "Bad MSZIP uncompressed_len [%u] != [%d] (PULL)", - (int)uncompressed.length, (int)decompressed_len); + NDR_CHECK(ndr_push_uint32(ndrpush, NDR_SCALARS, plain_chunk_size)); + comp_chunk_size_offset = ndrpush->offset; + NDR_CHECK(ndr_push_uint32(ndrpush, NDR_SCALARS, 0xFEFEFEFE)); + + NDR_CHECK(ndr_push_expand(ndrpush, max_comp_size)); + + comp_chunk.data = ndrpush->data + ndrpush->offset; + comp_chunk.length = max_comp_size; + + /* CK = Chris Kirmse, official Microsoft purloiner */ + comp_chunk.data[0] = 'C'; + comp_chunk.data[1] = 'K'; + + z->next_in = plain_chunk.data; + z->avail_in = plain_chunk.length; + z->total_in = 0; + + z->next_out = comp_chunk.data + 2; + z->avail_out = comp_chunk.length - 2; + z->total_out = 0; + + if (!z->opaque) { + /* the first time we need to intialize completely */ + z->zalloc = ndr_zlib_alloc; + z->zfree = ndr_zlib_free; + z->opaque = ndrpull; + + /* TODO: find how to trigger the same parameters windows uses */ + z_ret = deflateInit2(z, + Z_DEFAULT_COMPRESSION, + Z_DEFLATED, + -15, + 9, + Z_DEFAULT_STRATEGY); + if (z_ret != Z_OK) { + return ndr_push_error(ndrpush, NDR_ERR_COMPRESSION, + "Bad deflateInit2 error %s(%d) (PUSH)", + zError(z_ret), z_ret); + + } + } else { + /* TODO: keep the window */ + z_ret = deflateReset(z); + if (z_ret != Z_OK) { + return ndr_push_error(ndrpush, NDR_ERR_COMPRESSION, + "Bad delateReset2 error %s(%d) (PUSH)", + zError(z_ret), z_ret); + } } - comndr = talloc_zero(subndr, struct ndr_pull); - NDR_ERR_HAVE_NO_MEMORY(comndr); - comndr->flags = subndr->flags; - comndr->current_mem_ctx = subndr->current_mem_ctx; - - comndr->data = uncompressed.data; - comndr->data_size = uncompressed.length; - comndr->offset = 0; - - comndr->iconv_convenience = talloc_reference(comndr, subndr->iconv_convenience); - - NDR_CHECK(ndr_pull_uint32(comndr, NDR_SCALARS, &payload_header[0])); - NDR_CHECK(ndr_pull_uint32(comndr, NDR_SCALARS, &payload_header[1])); - NDR_CHECK(ndr_pull_uint32(comndr, NDR_SCALARS, &payload_header[2])); - NDR_CHECK(ndr_pull_uint32(comndr, NDR_SCALARS, &payload_header[3])); - - if (payload_header[0] != 0x00081001) { - return ndr_pull_error(subndr, NDR_ERR_COMPRESSION, "Bad MSZIP payload_header[0] [0x%08X] != [0x00081001] (PULL)", - payload_header[0]); + /* call deflate untill we get Z_STREAM_END or an error */ + while (true) { + z_ret = deflate(z, Z_FINISH); + if (z_ret != Z_OK) break; } - if (payload_header[1] != 0xCCCCCCCC) { - return ndr_pull_error(subndr, NDR_ERR_COMPRESSION, "Bad MSZIP payload_header[1] [0x%08X] != [0xCCCCCCCC] (PULL)", - payload_header[1]); + if (z_ret != Z_STREAM_END) { + return ndr_push_error(ndrpush, NDR_ERR_COMPRESSION, + "Bad delate(Z_BLOCK) error %s(%d) (PUSH)", + zError(z_ret), z_ret); } - payload_size = payload_header[2]; - - if (payload_header[3] != 0x00000000) { - return ndr_pull_error(subndr, NDR_ERR_COMPRESSION, "Bad MSZIP payload_header[3] [0x%08X] != [0x00000000] (PULL)", - payload_header[3]); + if (z->avail_in) { + return ndr_push_error(ndrpush, NDR_ERR_COMPRESSION, + "MSZIP not all avail_in[%u] bytes consumed (PUSH)", + z->avail_in); } - payload_offset = comndr->offset; - NDR_CHECK(ndr_pull_advance(comndr, payload_size)); - payload = comndr->data + payload_offset; + comp_chunk_size = 2 + z->total_out; - comndr->data = payload; - comndr->data_size = payload_size; - comndr->offset = 0; + tmp_offset = ndrpush->offset; + ndrpush->offset = comp_chunk_size_offset; + NDR_CHECK(ndr_push_uint32(ndrpush, NDR_SCALARS, comp_chunk_size)); + ndrpush->offset = tmp_offset; - *_comndr = comndr; + ndrpush->offset += comp_chunk_size; return NDR_ERR_SUCCESS; } -static enum ndr_err_code ndr_push_compression_mszip(struct ndr_push *subndr, - struct ndr_push *comndr) -{ - return ndr_push_error(subndr, NDR_ERR_COMPRESSION, "Sorry MSZIP compression is not supported yet (PUSH)"); -} - static enum ndr_err_code ndr_pull_compression_xpress_chunk(struct ndr_pull *ndrpull, struct ndr_push *ndrpush, bool *last) { DATA_BLOB comp_chunk; + DATA_BLOB plain_chunk; uint32_t comp_chunk_offset; + uint32_t plain_chunk_offset; uint32_t comp_chunk_size; uint32_t plain_chunk_size; - comp_chunk_offset = ndrpull->offset; - NDR_CHECK(ndr_pull_uint32(ndrpull, NDR_SCALARS, &plain_chunk_size)); if (plain_chunk_size > 0x00010000) { return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, "Bad XPRESS plain chunk size %08X > 0x00010000 (PULL)", @@ -172,15 +269,21 @@ static enum ndr_err_code ndr_pull_compression_xpress_chunk(struct ndr_pull *ndrp NDR_CHECK(ndr_pull_uint32(ndrpull, NDR_SCALARS, &comp_chunk_size)); + comp_chunk_offset = ndrpull->offset; NDR_CHECK(ndr_pull_advance(ndrpull, comp_chunk_size)); - comp_chunk.length = comp_chunk_size + 8; + comp_chunk.length = comp_chunk_size; comp_chunk.data = ndrpull->data + comp_chunk_offset; + plain_chunk_offset = ndrpush->offset; + NDR_CHECK(ndr_push_zero(ndrpush, plain_chunk_size)); + plain_chunk.length = plain_chunk_size; + plain_chunk.data = ndrpush->data + plain_chunk_offset; + DEBUG(10,("XPRESS plain_chunk_size: %08X (%u) comp_chunk_size: %08X (%u)\n", plain_chunk_size, plain_chunk_size, comp_chunk_size, comp_chunk_size)); - /* For now, we just copy over the compressed blob */ - NDR_CHECK(ndr_push_bytes(ndrpush, comp_chunk.data, comp_chunk.length)); + /* Uncompressing the buffer using LZ Xpress algorithm */ + lzxpress_decompress(&comp_chunk, &plain_chunk); if ((plain_chunk_size < 0x00010000) || (ndrpull->offset+4 >= ndrpull->data_size)) { /* this is the last chunk */ @@ -190,23 +293,58 @@ static enum ndr_err_code ndr_pull_compression_xpress_chunk(struct ndr_pull *ndrp return NDR_ERR_SUCCESS; } -static enum ndr_err_code ndr_pull_compression_xpress(struct ndr_pull *subndr, - struct ndr_pull **_comndr, - ssize_t decompressed_len) +static enum ndr_err_code ndr_push_compression_xpress_chunk(struct ndr_push *ndrpush, + struct ndr_pull *ndrpull, + bool *last) +{ + return ndr_push_error(ndrpush, NDR_ERR_COMPRESSION, "XPRESS compression is not supported yet (PUSH)"); +} + +/* + handle compressed subcontext buffers, which in midl land are user-marshalled, but + we use magic in pidl to make them easier to cope with +*/ +enum ndr_err_code ndr_pull_compression_start(struct ndr_pull *subndr, + struct ndr_pull **_comndr, + enum ndr_compression_alg compression_alg, + ssize_t decompressed_len) { struct ndr_push *ndrpush; struct ndr_pull *comndr; DATA_BLOB uncompressed; bool last = false; + z_stream z; ndrpush = ndr_push_init_ctx(subndr, subndr->iconv_convenience); NDR_ERR_HAVE_NO_MEMORY(ndrpush); - while (!last) { - NDR_CHECK(ndr_pull_compression_xpress_chunk(subndr, ndrpush, &last)); + switch (compression_alg) { + case NDR_COMPRESSION_MSZIP: + ZERO_STRUCT(z); + while (!last) { + NDR_CHECK(ndr_pull_compression_mszip_chunk(subndr, ndrpush, &z, &last)); + } + break; + + case NDR_COMPRESSION_XPRESS: + while (!last) { + NDR_CHECK(ndr_pull_compression_xpress_chunk(subndr, ndrpush, &last)); + } + break; + + default: + return ndr_pull_error(subndr, NDR_ERR_COMPRESSION, "Bad compression algorithm %d (PULL)", + compression_alg); } uncompressed = ndr_push_blob(ndrpush); + if (uncompressed.length != decompressed_len) { + return ndr_pull_error(subndr, NDR_ERR_COMPRESSION, + "Bad uncompressed_len [%u] != [%u](0x%08X) (PULL)", + (int)uncompressed.length, + (int)decompressed_len, + (int)decompressed_len); + } comndr = talloc_zero(subndr, struct ndr_pull); NDR_ERR_HAVE_NO_MEMORY(comndr); @@ -223,33 +361,6 @@ static enum ndr_err_code ndr_pull_compression_xpress(struct ndr_pull *subndr, return NDR_ERR_SUCCESS; } -static enum ndr_err_code ndr_push_compression_xpress(struct ndr_push *subndr, - struct ndr_push *comndr) -{ - return ndr_push_error(subndr, NDR_ERR_COMPRESSION, "XPRESS compression is not supported yet (PUSH)"); -} - -/* - handle compressed subcontext buffers, which in midl land are user-marshalled, but - we use magic in pidl to make them easier to cope with -*/ -enum ndr_err_code ndr_pull_compression_start(struct ndr_pull *subndr, - struct ndr_pull **_comndr, - enum ndr_compression_alg compression_alg, - ssize_t decompressed_len) -{ - switch (compression_alg) { - case NDR_COMPRESSION_MSZIP: - return ndr_pull_compression_mszip(subndr, _comndr, decompressed_len); - case NDR_COMPRESSION_XPRESS: - return ndr_pull_compression_xpress(subndr, _comndr, decompressed_len); - default: - return ndr_pull_error(subndr, NDR_ERR_COMPRESSION, "Bad compression algorithm %d (PULL)", - compression_alg); - } - return NDR_ERR_SUCCESS; -} - enum ndr_err_code ndr_pull_compression_end(struct ndr_pull *subndr, struct ndr_pull *comndr, enum ndr_compression_alg compression_alg, @@ -262,17 +373,27 @@ enum ndr_err_code ndr_pull_compression_end(struct ndr_pull *subndr, push a compressed subcontext */ enum ndr_err_code ndr_push_compression_start(struct ndr_push *subndr, - struct ndr_push **_comndr, + struct ndr_push **_uncomndr, enum ndr_compression_alg compression_alg, ssize_t decompressed_len) { - struct ndr_push *comndr; + struct ndr_push *uncomndr; - comndr = ndr_push_init_ctx(subndr, subndr->iconv_convenience); - NDR_ERR_HAVE_NO_MEMORY(comndr); - comndr->flags = subndr->flags; + switch (compression_alg) { + case NDR_COMPRESSION_MSZIP: + case NDR_COMPRESSION_XPRESS: + break; + default: + return ndr_push_error(subndr, NDR_ERR_COMPRESSION, + "Bad compression algorithm %d (PUSH)", + compression_alg); + } - *_comndr = comndr; + uncomndr = ndr_push_init_ctx(subndr, subndr->iconv_convenience); + NDR_ERR_HAVE_NO_MEMORY(uncomndr); + uncomndr->flags = subndr->flags; + + *_uncomndr = uncomndr; return NDR_ERR_SUCCESS; } @@ -280,18 +401,42 @@ enum ndr_err_code ndr_push_compression_start(struct ndr_push *subndr, push a compressed subcontext */ enum ndr_err_code ndr_push_compression_end(struct ndr_push *subndr, - struct ndr_push *comndr, + struct ndr_push *uncomndr, enum ndr_compression_alg compression_alg, ssize_t decompressed_len) { + struct ndr_pull *ndrpull; + bool last = false; + z_stream z; + + ndrpull = talloc_zero(uncomndr, struct ndr_pull); + NDR_ERR_HAVE_NO_MEMORY(ndrpull); + ndrpull->flags = uncomndr->flags; + ndrpull->data = uncomndr->data; + ndrpull->data_size = uncomndr->offset; + ndrpull->offset = 0; + + ndrpull->iconv_convenience = talloc_reference(ndrpull, subndr->iconv_convenience); + switch (compression_alg) { case NDR_COMPRESSION_MSZIP: - return ndr_push_compression_mszip(subndr, comndr); + ZERO_STRUCT(z); + while (!last) { + NDR_CHECK(ndr_push_compression_mszip_chunk(subndr, ndrpull, &z, &last)); + } + break; + case NDR_COMPRESSION_XPRESS: - return ndr_push_compression_xpress(subndr, comndr); + while (!last) { + NDR_CHECK(ndr_push_compression_xpress_chunk(subndr, ndrpull, &last)); + } + break; + default: return ndr_push_error(subndr, NDR_ERR_COMPRESSION, "Bad compression algorithm %d (PUSH)", compression_alg); } + + talloc_free(uncomndr); return NDR_ERR_SUCCESS; } diff --git a/source4/librpc/ndr/ndr_drsuapi.c b/source4/librpc/ndr/ndr_drsuapi.c index 1b6be9ed8e..e77ab54071 100644 --- a/source4/librpc/ndr/ndr_drsuapi.c +++ b/source4/librpc/ndr/ndr_drsuapi.c @@ -24,6 +24,7 @@ #include "librpc/gen_ndr/ndr_drsuapi.h" #include "librpc/gen_ndr/ndr_misc.h" #include "lib/util/asn1.h" +#include "librpc/ndr/ndr_compression.h" void ndr_print_drsuapi_DsReplicaObjectListItem(struct ndr_print *ndr, const char *name, const struct drsuapi_DsReplicaObjectListItem *r) @@ -176,3 +177,175 @@ size_t ndr_size_drsuapi_DsReplicaOID_oid(const char *oid, int flags) data_blob_free(&_blob); return ret; } + +enum ndr_err_code ndr_push_drsuapi_DsGetNCChangesMSZIPCtr1(struct ndr_push *ndr, int ndr_flags, const struct drsuapi_DsGetNCChangesMSZIPCtr1 *r) +{ + if (ndr_flags & NDR_SCALARS) { + uint32_t decompressed_length = 0; + uint32_t compressed_length = 0; + if (r->ts) { + { + struct ndr_push *_ndr_ts; + NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_ts, 4, -1)); + { + struct ndr_push *_ndr_ts_compressed; + NDR_CHECK(ndr_push_compression_start(_ndr_ts, &_ndr_ts_compressed, NDR_COMPRESSION_MSZIP, -1)); + NDR_CHECK(ndr_push_drsuapi_DsGetNCChangesCtr1TS(_ndr_ts_compressed, NDR_SCALARS|NDR_BUFFERS, r->ts)); + decompressed_length = _ndr_ts_compressed->offset; + NDR_CHECK(ndr_push_compression_end(_ndr_ts, _ndr_ts_compressed, NDR_COMPRESSION_MSZIP, -1)); + } + compressed_length = _ndr_ts->offset; + talloc_free(_ndr_ts); + } + } + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, decompressed_length)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, compressed_length)); + NDR_CHECK(ndr_push_unique_ptr(ndr, r->ts)); + } + if (ndr_flags & NDR_BUFFERS) { + if (r->ts) { + { + struct ndr_push *_ndr_ts; + NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_ts, 4, -1)); + { + struct ndr_push *_ndr_ts_compressed; + NDR_CHECK(ndr_push_compression_start(_ndr_ts, &_ndr_ts_compressed, NDR_COMPRESSION_MSZIP, -1)); + NDR_CHECK(ndr_push_drsuapi_DsGetNCChangesCtr1TS(_ndr_ts_compressed, NDR_SCALARS|NDR_BUFFERS, r->ts)); + NDR_CHECK(ndr_push_compression_end(_ndr_ts, _ndr_ts_compressed, NDR_COMPRESSION_MSZIP, -1)); + } + NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_ts, 4, -1)); + } + } + } + return NDR_ERR_SUCCESS; +} + +enum ndr_err_code ndr_push_drsuapi_DsGetNCChangesMSZIPCtr6(struct ndr_push *ndr, int ndr_flags, const struct drsuapi_DsGetNCChangesMSZIPCtr6 *r) +{ + if (ndr_flags & NDR_SCALARS) { + uint32_t decompressed_length = 0; + uint32_t compressed_length = 0; + if (r->ts) { + { + struct ndr_push *_ndr_ts; + NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_ts, 4, -1)); + { + struct ndr_push *_ndr_ts_compressed; + NDR_CHECK(ndr_push_compression_start(_ndr_ts, &_ndr_ts_compressed, NDR_COMPRESSION_MSZIP, -1)); + NDR_CHECK(ndr_push_drsuapi_DsGetNCChangesCtr6TS(_ndr_ts_compressed, NDR_SCALARS|NDR_BUFFERS, r->ts)); + decompressed_length = _ndr_ts_compressed->offset; + NDR_CHECK(ndr_push_compression_end(_ndr_ts, _ndr_ts_compressed, NDR_COMPRESSION_MSZIP, -1)); + } + compressed_length = _ndr_ts->offset; + talloc_free(_ndr_ts); + } + } + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, decompressed_length)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, compressed_length)); + NDR_CHECK(ndr_push_unique_ptr(ndr, r->ts)); + } + if (ndr_flags & NDR_BUFFERS) { + if (r->ts) { + { + struct ndr_push *_ndr_ts; + NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_ts, 4, -1)); + { + struct ndr_push *_ndr_ts_compressed; + NDR_CHECK(ndr_push_compression_start(_ndr_ts, &_ndr_ts_compressed, NDR_COMPRESSION_MSZIP, -1)); + NDR_CHECK(ndr_push_drsuapi_DsGetNCChangesCtr6TS(_ndr_ts_compressed, NDR_SCALARS|NDR_BUFFERS, r->ts)); + NDR_CHECK(ndr_push_compression_end(_ndr_ts, _ndr_ts_compressed, NDR_COMPRESSION_MSZIP, -1)); + } + NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_ts, 4, -1)); + } + } + } + return NDR_ERR_SUCCESS; +} + +enum ndr_err_code ndr_push_drsuapi_DsGetNCChangesXPRESSCtr1(struct ndr_push *ndr, int ndr_flags, const struct drsuapi_DsGetNCChangesXPRESSCtr1 *r) +{ + if (ndr_flags & NDR_SCALARS) { + uint32_t decompressed_length = 0; + uint32_t compressed_length = 0; + if (r->ts) { + { + struct ndr_push *_ndr_ts; + NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_ts, 4, -1)); + { + struct ndr_push *_ndr_ts_compressed; + NDR_CHECK(ndr_push_compression_start(_ndr_ts, &_ndr_ts_compressed, NDR_COMPRESSION_XPRESS, -1)); + NDR_CHECK(ndr_push_drsuapi_DsGetNCChangesCtr1TS(_ndr_ts_compressed, NDR_SCALARS|NDR_BUFFERS, r->ts)); + decompressed_length = _ndr_ts_compressed->offset; + NDR_CHECK(ndr_push_compression_end(_ndr_ts, _ndr_ts_compressed, NDR_COMPRESSION_XPRESS, -1)); + } + compressed_length = _ndr_ts->offset; + talloc_free(_ndr_ts); + } + } + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, decompressed_length)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, compressed_length)); + NDR_CHECK(ndr_push_unique_ptr(ndr, r->ts)); + } + if (ndr_flags & NDR_BUFFERS) { + if (r->ts) { + { + struct ndr_push *_ndr_ts; + NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_ts, 4, -1)); + { + struct ndr_push *_ndr_ts_compressed; + NDR_CHECK(ndr_push_compression_start(_ndr_ts, &_ndr_ts_compressed, NDR_COMPRESSION_XPRESS, -1)); + NDR_CHECK(ndr_push_drsuapi_DsGetNCChangesCtr1TS(_ndr_ts_compressed, NDR_SCALARS|NDR_BUFFERS, r->ts)); + NDR_CHECK(ndr_push_compression_end(_ndr_ts, _ndr_ts_compressed, NDR_COMPRESSION_XPRESS, -1)); + } + NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_ts, 4, -1)); + } + } + } + return NDR_ERR_SUCCESS; +} + +enum ndr_err_code ndr_push_drsuapi_DsGetNCChangesXPRESSCtr6(struct ndr_push *ndr, int ndr_flags, const struct drsuapi_DsGetNCChangesXPRESSCtr6 *r) +{ + if (ndr_flags & NDR_SCALARS) { + uint32_t decompressed_length = 0; + uint32_t compressed_length = 0; + if (r->ts) { + { + struct ndr_push *_ndr_ts; + NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_ts, 4, -1)); + { + struct ndr_push *_ndr_ts_compressed; + NDR_CHECK(ndr_push_compression_start(_ndr_ts, &_ndr_ts_compressed, NDR_COMPRESSION_XPRESS, -1)); + NDR_CHECK(ndr_push_drsuapi_DsGetNCChangesCtr6TS(_ndr_ts_compressed, NDR_SCALARS|NDR_BUFFERS, r->ts)); + decompressed_length = _ndr_ts_compressed->offset; + NDR_CHECK(ndr_push_compression_end(_ndr_ts, _ndr_ts_compressed, NDR_COMPRESSION_XPRESS, -1)); + } + compressed_length = _ndr_ts->offset; + talloc_free(_ndr_ts); + } + } + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, decompressed_length)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, compressed_length)); + NDR_CHECK(ndr_push_unique_ptr(ndr, r->ts)); + } + if (ndr_flags & NDR_BUFFERS) { + if (r->ts) { + { + struct ndr_push *_ndr_ts; + NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_ts, 4, -1)); + { + struct ndr_push *_ndr_ts_compressed; + NDR_CHECK(ndr_push_compression_start(_ndr_ts, &_ndr_ts_compressed, NDR_COMPRESSION_XPRESS, -1)); + NDR_CHECK(ndr_push_drsuapi_DsGetNCChangesCtr6TS(_ndr_ts_compressed, NDR_SCALARS|NDR_BUFFERS, r->ts)); + NDR_CHECK(ndr_push_compression_end(_ndr_ts, _ndr_ts_compressed, NDR_COMPRESSION_XPRESS, -1)); + } + NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_ts, 4, -1)); + } + } + } + return NDR_ERR_SUCCESS; +} diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c index a6c7e0020d..28b5cd65a9 100644 --- a/source4/librpc/rpc/dcerpc.c +++ b/source4/librpc/rpc/dcerpc.c @@ -334,6 +334,7 @@ static NTSTATUS ncacn_pull_request_auth(struct dcerpc_connection *c, TALLOC_CTX */ static NTSTATUS ncacn_push_request_sign(struct dcerpc_connection *c, DATA_BLOB *blob, TALLOC_CTX *mem_ctx, + size_t sig_size, struct ncacn_packet *pkt) { NTSTATUS status; @@ -384,8 +385,7 @@ static NTSTATUS ncacn_push_request_sign(struct dcerpc_connection *c, * GENSEC mech does AEAD signing of the packet * headers */ c->security_state.auth_info->credentials - = data_blob_talloc(mem_ctx, NULL, gensec_sig_size(c->security_state.generic_state, - payload_length)); + = data_blob_talloc(mem_ctx, NULL, sig_size); data_blob_clear(&c->security_state.auth_info->credentials); break; @@ -1042,6 +1042,7 @@ static void dcerpc_ship_next_request(struct dcerpc_connection *c) DATA_BLOB blob; uint32_t remaining, chunk_size; bool first_packet = true; + size_t sig_size = 0; req = c->request_queue; if (req == NULL) { @@ -1065,7 +1066,15 @@ static void dcerpc_ship_next_request(struct dcerpc_connection *c) /* we can write a full max_recv_frag size, minus the dcerpc request header size */ - chunk_size = p->conn->srv_max_recv_frag - (DCERPC_MAX_SIGN_SIZE+DCERPC_REQUEST_LENGTH); + chunk_size = p->conn->srv_max_recv_frag; + chunk_size -= DCERPC_REQUEST_LENGTH; + if (c->security_state.generic_state) { + chunk_size -= DCERPC_AUTH_TRAILER_LENGTH; + sig_size = gensec_sig_size(c->security_state.generic_state, + p->conn->srv_max_recv_frag); + chunk_size -= sig_size; + chunk_size -= (chunk_size % 16); + } pkt.ptype = DCERPC_PKT_REQUEST; pkt.call_id = req->call_id; @@ -1101,7 +1110,7 @@ static void dcerpc_ship_next_request(struct dcerpc_connection *c) (stub_data->length - remaining); pkt.u.request.stub_and_verifier.length = chunk; - req->status = ncacn_push_request_sign(p->conn, &blob, req, &pkt); + req->status = ncacn_push_request_sign(p->conn, &blob, req, sig_size, &pkt); if (!NT_STATUS_IS_OK(req->status)) { req->state = RPC_REQUEST_DONE; DLIST_REMOVE(p->conn->pending, req); |