Module: wine Branch: master Commit: d918587f1d15437f42ad57086f637668a95754a9 URL: http://source.winehq.org/git/wine.git/?a=commit;h=d918587f1d15437f42ad57086f...
Author: Rob Shearman robertshearman@gmail.com Date: Sun Dec 13 21:36:01 2009 +0000
rpcrt4: Implement client impersonation.
---
dlls/rpcrt4/rpc_binding.c | 32 ++++++++++++++++++------ dlls/rpcrt4/rpc_binding.h | 14 ++++++++++ dlls/rpcrt4/rpc_message.c | 56 +++++++++++++++++++++++++++++++++++++++++++ dlls/rpcrt4/rpc_message.h | 2 + dlls/rpcrt4/rpc_transport.c | 50 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 146 insertions(+), 8 deletions(-)
diff --git a/dlls/rpcrt4/rpc_binding.c b/dlls/rpcrt4/rpc_binding.c index a4dff4a..68ab461 100644 --- a/dlls/rpcrt4/rpc_binding.c +++ b/dlls/rpcrt4/rpc_binding.c @@ -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); }
/*********************************************************************** diff --git a/dlls/rpcrt4/rpc_binding.h b/dlls/rpcrt4/rpc_binding.h index fc3fd7d..908967c 100644 --- a/dlls/rpcrt4/rpc_binding.h +++ b/dlls/rpcrt4/rpc_binding.h @@ -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); diff --git a/dlls/rpcrt4/rpc_message.c b/dlls/rpcrt4/rpc_message.c index 0f4b61c..520f247 100644 --- a/dlls/rpcrt4/rpc_message.c +++ b/dlls/rpcrt4/rpc_message.c @@ -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. diff --git a/dlls/rpcrt4/rpc_message.h b/dlls/rpcrt4/rpc_message.h index 07a2581..2a441d6 100644 --- a/dlls/rpcrt4/rpc_message.h +++ b/dlls/rpcrt4/rpc_message.h @@ -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 diff --git a/dlls/rpcrt4/rpc_transport.c b/dlls/rpcrt4/rpc_transport.c index f8c8d1f..6dbac41 100644 --- a/dlls/rpcrt4/rpc_transport.c +++ b/dlls/rpcrt4/rpc_transport.c @@ -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, }, };