diff options
-rw-r--r-- | librpc/idl/dcerpc.idl | 3 | ||||
-rw-r--r-- | librpc/ndr/ndr_dcerpc.c | 121 | ||||
-rw-r--r-- | librpc/ndr/ndr_dcerpc.h | 25 | ||||
-rw-r--r-- | librpc/wscript_build | 4 |
4 files changed, 151 insertions, 2 deletions
diff --git a/librpc/idl/dcerpc.idl b/librpc/idl/dcerpc.idl index 276ddd878f..32f9514bbf 100644 --- a/librpc/idl/dcerpc.idl +++ b/librpc/idl/dcerpc.idl @@ -21,6 +21,9 @@ import "misc.idl"; cpp_quote("extern const uint8_t DCERPC_SEC_VT_MAGIC[8];") +[ + helper("../librpc/ndr/ndr_dcerpc.h") +] interface dcerpc { typedef struct { diff --git a/librpc/ndr/ndr_dcerpc.c b/librpc/ndr/ndr_dcerpc.c index 88a7f38fdb..3cbcef0445 100644 --- a/librpc/ndr/ndr_dcerpc.c +++ b/librpc/ndr/ndr_dcerpc.c @@ -24,6 +24,7 @@ #include "bin/default/librpc/gen_ndr/ndr_dcerpc.h" #include "librpc/gen_ndr/ndr_misc.h" +#include "lib/util/bitmap.h" const uint8_t DCERPC_SEC_VT_MAGIC[] = {0x8a,0xe3,0x13,0x71,0x02,0xf4,0x36,0x71}; @@ -64,3 +65,123 @@ _PUBLIC_ enum ndr_err_code ndr_pull_dcerpc_sec_vt_count(struct ndr_pull *ndr, in ndr->offset = _saved_ofs; return NDR_ERR_SUCCESS; } + +_PUBLIC_ enum ndr_err_code ndr_pop_dcerpc_sec_verification_trailer( + struct ndr_pull *ndr, TALLOC_CTX *mem_ctx, + struct dcerpc_sec_verification_trailer **_r) +{ + enum ndr_err_code ndr_err; + uint32_t ofs; + uint32_t min_ofs = 0; + struct dcerpc_sec_verification_trailer *r; + DATA_BLOB sub_blob = data_blob_null; + struct ndr_pull *sub_ndr = NULL; + uint32_t remaining; + + *_r = NULL; + + r = talloc_zero(mem_ctx, struct dcerpc_sec_verification_trailer); + if (r == NULL) { + return NDR_ERR_ALLOC; + } + + if (ndr->data_size < sizeof(DCERPC_SEC_VT_MAGIC)) { + /* + * we return with r->count = 0 + */ + *_r = r; + return NDR_ERR_SUCCESS; + } + + ofs = ndr->data_size - sizeof(DCERPC_SEC_VT_MAGIC); + /* the magic is 4 byte aligned */ + ofs &= ~3; + + if (ofs > DCERPC_SEC_VT_MAX_SIZE) { + /* + * We just scan the last 1024 bytes. + */ + min_ofs = ofs - DCERPC_SEC_VT_MAX_SIZE; + } else { + min_ofs = 0; + } + + while (true) { + int ret; + + ret = memcmp(&ndr->data[ofs], + DCERPC_SEC_VT_MAGIC, + sizeof(DCERPC_SEC_VT_MAGIC)); + if (ret == 0) { + sub_blob = data_blob_const(&ndr->data[ofs], + ndr->data_size - ofs); + break; + } + + if (ofs <= min_ofs) { + break; + } + + ofs -= 4; + } + + if (sub_blob.length == 0) { + /* + * we return with r->count = 0 + */ + *_r = r; + return NDR_ERR_SUCCESS; + } + + sub_ndr = ndr_pull_init_blob(&sub_blob, r); + if (sub_ndr == NULL) { + TALLOC_FREE(r); + return NDR_ERR_ALLOC; + } + + ndr_err = ndr_pull_dcerpc_sec_verification_trailer(sub_ndr, + NDR_SCALARS | NDR_BUFFERS, + r); + if (ndr_err == NDR_ERR_ALLOC) { + TALLOC_FREE(r); + return NDR_ERR_ALLOC; + } + + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + goto ignore_error; + } + + remaining = sub_ndr->data_size - sub_ndr->offset; + if (remaining > 16) { + /* + * we expect not more than 16 byte of additional + * padding after the verification trailer. + */ + goto ignore_error; + } + + /* + * We assume that we got a real verification trailer. + * + * We remove it from the available stub data. + */ + ndr->data_size = ofs; + + TALLOC_FREE(sub_ndr); + + *_r = r; + return NDR_ERR_SUCCESS; + +ignore_error: + TALLOC_FREE(sub_ndr); + /* + * just ignore the error, it's likely + * that the magic we found belongs to + * the stub data. + * + * we return with r->count = 0 + */ + ZERO_STRUCTP(r); + *_r = r; + return NDR_ERR_SUCCESS; +} diff --git a/librpc/ndr/ndr_dcerpc.h b/librpc/ndr/ndr_dcerpc.h new file mode 100644 index 0000000000..f544fb185d --- /dev/null +++ b/librpc/ndr/ndr_dcerpc.h @@ -0,0 +1,25 @@ +/* + Unix SMB/CIFS implementation. + + Manually parsed structures found in the DCERPC protocol + + Copyright (C) Stefan Metzmacher 2014 + Copyright (C) Gregor Beck 2014 + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +enum ndr_err_code ndr_pop_dcerpc_sec_verification_trailer( + struct ndr_pull *ndr, TALLOC_CTX *mem_ctx, + struct dcerpc_sec_verification_trailer **_r); diff --git a/librpc/wscript_build b/librpc/wscript_build index a5cf687f1b..b99ec9e0a9 100644 --- a/librpc/wscript_build +++ b/librpc/wscript_build @@ -303,8 +303,8 @@ bld.SAMBA_SUBSYSTEM('NDR_FSRVP', bld.SAMBA_SUBSYSTEM('NDR_DCERPC', source='gen_ndr/ndr_dcerpc.c ndr/ndr_dcerpc.c', public_deps='ndr', - public_headers='gen_ndr/ndr_dcerpc.h gen_ndr/dcerpc.h', - header_path= [ ('*gen_ndr*', 'gen_ndr') ], + public_headers='gen_ndr/ndr_dcerpc.h gen_ndr/dcerpc.h ndr/ndr_dcerpc.h', + header_path=[ ('gen_ndr*', 'gen_ndr'), ('ndr*', 'ndr')] ) bld.SAMBA_SUBSYSTEM('NDR_DRSUAPI', |