Commit d918587f authored by Rob Shearman's avatar Rob Shearman Committed by Alexandre Julliard

rpcrt4: Implement client impersonation.

parent 95026f9d
......@@ -1052,9 +1052,17 @@ RPC_STATUS RPC_ENTRY RpcBindingReset(RPC_BINDING_HANDLE Binding)
*/
RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
{
FIXME("(%p): stub\n", BindingHandle);
ImpersonateSelf(SecurityImpersonation);
return RPC_S_OK;
RpcBinding *bind;
TRACE("(%p)\n", BindingHandle);
if (!BindingHandle) BindingHandle = I_RpcGetCurrentCallHandle();
if (!BindingHandle) return RPC_S_INVALID_BINDING;
bind = BindingHandle;
if (bind->FromConn)
return rpcrt4_conn_impersonate_client(bind->FromConn);
return RPC_S_WRONG_KIND_OF_BINDING;
}
/***********************************************************************
......@@ -1077,8 +1085,17 @@ RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
*/
RPC_STATUS WINAPI RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle)
{
FIXME("(%p): stub\n", BindingHandle);
return RPC_S_OK;
RpcBinding *bind;
TRACE("(%p)\n", BindingHandle);
if (!BindingHandle) BindingHandle = I_RpcGetCurrentCallHandle();
if (!BindingHandle) return RPC_S_INVALID_BINDING;
bind = BindingHandle;
if (bind->FromConn)
return rpcrt4_conn_revert_to_self(bind->FromConn);
return RPC_S_WRONG_KIND_OF_BINDING;
}
static inline BOOL has_nt_auth_identity(ULONG AuthnLevel)
......@@ -1431,9 +1448,8 @@ BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQuali
*/
RPC_STATUS WINAPI RpcRevertToSelf(void)
{
FIXME("stub\n");
RevertToSelf();
return RPC_S_OK;
TRACE("\n");
return RpcRevertToSelfEx(NULL);
}
/***********************************************************************
......
......@@ -109,6 +109,8 @@ struct connection_ops {
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);
RPC_STATUS (*impersonate_client)(RpcConnection *conn);
RPC_STATUS (*revert_to_self)(RpcConnection *conn);
};
/* don't know what MS's structure looks like */
......@@ -216,6 +218,18 @@ static inline RPC_STATUS rpcrt4_conn_secure_packet(
return conn->ops->secure_packet(conn, dir, hdr, hdr_size, stub_data, stub_data_size, auth_hdr, auth_value, auth_value_size);
}
static inline RPC_STATUS rpcrt4_conn_impersonate_client(
RpcConnection *conn)
{
return conn->ops->impersonate_client(conn);
}
static inline RPC_STATUS rpcrt4_conn_revert_to_self(
RpcConnection *conn)
{
return conn->ops->revert_to_self(conn);
}
/* 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);
......
......@@ -1121,6 +1121,62 @@ BOOL RPCRT4_default_is_authorized(RpcConnection *Connection)
}
/***********************************************************************
* RPCRT4_default_impersonate_client (internal)
*
*/
RPC_STATUS RPCRT4_default_impersonate_client(RpcConnection *conn)
{
SECURITY_STATUS sec_status;
TRACE("(%p)\n", conn);
if (!conn->AuthInfo || !SecIsValidHandle(&conn->ctx))
return RPC_S_NO_CONTEXT_AVAILABLE;
sec_status = ImpersonateSecurityContext(&conn->ctx);
if (sec_status != SEC_E_OK)
WARN("ImpersonateSecurityContext returned 0x%08x\n", sec_status);
switch (sec_status)
{
case SEC_E_UNSUPPORTED_FUNCTION:
return RPC_S_CANNOT_SUPPORT;
case SEC_E_NO_IMPERSONATION:
return RPC_S_NO_CONTEXT_AVAILABLE;
case SEC_E_OK:
return RPC_S_OK;
default:
return RPC_S_SEC_PKG_ERROR;
}
}
/***********************************************************************
* RPCRT4_default_revert_to_self (internal)
*
*/
RPC_STATUS RPCRT4_default_revert_to_self(RpcConnection *conn)
{
SECURITY_STATUS sec_status;
TRACE("(%p)\n", conn);
if (!conn->AuthInfo || !SecIsValidHandle(&conn->ctx))
return RPC_S_NO_CONTEXT_AVAILABLE;
sec_status = RevertSecurityContext(&conn->ctx);
if (sec_status != SEC_E_OK)
WARN("RevertSecurityContext returned 0x%08x\n", sec_status);
switch (sec_status)
{
case SEC_E_UNSUPPORTED_FUNCTION:
return RPC_S_CANNOT_SUPPORT;
case SEC_E_NO_IMPERSONATION:
return RPC_S_NO_CONTEXT_AVAILABLE;
case SEC_E_OK:
return RPC_S_OK;
default:
return RPC_S_SEC_PKG_ERROR;
}
}
/***********************************************************************
* RPCRT4_Send (internal)
*
* Transmit a packet over connection in acceptable fragments.
......
......@@ -53,5 +53,7 @@ RPC_STATUS RPCRT4_ServerGetRegisteredAuthInfo(USHORT auth_type, CredHandle *cred
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);
RPC_STATUS RPCRT4_default_impersonate_client(RpcConnection *conn);
RPC_STATUS RPCRT4_default_revert_to_self(RpcConnection *conn);
#endif
......@@ -586,6 +586,48 @@ static RPC_STATUS rpcrt4_ncacn_np_parse_top_of_tower(const unsigned char *tower_
return RPC_S_OK;
}
static RPC_STATUS rpcrt4_conn_np_impersonate_client(RpcConnection *conn)
{
RpcConnection_np *npc = (RpcConnection_np *)conn;
BOOL ret;
TRACE("(%p)\n", conn);
if (conn->AuthInfo && SecIsValidHandle(&conn->ctx))
return RPCRT4_default_impersonate_client(conn);
ret = ImpersonateNamedPipeClient(npc->pipe);
if (!ret)
{
DWORD error = GetLastError();
WARN("ImpersonateNamedPipeClient failed with error %u\n", error);
switch (error)
{
case ERROR_CANNOT_IMPERSONATE:
return RPC_S_NO_CONTEXT_AVAILABLE;
}
}
return RPC_S_OK;
}
static RPC_STATUS rpcrt4_conn_np_revert_to_self(RpcConnection *conn)
{
BOOL ret;
TRACE("(%p)\n", conn);
if (conn->AuthInfo && SecIsValidHandle(&conn->ctx))
return RPCRT4_default_revert_to_self(conn);
ret = RevertToSelf();
if (!ret)
{
WARN("RevertToSelf failed with error %u\n", GetLastError());
return RPC_S_NO_CONTEXT_AVAILABLE;
}
return RPC_S_OK;
}
typedef struct _RpcServerProtseq_np
{
RpcServerProtseq common;
......@@ -2709,6 +2751,8 @@ static const struct connection_ops conn_protseq_list[] = {
RPCRT4_default_is_authorized,
RPCRT4_default_authorize,
RPCRT4_default_secure_packet,
rpcrt4_conn_np_impersonate_client,
rpcrt4_conn_np_revert_to_self,
},
{ "ncalrpc",
{ EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_PIPE },
......@@ -2726,6 +2770,8 @@ static const struct connection_ops conn_protseq_list[] = {
rpcrt4_ncalrpc_is_authorized,
rpcrt4_ncalrpc_authorize,
rpcrt4_ncalrpc_secure_packet,
rpcrt4_conn_np_impersonate_client,
rpcrt4_conn_np_revert_to_self,
},
{ "ncacn_ip_tcp",
{ EPM_PROTOCOL_NCACN, EPM_PROTOCOL_TCP },
......@@ -2743,6 +2789,8 @@ static const struct connection_ops conn_protseq_list[] = {
RPCRT4_default_is_authorized,
RPCRT4_default_authorize,
RPCRT4_default_secure_packet,
RPCRT4_default_impersonate_client,
RPCRT4_default_revert_to_self,
},
{ "ncacn_http",
{ EPM_PROTOCOL_NCACN, EPM_PROTOCOL_HTTP },
......@@ -2760,6 +2808,8 @@ static const struct connection_ops conn_protseq_list[] = {
RPCRT4_default_is_authorized,
RPCRT4_default_authorize,
RPCRT4_default_secure_packet,
RPCRT4_default_impersonate_client,
RPCRT4_default_revert_to_self,
},
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment