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

This commit is contained in:
Rob Shearman 2007-01-19 06:59:35 -06:00 committed by Alexandre Julliard
parent fda7775c7d
commit 4b79a0252a
3 changed files with 188 additions and 10 deletions

View File

@ -224,6 +224,8 @@ RPC_STATUS RPCRT4_DestroyBinding(RpcBinding* Binding)
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* Binding, RpcConnection** Connection,
/* 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* Binding, RpcConnection** Connection,
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(unsigned long AuthnLevel, unsigned long Aut
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 *AuthInfo)
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_HANDLE Binding, RPC_CSTR ServerPrincName,
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_HANDLE Binding, RPC_WSTR ServerPrincName,
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;

View File

@ -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 @@ void RPCRT4_strfree(LPSTR src);
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);

View File

@ -219,7 +219,7 @@ static RPC_STATUS rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq* protseq
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_np_open_endpoint(RpcServerProtseq *protse
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_ip_tcp_open_endpoint(RpcServerProtseq *pr
}
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(RpcConnection* Connection)
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(RpcConnection** Connection, BOOL server,
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(RpcConnection** Connection, BOOL server,
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(RpcConnection** Connection, RpcConnection* Old
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(RpcConnection* Connection)
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;
}