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