From e5d1f3fc0ff8876b6bda8016bc45f76024f92a4b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 21 Oct 2015 12:01:26 +0200 Subject: [PATCH] dcerpc.idl: accept invalid dcerpc_bind_nak pdus Older Samba versions (<= 4.1) had a bug in the dcerpc_bind_nak idl, see commit f73ef3028c4f4583c81b611a9714608eae79360c. Note: ndr_pull_dcerpc_bind_nak() was generated by pidl and has been extended by the (_available == 0) check. That's why we ignore the 80 char per line limit. BUG: https://bugzilla.samba.org/show_bug.cgi?id=11327 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Wed Oct 21 20:34:28 CEST 2015 on sn-devel-104 (cherry picked from commit 38d547bc0d39b56a7491a5f220905f1756c1530a) --- librpc/idl/dcerpc.idl | 6 +++--- librpc/ndr/ndr_dcerpc.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/librpc/idl/dcerpc.idl b/librpc/idl/dcerpc.idl index 67f4b9d..cb7f5b8 100644 --- a/librpc/idl/dcerpc.idl +++ b/librpc/idl/dcerpc.idl @@ -114,7 +114,7 @@ interface dcerpc [flag(NDR_REMAINING)] DATA_BLOB auth_info; } dcerpc_bind_ack; - typedef [enum16bit] enum { + typedef [public,enum16bit] enum { DCERPC_BIND_NAK_REASON_NOT_SPECIFIED = 0, DCERPC_BIND_NAK_REASON_TEMPORARY_CONGESTION = 1, DCERPC_BIND_NAK_REASON_LOCAL_LIMIT_EXCEEDED = 2, @@ -128,12 +128,12 @@ interface dcerpc const int DCERPC_BIND_REASON_INVALID_AUTH_TYPE = DCERPC_BIND_NAK_REASON_INVALID_AUTH_TYPE; - typedef struct { + typedef [public] struct { uint8 rpc_vers; /* RPC version */ uint8 rpc_vers_minor; /* Minor version */ } dcerpc_bind_nak_version; - typedef struct { + typedef [public,nopull] struct { dcerpc_bind_nak_reason reject_reason; uint8 num_versions; dcerpc_bind_nak_version versions[num_versions]; diff --git a/librpc/ndr/ndr_dcerpc.c b/librpc/ndr/ndr_dcerpc.c index ca09fb6..0224b2c 100644 --- a/librpc/ndr/ndr_dcerpc.c +++ b/librpc/ndr/ndr_dcerpc.c @@ -24,6 +24,55 @@ #include "librpc/gen_ndr/ndr_dcerpc.h" #include "librpc/gen_ndr/ndr_misc.h" +/* + * This function was generated by pidl and + * has been extended by the (_available == 0) check. + * + * That's why we ignore the 80 char per line limit. + */ +enum ndr_err_code ndr_pull_dcerpc_bind_nak(struct ndr_pull *ndr, int ndr_flags, struct dcerpc_bind_nak *r) +{ + uint32_t size_versions_0 = 0; + uint32_t cntr_versions_0; + TALLOC_CTX *_mem_save_versions_0 = NULL; + NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + uint32_t _available; + NDR_CHECK(ndr_pull_align(ndr, 4)); + NDR_CHECK(ndr_pull_dcerpc_bind_nak_reason(ndr, NDR_SCALARS, &r->reject_reason)); + _available = ndr->data_size - ndr->offset; + if (_available == 0) { + /* + * This works around a bug in older + * Samba (<= 4.1) releases. + * + * See bug #11327. + */ + r->num_versions = 0; + } else { + NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->num_versions)); + } + size_versions_0 = r->num_versions; + NDR_PULL_ALLOC_N(ndr, r->versions, size_versions_0); + _mem_save_versions_0 = NDR_PULL_GET_MEM_CTX(ndr); + NDR_PULL_SET_MEM_CTX(ndr, r->versions, 0); + for (cntr_versions_0 = 0; cntr_versions_0 < (size_versions_0); cntr_versions_0++) { + NDR_CHECK(ndr_pull_dcerpc_bind_nak_version(ndr, NDR_SCALARS, &r->versions[cntr_versions_0])); + } + NDR_PULL_SET_MEM_CTX(ndr, _mem_save_versions_0, 0); + { + uint32_t _flags_save_DATA_BLOB = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING); + NDR_CHECK(ndr_pull_DATA_BLOB(ndr, NDR_SCALARS, &r->_pad)); + ndr->flags = _flags_save_DATA_BLOB; + } + NDR_CHECK(ndr_pull_trailer_align(ndr, 4)); + } + if (ndr_flags & NDR_BUFFERS) { + } + return NDR_ERR_SUCCESS; +} + const uint8_t DCERPC_SEC_VT_MAGIC[] = {0x8a,0xe3,0x13,0x71,0x02,0xf4,0x36,0x71}; _PUBLIC_ enum ndr_err_code ndr_push_dcerpc_sec_vt_count(struct ndr_push *ndr, int ndr_flags, const struct dcerpc_sec_vt_count *r) -- 1.9.1