Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
51dd6f9f
Commit
51dd6f9f
authored
Nov 15, 2006
by
Rob Shearman
Committed by
Alexandre Julliard
Nov 15, 2006
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
rpcrt4: Add support for signing, verifying, encrypting and decrypting RPC packets.
parent
8e178b2d
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
157 additions
and
21 deletions
+157
-21
rpc_message.c
dlls/rpcrt4/rpc_message.c
+157
-21
No files found.
dlls/rpcrt4/rpc_message.c
View file @
51dd6f9f
...
...
@@ -51,6 +51,12 @@ WINE_DEFAULT_DEBUG_CHANNEL(rpc);
(((alignment) - (((value) % (alignment)))) % (alignment))
#define ROUND_UP(value, alignment) (((value) + ((alignment) - 1)) & ~((alignment)-1))
enum
secure_packet_direction
{
SECURE_PACKET_SEND
,
SECURE_PACKET_RECEIVE
};
static
RPC_STATUS
I_RpcReAllocateBuffer
(
PRPC_MESSAGE
pMsg
);
static
DWORD
RPCRT4_GetHeaderSize
(
RpcPktHdr
*
Header
)
...
...
@@ -76,6 +82,19 @@ static DWORD RPCRT4_GetHeaderSize(RpcPktHdr *Header)
return
ret
;
}
static
int
packet_has_body
(
RpcPktHdr
*
Header
)
{
return
(
Header
->
common
.
ptype
==
PKT_FAULT
)
||
(
Header
->
common
.
ptype
==
PKT_REQUEST
)
||
(
Header
->
common
.
ptype
==
PKT_RESPONSE
);
}
static
int
packet_has_auth_verifier
(
RpcPktHdr
*
Header
)
{
return
!
(
Header
->
common
.
ptype
==
PKT_BIND_NACK
)
&&
!
(
Header
->
common
.
ptype
==
PKT_SHUTDOWN
);
}
static
VOID
RPCRT4_BuildCommonHeader
(
RpcPktHdr
*
Header
,
unsigned
char
PacketType
,
unsigned
long
DataRepresentation
)
{
...
...
@@ -264,6 +283,80 @@ VOID RPCRT4_FreeHeader(RpcPktHdr *Header)
HeapFree
(
GetProcessHeap
(),
0
,
Header
);
}
static
RPC_STATUS
RPCRT4_SecurePacket
(
RpcConnection
*
Connection
,
enum
secure_packet_direction
dir
,
RpcPktHdr
*
hdr
,
unsigned
int
hdr_size
,
unsigned
char
*
stub_data
,
unsigned
int
stub_data_size
,
RpcAuthVerifier
*
auth_hdr
,
unsigned
char
*
auth_value
,
unsigned
int
auth_value_size
)
{
SecBufferDesc
message
;
SecBuffer
buffers
[
4
];
SECURITY_STATUS
sec_status
;
message
.
ulVersion
=
SECBUFFER_VERSION
;
message
.
cBuffers
=
sizeof
(
buffers
)
/
sizeof
(
buffers
[
0
]);
message
.
pBuffers
=
buffers
;
buffers
[
0
].
cbBuffer
=
hdr_size
;
buffers
[
0
].
BufferType
=
SECBUFFER_DATA
|
SECBUFFER_READONLY_WITH_CHECKSUM
;
buffers
[
0
].
pvBuffer
=
hdr
;
buffers
[
1
].
cbBuffer
=
stub_data_size
;
buffers
[
1
].
BufferType
=
SECBUFFER_DATA
;
buffers
[
1
].
pvBuffer
=
stub_data
;
buffers
[
2
].
cbBuffer
=
sizeof
(
*
auth_hdr
);
buffers
[
2
].
BufferType
=
SECBUFFER_DATA
|
SECBUFFER_READONLY_WITH_CHECKSUM
;
buffers
[
2
].
pvBuffer
=
auth_hdr
;
buffers
[
3
].
cbBuffer
=
auth_value_size
;
buffers
[
3
].
BufferType
=
SECBUFFER_TOKEN
;
buffers
[
3
].
pvBuffer
=
auth_value
;
if
(
dir
==
SECURE_PACKET_SEND
)
{
if
((
auth_hdr
->
auth_level
==
RPC_C_AUTHN_LEVEL_PKT_PRIVACY
)
&&
packet_has_body
(
hdr
))
{
sec_status
=
EncryptMessage
(
&
Connection
->
ctx
,
0
,
&
message
,
0
/* FIXME */
);
if
(
sec_status
!=
SEC_E_OK
)
{
ERR
(
"EncryptMessage failed with 0x%08x
\n
"
,
sec_status
);
return
RPC_S_SEC_PKG_ERROR
;
}
}
else
if
(
auth_hdr
->
auth_level
!=
RPC_C_AUTHN_LEVEL_NONE
)
{
sec_status
=
MakeSignature
(
&
Connection
->
ctx
,
0
,
&
message
,
0
/* FIXME */
);
if
(
sec_status
!=
SEC_E_OK
)
{
ERR
(
"MakeSignature failed with 0x%08x
\n
"
,
sec_status
);
return
RPC_S_SEC_PKG_ERROR
;
}
}
}
else
if
(
dir
==
SECURE_PACKET_RECEIVE
)
{
if
((
auth_hdr
->
auth_level
==
RPC_C_AUTHN_LEVEL_PKT_PRIVACY
)
&&
packet_has_body
(
hdr
))
{
sec_status
=
DecryptMessage
(
&
Connection
->
ctx
,
&
message
,
0
/* FIXME */
,
0
);
if
(
sec_status
!=
SEC_E_OK
)
{
ERR
(
"EncryptMessage failed with 0x%08x
\n
"
,
sec_status
);
return
RPC_S_SEC_PKG_ERROR
;
}
}
else
if
(
auth_hdr
->
auth_level
!=
RPC_C_AUTHN_LEVEL_NONE
)
{
sec_status
=
VerifySignature
(
&
Connection
->
ctx
,
&
message
,
0
/* FIXME */
,
NULL
);
if
(
sec_status
!=
SEC_E_OK
)
{
ERR
(
"VerifySignature failed with 0x%08x
\n
"
,
sec_status
);
return
RPC_S_SEC_PKG_ERROR
;
}
}
}
return
RPC_S_OK
;
}
/***********************************************************************
* RPCRT4_SendAuth (internal)
*
...
...
@@ -277,16 +370,25 @@ static RPC_STATUS RPCRT4_SendAuth(RpcConnection *Connection, RpcPktHdr *Header,
DWORD
hdr_size
;
LONG
count
;
unsigned
char
*
pkt
;
LONG
alen
=
AuthLength
?
(
AuthLength
+
sizeof
(
RpcAuthVerifier
))
:
0
;
LONG
alen
;
RPC_STATUS
status
;
buffer_pos
=
Buffer
;
/* The packet building functions save the packet header size, so we can use it. */
hdr_size
=
Header
->
common
.
frag_len
;
Header
->
common
.
auth_len
=
AuthLength
;
if
(
AuthLength
)
Header
->
common
.
auth_len
=
AuthLength
;
else
if
(
Connection
->
AuthInfo
&&
packet_has_auth_verifier
(
Header
))
Header
->
common
.
auth_len
=
16
/* FIXME */
;
else
Header
->
common
.
auth_len
=
0
;
Header
->
common
.
flags
|=
RPC_FLG_FIRST
;
Header
->
common
.
flags
&=
~
RPC_FLG_LAST
;
alen
=
RPC_AUTH_VERIFIER_LEN
(
&
Header
->
common
);
while
(
!
(
Header
->
common
.
flags
&
RPC_FLG_LAST
))
{
unsigned
char
auth_pad_len
=
AuthLength
?
ROUND_UP_AMOUNT
(
BufferLength
,
AUTH_ALIGNMENT
)
:
0
;
unsigned
char
auth_pad_len
=
Header
->
common
.
auth_len
?
ROUND_UP_AMOUNT
(
BufferLength
,
AUTH_ALIGNMENT
)
:
0
;
unsigned
int
pkt_size
=
BufferLength
+
hdr_size
+
alen
+
auth_pad_len
;
/* decide if we need to split the packet into fragments */
...
...
@@ -312,7 +414,7 @@ static RPC_STATUS RPCRT4_SendAuth(RpcConnection *Connection, RpcPktHdr *Header,
memcpy
(
pkt
+
hdr_size
,
buffer_pos
,
Header
->
common
.
frag_len
-
hdr_size
-
auth_pad_len
-
alen
);
/* add the authorization info */
if
(
Connection
->
AuthInfo
&&
AuthLength
)
if
(
Connection
->
AuthInfo
&&
packet_has_auth_verifier
(
Header
)
)
{
RpcAuthVerifier
*
auth_hdr
=
(
RpcAuthVerifier
*
)
&
pkt
[
Header
->
common
.
frag_len
-
alen
];
...
...
@@ -323,7 +425,21 @@ static RPC_STATUS RPCRT4_SendAuth(RpcConnection *Connection, RpcPktHdr *Header,
/* a unique number... */
auth_hdr
->
auth_context_id
=
(
unsigned
long
)
Connection
;
memcpy
(
auth_hdr
+
1
,
Auth
,
AuthLength
);
if
(
AuthLength
)
memcpy
(
auth_hdr
+
1
,
Auth
,
AuthLength
);
else
{
status
=
RPCRT4_SecurePacket
(
Connection
,
SECURE_PACKET_SEND
,
(
RpcPktHdr
*
)
pkt
,
hdr_size
,
pkt
+
hdr_size
,
Header
->
common
.
frag_len
-
hdr_size
-
alen
,
auth_hdr
,
(
unsigned
char
*
)(
auth_hdr
+
1
),
Header
->
common
.
auth_len
);
if
(
status
!=
RPC_S_OK
)
{
HeapFree
(
GetProcessHeap
(),
0
,
pkt
);
return
status
;
}
}
}
write:
...
...
@@ -350,6 +466,13 @@ static void RPCRT4_AuthNegotiate(RpcConnection *conn, SecBuffer *out)
SECURITY_STATUS
r
;
SecBufferDesc
out_desc
;
unsigned
char
*
buffer
;
ULONG
context_req
=
ISC_REQ_CONNECTION
|
ISC_REQ_USE_DCE_STYLE
|
ISC_REQ_MUTUAL_AUTH
|
ISC_REQ_DELEGATE
;
if
(
conn
->
AuthInfo
->
AuthnLevel
==
RPC_C_AUTHN_LEVEL_PKT_INTEGRITY
)
context_req
|=
ISC_REQ_INTEGRITY
;
else
if
(
conn
->
AuthInfo
->
AuthnLevel
==
RPC_C_AUTHN_LEVEL_PKT_PRIVACY
)
context_req
|=
ISC_REQ_CONFIDENTIALITY
|
ISC_REQ_INTEGRITY
;
buffer
=
HeapAlloc
(
GetProcessHeap
(),
0
,
0x100
);
...
...
@@ -366,8 +489,7 @@ static void RPCRT4_AuthNegotiate(RpcConnection *conn, SecBuffer *out)
conn
->
ctx
.
dwUpper
=
0
;
r
=
InitializeSecurityContextA
(
&
conn
->
AuthInfo
->
cred
,
NULL
,
NULL
,
ISC_REQ_CONNECTION
|
ISC_REQ_USE_DCE_STYLE
|
ISC_REQ_MUTUAL_AUTH
|
ISC_REQ_DELEGATE
,
0
,
SECURITY_NETWORK_DREP
,
context_req
,
0
,
SECURITY_NETWORK_DREP
,
NULL
,
0
,
&
conn
->
ctx
,
&
out_desc
,
&
conn
->
attr
,
&
conn
->
exp
);
TRACE
(
"r = %08x cbBuffer = %ld attr = %08x
\n
"
,
r
,
out
->
cbBuffer
,
conn
->
attr
);
...
...
@@ -385,9 +507,16 @@ static RPC_STATUS RPCRT_AuthorizeConnection(RpcConnection* conn,
unsigned
char
buffer
[
0x100
];
RpcPktHdr
*
resp_hdr
;
RPC_STATUS
status
;
ULONG
context_req
=
ISC_REQ_CONNECTION
|
ISC_REQ_USE_DCE_STYLE
|
ISC_REQ_MUTUAL_AUTH
|
ISC_REQ_DELEGATE
;
TRACE
(
"challenge %s, %d bytes
\n
"
,
challenge
,
count
);
if
(
conn
->
AuthInfo
->
AuthnLevel
==
RPC_C_AUTHN_LEVEL_PKT_INTEGRITY
)
context_req
|=
ISC_REQ_INTEGRITY
;
else
if
(
conn
->
AuthInfo
->
AuthnLevel
==
RPC_C_AUTHN_LEVEL_PKT_PRIVACY
)
context_req
|=
ISC_REQ_CONFIDENTIALITY
|
ISC_REQ_INTEGRITY
;
out
.
BufferType
=
SECBUFFER_TOKEN
;
out
.
cbBuffer
=
sizeof
buffer
;
out
.
pvBuffer
=
buffer
;
...
...
@@ -405,8 +534,7 @@ static RPC_STATUS RPCRT_AuthorizeConnection(RpcConnection* conn,
inp_desc
.
ulVersion
=
0
;
r
=
InitializeSecurityContextA
(
&
conn
->
AuthInfo
->
cred
,
&
conn
->
ctx
,
NULL
,
ISC_REQ_CONNECTION
|
ISC_REQ_USE_DCE_STYLE
|
ISC_REQ_MUTUAL_AUTH
|
ISC_REQ_DELEGATE
,
0
,
SECURITY_NETWORK_DREP
,
context_req
,
0
,
SECURITY_NETWORK_DREP
,
&
inp_desc
,
0
,
&
conn
->
ctx
,
&
out_desc
,
&
conn
->
attr
,
&
conn
->
exp
);
if
(
r
)
{
...
...
@@ -436,20 +564,10 @@ RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header,
RPC_STATUS
r
;
SecBuffer
out
;
/* if we've already authenticated, just send the context */
if
(
Connection
->
ctx
.
dwUpper
||
Connection
->
ctx
.
dwLower
)
{
unsigned
char
buffer
[
0x10
];
memset
(
buffer
,
0
,
sizeof
buffer
);
buffer
[
0
]
=
1
;
/* version number lsb */
return
RPCRT4_SendAuth
(
Connection
,
Header
,
Buffer
,
BufferLength
,
buffer
,
sizeof
buffer
);
}
if
(
!
Connection
->
AuthInfo
||
Connection
->
AuthInfo
->
AuthnLevel
==
RPC_C_AUTHN_LEVEL_DEFAULT
||
Connection
->
AuthInfo
->
AuthnLevel
==
RPC_C_AUTHN_LEVEL_NONE
)
Connection
->
AuthInfo
->
AuthnLevel
==
RPC_C_AUTHN_LEVEL_NONE
||
(
Connection
->
ctx
.
dwUpper
||
Connection
->
ctx
.
dwLower
))
{
return
RPCRT4_SendAuth
(
Connection
,
Header
,
Buffer
,
BufferLength
,
NULL
,
0
);
}
...
...
@@ -595,6 +713,12 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header,
}
if
(
header_auth_len
)
{
if
(
header_auth_len
<
sizeof
(
RpcAuthVerifier
))
{
WARN
(
"bad auth verifier length %d
\n
"
,
header_auth_len
);
status
=
RPC_S_PROTOCOL_ERROR
;
goto
fail
;
}
/* 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
...
...
@@ -607,6 +731,18 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header,
status
=
RPC_S_PROTOCOL_ERROR
;
goto
fail
;
}
/* these packets are handled specially, not by the generic SecurePacket
* function */
if
((
common_hdr
.
ptype
!=
PKT_BIND
)
&&
(
common_hdr
.
ptype
!=
PKT_BIND_ACK
)
&&
(
common_hdr
.
ptype
!=
PKT_AUTH3
))
status
=
RPCRT4_SecurePacket
(
Connection
,
SECURE_PACKET_RECEIVE
,
*
Header
,
hdr_length
,
(
unsigned
char
*
)
pMsg
->
Buffer
+
buffer_length
,
data_length
,
(
RpcAuthVerifier
*
)
auth_data
,
(
unsigned
char
*
)
auth_data
+
sizeof
(
RpcAuthVerifier
),
header_auth_len
-
sizeof
(
RpcAuthVerifier
));
}
buffer_length
+=
data_length
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment