1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-24 21:34:56 +03:00

librpc/rpc: add dcerpc_sec_verification_trailer_check()

Signed-off-by: Gregor Beck <gbeck@sernet.de>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Guenther Deschner <gd@samba.org>
This commit is contained in:
Gregor Beck 2014-01-08 09:50:33 +01:00 committed by Günther Deschner
parent 9c5664f58d
commit 1fd4842701
2 changed files with 154 additions and 0 deletions

View File

@ -27,6 +27,7 @@
#include "librpc/rpc/dcerpc.h" #include "librpc/rpc/dcerpc.h"
#include "librpc/gen_ndr/ndr_dcerpc.h" #include "librpc/gen_ndr/ndr_dcerpc.h"
#include "rpc_common.h" #include "rpc_common.h"
#include "lib/util/bitmap.h"
/* we need to be able to get/set the fragment length without doing a full /* we need to be able to get/set the fragment length without doing a full
decode */ decode */
@ -449,3 +450,138 @@ bool dcerpc_sec_vt_header2_equal(const struct dcerpc_sec_vt_header2 *v1,
return true; return true;
} }
static bool dcerpc_sec_vt_is_valid(const struct dcerpc_sec_verification_trailer *r)
{
bool ret = false;
TALLOC_CTX *frame = talloc_stackframe();
struct bitmap *commands_seen;
int i;
if (r->count.count == 0) {
ret = true;
goto done;
}
if (memcmp(r->magic, DCERPC_SEC_VT_MAGIC, sizeof(r->magic)) != 0) {
goto done;
}
commands_seen = bitmap_talloc(frame, DCERPC_SEC_VT_COMMAND_ENUM + 1);
if (commands_seen == NULL) {
goto done;
}
for (i=0; i < r->count.count; i++) {
enum dcerpc_sec_vt_command_enum cmd =
r->commands[i].command & DCERPC_SEC_VT_COMMAND_ENUM;
if (bitmap_query(commands_seen, cmd)) {
/* Each command must appear at most once. */
goto done;
}
bitmap_set(commands_seen, cmd);
switch (cmd) {
case DCERPC_SEC_VT_COMMAND_BITMASK1:
case DCERPC_SEC_VT_COMMAND_PCONTEXT:
case DCERPC_SEC_VT_COMMAND_HEADER2:
break;
default:
if ((r->commands[i].u._unknown.length % 4) != 0) {
goto done;
}
break;
}
}
ret = true;
done:
TALLOC_FREE(frame);
return ret;
}
#define CHECK(msg, ok) \
do { \
if (!ok) { \
DEBUG(10, ("SEC_VT check %s failed\n", msg)); \
return false; \
} \
} while(0)
#define CHECK_SYNTAX(msg, s1, s2) \
do { \
if (!ndr_syntax_id_equal(&s1, &s2)) { \
TALLOC_CTX *frame = talloc_stackframe(); \
DEBUG(10, ("SEC_VT check %s failed: %s vs. %s\n", msg, \
ndr_syntax_id_to_string(frame, &s1), \
ndr_syntax_id_to_string(frame, &s1))); \
TALLOC_FREE(frame); \
return false; \
} \
} while(0)
bool dcerpc_sec_verification_trailer_check(
const struct dcerpc_sec_verification_trailer *vt,
const uint32_t *bitmask1,
const struct dcerpc_sec_vt_pcontext *pcontext,
const struct dcerpc_sec_vt_header2 *header2)
{
size_t i;
if (!dcerpc_sec_vt_is_valid(vt)) {
return false;
}
for (i=0; i < vt->count.count; i++) {
struct dcerpc_sec_vt *c = &vt->commands[i];
switch (c->command & DCERPC_SEC_VT_COMMAND_ENUM) {
case DCERPC_SEC_VT_COMMAND_BITMASK1:
if (bitmask1 == NULL) {
CHECK("Bitmask1 must_process_command",
!(c->command & DCERPC_SEC_VT_MUST_PROCESS));
break;
}
if (c->u.bitmask1 & DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING) {
CHECK("Bitmask1 client_header_signing",
*bitmask1 & DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING);
}
break;
case DCERPC_SEC_VT_COMMAND_PCONTEXT:
if (pcontext == NULL) {
CHECK("Pcontext must_process_command",
!(c->command & DCERPC_SEC_VT_MUST_PROCESS));
break;
}
CHECK_SYNTAX("Pcontect abstract_syntax",
pcontext->abstract_syntax,
c->u.pcontext.abstract_syntax);
CHECK_SYNTAX("Pcontext transfer_syntax",
pcontext->transfer_syntax,
c->u.pcontext.transfer_syntax);
break;
case DCERPC_SEC_VT_COMMAND_HEADER2: {
if (header2 == NULL) {
CHECK("Header2 must_process_command",
!(c->command & DCERPC_SEC_VT_MUST_PROCESS));
break;
}
CHECK("Header2", dcerpc_sec_vt_header2_equal(header2, &c->u.header2));
break;
}
default:
CHECK("Unknown must_process_command",
!(c->command & DCERPC_SEC_VT_MUST_PROCESS));
break;
}
}
return true;
}

View File

@ -338,4 +338,22 @@ struct dcerpc_sec_vt_header2 dcerpc_sec_vt_header2_from_ncacn_packet(const struc
bool dcerpc_sec_vt_header2_equal(const struct dcerpc_sec_vt_header2 *v1, bool dcerpc_sec_vt_header2_equal(const struct dcerpc_sec_vt_header2 *v1,
const struct dcerpc_sec_vt_header2 *v2); const struct dcerpc_sec_vt_header2 *v2);
/**
* Check for consistency of the security verification trailer with the PDU header.
* See <a href="http://msdn.microsoft.com/en-us/library/cc243559.aspx">MS-RPCE 2.2.2.13</a>.
* A check with an empty trailer succeeds.
*
* @param[in] vt a pointer to the security verification trailer.
* @param[in] bitmask1 which flags were negotiated on the connection.
* @param[in] pcontext the syntaxes negotiatied for the presentation context.
* @param[in] header2 some fields from the PDU header.
*
* @retval true on success.
*/
bool dcerpc_sec_verification_trailer_check(
const struct dcerpc_sec_verification_trailer *vt,
const uint32_t *bitmask1,
const struct dcerpc_sec_vt_pcontext *pcontext,
const struct dcerpc_sec_vt_header2 *header2);
#endif /* __DEFAULT_LIBRPC_RPCCOMMON_H__ */ #endif /* __DEFAULT_LIBRPC_RPCCOMMON_H__ */