rpcrt4: Track the security quality of service settings for bindings and connections.

Robert Shearman rob at codeweavers.com
Fri Jan 19 06:59:35 CST 2007


---
  dlls/rpcrt4/rpc_binding.c   |  164 
++++++++++++++++++++++++++++++++++++++++++-
  dlls/rpcrt4/rpc_binding.h   |   15 +++-
  dlls/rpcrt4/rpc_transport.c |   19 +++--
  3 files changed, 188 insertions(+), 10 deletions(-)
-------------- next part --------------
diff --git a/dlls/rpcrt4/rpc_binding.c b/dlls/rpcrt4/rpc_binding.c
index 7b55f21..d56b4fa 100644
--- a/dlls/rpcrt4/rpc_binding.c
+++ b/dlls/rpcrt4/rpc_binding.c
@@ -224,6 +224,8 @@ RPC_STATUS RPCRT4_DestroyBinding(RpcBind
   RPCRT4_strfree(Binding->Endpoint);
   RPCRT4_strfree(Binding->NetworkAddr);
   RPCRT4_strfree(Binding->Protseq);
+  if (Binding->AuthInfo) RpcAuthInfo_Release(Binding->AuthInfo);
+  if (Binding->QOS) RpcQualityOfService_Release(Binding->QOS);
   HeapFree(GetProcessHeap(), 0, Binding);
   return RPC_S_OK;
 }
@@ -241,7 +243,7 @@ RPC_STATUS RPCRT4_OpenBinding(RpcBinding
     /* try to find a compatible connection from the connection pool */
     NewConnection = RPCRT4_GetIdleConnection(InterfaceId, TransferSyntax,
         Binding->Protseq, Binding->NetworkAddr, Binding->Endpoint,
-        Binding->AuthInfo);
+        Binding->AuthInfo, Binding->QOS);
     if (NewConnection) {
       *Connection = NewConnection;
       return RPC_S_OK;
@@ -258,7 +260,7 @@ RPC_STATUS RPCRT4_OpenBinding(RpcBinding
   status = RPCRT4_CreateConnection(&NewConnection, Binding->server,
                                    Binding->Protseq, Binding->NetworkAddr,
                                    Binding->Endpoint, NULL, Binding->AuthInfo,
-                                   Binding);
+                                   Binding->QOS, Binding);
   if (status != RPC_S_OK)
     return status;
 
@@ -874,6 +876,8 @@ RPC_STATUS RPC_ENTRY RpcBindingCopy(
 
   if (SrcBinding->AuthInfo) RpcAuthInfo_AddRef(SrcBinding->AuthInfo);
   DestBinding->AuthInfo = SrcBinding->AuthInfo;
+  if (SrcBinding->QOS) RpcQualityOfService_AddRef(SrcBinding->QOS);
+  DestBinding->QOS = SrcBinding->QOS;
 
   *DestinationBinding = DestBinding;
   return RPC_S_OK;
@@ -934,6 +938,7 @@ static RPC_STATUS RpcAuthInfo_Create(uns
     if (!AuthInfo)
         return ERROR_OUTOFMEMORY;
 
+    AuthInfo->refs = 1;
     AuthInfo->AuthnLevel = AuthnLevel;
     AuthInfo->AuthnSvc = AuthnSvc;
     AuthInfo->cred = cred;
@@ -960,6 +965,101 @@ ULONG RpcAuthInfo_Release(RpcAuthInfo *A
     return refs;
 }
 
+static RPC_STATUS RpcQualityOfService_Create(const RPC_SECURITY_QOS *qos_src, BOOL unicode, RpcQualityOfService **qos_dst)
+{
+    RpcQualityOfService *qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos));
+
+    if (!qos)
+        return RPC_S_OUT_OF_RESOURCES;
+
+    qos->refs = 1;
+    qos->qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos->qos));
+    if (!qos->qos) goto error;
+    qos->qos->Version = qos_src->Version;
+    qos->qos->Capabilities = qos_src->Capabilities;
+    qos->qos->IdentityTracking = qos_src->IdentityTracking;
+    qos->qos->ImpersonationType = qos_src->ImpersonationType;
+    qos->qos->AdditionalSecurityInfoType = 0;
+
+    if (qos_src->Version >= 2)
+    {
+        const RPC_SECURITY_QOS_V2_W *qos_src2 = (const RPC_SECURITY_QOS_V2_W *)qos_src;
+        qos->qos->AdditionalSecurityInfoType = qos_src2->AdditionalSecurityInfoType;
+        if (qos_src2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
+        {
+            const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_src = qos_src2->u.HttpCredentials;
+            RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_dst;
+
+            http_credentials_dst = HeapAlloc(GetProcessHeap(), 0, sizeof(*http_credentials_dst));
+            qos->qos->u.HttpCredentials = http_credentials_dst;
+            if (!http_credentials_dst) goto error;
+            http_credentials_dst->TransportCredentials = http_credentials_src->TransportCredentials;
+            http_credentials_dst->Flags = http_credentials_src->Flags;
+            http_credentials_dst->AuthenticationTarget = http_credentials_src->AuthenticationTarget;
+            http_credentials_dst->NumberOfAuthnSchemes = http_credentials_src->NumberOfAuthnSchemes;
+            http_credentials_dst->AuthnSchemes = NULL;
+            http_credentials_dst->ServerCertificateSubject = NULL;
+            if (http_credentials_src->NumberOfAuthnSchemes)
+            {
+                http_credentials_dst->AuthnSchemes = HeapAlloc(GetProcessHeap(), 0, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes));
+                if (!http_credentials_dst->AuthnSchemes) goto error;
+                memcpy(http_credentials_dst->AuthnSchemes, http_credentials_src->AuthnSchemes, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes));
+            }
+            if (http_credentials_src->ServerCertificateSubject)
+            {
+                if (unicode)
+                    http_credentials_dst->ServerCertificateSubject =
+                        RPCRT4_strndupW(http_credentials_src->ServerCertificateSubject,
+                                        strlenW(http_credentials_src->ServerCertificateSubject));
+                else
+                    http_credentials_dst->ServerCertificateSubject =
+                        RPCRT4_strdupAtoW((char *)http_credentials_src->ServerCertificateSubject);
+                if (!http_credentials_dst->ServerCertificateSubject) goto error;
+            }
+        }
+    }
+    *qos_dst = qos;
+    return RPC_S_OK;
+
+error:
+    if (qos->qos)
+    {
+        if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP &&
+            qos->qos->u.HttpCredentials)
+        {
+            HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes);
+            HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject);
+            HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials);
+        }
+        HeapFree(GetProcessHeap(), 0, qos->qos);
+    }
+    HeapFree(GetProcessHeap(), 0, qos);
+    return RPC_S_OUT_OF_RESOURCES;
+}
+
+ULONG RpcQualityOfService_AddRef(RpcQualityOfService *qos)
+{
+    return InterlockedIncrement(&qos->refs);
+}
+
+ULONG RpcQualityOfService_Release(RpcQualityOfService *qos)
+{
+    ULONG refs = InterlockedDecrement(&qos->refs);
+
+    if (!refs)
+    {
+        if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
+        {
+            HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes);
+            HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject);
+            HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials);
+        }
+        HeapFree(GetProcessHeap(), 0, qos->qos);
+        HeapFree(GetProcessHeap(), 0, qos);
+    }
+    return refs;
+}
+
 /***********************************************************************
  *             RpcRevertToSelf (RPCRT4.@)
  */
@@ -1049,6 +1149,36 @@ RpcBindingSetAuthInfoExA( RPC_BINDING_HA
   TRACE("%p %s %lu %lu %p %lu %p\n", Binding, debugstr_a((const char*)ServerPrincName),
         AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
 
+  if (SecurityQos)
+  {
+      RPC_STATUS status;
+      
+      TRACE("SecurityQos { Version=%ld, Capabilties=0x%lx, IdentityTracking=%ld, ImpersonationLevel=%ld",
+            SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType);
+      if (SecurityQos->Version >= 2)
+      {
+          const RPC_SECURITY_QOS_V2_A *SecurityQos2 = (const RPC_SECURITY_QOS_V2_A *)SecurityQos;
+          TRACE(", AdditionalSecurityInfoType=%ld", SecurityQos2->AdditionalSecurityInfoType);
+          if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
+              TRACE(", { %p, 0x%lx, %ld, %ld, %p, %s }",
+                    SecurityQos2->u.HttpCredentials->TransportCredentials,
+                    SecurityQos2->u.HttpCredentials->Flags,
+                    SecurityQos2->u.HttpCredentials->AuthenticationTarget,
+                    SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes,
+                    SecurityQos2->u.HttpCredentials->AuthnSchemes,
+                    SecurityQos2->u.HttpCredentials->ServerCertificateSubject);
+      }
+      TRACE("}\n");
+      status = RpcQualityOfService_Create(SecurityQos, FALSE, &bind->QOS);
+      if (status != RPC_S_OK)
+          return status;
+  }
+  else
+  {
+      if (bind->QOS) RpcQualityOfService_Release(bind->QOS);
+      bind->QOS = NULL;
+  }
+  
   if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
     AuthnSvc = RPC_C_AUTHN_WINNT;
 
@@ -1135,6 +1265,36 @@ RpcBindingSetAuthInfoExW( RPC_BINDING_HA
   TRACE("%p %s %lu %lu %p %lu %p\n", Binding, debugstr_w((const WCHAR*)ServerPrincName),
         AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
 
+  if (SecurityQos)
+  {
+      RPC_STATUS status;
+
+      TRACE("SecurityQos { Version=%ld, Capabilties=0x%lx, IdentityTracking=%ld, ImpersonationLevel=%ld",
+            SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType);
+      if (SecurityQos->Version >= 2)
+      {
+          const RPC_SECURITY_QOS_V2_W *SecurityQos2 = (const RPC_SECURITY_QOS_V2_W *)SecurityQos;
+          TRACE(", AdditionalSecurityInfoType=%ld", SecurityQos2->AdditionalSecurityInfoType);
+          if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
+              TRACE(", { %p, 0x%lx, %ld, %ld, %p, %s }",
+                    SecurityQos2->u.HttpCredentials->TransportCredentials,
+                    SecurityQos2->u.HttpCredentials->Flags,
+                    SecurityQos2->u.HttpCredentials->AuthenticationTarget,
+                    SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes,
+                    SecurityQos2->u.HttpCredentials->AuthnSchemes,
+                    debugstr_w(SecurityQos2->u.HttpCredentials->ServerCertificateSubject));
+      }
+      TRACE("}\n");
+      status = RpcQualityOfService_Create(SecurityQos, TRUE, &bind->QOS);
+      if (status != RPC_S_OK)
+          return status;
+  }
+  else
+  {
+      if (bind->QOS) RpcQualityOfService_Release(bind->QOS);
+      bind->QOS = NULL;
+  }
+  
   if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
     AuthnSvc = RPC_C_AUTHN_WINNT;
 
diff --git a/dlls/rpcrt4/rpc_binding.h b/dlls/rpcrt4/rpc_binding.h
index 4df3d73..6b5ca21 100644
--- a/dlls/rpcrt4/rpc_binding.h
+++ b/dlls/rpcrt4/rpc_binding.h
@@ -36,6 +36,13 @@ typedef struct _RpcAuthInfo
   TimeStamp exp;
 } RpcAuthInfo;
 
+typedef struct _RpcQualityOfService
+{
+    LONG refs;
+
+    RPC_SECURITY_QOS_V2_W *qos;
+} RpcQualityOfService;
+
 struct connection_ops;
 
 typedef struct _RpcConnection
@@ -56,6 +63,7 @@ typedef struct _RpcConnection
   TimeStamp exp;
   ULONG attr;
   RpcAuthInfo *AuthInfo;
+  RpcQualityOfService *QOS;
 
   /* client-only */
   struct list conn_pool_entry;
@@ -90,6 +98,7 @@ typedef struct _RpcBinding
 
   /* authentication */
   RpcAuthInfo *AuthInfo;
+  RpcQualityOfService *QOS;
 } RpcBinding;
 
 LPSTR RPCRT4_strndupA(LPCSTR src, INT len);
@@ -103,10 +112,12 @@ #define RPCRT4_strdupW(x) RPCRT4_strndup
 
 ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo);
 ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo);
+ULONG RpcQualityOfService_AddRef(RpcQualityOfService *qos);
+ULONG RpcQualityOfService_Release(RpcQualityOfService *qos);
 
-RpcConnection *RPCRT4_GetIdleConnection(const RPC_SYNTAX_IDENTIFIER *InterfaceId, const RPC_SYNTAX_IDENTIFIER *TransferSyntax, LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, RpcAuthInfo* AuthInfo);
+RpcConnection *RPCRT4_GetIdleConnection(const RPC_SYNTAX_IDENTIFIER *InterfaceId, const RPC_SYNTAX_IDENTIFIER *TransferSyntax, LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, const RpcAuthInfo* AuthInfo, const RpcQualityOfService *QOS);
 void RPCRT4_ReleaseIdleConnection(RpcConnection *Connection);
-RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcBinding* Binding);
+RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS, RpcBinding* Binding);
 RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection);
 RPC_STATUS RPCRT4_OpenClientConnection(RpcConnection* Connection);
 RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection);
diff --git a/dlls/rpcrt4/rpc_transport.c b/dlls/rpcrt4/rpc_transport.c
index ceae31d..7f6d8a2 100644
--- a/dlls/rpcrt4/rpc_transport.c
+++ b/dlls/rpcrt4/rpc_transport.c
@@ -219,7 +219,7 @@ static RPC_STATUS rpcrt4_protseq_ncalrpc
   RpcConnection *Connection;
 
   r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL,
-                              endpoint, NULL, NULL, NULL);
+                              endpoint, NULL, NULL, NULL, NULL);
   if (r != RPC_S_OK)
       return r;
 
@@ -266,7 +266,7 @@ static RPC_STATUS rpcrt4_protseq_ncacn_n
   RpcConnection *Connection;
 
   r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL,
-                              endpoint, NULL, NULL, NULL);
+                              endpoint, NULL, NULL, NULL, NULL);
   if (r != RPC_S_OK)
     return r;
 
@@ -795,7 +795,8 @@ static RPC_STATUS rpcrt4_protseq_ncacn_i
         }
         create_status = RPCRT4_CreateConnection((RpcConnection **)&tcpc, TRUE,
                                                 protseq->Protseq, NULL,
-                                                endpoint, NULL, NULL, NULL);
+                                                endpoint, NULL, NULL, NULL,
+                                                NULL);
         if (create_status != RPC_S_OK)
         {
             close(sock);
@@ -1291,7 +1292,8 @@ RPC_STATUS RPCRT4_CloseConnection(RpcCon
 
 RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server,
     LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint,
-    LPCSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcBinding* Binding)
+    LPCSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS,
+    RpcBinding* Binding)
 {
   const struct connection_ops *ops;
   RpcConnection* NewConnection;
@@ -1317,6 +1319,8 @@ RPC_STATUS RPCRT4_CreateConnection(RpcCo
   SecInvalidateHandle(&NewConnection->ctx);
   if (AuthInfo) RpcAuthInfo_AddRef(AuthInfo);
   NewConnection->AuthInfo = AuthInfo;
+  if (QOS) RpcQualityOfService_AddRef(QOS);
+  NewConnection->QOS = QOS;
   list_init(&NewConnection->conn_pool_entry);
 
   TRACE("connection: %p\n", NewConnection);
@@ -1327,13 +1331,14 @@ RPC_STATUS RPCRT4_CreateConnection(RpcCo
 
 RpcConnection *RPCRT4_GetIdleConnection(const RPC_SYNTAX_IDENTIFIER *InterfaceId,
     const RPC_SYNTAX_IDENTIFIER *TransferSyntax, LPCSTR Protseq, LPCSTR NetworkAddr,
-    LPCSTR Endpoint, RpcAuthInfo* AuthInfo)
+    LPCSTR Endpoint, const RpcAuthInfo* AuthInfo, const RpcQualityOfService *QOS)
 {
   RpcConnection *Connection;
   /* try to find a compatible connection from the connection pool */
   EnterCriticalSection(&connection_pool_cs);
   LIST_FOR_EACH_ENTRY(Connection, &connection_pool, RpcConnection, conn_pool_entry)
     if ((Connection->AuthInfo == AuthInfo) &&
+        (Connection->QOS == QOS) &&
         !memcmp(&Connection->ActiveInterface, InterfaceId,
            sizeof(RPC_SYNTAX_IDENTIFIER)) &&
         !strcmp(rpcrt4_conn_get_name(Connection), Protseq) &&
@@ -1367,7 +1372,8 @@ RPC_STATUS RPCRT4_SpawnConnection(RpcCon
                                 rpcrt4_conn_get_name(OldConnection),
                                 OldConnection->NetworkAddr,
                                 OldConnection->Endpoint, NULL,
-                                OldConnection->AuthInfo, NULL);
+                                OldConnection->AuthInfo, OldConnection->QOS,
+                                NULL);
   if (err == RPC_S_OK)
     rpcrt4_conn_handoff(OldConnection, *Connection);
   return err;
@@ -1381,6 +1387,7 @@ RPC_STATUS RPCRT4_DestroyConnection(RpcC
   RPCRT4_strfree(Connection->Endpoint);
   RPCRT4_strfree(Connection->NetworkAddr);
   if (Connection->AuthInfo) RpcAuthInfo_Release(Connection->AuthInfo);
+  if (Connection->QOS) RpcQualityOfService_Release(Connection->QOS);
   HeapFree(GetProcessHeap(), 0, Connection);
   return RPC_S_OK;
 }


More information about the wine-patches mailing list