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) ...@@ -1052,9 +1052,17 @@ RPC_STATUS RPC_ENTRY RpcBindingReset(RPC_BINDING_HANDLE Binding)
*/ */
RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle) RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
{ {
FIXME("(%p): stub\n", BindingHandle); RpcBinding *bind;
ImpersonateSelf(SecurityImpersonation);
return RPC_S_OK; 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) ...@@ -1077,8 +1085,17 @@ RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
*/ */
RPC_STATUS WINAPI RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle) RPC_STATUS WINAPI RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle)
{ {
FIXME("(%p): stub\n", BindingHandle); RpcBinding *bind;
return RPC_S_OK;
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) static inline BOOL has_nt_auth_identity(ULONG AuthnLevel)
...@@ -1431,9 +1448,8 @@ BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQuali ...@@ -1431,9 +1448,8 @@ BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQuali
*/ */
RPC_STATUS WINAPI RpcRevertToSelf(void) RPC_STATUS WINAPI RpcRevertToSelf(void)
{ {
FIXME("stub\n"); TRACE("\n");
RevertToSelf(); return RpcRevertToSelfEx(NULL);
return RPC_S_OK;
} }
/*********************************************************************** /***********************************************************************
......
...@@ -109,6 +109,8 @@ struct connection_ops { ...@@ -109,6 +109,8 @@ struct connection_ops {
BOOL (*is_authorized)(RpcConnection *conn); 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 (*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 (*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 */ /* don't know what MS's structure looks like */
...@@ -216,6 +218,18 @@ static inline RPC_STATUS rpcrt4_conn_secure_packet( ...@@ -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); 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 */ /* 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_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); 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) ...@@ -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) * RPCRT4_Send (internal)
* *
* Transmit a packet over connection in acceptable fragments. * Transmit a packet over connection in acceptable fragments.
......
...@@ -53,5 +53,7 @@ RPC_STATUS RPCRT4_ServerGetRegisteredAuthInfo(USHORT auth_type, CredHandle *cred ...@@ -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); 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); 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_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 #endif
...@@ -586,6 +586,48 @@ static RPC_STATUS rpcrt4_ncacn_np_parse_top_of_tower(const unsigned char *tower_ ...@@ -586,6 +586,48 @@ static RPC_STATUS rpcrt4_ncacn_np_parse_top_of_tower(const unsigned char *tower_
return RPC_S_OK; 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 typedef struct _RpcServerProtseq_np
{ {
RpcServerProtseq common; RpcServerProtseq common;
...@@ -2709,6 +2751,8 @@ static const struct connection_ops conn_protseq_list[] = { ...@@ -2709,6 +2751,8 @@ static const struct connection_ops conn_protseq_list[] = {
RPCRT4_default_is_authorized, RPCRT4_default_is_authorized,
RPCRT4_default_authorize, RPCRT4_default_authorize,
RPCRT4_default_secure_packet, RPCRT4_default_secure_packet,
rpcrt4_conn_np_impersonate_client,
rpcrt4_conn_np_revert_to_self,
}, },
{ "ncalrpc", { "ncalrpc",
{ EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_PIPE }, { EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_PIPE },
...@@ -2726,6 +2770,8 @@ static const struct connection_ops conn_protseq_list[] = { ...@@ -2726,6 +2770,8 @@ static const struct connection_ops conn_protseq_list[] = {
rpcrt4_ncalrpc_is_authorized, rpcrt4_ncalrpc_is_authorized,
rpcrt4_ncalrpc_authorize, rpcrt4_ncalrpc_authorize,
rpcrt4_ncalrpc_secure_packet, rpcrt4_ncalrpc_secure_packet,
rpcrt4_conn_np_impersonate_client,
rpcrt4_conn_np_revert_to_self,
}, },
{ "ncacn_ip_tcp", { "ncacn_ip_tcp",
{ EPM_PROTOCOL_NCACN, EPM_PROTOCOL_TCP }, { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_TCP },
...@@ -2743,6 +2789,8 @@ static const struct connection_ops conn_protseq_list[] = { ...@@ -2743,6 +2789,8 @@ static const struct connection_ops conn_protseq_list[] = {
RPCRT4_default_is_authorized, RPCRT4_default_is_authorized,
RPCRT4_default_authorize, RPCRT4_default_authorize,
RPCRT4_default_secure_packet, RPCRT4_default_secure_packet,
RPCRT4_default_impersonate_client,
RPCRT4_default_revert_to_self,
}, },
{ "ncacn_http", { "ncacn_http",
{ EPM_PROTOCOL_NCACN, EPM_PROTOCOL_HTTP }, { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_HTTP },
...@@ -2760,6 +2808,8 @@ static const struct connection_ops conn_protseq_list[] = { ...@@ -2760,6 +2808,8 @@ static const struct connection_ops conn_protseq_list[] = {
RPCRT4_default_is_authorized, RPCRT4_default_is_authorized,
RPCRT4_default_authorize, RPCRT4_default_authorize,
RPCRT4_default_secure_packet, 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