rpcrt4: Track the security quality of service settings for bindings and connections.
This commit is contained in:
parent
fda7775c7d
commit
4b79a0252a
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue