Rob Shearman : rpcrt4: Implement client impersonation.
Alexandre Julliard
julliard at winehq.org
Mon Dec 14 09:51:19 CST 2009
Module: wine
Branch: master
Commit: d918587f1d15437f42ad57086f637668a95754a9
URL: http://source.winehq.org/git/wine.git/?a=commit;h=d918587f1d15437f42ad57086f637668a95754a9
Author: Rob Shearman <robertshearman at 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,
},
};
More information about the wine-cvs
mailing list