Module: wine Branch: master Commit: 28d3bd3e42fcd9388416efde0e9c5d2aa9b5886c URL: http://source.winehq.org/git/wine.git/?a=commit;h=28d3bd3e42fcd9388416efde0e...
Author: Rob Shearman rob@codeweavers.com Date: Thu Oct 26 23:15:00 2006 +0100
rpcrt4: Fix RPCRT4_Receive to accept authentication verifier data on any packets, not just bind packets.
---
dlls/rpcrt4/rpc_defs.h | 3 ++ dlls/rpcrt4/rpc_message.c | 59 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 54 insertions(+), 8 deletions(-)
diff --git a/dlls/rpcrt4/rpc_defs.h b/dlls/rpcrt4/rpc_defs.h index 1bc8f5b..4ee840c 100644 --- a/dlls/rpcrt4/rpc_defs.h +++ b/dlls/rpcrt4/rpc_defs.h @@ -143,6 +143,9 @@ typedef struct unsigned long auth_context_id; /* unique value for the authenticated connection */ } RpcAuthVerifier;
+#define RPC_AUTH_VERIFIER_LEN(common_hdr) \ + ((common_hdr)->auth_len ? (common_hdr)->auth_len + sizeof(RpcAuthVerifier) : 0) + #define RPC_VER_MAJOR 5 #define RPC_VER_MINOR 0
diff --git a/dlls/rpcrt4/rpc_message.c b/dlls/rpcrt4/rpc_message.c index 0120bf6..f102cf6 100644 --- a/dlls/rpcrt4/rpc_message.c +++ b/dlls/rpcrt4/rpc_message.c @@ -475,7 +475,9 @@ RPC_STATUS RPCRT4_Receive(RpcConnection unsigned short first_flag; unsigned long data_length; unsigned long buffer_length; + unsigned long auth_length; unsigned char *buffer_ptr; + unsigned char *auth_data = NULL; RpcPktCommonHdr common_hdr;
*Header = NULL; @@ -525,7 +527,7 @@ RPC_STATUS RPCRT4_Receive(RpcConnection pMsg->BufferLength = (*Header)->request.alloc_hint; break; default: - pMsg->BufferLength = common_hdr.frag_len - hdr_length; + pMsg->BufferLength = common_hdr.frag_len - hdr_length - RPC_AUTH_VERIFIER_LEN(&common_hdr); }
TRACE("buffer length = %u\n", pMsg->BufferLength); @@ -534,11 +536,38 @@ RPC_STATUS RPCRT4_Receive(RpcConnection if (status != RPC_S_OK) goto fail;
first_flag = RPC_FLG_FIRST; + auth_length = common_hdr.auth_len; + if (auth_length) { + auth_data = HeapAlloc(GetProcessHeap(), 0, RPC_AUTH_VERIFIER_LEN(&common_hdr)); + if (!auth_data) { + status = RPC_S_PROTOCOL_ERROR; + goto fail; + } + } buffer_length = 0; buffer_ptr = pMsg->Buffer; while (buffer_length < pMsg->BufferLength) { - data_length = (*Header)->common.frag_len - hdr_length; + unsigned int header_auth_len = RPC_AUTH_VERIFIER_LEN(&(*Header)->common); + + /* verify header fields */ + + if (((*Header)->common.frag_len < hdr_length) || + ((*Header)->common.frag_len - hdr_length < header_auth_len)) { + WARN("frag_len %d too small for hdr_length %ld and auth_len %d\n", + common_hdr.frag_len, hdr_length, common_hdr.auth_len); + status = RPC_S_PROTOCOL_ERROR; + goto fail; + } + + if ((*Header)->common.auth_len != auth_length) { + WARN("auth_len header field changed from %ld to %d\n", + auth_length, (*Header)->common.auth_len); + status = RPC_S_PROTOCOL_ERROR; + goto fail; + } + + data_length = (*Header)->common.frag_len - hdr_length - header_auth_len; if (((*Header)->common.flags & RPC_FLG_FIRST) != first_flag || data_length + buffer_length > pMsg->BufferLength) { TRACE("invalid packet flags or buffer length\n"); @@ -554,6 +583,21 @@ RPC_STATUS RPCRT4_Receive(RpcConnection goto fail; }
+ if (header_auth_len) { + /* FIXME: we should accumulate authentication data for the bind, + * bind_ack, alter_context and alter_context_response if necessary. + * however, the details of how this is done is very sketchy in the + * DCE/RPC spec. for all other packet types that have authentication + * verifier data then it is just duplicated in all the fragments */ + dwRead = rpcrt4_conn_read(Connection, auth_data, header_auth_len); + if (dwRead != header_auth_len) { + WARN("bad authentication data length, %ld/%d\n", dwRead, + header_auth_len); + status = RPC_S_PROTOCOL_ERROR; + goto fail; + } + } + /* when there is no more data left, it should be the last packet */ if (buffer_length == pMsg->BufferLength && ((*Header)->common.flags & RPC_FLG_LAST) == 0) { @@ -580,13 +624,11 @@ RPC_STATUS RPCRT4_Receive(RpcConnection }
/* respond to authorization request */ - if (common_hdr.ptype == PKT_BIND_ACK && common_hdr.auth_len > 8) + if (common_hdr.ptype == PKT_BIND_ACK && auth_length > sizeof(RpcAuthVerifier)) { - unsigned int offset; - - offset = common_hdr.frag_len - hdr_length - common_hdr.auth_len; - status = RPCRT_AuthorizeConnection(Connection, (LPBYTE)pMsg->Buffer + offset, - common_hdr.auth_len); + status = RPCRT_AuthorizeConnection(Connection, + auth_data + sizeof(RpcAuthVerifier), + auth_length); if (status) goto fail; } @@ -599,6 +641,7 @@ fail: RPCRT4_FreeHeader(*Header); *Header = NULL; } + HeapFree(GetProcessHeap(), 0, auth_data); return status; }