Made modifications to switch the client to communicate with ATSs over SSL. Still need to make changes to the linux rpc.c to have all of the necessary changes completed.
Also made a fix to allow credential store scoping all the way into the authentication mechanisms.
This commit is contained in:
parent
920c9c5dff
commit
c99e319a3a
@ -249,6 +249,7 @@ GetAuthTokenIf(
|
||||
CasaStatus
|
||||
GetAuthMechToken(
|
||||
IN AuthContext *pAuthContext,
|
||||
IN void *pCredStoreScope,
|
||||
INOUT char **ppAuthToken)
|
||||
//
|
||||
// Arguments:
|
||||
@ -285,6 +286,7 @@ GetAuthMechToken(
|
||||
retStatus = pAuthTokenIf->getAuthToken(pAuthTokenIf,
|
||||
pAuthContext->pContext,
|
||||
pAuthContext->pMechInfo,
|
||||
pCredStoreScope,
|
||||
pAuthToken,
|
||||
&authTokenBufLen);
|
||||
if (CasaStatusCode(retStatus) == CASA_STATUS_BUFFER_OVERFLOW)
|
||||
@ -297,6 +299,7 @@ GetAuthMechToken(
|
||||
retStatus = pAuthTokenIf->getAuthToken(pAuthTokenIf,
|
||||
pAuthContext->pContext,
|
||||
pAuthContext->pMechInfo,
|
||||
pCredStoreScope,
|
||||
pAuthToken,
|
||||
&authTokenBufLen);
|
||||
if (CASA_SUCCESS(retStatus))
|
||||
|
@ -25,24 +25,62 @@
|
||||
# Description: Used to configure the port utilized by the
|
||||
# ATS to listen for connections.
|
||||
#
|
||||
# If this parameter is not set, the client
|
||||
# assummes that the ATS is listening for
|
||||
# connections on port 443 if configured to
|
||||
# use SSL, otherwise it assumes that it is
|
||||
# listening for connections on port 80.
|
||||
# If this parameter is not set ....
|
||||
#
|
||||
ATS-port 8080
|
||||
#ATS-port 2645
|
||||
|
||||
#
|
||||
# UseSSL setting.
|
||||
# DisableSecureConnections setting.
|
||||
#
|
||||
# Description: Used to specify that communications to the ATS
|
||||
# should occur over SSL to ensure security.
|
||||
# Description: Used to disable the use of secure connections (SSL) between
|
||||
# the Client and ATSs.
|
||||
#
|
||||
# If this parameter is not set, the client
|
||||
# defaults to using SSL when communicating with
|
||||
# If this parameter is not set to true, the client
|
||||
# defaults to communicating securedly with ATSs.
|
||||
#
|
||||
# Security Note: Disabling secure connections allows
|
||||
# malicious users/processes to view confidential
|
||||
# information such as username/passwords and to tamper
|
||||
# with client-ATS communications without being detected.
|
||||
# You should not disable secure connections unless you are
|
||||
# trying to debug the authentication token infrastructure.
|
||||
#
|
||||
#DisableSecureConnections false
|
||||
|
||||
#
|
||||
# AllowInvalidCerts setting.
|
||||
#
|
||||
# Description: Used to specify that the client should ignore
|
||||
# invalid certificates presented by ATSs when
|
||||
# performing SSL communications.
|
||||
#
|
||||
# If this parameter is not set to true, the client defaults
|
||||
# to not ignoring invalid certificates presented by ATSs.
|
||||
# ATSs.
|
||||
#
|
||||
UseSSL false
|
||||
|
||||
# Security Note: Ignoring invalid certificates downgrades the
|
||||
# security of your infrastructure by allowing a malicious
|
||||
# process to impersonate an ATS and obtain information that
|
||||
# is confidential such as username and passwords.
|
||||
#
|
||||
AllowInvalidCerts true
|
||||
|
||||
#
|
||||
# UsersCannotAllowInvalidCerts setting.
|
||||
#
|
||||
# Description: Used to specify that the client should not allow users to
|
||||
# decide that invalid certificates presented by ATSs should be
|
||||
# ignored.
|
||||
#
|
||||
# If this parameter is not set to true, the client defaults
|
||||
# to allow users to choose whether or not invalid certificates
|
||||
# presented by ATSs.
|
||||
#
|
||||
# If this parameter is set to true then users are not consulted
|
||||
# when an invalid server certificate is received and communications
|
||||
# between the client and the ATS fail.
|
||||
#
|
||||
# Note: This parameter has no effect if the setting AllowInvalidCerts
|
||||
# is set to true.
|
||||
#
|
||||
#UsersCannotAllowInvalidCerts true
|
||||
|
@ -47,9 +47,9 @@ int DebugLevel = 0;
|
||||
// Operating parameter
|
||||
//
|
||||
bool g_bInitialized = false;
|
||||
bool g_secureRpcSetting = true;
|
||||
long g_rpcFlags = SECURE_RPC_FLAG | ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG;
|
||||
char *g_pATSHostName = NULL;
|
||||
uint16_t g_ATSPort = 443; // Default HTTPS
|
||||
uint16_t g_ATSPort = 2645;
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
@ -138,7 +138,9 @@ ObtainSessionToken(
|
||||
int respLen;
|
||||
|
||||
// Get authentication mechanism token
|
||||
retStatus = GetAuthMechToken(pAuthContext, &pAuthMechToken);
|
||||
retStatus = GetAuthMechToken(pAuthContext,
|
||||
pCredStoreScope,
|
||||
&pAuthMechToken);
|
||||
if (!CASA_SUCCESS(retStatus))
|
||||
{
|
||||
// We were not able to obtain an authentication mechanism token
|
||||
@ -156,7 +158,7 @@ ObtainSessionToken(
|
||||
// Issue rpc
|
||||
retStatus = Rpc(pRpcSession,
|
||||
"Authenticate",
|
||||
g_secureRpcSetting,
|
||||
g_rpcFlags,
|
||||
pReqMsg,
|
||||
&pRespMsg,
|
||||
&respLen);
|
||||
@ -307,7 +309,7 @@ ObtainAuthTokenFromServer(
|
||||
// Issue rpc
|
||||
retStatus = Rpc(pRpcSession,
|
||||
"GetAuthPolicy",
|
||||
g_secureRpcSetting,
|
||||
g_rpcFlags,
|
||||
pReqMsg,
|
||||
&pRespMsg,
|
||||
&respLen);
|
||||
@ -342,7 +344,7 @@ ObtainAuthTokenFromServer(
|
||||
// Issue rpc
|
||||
retStatus = Rpc(pRpcSession,
|
||||
"GetAuthToken",
|
||||
g_secureRpcSetting,
|
||||
g_rpcFlags,
|
||||
pReqMsg,
|
||||
&pRespMsg,
|
||||
&respLen);
|
||||
@ -733,7 +735,9 @@ InitializeLibrary(void)
|
||||
int getConfigStatus = -1;
|
||||
ConfigIf *pClientConfigIf;
|
||||
char *pATSPortSetting;
|
||||
char *pUseSSLSetting;
|
||||
char *pDisableSecureConnections;
|
||||
char *pAllowInvalidCerts;
|
||||
char *pUsersCannotAllowInvalidCerts;
|
||||
|
||||
DbgTrace(1, "-InitializeLibrary- Start\n", 0);
|
||||
|
||||
@ -748,37 +752,85 @@ InitializeLibrary(void)
|
||||
g_pATSHostName = pClientConfigIf->getEntryValue(pClientConfigIf, "ATS-hostname");
|
||||
if (g_pATSHostName != NULL)
|
||||
{
|
||||
DbgTrace(0, "-InitializeLibrary- ATS hostname %s configured\n", g_pATSHostName);
|
||||
DbgTrace(0, "-InitializeLibrary- ATS hostname configured = %s\n", g_pATSHostName);
|
||||
}
|
||||
|
||||
// Check if the UseSSL setting has been configured
|
||||
pUseSSLSetting = pClientConfigIf->getEntryValue(pClientConfigIf, "UseSSL");
|
||||
if (pUseSSLSetting != NULL)
|
||||
// Check if the DisableSecureConnections setting has been configured
|
||||
pDisableSecureConnections = pClientConfigIf->getEntryValue(pClientConfigIf, "DisableSecureConnections");
|
||||
if (pDisableSecureConnections != NULL)
|
||||
{
|
||||
DbgTrace(0, "-InitializeLibrary- UseSSL setting %s configured\n", pUseSSLSetting);
|
||||
DbgTrace(0, "-InitializeLibrary- DisableSecureConnections setting configured = %s\n", pDisableSecureConnections);
|
||||
|
||||
// Set the g_secureRpcSetting variable based on the setting
|
||||
if (stricmp(pUseSSLSetting, "false") == 0)
|
||||
// Adjust the g_rpcFlags variable based on the setting
|
||||
if (stricmp(pDisableSecureConnections, "true") == 0)
|
||||
{
|
||||
g_secureRpcSetting = false;
|
||||
g_rpcFlags &= ~SECURE_RPC_FLAG;
|
||||
|
||||
// Change the default ATS port to 80 from 443
|
||||
g_ATSPort = 80;
|
||||
}
|
||||
else if (stricmp(pUseSSLSetting, "true") == 0)
|
||||
else if (stricmp(pDisableSecureConnections, "false") == 0)
|
||||
{
|
||||
g_secureRpcSetting = true;
|
||||
g_rpcFlags |= SECURE_RPC_FLAG;
|
||||
}
|
||||
|
||||
// Free the buffer holding the UseSSL setting
|
||||
free(pUseSSLSetting);
|
||||
// Free the buffer holding the DisableSecureConnections setting
|
||||
free(pDisableSecureConnections);
|
||||
}
|
||||
|
||||
// Check the AllowInvalidCerts setting if using secure connections
|
||||
if (g_rpcFlags & SECURE_RPC_FLAG)
|
||||
{
|
||||
// Check if the AllowInvalidCerts setting has been configured
|
||||
pAllowInvalidCerts = pClientConfigIf->getEntryValue(pClientConfigIf, "AllowInvalidCerts");
|
||||
if (pAllowInvalidCerts != NULL)
|
||||
{
|
||||
DbgTrace(0, "-InitializeLibrary- AllowInvalidCerts setting configured = %s\n", pAllowInvalidCerts);
|
||||
|
||||
// Adjust the g_rpcFlags variable based on the setting
|
||||
if (stricmp(pAllowInvalidCerts, "false") == 0)
|
||||
{
|
||||
g_rpcFlags &= ~ALLOW_INVALID_CERTS_RPC_FLAG;
|
||||
}
|
||||
else if (stricmp(pAllowInvalidCerts, "true") == 0)
|
||||
{
|
||||
g_rpcFlags |= ALLOW_INVALID_CERTS_RPC_FLAG;
|
||||
}
|
||||
|
||||
// Free the buffer holding the AllowInvalidCerts setting
|
||||
free(pAllowInvalidCerts);
|
||||
}
|
||||
|
||||
// Check the UsersCannotAllowInvalidCerts setting if not allowing invalid certs.
|
||||
if ((g_rpcFlags & ALLOW_INVALID_CERTS_RPC_FLAG) == 0)
|
||||
{
|
||||
// Check if the UsersCannotAllowInvalidCerts setting has been configured
|
||||
pUsersCannotAllowInvalidCerts = pClientConfigIf->getEntryValue(pClientConfigIf, "UsersCannotAllowInvalidCerts");
|
||||
if (pUsersCannotAllowInvalidCerts != NULL)
|
||||
{
|
||||
DbgTrace(0, "-InitializeLibrary- UsersCannotAllowInvalidCerts setting configured = %s\n", pUsersCannotAllowInvalidCerts);
|
||||
|
||||
// Adjust the g_rpcFlags variable based on the setting
|
||||
if (stricmp(pUsersCannotAllowInvalidCerts, "false") == 0)
|
||||
{
|
||||
g_rpcFlags |= ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG;
|
||||
}
|
||||
else if (stricmp(pUsersCannotAllowInvalidCerts, "true") == 0)
|
||||
{
|
||||
g_rpcFlags &= ~ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG;
|
||||
}
|
||||
|
||||
// Free the buffer holding the UsersCannotAllowInvalidCerts setting
|
||||
free(pUsersCannotAllowInvalidCerts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if an ATS port number has been configured
|
||||
pATSPortSetting = pClientConfigIf->getEntryValue(pClientConfigIf, "ATS-port");
|
||||
if (pATSPortSetting != NULL)
|
||||
{
|
||||
DbgTrace(0, "-InitializeLibrary- ATS port number %s configured\n", pATSPortSetting);
|
||||
DbgTrace(0, "-InitializeLibrary- ATS port number configured = %s\n", pATSPortSetting);
|
||||
|
||||
// Convert the number to hex
|
||||
g_ATSPort = (int) dtoul(pATSPortSetting, strlen(pATSPortSetting));
|
||||
|
@ -149,6 +149,7 @@ extern
|
||||
CasaStatus
|
||||
GetAuthMechToken(
|
||||
IN AuthContext *pAuthContext,
|
||||
IN void *pCredStoreScope,
|
||||
INOUT char **ppAuthMechToken);
|
||||
|
||||
//
|
||||
@ -358,12 +359,16 @@ void
|
||||
CloseRpcSession(
|
||||
IN RpcSession *pSession);
|
||||
|
||||
#define SECURE_RPC_FLAG 1
|
||||
#define ALLOW_INVALID_CERTS_RPC_FLAG 2
|
||||
#define ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG 4
|
||||
|
||||
extern
|
||||
CasaStatus
|
||||
Rpc(
|
||||
IN RpcSession *pSession,
|
||||
IN char *pMethod,
|
||||
IN bool secure,
|
||||
IN long flags,
|
||||
IN char *pRequestData,
|
||||
INOUT char **ppResponseData,
|
||||
INOUT int *pResponseDataLen);
|
||||
@ -373,7 +378,7 @@ CasaStatus
|
||||
InitializeRpc(void);
|
||||
|
||||
//
|
||||
// Defined in utils.c
|
||||
// Functions exported by utils.c
|
||||
//
|
||||
|
||||
extern
|
||||
@ -398,6 +403,32 @@ dtoul(
|
||||
IN const char *cp,
|
||||
IN const int len);
|
||||
|
||||
//
|
||||
// Functions exported by invalidcert.c
|
||||
//
|
||||
|
||||
extern
|
||||
bool
|
||||
InvalidCertsFromHostAllowed(
|
||||
IN char *pHostName);
|
||||
|
||||
extern
|
||||
void
|
||||
AllowInvalidCertsFromHost(
|
||||
IN char *pHostName);
|
||||
|
||||
#define INVALID_CERT_CA_FLAG 1
|
||||
#define INVALID_CERT_CN_FLAG 2
|
||||
#define INVALID_CERT_DATE_FLAG 4
|
||||
|
||||
extern
|
||||
bool
|
||||
UserApprovedCert(
|
||||
IN char *pHostName,
|
||||
IN char *pCertSubject,
|
||||
IN char *pCertIssuer,
|
||||
IN long invalidCertFlags);
|
||||
|
||||
|
||||
//=========================================================================
|
||||
|
||||
|
140
CASA-auth-token/non-java/client/invalidcert.c
Normal file
140
CASA-auth-token/non-java/client/invalidcert.c
Normal file
@ -0,0 +1,140 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, Novell, Inc.
|
||||
*
|
||||
* To contact Novell about this file by physical or electronic mail,
|
||||
* you may find current contact information at www.novell.com.
|
||||
*
|
||||
* Author: Juan Carlos Luciani <jluciani@novell.com>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
//===[ Include files ]=====================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
//===[ Type definitions ]==================================================
|
||||
|
||||
//===[ Function prototypes ]===============================================
|
||||
|
||||
//===[ Global variables ]==================================================
|
||||
|
||||
//++=======================================================================
|
||||
bool
|
||||
InvalidCertsFromHostAllowed(
|
||||
IN char *pHostName)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L0
|
||||
//=======================================================================--
|
||||
{
|
||||
bool retStatus = false;
|
||||
|
||||
DbgTrace(2, "-InvalidCertsFromHostAllowed- Start\n", 0);
|
||||
|
||||
// tbd
|
||||
|
||||
DbgTrace(2, "-InvalidCertsFromHostAllowed- End, retStatus = %0X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
void
|
||||
AllowInvalidCertsFromHost(
|
||||
IN char *pHostName)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L0
|
||||
//=======================================================================--
|
||||
{
|
||||
bool retStatus = true;
|
||||
|
||||
DbgTrace(2, "-AllowInvalidCertsFromHost- Start\n", 0);
|
||||
|
||||
// tbd
|
||||
|
||||
DbgTrace(2, "-AllowInvalidCertsFromHost- End\n", 0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
bool
|
||||
UserApprovedCert(
|
||||
IN char *pHostName,
|
||||
IN char *pCertSubject,
|
||||
IN char *pCertIssuer,
|
||||
IN long invalidCertFlags)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L0
|
||||
//=======================================================================--
|
||||
{
|
||||
bool retStatus = false;
|
||||
|
||||
DbgTrace(2, "-UserApprovedCert- Start\n", 0);
|
||||
|
||||
// tbd
|
||||
|
||||
if (invalidCertFlags & INVALID_CERT_CN_FLAG)
|
||||
{
|
||||
DbgTrace(0, "-UserApprovedCert- Invalid Cert from Host = %s\n", pHostName);
|
||||
}
|
||||
if (invalidCertFlags & INVALID_CERT_CA_FLAG)
|
||||
{
|
||||
DbgTrace(0, "-UserApprovedCert- Invalid CA in Cert from Host = %s\n", pHostName);
|
||||
}
|
||||
if (invalidCertFlags & INVALID_CERT_DATE_FLAG)
|
||||
{
|
||||
DbgTrace(0, "-UserApprovedCert- Invalid DATE in Cert from Host = %s\n", pHostName);
|
||||
}
|
||||
DbgTrace(0, "-UserApprovedCert- Approving Invalid Cert from Host = %s\n", pHostName);
|
||||
DbgTrace(0, "-UserApprovedCert- Invalid Cert Subject = %s\n", pCertSubject);
|
||||
DbgTrace(0, "-UserApprovedCert- Invalid Cert Issuer = %s\n", pCertIssuer);
|
||||
|
||||
DbgTrace(2, "-UserApprovedCert- End, retStatus = %0X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
|
@ -294,7 +294,7 @@ CasaStatus
|
||||
InternalRpc(
|
||||
IN RpcSession *pSession,
|
||||
IN char *pMethod,
|
||||
IN bool secure,
|
||||
IN long flags,
|
||||
IN char *pRequestData,
|
||||
INOUT char **ppResponseData,
|
||||
INOUT int *pResponseDataLen)
|
||||
@ -324,7 +324,7 @@ InternalRpc(
|
||||
*pResponseDataLen = 0;
|
||||
|
||||
// Setup the URL using the input parameters
|
||||
if (secure)
|
||||
if (flags & SECURE_RPC_FLAG)
|
||||
{
|
||||
pPartialUrl = pSession->pPartialHttpsUrl;
|
||||
partialUrlLen = pSession->partialHttpsUrlLen;
|
||||
@ -449,7 +449,7 @@ CasaStatus
|
||||
Rpc(
|
||||
IN RpcSession *pSession,
|
||||
IN char *pMethod,
|
||||
IN bool secure,
|
||||
IN long flags,
|
||||
IN char *pRequestData,
|
||||
INOUT char **ppResponseData,
|
||||
INOUT int *pResponseDataLen)
|
||||
@ -476,7 +476,7 @@ Rpc(
|
||||
// Issue the RPC
|
||||
retStatus = InternalRpc(pSession,
|
||||
pMethod,
|
||||
secure,
|
||||
flags,
|
||||
pRequestData,
|
||||
ppResponseData,
|
||||
pResponseDataLen);
|
||||
|
@ -88,6 +88,7 @@ CasaStatus
|
||||
IN const void *pIfInstance,
|
||||
IN const char *pContext,
|
||||
IN const char *pMechInfo,
|
||||
IN void *pCredStoreScope,
|
||||
INOUT char *pTokenBuf,
|
||||
INOUT int *pTokenBufLen);
|
||||
//
|
||||
@ -95,10 +96,6 @@ CasaStatus
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// pServiceConfigIf -
|
||||
// Pointer to service config object to which the client is trying to
|
||||
// authenticate.
|
||||
//
|
||||
// pContext -
|
||||
// Pointer to null terminated string containing mechanism specific
|
||||
// context information. Another name for context is Authentication
|
||||
@ -112,6 +109,11 @@ CasaStatus
|
||||
// may be the service principal name to which the user will be
|
||||
// authenticating.
|
||||
//
|
||||
// pCredStoreScope -
|
||||
// Pointer to CASA structure for scoping credential store access
|
||||
// to specific users. This can only be leveraged when running in
|
||||
// the context of System under Windows.
|
||||
//
|
||||
// pTokenBuf -
|
||||
// Pointer to buffer that will receive the authentication
|
||||
// token. The length of this buffer is specified by the
|
||||
|
@ -57,6 +57,7 @@ AuthTokenIf_GetAuthToken(
|
||||
IN const void *pIfInstance,
|
||||
IN const char *pContext,
|
||||
IN const char *pMechInfo,
|
||||
IN void *pCredStoreScope,
|
||||
INOUT char *pTokenBuf,
|
||||
INOUT int *pTokenBufLen);
|
||||
|
||||
|
@ -40,6 +40,7 @@ AuthTokenIf_GetAuthToken(
|
||||
IN const void *pIfInstance,
|
||||
IN const char *pContext,
|
||||
IN const char *pMechInfo,
|
||||
IN void *pCredStoreScope,
|
||||
INOUT char *pTokenBuf,
|
||||
INOUT int *pTokenBufLen)
|
||||
//
|
||||
@ -47,10 +48,6 @@ AuthTokenIf_GetAuthToken(
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// pServiceConfigIf -
|
||||
// Pointer to service config object to which the client is trying to
|
||||
// authenticate.
|
||||
//
|
||||
// pContext -
|
||||
// Pointer to null terminated string containing mechanism specific
|
||||
// context information. Another name for context is Authentication
|
||||
@ -64,6 +61,11 @@ AuthTokenIf_GetAuthToken(
|
||||
// may be the service principal name to which the user will be
|
||||
// authenticating.
|
||||
//
|
||||
// pCredStoreScope -
|
||||
// Pointer to CASA structure for scoping credential store access
|
||||
// to specific users. This can only be leveraged when running in
|
||||
// the context of System under Windows.
|
||||
//
|
||||
// pTokenBuf -
|
||||
// Pointer to buffer that will receive the authentication
|
||||
// token. The length of this buffer is specified by the
|
||||
|
@ -39,6 +39,7 @@ static
|
||||
CasaStatus
|
||||
GetUserCredentials(
|
||||
IN const char *pRealm,
|
||||
IN void *pCredStoreScope,
|
||||
INOUT char **ppUsername,
|
||||
INOUT char **ppPassword)
|
||||
//
|
||||
@ -46,6 +47,11 @@ GetUserCredentials(
|
||||
// pRealm -
|
||||
// The realm to which the credentials apply.
|
||||
//
|
||||
// pCredStoreScope -
|
||||
// Pointer to CASA structure for scoping credential store access
|
||||
// to specific users. This can only be leveraged when running in
|
||||
// the context of System under Windows.
|
||||
//
|
||||
// ppUsername -
|
||||
// Pointer to variable that will receive buffer with the username.
|
||||
//
|
||||
@ -94,7 +100,7 @@ GetUserCredentials(
|
||||
NULL,
|
||||
&credtype,
|
||||
&credential,
|
||||
(SSCS_EXT_T*) NULL);
|
||||
(SSCS_EXT_T*) pCredStoreScope);
|
||||
if (rcode != NSSCS_SUCCESS)
|
||||
{
|
||||
// There were no credentials for the realm, now try to obtain the
|
||||
@ -106,7 +112,7 @@ GetUserCredentials(
|
||||
NULL,
|
||||
&credtype,
|
||||
&credential,
|
||||
(SSCS_EXT_T*) NULL);
|
||||
(SSCS_EXT_T*) pCredStoreScope);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -184,6 +190,7 @@ AuthTokenIf_GetAuthToken(
|
||||
IN const void *pIfInstance,
|
||||
IN const char *pContext,
|
||||
IN const char *pMechInfo,
|
||||
IN void *pCredStoreScope,
|
||||
INOUT char *pTokenBuf,
|
||||
INOUT int *pTokenBufLen)
|
||||
//
|
||||
@ -191,10 +198,6 @@ AuthTokenIf_GetAuthToken(
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// pServiceConfigIf -
|
||||
// Pointer to service config object to which the client is trying to
|
||||
// authenticate.
|
||||
//
|
||||
// pContext -
|
||||
// Pointer to null terminated string containing mechanism specific
|
||||
// context information. Another name for context is Authentication
|
||||
@ -208,6 +211,11 @@ AuthTokenIf_GetAuthToken(
|
||||
// may be the service principal name to which the user will be
|
||||
// authenticating.
|
||||
//
|
||||
// pCredStoreScope -
|
||||
// Pointer to CASA structure for scoping credential store access
|
||||
// to specific users. This can only be leveraged when running in
|
||||
// the context of System under Windows.
|
||||
//
|
||||
// pTokenBuf -
|
||||
// Pointer to buffer that will receive the authentication
|
||||
// token. The length of this buffer is specified by the
|
||||
@ -255,7 +263,10 @@ AuthTokenIf_GetAuthToken(
|
||||
}
|
||||
|
||||
// Get the user credentials
|
||||
retStatus = GetUserCredentials(pContext, &pUsername, &pPassword);
|
||||
retStatus = GetUserCredentials(pContext,
|
||||
pCredStoreScope,
|
||||
&pUsername,
|
||||
&pPassword);
|
||||
if (CASA_SUCCESS(retStatus))
|
||||
{
|
||||
// Now construct the PW token with the following format:
|
||||
|
@ -59,6 +59,7 @@ AuthTokenIf_GetAuthToken(
|
||||
IN const void *pIfInstance,
|
||||
IN const char *pContext,
|
||||
IN const char *pMechInfo,
|
||||
IN void *pCredStoreScope,
|
||||
INOUT char *pTokenBuf,
|
||||
INOUT int *pTokenBufLen);
|
||||
|
||||
|
@ -7,4 +7,5 @@ EXPORTS
|
||||
; DllUnregisterServer PRIVATE
|
||||
; DllGetClassObject PRIVATE
|
||||
ObtainAuthToken PRIVATE
|
||||
ObtainAuthTokenEx PRIVATE
|
||||
; DllCanUnloadNow PRIVATE
|
@ -21,7 +21,7 @@
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/D "XML_STATIC""
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=".;..\;..\..\include;"C:\Dev\casa\CASA-auth-token\non-java\include\windows";"\Program Files\novell\casa\include";"C:\Dev\Expat-2.0.0\Source\lib""
|
||||
AdditionalIncludeDirectories=".;..\;..\..\include;..\..\include\windows;"\Program Files\novell\casa\include";"C:\Dev\Expat-2.0.0\Source\lib""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
@ -35,7 +35,7 @@
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
IgnoreImportLibrary="FALSE"
|
||||
AdditionalOptions="/EXPORT:ObtainAuthToken"
|
||||
AdditionalOptions="/EXPORT:ObtainAuthToken /EXPORT:ObtainAuthTokenEx"
|
||||
AdditionalDependencies="ws2_32.lib winhttp.lib libexpatml.lib micasa.lib shlwapi.lib"
|
||||
OutputFile="$(OutDir)/authtoken.dll"
|
||||
LinkIncremental="1"
|
||||
@ -53,7 +53,7 @@
|
||||
mkdir \"Program Files"\novell\casa
|
||||
mkdir \"Program Files"\novell\casa\lib\
|
||||
copy $(OutDir)\authtoken.dll \"Program Files"\novell\casa\lib\authtoken.dll
|
||||
copy $(SolutionDir)client\windows\authtoken.lib \"Program Files"\novell\casa\lib\authtoken.lib
|
||||
copy $(SolutionDir)\client\windows\authtoken.lib \"Program Files"\novell\casa\lib\authtoken.lib
|
||||
"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
@ -81,7 +81,7 @@ copy $(SolutionDir)client\windows\authtoken.lib \"Program Files"\novel
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/D "XML_STATIC""
|
||||
AdditionalIncludeDirectories=".;..\;..\..\include;"C:\Dev\casa\CASA-auth-token\non-java\include\windows";"\Program Files\novell\casa\include";"C:\Dev\Expat-2.0.0\Source\lib""
|
||||
AdditionalIncludeDirectories=".;..\;..\..\include;..\..\include\windows;"\Program Files\novell\casa\include";"C:\Dev\Expat-2.0.0\Source\lib""
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="4"
|
||||
UsePrecompiledHeader="0"
|
||||
@ -92,7 +92,7 @@ copy $(SolutionDir)client\windows\authtoken.lib \"Program Files"\novel
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/EXPORT:ObtainAuthToken"
|
||||
AdditionalOptions="/EXPORT:ObtainAuthToken /EXPORT:ObtainAuthTokenEx"
|
||||
AdditionalDependencies="ws2_32.lib winhttp.lib libexpatml.lib micasa.lib shlwapi.lib"
|
||||
OutputFile="$(OutDir)/authtoken.dll"
|
||||
LinkIncremental="1"
|
||||
@ -111,7 +111,7 @@ copy $(SolutionDir)client\windows\authtoken.lib \"Program Files"\novel
|
||||
mkdir \"Program Files"\novell\casa
|
||||
mkdir \"Program Files"\novell\casa\lib\
|
||||
copy $(OutDir)\authtoken.dll \"Program Files"\novell\casa\lib\authtoken.dll
|
||||
copy $(SolutionDir)client\windows\authtoken.lib \"Program Files"\novell\casa\lib\authtoken.lib
|
||||
copy $(SolutionDir)\client\windows\authtoken.lib \"Program Files"\novell\casa\lib\authtoken.lib
|
||||
"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
@ -148,7 +148,7 @@ copy $(SolutionDir)client\windows\authtoken.lib \"Program Files"\novel
|
||||
RelativePath="..\authpolicy.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\win32\authtoken.def">
|
||||
RelativePath=".\authtoken.def">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\cache.c">
|
||||
@ -171,6 +171,9 @@ copy $(SolutionDir)client\windows\authtoken.lib \"Program Files"\novel
|
||||
<File
|
||||
RelativePath="..\gettokenmsg.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\invalidcert.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\platform.c">
|
||||
</File>
|
||||
|
@ -71,6 +71,7 @@ typedef struct _RpcSession
|
||||
{
|
||||
HINTERNET hSession;
|
||||
HINTERNET hConnection;
|
||||
char *pHostName;
|
||||
|
||||
} RpcSession, *PRpcSession;
|
||||
|
||||
|
@ -94,6 +94,62 @@ CopyMultiToWideAlloc(
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
static
|
||||
CasaStatus
|
||||
CopyWideToMultiAlloc(
|
||||
IN LPWSTR pWide,
|
||||
IN int wideSize,
|
||||
INOUT char **ppMulti,
|
||||
INOUT int *pMultiSize)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
int retStatus;
|
||||
int size, i;
|
||||
|
||||
DbgTrace(2, "-CopyWideToMultiAlloc- Start\n", 0);
|
||||
|
||||
size = wideSize + 1;
|
||||
|
||||
if ((*ppMulti = malloc(size)) != NULL)
|
||||
{
|
||||
for (i = 0; i < wideSize; i++)
|
||||
{
|
||||
*(*ppMulti + i) = (char) *(pWide + i);
|
||||
}
|
||||
|
||||
*(*ppMulti + i) = '\0';
|
||||
|
||||
if (pMultiSize)
|
||||
{
|
||||
*pMultiSize = size - 1;
|
||||
}
|
||||
|
||||
retStatus = CASA_STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
|
||||
DbgTrace(2, "-CopyWideToMultiAlloc- End, retStatus = %08X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
RpcSession*
|
||||
OpenRpcSession(
|
||||
@ -112,6 +168,7 @@ OpenRpcSession(
|
||||
//=======================================================================--
|
||||
{
|
||||
RpcSession *pSession;
|
||||
bool success = false;
|
||||
|
||||
DbgTrace(1, "-OpenRpcSession- Start\n", 0);
|
||||
|
||||
@ -122,55 +179,60 @@ OpenRpcSession(
|
||||
// Zero the session structure
|
||||
memset(pSession, 0, sizeof(*pSession));
|
||||
|
||||
// Open a Winhttp session
|
||||
pSession->hSession = WinHttpOpen(L"CASA Client/1.0",
|
||||
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
|
||||
WINHTTP_NO_PROXY_NAME,
|
||||
WINHTTP_NO_PROXY_BYPASS,
|
||||
0);
|
||||
if (pSession->hSession)
|
||||
// Save copy of the hostname
|
||||
pSession->pHostName = malloc(strlen(pHostName) + 1);
|
||||
if (pSession->pHostName)
|
||||
{
|
||||
LPWSTR pWideHostName;
|
||||
int wideHostLen;
|
||||
strcpy(pSession->pHostName, pHostName);
|
||||
|
||||
// Session opened, now convert the host name to Unicode so that
|
||||
// we can open a connection.
|
||||
if (CopyMultiToWideAlloc(pHostName,
|
||||
(int) strlen(pHostName),
|
||||
&pWideHostName,
|
||||
&wideHostLen) == CASA_STATUS_SUCCESS)
|
||||
// Open a Winhttp session
|
||||
pSession->hSession = WinHttpOpen(L"CASA Client/1.0",
|
||||
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
|
||||
WINHTTP_NO_PROXY_NAME,
|
||||
WINHTTP_NO_PROXY_BYPASS,
|
||||
0);
|
||||
if (pSession->hSession)
|
||||
{
|
||||
// Now open connection
|
||||
pSession->hConnection = WinHttpConnect(pSession->hSession,
|
||||
pWideHostName,
|
||||
hostPort,
|
||||
0);
|
||||
if (pSession->hConnection == NULL)
|
||||
LPWSTR pWideHostName;
|
||||
int wideHostLen;
|
||||
|
||||
// Session opened, now convert the host name to Unicode so that
|
||||
// we can open a connection.
|
||||
if (CopyMultiToWideAlloc(pHostName,
|
||||
(int) strlen(pHostName),
|
||||
&pWideHostName,
|
||||
&wideHostLen) == CASA_STATUS_SUCCESS)
|
||||
{
|
||||
DbgTrace(0, "-OpenRpcSession- Failed to open connection, error = %d\n", GetLastError());
|
||||
// Now open connection
|
||||
pSession->hConnection = WinHttpConnect(pSession->hSession,
|
||||
pWideHostName,
|
||||
hostPort,
|
||||
0);
|
||||
if (pSession->hConnection == NULL)
|
||||
{
|
||||
DbgTrace(0, "-OpenRpcSession- Failed to open connection, error = %d\n", GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
|
||||
// Free allocated resources
|
||||
WinHttpCloseHandle(pSession->hSession);
|
||||
free(pSession);
|
||||
pSession = NULL;
|
||||
// Free the host name wide string buffer
|
||||
free(pWideHostName);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-OpenRpcSession- Error converting host name to wide string\n", 0);
|
||||
}
|
||||
|
||||
// Free the host name wide string buffer
|
||||
free(pWideHostName);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-OpenRpcSession- Error converting host name to wide string\n", 0);
|
||||
|
||||
// Free allocated resources
|
||||
WinHttpCloseHandle(pSession->hSession);
|
||||
free(pSession);
|
||||
pSession = NULL;
|
||||
DbgTrace(0, "-OpenRpcSession- Failed to open session, error = %d\n", GetLastError());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-OpenRpcSession- Failed to open session, error = %d\n", GetLastError());
|
||||
DbgTrace(0, "-OpenRpcSession- Failed to allocate buffer for host name\n", 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -178,6 +240,25 @@ OpenRpcSession(
|
||||
DbgTrace(0, "-OpenRpcSession- Failed to allocate buffer for rpc session\n", 0);
|
||||
}
|
||||
|
||||
// Clean up if we did not succeed
|
||||
if (!success)
|
||||
{
|
||||
if (pSession)
|
||||
{
|
||||
if (pSession->hConnection)
|
||||
WinHttpCloseHandle(pSession->hConnection);
|
||||
|
||||
if (pSession->hSession)
|
||||
WinHttpCloseHandle(pSession->hSession);
|
||||
|
||||
if (pSession->pHostName)
|
||||
free(pSession->pHostName);
|
||||
|
||||
free(pSession);
|
||||
pSession = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
DbgTrace(2, "-OpenRpcSession- End, pSession = %08X\n", pSession);
|
||||
|
||||
return pSession;
|
||||
@ -208,6 +289,10 @@ CloseRpcSession(
|
||||
// Close the session handle
|
||||
WinHttpCloseHandle(pSession->hSession);
|
||||
|
||||
// Free hostname buffer if necessary
|
||||
if (pSession->pHostName)
|
||||
free(pSession->pHostName);
|
||||
|
||||
// Free the space allocated for the session
|
||||
free(pSession);
|
||||
|
||||
@ -215,13 +300,47 @@ CloseRpcSession(
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
static
|
||||
void CALLBACK
|
||||
SecureFailureStatusCallback(
|
||||
IN HINTERNET hRequest,
|
||||
IN DWORD *pContext,
|
||||
IN DWORD internetStatus,
|
||||
IN LPVOID pStatusInformation,
|
||||
IN DWORD statusInformationLength)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L0
|
||||
//=======================================================================--
|
||||
{
|
||||
DbgTrace(1, "-SecureFailureStatusCallback- Start\n", 0);
|
||||
|
||||
// Only deal with failures related to certificates
|
||||
if (internetStatus == WINHTTP_CALLBACK_STATUS_SECURE_FAILURE)
|
||||
{
|
||||
// Save the specific failure status
|
||||
*pContext = *(DWORD*) pStatusInformation;
|
||||
}
|
||||
|
||||
DbgTrace(1, "-SecureFailureStatusCallback- End\n", 0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
static
|
||||
CasaStatus
|
||||
InternalRpc(
|
||||
IN RpcSession *pSession,
|
||||
IN char *pMethod,
|
||||
IN bool secure,
|
||||
IN long flags,
|
||||
IN char *pRequestData,
|
||||
INOUT char **ppResponseData,
|
||||
INOUT int *pResponseDataLen)
|
||||
@ -237,11 +356,16 @@ InternalRpc(
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
#define CASA_STATUS_INVALID_SERVER_CERTIFICATE CASA_STATUS_UNSUCCESSFUL // temporary until casa_status.h is updated
|
||||
|
||||
CasaStatus retStatus = CASA_STATUS_SUCCESS;
|
||||
char rpcTarget[256];
|
||||
LPWSTR pWideRpcTarget;
|
||||
int wideRpcTargetLen;
|
||||
WCHAR sendHeaders[] = L"Content-Type: text/html";
|
||||
DWORD securityFailureStatusFlags;
|
||||
int retriesAllowed = 1;
|
||||
bool attemptRetry;
|
||||
|
||||
DbgTrace(1, "-InternalRpc- Start\n", 0);
|
||||
|
||||
@ -258,124 +382,172 @@ InternalRpc(
|
||||
{
|
||||
HINTERNET hRequest;
|
||||
|
||||
// Open a request handle
|
||||
hRequest = WinHttpOpenRequest(pSession->hConnection,
|
||||
L"POST",
|
||||
pWideRpcTarget,
|
||||
NULL,
|
||||
WINHTTP_NO_REFERER,
|
||||
WINHTTP_DEFAULT_ACCEPT_TYPES,
|
||||
secure? WINHTTP_FLAG_REFRESH | WINHTTP_FLAG_SECURE : WINHTTP_FLAG_REFRESH);
|
||||
if (hRequest)
|
||||
do
|
||||
{
|
||||
int reqDataLen = (int) strlen(pRequestData);
|
||||
// Forget about having been told to retry
|
||||
attemptRetry = false;
|
||||
|
||||
// Send the request
|
||||
if (WinHttpSendRequest(hRequest,
|
||||
sendHeaders,
|
||||
-1,
|
||||
pRequestData,
|
||||
reqDataLen,
|
||||
reqDataLen,
|
||||
0))
|
||||
{
|
||||
// Request sent, now await for the response.
|
||||
if (WinHttpReceiveResponse(hRequest, NULL))
|
||||
{
|
||||
WCHAR httpCompStatus[4] = {0};
|
||||
DWORD httpCompStatusLen = sizeof(httpCompStatus);
|
||||
|
||||
// Response received, make sure that it completed successfully.
|
||||
if (WinHttpQueryHeaders(hRequest,
|
||||
WINHTTP_QUERY_STATUS_CODE,
|
||||
// Open a request handle
|
||||
hRequest = WinHttpOpenRequest(pSession->hConnection,
|
||||
L"POST",
|
||||
pWideRpcTarget,
|
||||
NULL,
|
||||
&httpCompStatus,
|
||||
&httpCompStatusLen,
|
||||
WINHTTP_NO_HEADER_INDEX))
|
||||
WINHTTP_NO_REFERER,
|
||||
WINHTTP_DEFAULT_ACCEPT_TYPES,
|
||||
flags & SECURE_RPC_FLAG? WINHTTP_FLAG_REFRESH | WINHTTP_FLAG_SECURE : WINHTTP_FLAG_REFRESH);
|
||||
if (hRequest)
|
||||
{
|
||||
int reqDataLen = (int) strlen(pRequestData);
|
||||
|
||||
// Check if we need to set options to deal with secure connections
|
||||
if (flags & SECURE_RPC_FLAG)
|
||||
{
|
||||
// We are using secure connections, now proceed based on whether or not
|
||||
// we are configured to allow invalid certificates.
|
||||
if (flags & ALLOW_INVALID_CERTS_RPC_FLAG
|
||||
|| (flags & ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG
|
||||
&& InvalidCertsFromHostAllowed(pSession->pHostName)))
|
||||
{
|
||||
// Check that the request completed successfully
|
||||
if (memcmp(httpCompStatus, L"200", sizeof(httpCompStatus)) == 0)
|
||||
DWORD secFlags = SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_UNKNOWN_CA;
|
||||
|
||||
// We are configured to allow invalid certificates, inform the HTTP stack.
|
||||
if (WinHttpSetOption(hRequest,
|
||||
WINHTTP_OPTION_SECURITY_FLAGS,
|
||||
&secFlags,
|
||||
sizeof(secFlags)) == FALSE)
|
||||
{
|
||||
char *pResponseData;
|
||||
int responseDataBufSize = INITIAL_RESPONSE_DATA_BUF_SIZE;
|
||||
int responseDataRead = 0;
|
||||
DbgTrace(0, "-InternalRpc- Failed setting options to ignore invalid certs, error = %d\n", GetLastError());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We are not configured to allow invalid certificates, set a callback handler
|
||||
// to detect invalid certificate conditions.
|
||||
if (WinHttpSetStatusCallback(hRequest,
|
||||
SecureFailureStatusCallback,
|
||||
WINHTTP_CALLBACK_FLAG_SECURE_FAILURE,
|
||||
(DWORD_PTR) NULL) == WINHTTP_INVALID_STATUS_CALLBACK)
|
||||
{
|
||||
DbgTrace(0, "-InternalRpc- Failed setting status callback, error = %d\n", GetLastError());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now read the response data, to do so we need to allocate a buffer.
|
||||
pResponseData = (char*) malloc(INITIAL_RESPONSE_DATA_BUF_SIZE);
|
||||
if (pResponseData)
|
||||
// Send the request
|
||||
securityFailureStatusFlags = 0;
|
||||
if (WinHttpSendRequest(hRequest,
|
||||
sendHeaders,
|
||||
-1,
|
||||
pRequestData,
|
||||
reqDataLen,
|
||||
reqDataLen,
|
||||
(DWORD_PTR) &securityFailureStatusFlags))
|
||||
{
|
||||
// Request sent, now await for the response.
|
||||
if (WinHttpReceiveResponse(hRequest, NULL))
|
||||
{
|
||||
WCHAR httpCompStatus[4] = {0};
|
||||
DWORD httpCompStatusLen = sizeof(httpCompStatus);
|
||||
|
||||
// Response received, make sure that it completed successfully.
|
||||
if (WinHttpQueryHeaders(hRequest,
|
||||
WINHTTP_QUERY_STATUS_CODE,
|
||||
NULL,
|
||||
&httpCompStatus,
|
||||
&httpCompStatusLen,
|
||||
WINHTTP_NO_HEADER_INDEX))
|
||||
{
|
||||
// Check that the request completed successfully
|
||||
if (memcmp(httpCompStatus, L"200", sizeof(httpCompStatus)) == 0)
|
||||
{
|
||||
char *pCurrLocation = pResponseData;
|
||||
DWORD bytesRead;
|
||||
char *pResponseData;
|
||||
int responseDataBufSize = INITIAL_RESPONSE_DATA_BUF_SIZE;
|
||||
int responseDataRead = 0;
|
||||
|
||||
do
|
||||
// Now read the response data, to do so we need to allocate a buffer.
|
||||
pResponseData = (char*) malloc(INITIAL_RESPONSE_DATA_BUF_SIZE);
|
||||
if (pResponseData)
|
||||
{
|
||||
bytesRead = 0;
|
||||
if (WinHttpReadData(hRequest,
|
||||
(LPVOID) pCurrLocation,
|
||||
responseDataBufSize - responseDataRead,
|
||||
&bytesRead))
|
||||
char *pCurrLocation = pResponseData;
|
||||
DWORD bytesRead;
|
||||
|
||||
do
|
||||
{
|
||||
pCurrLocation += bytesRead;
|
||||
responseDataRead += bytesRead;
|
||||
|
||||
// Check if we need to allocate a larger buffer
|
||||
if (responseDataRead == responseDataBufSize)
|
||||
bytesRead = 0;
|
||||
if (WinHttpReadData(hRequest,
|
||||
(LPVOID) pCurrLocation,
|
||||
responseDataBufSize - responseDataRead,
|
||||
&bytesRead))
|
||||
{
|
||||
char *pTmpBuf;
|
||||
pCurrLocation += bytesRead;
|
||||
responseDataRead += bytesRead;
|
||||
|
||||
// We need to upgrade the receive buffer
|
||||
pTmpBuf = (char*) malloc(responseDataBufSize + INCREMENT_RESPONSE_DATA_BUF_SIZE);
|
||||
if (pTmpBuf)
|
||||
// Check if we need to allocate a larger buffer
|
||||
if (responseDataRead == responseDataBufSize)
|
||||
{
|
||||
memcpy(pTmpBuf, pResponseData, responseDataBufSize);
|
||||
free(pResponseData);
|
||||
pResponseData = pTmpBuf;
|
||||
pCurrLocation = pResponseData + responseDataBufSize;
|
||||
responseDataBufSize += INCREMENT_RESPONSE_DATA_BUF_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-InternalRpc- Buffer allocation failure\n", 0);
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
||||
char *pTmpBuf;
|
||||
|
||||
// We need to upgrade the receive buffer
|
||||
pTmpBuf = (char*) malloc(responseDataBufSize + INCREMENT_RESPONSE_DATA_BUF_SIZE);
|
||||
if (pTmpBuf)
|
||||
{
|
||||
memcpy(pTmpBuf, pResponseData, responseDataBufSize);
|
||||
free(pResponseData);
|
||||
pResponseData = pTmpBuf;
|
||||
pCurrLocation = pResponseData + responseDataBufSize;
|
||||
responseDataBufSize += INCREMENT_RESPONSE_DATA_BUF_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-InternalRpc- Buffer allocation failure\n", 0);
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-InternalRpc- Failed reading response data, error = %d\n", GetLastError());
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
} while (CASA_SUCCESS(retStatus)
|
||||
&& bytesRead != 0);
|
||||
|
||||
// Check if the response data was successfully received
|
||||
if (CASA_SUCCESS(retStatus))
|
||||
{
|
||||
// The response data was received, return it to the caller.
|
||||
*ppResponseData = pResponseData;
|
||||
*pResponseDataLen = responseDataRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-InternalRpc- Failed reading response data, error = %d\n", GetLastError());
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_UNSUCCESSFUL);
|
||||
// Failed to receive the response data, free the allocated buffer.
|
||||
free(pResponseData);
|
||||
}
|
||||
} while (CASA_SUCCESS(retStatus)
|
||||
&& bytesRead != 0);
|
||||
|
||||
// Check if the response data was successfully received
|
||||
if (CASA_SUCCESS(retStatus))
|
||||
{
|
||||
// The response data was received, return it to the caller.
|
||||
*ppResponseData = pResponseData;
|
||||
*pResponseDataLen = responseDataRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Failed to receive the response data, free the allocated buffer.
|
||||
free(pResponseData);
|
||||
DbgTrace(0, "-InternalRpc- Buffer allocation failure\n", 0);
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-InternalRpc- Buffer allocation failure\n", 0);
|
||||
DbgTrace(0, "-InternalRpc- HTTP request did not complete successfully, status = %S\n", httpCompStatus);
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
||||
CASA_STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-InternalRpc- HTTP request did not complete successfully, status = %S\n", httpCompStatus);
|
||||
DbgTrace(0, "-InternalRpc- Unable to obtain http request completion status, error = %d\n", GetLastError());
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_UNSUCCESSFUL);
|
||||
@ -383,7 +555,7 @@ InternalRpc(
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-InternalRpc- Unable to obtain http request completion status, error = %d\n", GetLastError());
|
||||
DbgTrace(0, "-InternalRpc- Unable to receive response, error = %d\n", GetLastError());
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_UNSUCCESSFUL);
|
||||
@ -391,41 +563,141 @@ InternalRpc(
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-InternalRpc- Unable to receive response, error = %d\n", GetLastError());
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_UNSUCCESSFUL);
|
||||
int error = GetLastError();
|
||||
|
||||
if (error == ERROR_WINHTTP_CANNOT_CONNECT)
|
||||
{
|
||||
DbgTrace(0, "-InternalRpc- Unable to connect to server\n", 0);
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_AUTH_SERVER_UNAVAILABLE);
|
||||
}
|
||||
else if (error == ERROR_WINHTTP_SECURE_FAILURE)
|
||||
{
|
||||
DbgTrace(1, "-InternalRpc- Secure connection failure, flags = %0x\n", securityFailureStatusFlags);
|
||||
|
||||
// Try to deal with the issue
|
||||
if ((securityFailureStatusFlags & ~(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA
|
||||
| WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID
|
||||
| WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID)) == 0
|
||||
&& flags & ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG)
|
||||
{
|
||||
WINHTTP_CERTIFICATE_INFO certInfo;
|
||||
DWORD certInfoLen = sizeof(certInfo);
|
||||
|
||||
// The failure was due to an invalid CN, CA, or both.
|
||||
//
|
||||
// Obtain information about the server certificate to give user
|
||||
// the choice of accepting it.
|
||||
if (WinHttpQueryOption(hRequest,
|
||||
WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT,
|
||||
&certInfo,
|
||||
&certInfoLen)
|
||||
&& certInfo.lpszSubjectInfo != NULL
|
||||
&& certInfo.lpszIssuerInfo != NULL)
|
||||
{
|
||||
char *pSubjectInfo;
|
||||
int subjectInfoLen;
|
||||
|
||||
// Convert the subjectInfo to multi-byte
|
||||
retStatus = CopyWideToMultiAlloc(certInfo.lpszSubjectInfo,
|
||||
(int) wcslen(certInfo.lpszSubjectInfo),
|
||||
&pSubjectInfo,
|
||||
&subjectInfoLen);
|
||||
if (CASA_SUCCESS(retStatus))
|
||||
{
|
||||
char *pIssuerInfo;
|
||||
int issuerInfoLen;
|
||||
|
||||
// Convert the issuerInfo to multi-byte
|
||||
retStatus = CopyWideToMultiAlloc(certInfo.lpszIssuerInfo,
|
||||
(int) wcslen(certInfo.lpszIssuerInfo),
|
||||
&pIssuerInfo,
|
||||
&issuerInfoLen);
|
||||
if (CASA_SUCCESS(retStatus))
|
||||
{
|
||||
long invalidCertFlags = 0;
|
||||
|
||||
// Setup the invalid cert flags
|
||||
if (securityFailureStatusFlags & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA)
|
||||
invalidCertFlags |= INVALID_CERT_CA_FLAG;
|
||||
|
||||
if (securityFailureStatusFlags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID)
|
||||
invalidCertFlags |= INVALID_CERT_CN_FLAG;
|
||||
|
||||
if (securityFailureStatusFlags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID)
|
||||
invalidCertFlags |= INVALID_CERT_DATE_FLAG;
|
||||
|
||||
// Give user the choice to accept the certificate
|
||||
if (UserApprovedCert(pSession->pHostName,
|
||||
pSubjectInfo,
|
||||
pIssuerInfo,
|
||||
invalidCertFlags))
|
||||
{
|
||||
DbgTrace(1, "-InternalRpc- User approved invalid certificate from %s\n", pSession->pHostName);
|
||||
|
||||
AllowInvalidCertsFromHost(pSession->pHostName);
|
||||
|
||||
// Try to retry the request
|
||||
attemptRetry = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(1, "-InternalRpc- User did not approve invalid certificate from %s\n", pSession->pHostName);
|
||||
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INVALID_SERVER_CERTIFICATE);
|
||||
}
|
||||
|
||||
// Free the buffer containing the issuerInfo
|
||||
free(pIssuerInfo);
|
||||
}
|
||||
|
||||
// Free the buffer containing the subjectInfo
|
||||
free(pSubjectInfo);
|
||||
}
|
||||
|
||||
// Free necessary certificate information
|
||||
if (certInfo.lpszSubjectInfo) LocalFree(certInfo.lpszSubjectInfo);
|
||||
if (certInfo.lpszIssuerInfo) LocalFree(certInfo.lpszIssuerInfo);
|
||||
if (certInfo.lpszProtocolName) LocalFree(certInfo.lpszProtocolName);
|
||||
if (certInfo.lpszSignatureAlgName) LocalFree(certInfo.lpszSignatureAlgName);
|
||||
if (certInfo.lpszEncryptionAlgName) LocalFree(certInfo.lpszEncryptionAlgName);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-InternalRpc- Unable to obtain server certificate struct, error = %0x\n", GetLastError());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Decided to no give the user a choice to accept invalid server certificate
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INVALID_SERVER_CERTIFICATE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-InternalRpc- Unsuccessful send http request, error = %d\n", error);
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
}
|
||||
|
||||
// Close the request handle
|
||||
WinHttpCloseHandle(hRequest);
|
||||
}
|
||||
else
|
||||
{
|
||||
int error = GetLastError();
|
||||
|
||||
DbgTrace(0, "-InternalRpc- Unsuccessful send http request, error = %d\n", error);
|
||||
if (error == ERROR_WINHTTP_CANNOT_CONNECT)
|
||||
{
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_AUTH_SERVER_UNAVAILABLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
DbgTrace(0, "-InternalRpc- Unable to open http request, error = %d\n", GetLastError());
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
// Close the request handle
|
||||
WinHttpCloseHandle(hRequest);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-InternalRpc- Unable to open http request, error = %d\n", GetLastError());
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
} while (attemptRetry && retriesAllowed--);
|
||||
|
||||
// Free the rpc target wide string buffer
|
||||
free(pWideRpcTarget);
|
||||
@ -446,7 +718,7 @@ CasaStatus
|
||||
Rpc(
|
||||
IN RpcSession *pSession,
|
||||
IN char *pMethod,
|
||||
IN bool secure,
|
||||
IN long flags,
|
||||
IN char *pRequestData,
|
||||
INOUT char **ppResponseData,
|
||||
INOUT int *pResponseDataLen)
|
||||
@ -473,7 +745,7 @@ Rpc(
|
||||
// Issue the RPC
|
||||
retStatus = InternalRpc(pSession,
|
||||
pMethod,
|
||||
secure,
|
||||
flags,
|
||||
pRequestData,
|
||||
ppResponseData,
|
||||
pResponseDataLen);
|
||||
|
@ -28,7 +28,7 @@
|
||||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_313DE095D13281AF91A64E3F3D472413"
|
||||
"OwnerKey" = "8:_8EA1E8FA8F1644718162CEF87F556652"
|
||||
"OwnerKey" = "8:_7A5EA42289F94648877FA695EB1853CE"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
}
|
||||
"Entry"
|
||||
@ -39,7 +39,7 @@
|
||||
}
|
||||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_56E85D8D3ACE4CFEAA7D83C8C65771A7"
|
||||
"MsmKey" = "8:_472FEAD17E7B45FF92E93D80B3379C47"
|
||||
"OwnerKey" = "8:_8292EFFD84EF46C6BD2F1F3E20808684"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
}
|
||||
@ -51,14 +51,20 @@
|
||||
}
|
||||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_7A5EA42289F94648877FA695EB1853CE"
|
||||
"OwnerKey" = "8:_UNDEFINED"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
}
|
||||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_8292EFFD84EF46C6BD2F1F3E20808684"
|
||||
"OwnerKey" = "8:_UNDEFINED"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
}
|
||||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_8EA1E8FA8F1644718162CEF87F556652"
|
||||
"OwnerKey" = "8:_UNDEFINED"
|
||||
"MsmKey" = "8:_92336612AC7D083F97ED302BB7674A2D"
|
||||
"OwnerKey" = "8:_191525A919DD46AD8D70B7735EE4F451"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
}
|
||||
"Entry"
|
||||
@ -69,12 +75,6 @@
|
||||
}
|
||||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_92336612AC7D083F97ED302BB7674A2D"
|
||||
"OwnerKey" = "8:_191525A919DD46AD8D70B7735EE4F451"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
}
|
||||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_9A3A0F1784E448538A42AE8722C1FE40"
|
||||
"OwnerKey" = "8:_UNDEFINED"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
@ -468,7 +468,7 @@
|
||||
}
|
||||
"MergeModule"
|
||||
{
|
||||
"{35A69C6E-5BA4-440D-803D-762B59A45393}:_56E85D8D3ACE4CFEAA7D83C8C65771A7"
|
||||
"{35A69C6E-5BA4-440D-803D-762B59A45393}:_472FEAD17E7B45FF92E93D80B3379C47"
|
||||
{
|
||||
"UseDynamicProperties" = "11:FALSE"
|
||||
"IsDependency" = "11:TRUE"
|
||||
@ -550,6 +550,34 @@
|
||||
{
|
||||
}
|
||||
}
|
||||
"{8062640A-2EEE-46E9-AB67-688E9A886E9F}:_7A5EA42289F94648877FA695EB1853CE"
|
||||
{
|
||||
"SourcePath" = "8:..\\..\\..\\client\\mechanisms\\krb5\\windows\\Debug\\krb5mech.dll"
|
||||
"TargetName" = "8:"
|
||||
"Tag" = "8:"
|
||||
"Folder" = "8:_F5F5F604B81645F8B6463F7A7D6A53AD"
|
||||
"Condition" = "8:"
|
||||
"Transitive" = "11:FALSE"
|
||||
"Vital" = "11:TRUE"
|
||||
"ReadOnly" = "11:FALSE"
|
||||
"Hidden" = "11:FALSE"
|
||||
"System" = "11:FALSE"
|
||||
"Permanent" = "11:FALSE"
|
||||
"SharedLegacy" = "11:FALSE"
|
||||
"PackageAs" = "3:1"
|
||||
"Register" = "3:1"
|
||||
"Exclude" = "11:FALSE"
|
||||
"IsDependency" = "11:FALSE"
|
||||
"IsolateTo" = "8:"
|
||||
"ProjectOutputGroupRegister" = "3:1"
|
||||
"OutputConfiguration" = "8:"
|
||||
"OutputGroupCanonicalName" = "8:Built"
|
||||
"OutputProjectGuid" = "8:{5499F624-F371-4559-B4C2-A484BCE892FD}"
|
||||
"ShowKeyOutput" = "11:FALSE"
|
||||
"ExcludeFilters"
|
||||
{
|
||||
}
|
||||
}
|
||||
"{8062640A-2EEE-46E9-AB67-688E9A886E9F}:_8292EFFD84EF46C6BD2F1F3E20808684"
|
||||
{
|
||||
"SourcePath" = "8:..\\..\\..\\client\\csharp\\Novell.Casa.Authtoken\\obj\\Debug\\Novell.Casa.Client.Auth.dll"
|
||||
@ -578,34 +606,6 @@
|
||||
{
|
||||
}
|
||||
}
|
||||
"{8062640A-2EEE-46E9-AB67-688E9A886E9F}:_8EA1E8FA8F1644718162CEF87F556652"
|
||||
{
|
||||
"SourcePath" = "8:..\\..\\..\\client\\mechanisms\\krb5\\windows\\Debug\\krb5mech.dll"
|
||||
"TargetName" = "8:"
|
||||
"Tag" = "8:"
|
||||
"Folder" = "8:_F5F5F604B81645F8B6463F7A7D6A53AD"
|
||||
"Condition" = "8:"
|
||||
"Transitive" = "11:FALSE"
|
||||
"Vital" = "11:TRUE"
|
||||
"ReadOnly" = "11:FALSE"
|
||||
"Hidden" = "11:FALSE"
|
||||
"System" = "11:FALSE"
|
||||
"Permanent" = "11:FALSE"
|
||||
"SharedLegacy" = "11:FALSE"
|
||||
"PackageAs" = "3:1"
|
||||
"Register" = "3:1"
|
||||
"Exclude" = "11:FALSE"
|
||||
"IsDependency" = "11:FALSE"
|
||||
"IsolateTo" = "8:"
|
||||
"ProjectOutputGroupRegister" = "3:1"
|
||||
"OutputConfiguration" = "8:"
|
||||
"OutputGroupCanonicalName" = "8:Built"
|
||||
"OutputProjectGuid" = "8:{5499F624-F371-4559-B4C2-A484BCE892FD}"
|
||||
"ShowKeyOutput" = "11:FALSE"
|
||||
"ExcludeFilters"
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
"Registry"
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user