rpcrt4: Allow the connection to override the authentication mechanism for a connection type.
This commit is contained in:
parent
a65f7b637a
commit
deae193ac8
|
@ -27,6 +27,12 @@
|
|||
#include "rpc_defs.h"
|
||||
|
||||
|
||||
enum secure_packet_direction
|
||||
{
|
||||
SECURE_PACKET_SEND,
|
||||
SECURE_PACKET_RECEIVE
|
||||
};
|
||||
|
||||
typedef struct _RpcAuthInfo
|
||||
{
|
||||
LONG refs;
|
||||
|
@ -100,6 +106,9 @@ struct connection_ops {
|
|||
size_t (*get_top_of_tower)(unsigned char *tower_data, const char *networkaddr, const char *endpoint);
|
||||
RPC_STATUS (*parse_top_of_tower)(const unsigned char *tower_data, size_t tower_size, char **networkaddr, char **endpoint);
|
||||
RPC_STATUS (*receive_fragment)(RpcConnection *conn, RpcPktHdr **Header, void **Payload);
|
||||
BOOL (*is_authorized)(RpcConnection *conn);
|
||||
RPC_STATUS (*authorize)(RpcConnection *conn, BOOL first_time, unsigned char *in_buffer, unsigned int in_len, unsigned char *out_buffer, unsigned int *out_len);
|
||||
RPC_STATUS (*secure_packet)(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);
|
||||
};
|
||||
|
||||
/* don't know what MS's structure looks like */
|
||||
|
@ -186,6 +195,27 @@ static inline RPC_STATUS rpcrt4_conn_handoff(RpcConnection *old_conn, RpcConnect
|
|||
return old_conn->ops->handoff(old_conn, new_conn);
|
||||
}
|
||||
|
||||
static inline BOOL rpcrt4_conn_is_authorized(RpcConnection *Connection)
|
||||
{
|
||||
return Connection->ops->is_authorized(Connection);
|
||||
}
|
||||
|
||||
static inline RPC_STATUS rpcrt4_conn_authorize(
|
||||
RpcConnection *conn, BOOL first_time, unsigned char *in_buffer,
|
||||
unsigned int in_len, unsigned char *out_buffer, unsigned int *out_len)
|
||||
{
|
||||
return conn->ops->authorize(conn, first_time, in_buffer, in_len, out_buffer, out_len);
|
||||
}
|
||||
|
||||
static inline RPC_STATUS rpcrt4_conn_secure_packet(
|
||||
RpcConnection *conn, 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)
|
||||
{
|
||||
return conn->ops->secure_packet(conn, dir, hdr, hdr_size, stub_data, stub_data_size, auth_hdr, auth_value, auth_value_size);
|
||||
}
|
||||
|
||||
/* floors 3 and up */
|
||||
RPC_STATUS RpcTransport_GetTopOfTower(unsigned char *tower_data, size_t *tower_size, const char *protseq, const char *networkaddr, const char *endpoint);
|
||||
RPC_STATUS RpcTransport_ParseTopOfTower(const unsigned char *tower_data, size_t tower_size, char **protseq, char **networkaddr, char **endpoint);
|
||||
|
|
|
@ -51,12 +51,6 @@ 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);
|
||||
|
||||
DWORD RPCRT4_GetHeaderSize(const RpcPktHdr *Header)
|
||||
|
@ -684,7 +678,7 @@ RPC_STATUS RPCRT4_ParseHttpFlowControlHeader(RpcPktHdr *header,
|
|||
}
|
||||
|
||||
|
||||
static RPC_STATUS RPCRT4_SecurePacket(RpcConnection *Connection,
|
||||
RPC_STATUS RPCRT4_default_secure_packet(RpcConnection *Connection,
|
||||
enum secure_packet_direction dir,
|
||||
RpcPktHdr *hdr, unsigned int hdr_size,
|
||||
unsigned char *stub_data, unsigned int stub_data_size,
|
||||
|
@ -837,7 +831,7 @@ RPC_STATUS RPCRT4_SendWithAuth(RpcConnection *Connection, RpcPktHdr *Header,
|
|||
memcpy(auth_hdr + 1, Auth, AuthLength);
|
||||
else
|
||||
{
|
||||
status = RPCRT4_SecurePacket(Connection, SECURE_PACKET_SEND,
|
||||
status = rpcrt4_conn_secure_packet(Connection, SECURE_PACKET_SEND,
|
||||
(RpcPktHdr *)pkt, hdr_size,
|
||||
pkt + hdr_size, Header->common.frag_len - hdr_size - alen,
|
||||
auth_hdr,
|
||||
|
@ -870,12 +864,15 @@ write:
|
|||
}
|
||||
|
||||
/***********************************************************************
|
||||
* RPCRT4_Authorize (internal)
|
||||
* RPCRT4_default_authorize (internal)
|
||||
*
|
||||
* Authorize a client connection.
|
||||
*/
|
||||
static RPC_STATUS RPCRT4_Authorize(RpcConnection *conn, BOOL first_time,
|
||||
SecBuffer *in, SecBuffer *out)
|
||||
RPC_STATUS RPCRT4_default_authorize(RpcConnection *conn, BOOL first_time,
|
||||
unsigned char *in_buffer,
|
||||
unsigned int in_size,
|
||||
unsigned char *out_buffer,
|
||||
unsigned int *out_size)
|
||||
{
|
||||
SECURITY_STATUS r;
|
||||
SecBufferDesc out_desc;
|
||||
|
@ -883,19 +880,29 @@ static RPC_STATUS RPCRT4_Authorize(RpcConnection *conn, BOOL first_time,
|
|||
SecPkgContext_Sizes secctx_sizes;
|
||||
BOOL continue_needed;
|
||||
ULONG context_req;
|
||||
SecBuffer in, out;
|
||||
|
||||
out->BufferType = SECBUFFER_TOKEN;
|
||||
out->cbBuffer = conn->AuthInfo->cbMaxToken;
|
||||
out->pvBuffer = HeapAlloc(GetProcessHeap(), 0, out->cbBuffer);
|
||||
if (!out->pvBuffer) return ERROR_OUTOFMEMORY;
|
||||
if (!out_buffer)
|
||||
{
|
||||
*out_size = conn->AuthInfo->cbMaxToken;
|
||||
return RPC_S_OK;
|
||||
}
|
||||
|
||||
in.BufferType = SECBUFFER_TOKEN;
|
||||
in.pvBuffer = in_buffer;
|
||||
in.cbBuffer = in_size;
|
||||
|
||||
out.BufferType = SECBUFFER_TOKEN;
|
||||
out.pvBuffer = out_buffer;
|
||||
out.cbBuffer = *out_size;
|
||||
|
||||
out_desc.ulVersion = 0;
|
||||
out_desc.cBuffers = 1;
|
||||
out_desc.pBuffers = out;
|
||||
out_desc.pBuffers = &out;
|
||||
|
||||
inp_desc.cBuffers = 1;
|
||||
inp_desc.pBuffers = in;
|
||||
inp_desc.ulVersion = 0;
|
||||
inp_desc.cBuffers = 1;
|
||||
inp_desc.pBuffers = ∈
|
||||
|
||||
if (conn->server)
|
||||
{
|
||||
|
@ -915,8 +922,7 @@ static RPC_STATUS RPCRT4_Authorize(RpcConnection *conn, BOOL first_time,
|
|||
if (r == SEC_E_OK || r == SEC_I_COMPLETE_NEEDED)
|
||||
{
|
||||
/* authorisation done, so nothing more to send */
|
||||
HeapFree(GetProcessHeap(), 0, out->pvBuffer);
|
||||
out->cbBuffer = 0;
|
||||
out.cbBuffer = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -933,7 +939,7 @@ static RPC_STATUS RPCRT4_Authorize(RpcConnection *conn, BOOL first_time,
|
|||
first_time ? NULL: &conn->ctx,
|
||||
first_time ? conn->AuthInfo->server_principal_name : NULL,
|
||||
context_req, 0, SECURITY_NETWORK_DREP,
|
||||
in ? &inp_desc : NULL, 0, &conn->ctx,
|
||||
first_time ? NULL : &inp_desc, 0, &conn->ctx,
|
||||
&out_desc, &conn->attr, &conn->exp);
|
||||
}
|
||||
if (FAILED(r))
|
||||
|
@ -957,7 +963,7 @@ static RPC_STATUS RPCRT4_Authorize(RpcConnection *conn, BOOL first_time,
|
|||
}
|
||||
}
|
||||
|
||||
TRACE("cbBuffer = %d\n", out->cbBuffer);
|
||||
TRACE("cbBuffer = %d\n", out.cbBuffer);
|
||||
|
||||
if (!continue_needed)
|
||||
{
|
||||
|
@ -971,11 +977,11 @@ static RPC_STATUS RPCRT4_Authorize(RpcConnection *conn, BOOL first_time,
|
|||
conn->encryption_auth_len = secctx_sizes.cbSecurityTrailer;
|
||||
}
|
||||
|
||||
*out_size = out.cbBuffer;
|
||||
return RPC_S_OK;
|
||||
|
||||
failed:
|
||||
HeapFree(GetProcessHeap(), 0, out->pvBuffer);
|
||||
out->pvBuffer = NULL;
|
||||
*out_size = 0;
|
||||
return ERROR_ACCESS_DENIED; /* FIXME: is this correct? */
|
||||
}
|
||||
|
||||
|
@ -985,26 +991,28 @@ failed:
|
|||
RPC_STATUS RPCRT4_ClientConnectionAuth(RpcConnection* conn, BYTE *challenge,
|
||||
ULONG count)
|
||||
{
|
||||
SecBuffer inp, out;
|
||||
RpcPktHdr *resp_hdr;
|
||||
RPC_STATUS status;
|
||||
unsigned char *out_buffer;
|
||||
unsigned int out_len = 0;
|
||||
|
||||
TRACE("challenge %s, %d bytes\n", challenge, count);
|
||||
|
||||
inp.BufferType = SECBUFFER_TOKEN;
|
||||
inp.pvBuffer = challenge;
|
||||
inp.cbBuffer = count;
|
||||
|
||||
status = RPCRT4_Authorize(conn, FALSE, &inp, &out);
|
||||
status = rpcrt4_conn_authorize(conn, FALSE, challenge, count, NULL, &out_len);
|
||||
if (status) return status;
|
||||
out_buffer = HeapAlloc(GetProcessHeap(), 0, out_len);
|
||||
if (!out_buffer) return RPC_S_OUT_OF_RESOURCES;
|
||||
status = rpcrt4_conn_authorize(conn, FALSE, challenge, count, out_buffer, &out_len);
|
||||
if (status) return status;
|
||||
|
||||
resp_hdr = RPCRT4_BuildAuthHeader(NDR_LOCAL_DATA_REPRESENTATION);
|
||||
if (!resp_hdr)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
status = RPCRT4_SendWithAuth(conn, resp_hdr, NULL, 0, out.pvBuffer, out.cbBuffer);
|
||||
if (resp_hdr)
|
||||
status = RPCRT4_SendWithAuth(conn, resp_hdr, NULL, 0, out_buffer, out_len);
|
||||
else
|
||||
status = RPC_S_OUT_OF_RESOURCES;
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, out.pvBuffer);
|
||||
HeapFree(GetProcessHeap(), 0, out_buffer);
|
||||
RPCRT4_FreeHeader(resp_hdr);
|
||||
|
||||
return status;
|
||||
|
@ -1020,7 +1028,8 @@ RPC_STATUS RPCRT4_ServerConnectionAuth(RpcConnection* conn,
|
|||
unsigned char **auth_data_out,
|
||||
ULONG *auth_length_out)
|
||||
{
|
||||
SecBuffer inp, out;
|
||||
unsigned char *out_buffer;
|
||||
unsigned int out_size;
|
||||
RPC_STATUS status;
|
||||
|
||||
if (start)
|
||||
|
@ -1068,29 +1077,49 @@ RPC_STATUS RPCRT4_ServerConnectionAuth(RpcConnection* conn,
|
|||
/* should have filled in authentication info by now */
|
||||
return RPC_S_PROTOCOL_ERROR;
|
||||
|
||||
inp.BufferType = SECBUFFER_TOKEN;
|
||||
inp.pvBuffer = auth_data_in + 1;
|
||||
inp.cbBuffer = auth_length_in - sizeof(RpcAuthVerifier);
|
||||
|
||||
status = RPCRT4_Authorize(conn, start, &inp, &out);
|
||||
status = rpcrt4_conn_authorize(
|
||||
conn, start, (unsigned char *)(auth_data_in + 1),
|
||||
auth_length_in - sizeof(RpcAuthVerifier), NULL, &out_size);
|
||||
if (status) return status;
|
||||
|
||||
if (out.cbBuffer && !auth_length_out)
|
||||
out_buffer = HeapAlloc(GetProcessHeap(), 0, out_size);
|
||||
if (!out_buffer) return RPC_S_OUT_OF_RESOURCES;
|
||||
|
||||
status = rpcrt4_conn_authorize(
|
||||
conn, start, (unsigned char *)(auth_data_in + 1),
|
||||
auth_length_in - sizeof(RpcAuthVerifier), out_buffer, &out_size);
|
||||
if (status != RPC_S_OK)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, out_buffer);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (out_size && !auth_length_out)
|
||||
{
|
||||
ERR("expected authentication to be complete but SSP returned data of "
|
||||
"%u bytes to be sent back to client\n", out.cbBuffer);
|
||||
HeapFree(GetProcessHeap(), 0, out.pvBuffer);
|
||||
"%u bytes to be sent back to client\n", out_size);
|
||||
HeapFree(GetProcessHeap(), 0, out_buffer);
|
||||
return RPC_S_SEC_PKG_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
*auth_data_out = out.pvBuffer;
|
||||
*auth_length_out = out.cbBuffer;
|
||||
*auth_data_out = out_buffer;
|
||||
*auth_length_out = out_size;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* RPCRT4_default_is_authorized (internal)
|
||||
*
|
||||
* Has a connection started the process of authorizing with the server?
|
||||
*/
|
||||
BOOL RPCRT4_default_is_authorized(RpcConnection *Connection)
|
||||
{
|
||||
return Connection->AuthInfo && SecIsValidHandle(&Connection->ctx);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* RPCRT4_Send (internal)
|
||||
*
|
||||
|
@ -1100,18 +1129,26 @@ RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header,
|
|||
void *Buffer, unsigned int BufferLength)
|
||||
{
|
||||
RPC_STATUS r;
|
||||
SecBuffer out;
|
||||
|
||||
if (packet_does_auth_negotiation(Header) &&
|
||||
Connection->AuthInfo && !SecIsValidHandle(&Connection->ctx))
|
||||
Connection->AuthInfo &&
|
||||
!rpcrt4_conn_is_authorized(Connection))
|
||||
{
|
||||
unsigned int out_size = 0;
|
||||
unsigned char *out_buffer;
|
||||
|
||||
r = rpcrt4_conn_authorize(Connection, TRUE, NULL, 0, NULL, &out_size);
|
||||
if (r != RPC_S_OK) return r;
|
||||
|
||||
out_buffer = HeapAlloc(GetProcessHeap(), 0, out_size);
|
||||
if (!out_buffer) return RPC_S_OUT_OF_RESOURCES;
|
||||
|
||||
/* tack on a negotiate packet */
|
||||
r = RPCRT4_Authorize(Connection, TRUE, NULL, &out);
|
||||
r = rpcrt4_conn_authorize(Connection, TRUE, NULL, 0, out_buffer, &out_size);
|
||||
if (r == RPC_S_OK)
|
||||
{
|
||||
r = RPCRT4_SendWithAuth(Connection, Header, Buffer, BufferLength, out.pvBuffer, out.cbBuffer);
|
||||
HeapFree(GetProcessHeap(), 0, out.pvBuffer);
|
||||
}
|
||||
r = RPCRT4_SendWithAuth(Connection, Header, Buffer, BufferLength, out_buffer, out_size);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, out_buffer);
|
||||
}
|
||||
else
|
||||
r = RPCRT4_SendWithAuth(Connection, Header, Buffer, BufferLength, NULL, 0);
|
||||
|
@ -1357,9 +1394,9 @@ RPC_STATUS RPCRT4_ReceiveWithAuth(RpcConnection *Connection, RpcPktHdr **Header,
|
|||
|
||||
/* these packets are handled specially, not by the generic SecurePacket
|
||||
* function */
|
||||
if (!packet_does_auth_negotiation(*Header) && SecIsValidHandle(&Connection->ctx))
|
||||
if (!packet_does_auth_negotiation(*Header) && rpcrt4_conn_is_authorized(Connection))
|
||||
{
|
||||
status = RPCRT4_SecurePacket(Connection, SECURE_PACKET_RECEIVE,
|
||||
status = rpcrt4_conn_secure_packet(Connection, SECURE_PACKET_RECEIVE,
|
||||
CurrentHeader, hdr_length,
|
||||
(unsigned char *)pMsg->Buffer + buffer_length, data_length,
|
||||
(RpcAuthVerifier *)auth_data,
|
||||
|
|
|
@ -50,5 +50,8 @@ RPC_STATUS RPCRT4_ClientConnectionAuth(RpcConnection* conn, BYTE *challenge, ULO
|
|||
RPC_STATUS RPCRT4_ServerConnectionAuth(RpcConnection* conn, BOOL start, RpcAuthVerifier *auth_data_in, ULONG auth_length_in, unsigned char **auth_data_out, ULONG *auth_length_out);
|
||||
RPC_STATUS RPCRT4_AuthorizeConnection(RpcConnection* conn, BYTE *challenge, ULONG count);
|
||||
RPC_STATUS RPCRT4_ServerGetRegisteredAuthInfo(USHORT auth_type, CredHandle *cred, TimeStamp *exp, ULONG *max_token);
|
||||
RPC_STATUS RPCRT4_default_authorize(RpcConnection *conn, BOOL first_time, unsigned char *in_buffer, unsigned int in_size, unsigned char *out_buffer, unsigned int *out_size);
|
||||
BOOL RPCRT4_default_is_authorized(RpcConnection *Connection);
|
||||
RPC_STATUS RPCRT4_default_secure_packet(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);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2677,6 +2677,9 @@ static const struct connection_ops conn_protseq_list[] = {
|
|||
rpcrt4_ncacn_np_get_top_of_tower,
|
||||
rpcrt4_ncacn_np_parse_top_of_tower,
|
||||
NULL,
|
||||
RPCRT4_default_is_authorized,
|
||||
RPCRT4_default_authorize,
|
||||
RPCRT4_default_secure_packet,
|
||||
},
|
||||
{ "ncalrpc",
|
||||
{ EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_PIPE },
|
||||
|
@ -2691,6 +2694,9 @@ static const struct connection_ops conn_protseq_list[] = {
|
|||
rpcrt4_ncalrpc_get_top_of_tower,
|
||||
rpcrt4_ncalrpc_parse_top_of_tower,
|
||||
NULL,
|
||||
RPCRT4_default_is_authorized,
|
||||
RPCRT4_default_authorize,
|
||||
RPCRT4_default_secure_packet,
|
||||
},
|
||||
{ "ncacn_ip_tcp",
|
||||
{ EPM_PROTOCOL_NCACN, EPM_PROTOCOL_TCP },
|
||||
|
@ -2705,6 +2711,9 @@ static const struct connection_ops conn_protseq_list[] = {
|
|||
rpcrt4_ncacn_ip_tcp_get_top_of_tower,
|
||||
rpcrt4_ncacn_ip_tcp_parse_top_of_tower,
|
||||
NULL,
|
||||
RPCRT4_default_is_authorized,
|
||||
RPCRT4_default_authorize,
|
||||
RPCRT4_default_secure_packet,
|
||||
},
|
||||
{ "ncacn_http",
|
||||
{ EPM_PROTOCOL_NCACN, EPM_PROTOCOL_HTTP },
|
||||
|
@ -2719,6 +2728,9 @@ static const struct connection_ops conn_protseq_list[] = {
|
|||
rpcrt4_ncacn_http_get_top_of_tower,
|
||||
rpcrt4_ncacn_http_parse_top_of_tower,
|
||||
rpcrt4_ncacn_http_receive_fragment,
|
||||
RPCRT4_default_is_authorized,
|
||||
RPCRT4_default_authorize,
|
||||
RPCRT4_default_secure_packet,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue