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