1
0
mirror of https://github.com/samba-team/samba.git synced 2025-08-26 01:49:31 +03:00

CVE-2015-5370: s4:librpc/rpc: send a dcerpc_sec_verification_trailer if needed

BUG: https://bugzilla.samba.org/show_bug.cgi?id=11344

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Günther Deschner <gd@samba.org>
This commit is contained in:
Stefan Metzmacher
2015-07-08 16:25:48 +02:00
parent 67f6fd305c
commit 335b3cee5c
2 changed files with 141 additions and 0 deletions

View File

@ -65,6 +65,8 @@ struct rpc_request {
DATA_BLOB request_data;
bool ignore_timeout;
bool wait_for_sync;
bool verify_bitmask1;
bool verify_pcontext;
struct {
void (*callback)(struct rpc_request *);
@ -1547,6 +1549,13 @@ static void dcerpc_request_recv_data(struct dcecli_connection *c,
return;
}
if (req->verify_bitmask1) {
req->p->conn->security_state.verified_bitmask1 = true;
}
if (req->verify_pcontext) {
req->p->verified_pcontext = true;
}
if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
req->flags |= DCERPC_PULL_BIGENDIAN;
} else {
@ -1571,6 +1580,8 @@ req_done:
}
}
static NTSTATUS dcerpc_request_prepare_vt(struct rpc_request *req);
/*
perform the send side of a async dcerpc request
*/
@ -1581,6 +1592,7 @@ static struct rpc_request *dcerpc_request_send(TALLOC_CTX *mem_ctx,
DATA_BLOB *stub_data)
{
struct rpc_request *req;
NTSTATUS status;
req = talloc_zero(mem_ctx, struct rpc_request);
if (req == NULL) {
@ -1603,6 +1615,12 @@ static struct rpc_request *dcerpc_request_send(TALLOC_CTX *mem_ctx,
req->request_data.length = stub_data->length;
req->request_data.data = stub_data->data;
status = dcerpc_request_prepare_vt(req);
if (!NT_STATUS_IS_OK(status)) {
talloc_free(req);
return NULL;
}
DLIST_ADD_END(p->conn->request_queue, req);
talloc_set_destructor(req, dcerpc_req_dequeue);
@ -1617,6 +1635,124 @@ static struct rpc_request *dcerpc_request_send(TALLOC_CTX *mem_ctx,
return req;
}
static NTSTATUS dcerpc_request_prepare_vt(struct rpc_request *req)
{
struct dcecli_security *sec = &req->p->conn->security_state;
struct dcerpc_sec_verification_trailer *t;
struct dcerpc_sec_vt *c = NULL;
struct ndr_push *ndr = NULL;
enum ndr_err_code ndr_err;
if (sec->auth_info == NULL) {
return NT_STATUS_OK;
}
if (sec->auth_info->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
return NT_STATUS_OK;
}
t = talloc_zero(req, struct dcerpc_sec_verification_trailer);
if (t == NULL) {
return NT_STATUS_NO_MEMORY;
}
if (!sec->verified_bitmask1) {
t->commands = talloc_realloc(t, t->commands,
struct dcerpc_sec_vt,
t->count.count + 1);
if (t->commands == NULL) {
return NT_STATUS_NO_MEMORY;
}
c = &t->commands[t->count.count++];
ZERO_STRUCTP(c);
c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
if (req->p->conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) {
c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
}
req->verify_bitmask1 = true;
}
if (!req->p->verified_pcontext) {
t->commands = talloc_realloc(t, t->commands,
struct dcerpc_sec_vt,
t->count.count + 1);
if (t->commands == NULL) {
return NT_STATUS_NO_MEMORY;
}
c = &t->commands[t->count.count++];
ZERO_STRUCTP(c);
c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
c->u.pcontext.abstract_syntax = req->p->syntax;
c->u.pcontext.transfer_syntax = req->p->transfer_syntax;
req->verify_pcontext = true;
}
if (!(req->p->conn->flags & DCERPC_HEADER_SIGNING)) {
t->commands = talloc_realloc(t, t->commands,
struct dcerpc_sec_vt,
t->count.count + 1);
if (t->commands == NULL) {
return NT_STATUS_NO_MEMORY;
}
c = &t->commands[t->count.count++];
ZERO_STRUCTP(c);
c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
c->u.header2.ptype = DCERPC_PKT_REQUEST;
if (req->p->conn->flags & DCERPC_PUSH_BIGENDIAN) {
c->u.header2.drep[0] = 0;
} else {
c->u.header2.drep[0] = DCERPC_DREP_LE;
}
c->u.header2.drep[1] = 0;
c->u.header2.drep[2] = 0;
c->u.header2.drep[3] = 0;
c->u.header2.call_id = req->call_id;
c->u.header2.context_id = req->p->context_id;
c->u.header2.opnum = req->opnum;
}
if (t->count.count == 0) {
TALLOC_FREE(t);
return NT_STATUS_OK;
}
c = &t->commands[t->count.count - 1];
c->command |= DCERPC_SEC_VT_COMMAND_END;
if (DEBUGLEVEL >= 10) {
NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
}
ndr = ndr_push_init_ctx(req);
if (ndr == NULL) {
return NT_STATUS_NO_MEMORY;
}
/*
* for now we just copy and append
*/
ndr_err = ndr_push_bytes(ndr, req->request_data.data,
req->request_data.length);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
return ndr_map_error2ntstatus(ndr_err);
}
ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
NDR_SCALARS | NDR_BUFFERS,
t);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
return ndr_map_error2ntstatus(ndr_err);
}
req->request_data = ndr_push_blob(ndr);
return NT_STATUS_OK;
}
/*
Send a request using the transport
*/

View File

@ -51,6 +51,9 @@ struct dcecli_security {
/* get the session key */
NTSTATUS (*session_key)(struct dcecli_connection *, DATA_BLOB *);
bool verified_bitmask1;
};
/*
@ -126,6 +129,8 @@ struct dcerpc_pipe {
*/
bool inhibit_timeout_processing;
bool timed_out;
bool verified_pcontext;
};
/* default timeout for all rpc requests, in seconds */