KMSAgentStorage.cpp revision 4f14b0f29aa144cc03efdde5508ae126ae197acf
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
*/
/**
* \file KMSAgentStorage.cpp
* This file provides an implementation of the KMSAgentStorage.h
* interface utilizing a filesystem for storage of KMS Client
* Profile elements.
*
* For storage of Certificates and Private key material the PKICommon
* interface is used.
*/
#include <stdio.h>
#include <string.h>
#ifndef METAWARE
#include <errno.h>
#endif
#ifdef K_SOLARIS_PLATFORM
#ifndef SOLARIS10
#include <cryptoutil.h>
#endif
#include <pthread.h>
#include <fcntl.h>
#endif
#include "stdsoap2.h"
#include "KMSClientProfile.h" // must be before agentstorage
#include "KMSAgentPKICommon.h" // must be before agentstorage
#include "KMSAgentStorage.h"
#include "SYSCommon.h"
#include "AutoMutex.h"
#include "KMSAuditLogger.h"
#include "KMSClientProfileImpl.h"
#include "KMSAgent_direct.h"
#ifdef K_SOLARIS_PLATFORM
#include "KMSAgent.h"
#endif
#include "k_setupssl.h" // K_ssl_client_context
#ifdef METAWARE
extern "C" int K_ssl_client_context(struct soap *soap,
int flags,
const char *keyfile, // NULL - SERVER
const char *password, // NULL - SERVER
const char *cafile,
const char *capath, // ALWAYS NULL
const char *randfile); // ALWAYS NULL
#include "debug.h"
#endif
#define CA_CERTIFICATE_FILE "ca.crt"
#define CLIENT_KEY_FILE "clientkey.pem"
#define PROFILE_CONFIG_FILE "profile.cfg"
#define PROFILE_CLUSTER_CONFIG_FILE "cluster.cfg"
static char g_sWorkingDirectory[KMS_MAX_PATH_LENGTH+1];
static char g_sStringbuf[10000]; // too large to be on the 9840D stack
static void BuildFullProfilePathWithName(utf8cstr o_pProfilePath,
const char* const i_pWorkingDirectory,
const char* const i_pProfileName)
{
int len;
FATAL_ASSERT( o_pProfilePath );
FATAL_ASSERT( i_pWorkingDirectory );
FATAL_ASSERT( i_pProfileName );
FATAL_ASSERT( (strlen(i_pWorkingDirectory) > 0) );
FATAL_ASSERT( (strlen(i_pProfileName) > 0) );
#if defined(DEBUG_TRACE) && defined(METAWARE)
ECPT_TRACE_ENTRY *trace = NULL;
ECPT_TRACE( trace, BuildFullProfilePathWithName );
#endif
strncpy(o_pProfilePath, i_pWorkingDirectory,
KMS_MAX_FILE_NAME );
if ( o_pProfilePath[ strlen(o_pProfilePath) -1 ] != PATH_SEPARATOR )
{
len = strlen(o_pProfilePath);
o_pProfilePath[ len ] = PATH_SEPARATOR ;
o_pProfilePath[ len + 1 ] = '\0';
}
strncat( o_pProfilePath, i_pProfileName, KMS_MAX_FILE_NAME );
len = strlen(o_pProfilePath);
o_pProfilePath[ len ] = PATH_SEPARATOR ;
o_pProfilePath[ len +1 ] = '\0';
return;
}
static void BuildFullProfilePath(utf8cstr o_sProfilePath,
const char* const i_pWorkingDirectory,
const char* const i_pProfileName)
{
FATAL_ASSERT( o_sProfilePath );
FATAL_ASSERT( i_pWorkingDirectory );
FATAL_ASSERT( i_pProfileName );
FATAL_ASSERT( (strlen(i_pProfileName) > 0) );
BuildFullProfilePathWithName( o_sProfilePath,
i_pWorkingDirectory,
i_pProfileName );
return;
}
#ifdef K_SOLARIS_PLATFORM
static struct flock cfgfl = {
0, 0, 0, 0, 0, 0,
{0, 0, 0, 0}
};
static struct flock clusterfl = {
0, 0, 0, 0, 0, 0,
{0, 0, 0, 0}
};
pthread_mutex_t cfg_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t cluster_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t keyfile_mutex = PTHREAD_MUTEX_INITIALIZER;
static int
flock_fd(int fd, int cmd, struct flock *fl, pthread_mutex_t *mutex)
{
int ret = 0;
(void) pthread_mutex_lock(mutex);
fl->l_type = cmd;
while ((ret = fcntl(fd, F_SETLKW, fl)) == -1) {
if (errno != EINTR)
break;
}
(void) pthread_mutex_unlock(mutex);
return (ret);
}
#endif
static bool Profile_WriteConfigFile(KMSClientProfile *i_pProfile,
const char *i_pFileName)
{
FATAL_ASSERT( i_pProfile );
FATAL_ASSERT( i_pFileName );
CAutoMutex oAutoMutex( (K_MUTEX_HANDLE)i_pProfile->m_pLock );
#if defined(DEBUG_TRACE) && defined(METAWARE)
ECPT_TRACE_ENTRY *trace = NULL;
ECPT_TRACE( trace, Profile_WriteConfigFile );
#endif
char *sp = g_sStringbuf;
size_t bytesWritten = 0;
// save config parameters
myFILE *fp = fopen(i_pFileName, "w");
if(fp == NULL)
{
LogError(i_pProfile,
AUDIT_PROFILE_WRITE_CONFIG_FILE_OPEN_CONFIGURATION_FILE_FAILED,
NULL,
NULL,
i_pFileName);
return false;
}
#ifdef K_SOLARIS_PLATFORM
int fd = fileno(fp);
(void) flock_fd(fd, F_WRLCK, &cfgfl, &cfg_mutex);
#endif
const char* const sProfileName = i_pProfile->m_wsProfileName;
sp += K_snprintf(sp, sizeof(i_pProfile->m_wsProfileName), "ProfileName=%s\n", sProfileName);
sp += K_snprintf(sp, sizeof(i_pProfile->m_wsProfileName), "AgentID=%s\n", i_pProfile->m_wsEntityID);
sp += K_snprintf(sp, sizeof(i_pProfile->m_wsProfileName), "ClusterDiscoveryFrequency=%d\n",
i_pProfile->m_iClusterDiscoveryFrequency);
sp += K_snprintf(sp, sizeof(i_pProfile->m_wsProfileName), "CAServicePortNumber=%d\n",
i_pProfile->m_iPortForCAService);
sp += K_snprintf(sp, sizeof(i_pProfile->m_wsProfileName), "CertificateServicePortNumber=%d\n",
i_pProfile->m_iPortForCertificateService);
if(i_pProfile->m_iPortForAgentService != 0)
{
sp += K_snprintf(sp, sizeof(i_pProfile->m_wsProfileName), "AgentServicePortNumber=%d\n",
i_pProfile->m_iPortForAgentService);
}
if(i_pProfile->m_iPortForDiscoveryService != 0)
{
sp += K_snprintf(sp, sizeof(i_pProfile->m_wsProfileName), "DiscoveryServicePortNumber=%d\n",
i_pProfile->m_iPortForDiscoveryService);
}
sp += K_snprintf(sp, sizeof(i_pProfile->m_wsProfileName), "ApplianceAddress=%s\n", i_pProfile->m_wsApplianceAddress);
sp += K_snprintf(sp, sizeof(i_pProfile->m_wsProfileName), "Timeout=%d\n", i_pProfile->m_iTransactionTimeout);
sp += K_snprintf(sp, sizeof(i_pProfile->m_wsProfileName), "FailoverLimt=%d\n", i_pProfile->m_iFailoverLimit);
sp += K_snprintf(sp, sizeof(i_pProfile->m_wsProfileName), "HexHashedPassphrase=%s\n", i_pProfile->m_sHexHashedPassphrase);
bytesWritten = fputs(g_sStringbuf, fp);
#ifdef K_SOLARIS_PLATFORM
(void) flock_fd(fd, F_UNLCK, &cfgfl, &cfg_mutex);
#endif
#ifndef WIN32
if ( strlen(g_sStringbuf) != bytesWritten )
#else
if ( bytesWritten < 0 )
#endif
{
fclose(fp);
return false;
}
fclose(fp);
return true;
}
static bool Profile_ReadConfigFile
( KMSClientProfile *i_pProfile,
const char *i_pFileName)
{
FATAL_ASSERT( i_pProfile );
FATAL_ASSERT( i_pFileName );
#if defined(DEBUG_TRACE) && defined(METAWARE)
ECPT_TRACE_ENTRY *trace = NULL;
ECPT_TRACE( trace, Profile_ReadConfigFile ) ;
#endif
CAutoMutex oAutoMutex( (K_MUTEX_HANDLE)i_pProfile->m_pLock );
const int iMaxLineSize = 1024;
myFILE *fp;
char acBuffer[iMaxLineSize+1];
fp = fopen(i_pFileName, "r");
if(fp == NULL)
{
LogError(i_pProfile,
AUDIT_PROFILE_READ_CONFIG_FILE_OPEN_CONFIGURATION_FILE_FAILED,
NULL,
NULL,
i_pFileName);
return false;
}
#ifdef K_SOLARIS_PLATFORM
int fd = fileno(fp);
(void) flock_fd(fd, F_RDLCK, &cfgfl, &cfg_mutex);
#endif
// read file one line by one line
while(1)
{
int i;
char *pName, *pValue;
memset(acBuffer, 0, iMaxLineSize+1);
//---------------------------
// get info from the file
//---------------------------
if(fgets(acBuffer, iMaxLineSize+1, fp) == NULL)
break;
if(strlen(acBuffer) < 3)
continue;
if(acBuffer[0] == '#' ||
acBuffer[0] == ';' ||
acBuffer[0] == '[') // jump comments
continue;
pName = acBuffer;
pValue = NULL;
for(i = 0; acBuffer[i] != '\0'; i++)
{
if(acBuffer[i] == '=')
pValue = acBuffer + i + 1;
if(acBuffer[i] == '=' ||
acBuffer[i] == '\r' ||
acBuffer[i] == '\n')
acBuffer[i] = '\0';
}
if(pValue == NULL)
{
LogError(i_pProfile,
AUDIT_PROFILE_READ_CONFIG_FILE_INVALID_CONFIGURATION_FILE_FORMAT,
NULL,
NULL,
i_pFileName);
#ifdef K_SOLARIS_PLATFORM
(void) flock_fd(fd, F_UNLCK, &cfgfl, &cfg_mutex);
#endif
fclose(fp);
return false;
}
if(strcmp(pName, "ProfileName") == 0)
{
utf8cstr wsValue = pValue;
strncpy(i_pProfile->m_wsProfileName, wsValue, KMS_MAX_ENTITY_ID);
i_pProfile->m_wsProfileName[KMS_MAX_ENTITY_ID] = 0;
}
if(strcmp(pName, "AgentID") == 0)
{
utf8cstr wsValue = pValue;
strncpy(i_pProfile->m_wsEntityID, wsValue, KMS_MAX_ENTITY_ID);
i_pProfile->m_wsEntityID[KMS_MAX_ENTITY_ID] = 0;
}
if(strcmp(pName, "ClusterDiscoveryFrequency") == 0)
{
sscanf(pValue, "%d", &(i_pProfile->m_iClusterDiscoveryFrequency));
}
if(strcmp(pName, "CAServicePortNumber") == 0)
{
sscanf(pValue, "%d", &(i_pProfile->m_iPortForCAService));
}
if(strcmp(pName, "CertificateServicePortNumber") == 0)
{
sscanf(pValue, "%d", &(i_pProfile->m_iPortForCertificateService));
}
if(strcmp(pName, "AgentServicePortNumber") == 0)
{
sscanf(pValue, "%d", &(i_pProfile->m_iPortForAgentService));
}
if(strcmp(pName, "DiscoveryServicePortNumber") == 0)
{
sscanf(pValue, "%d", &(i_pProfile->m_iPortForDiscoveryService));
}
if(strcmp(pName, "ApplianceAddress") == 0)
{
utf8cstr wsValue = pValue;
strncpy(i_pProfile->m_wsApplianceAddress,
wsValue, KMS_MAX_NETWORK_ADDRESS);
i_pProfile->m_wsApplianceAddress[KMS_MAX_NETWORK_ADDRESS] = 0;
}
if(strcmp(pName, "Timeout") == 0)
{
sscanf(pValue, "%d", &(i_pProfile->m_iTransactionTimeout));
}
if(strcmp(pName, "FailoverLimt") == 0)
{
sscanf(pValue, "%d", &(i_pProfile->m_iFailoverLimit));
}
if(strcmp(pName, "HexHashedPassphrase") == 0)
{
sscanf(pValue, "%s", i_pProfile->m_sHexHashedPassphrase);
}
}
#ifdef K_SOLARIS_PLATFORM
(void) flock_fd(fd, F_UNLCK, &cfgfl, &cfg_mutex);
#endif
fclose(fp);
return true;
}
/*! ProfileExists
*
*/
extern "C" bool ProfileExists(
const char* const i_pWorkingDirectory,
const char* const i_pProfileName)
{
FATAL_ASSERT( i_pWorkingDirectory );
FATAL_ASSERT( i_pProfileName );
#if defined(DEBUG_TRACE) && defined(METAWARE)
ECPT_TRACE_ENTRY *trace = NULL;
ECPT_TRACE( trace, ProfileExists );
#endif
// the profile is stored in the working folder
strncpy( g_sWorkingDirectory,
i_pWorkingDirectory,
KMS_MAX_PATH_LENGTH );
char sFullProfileDir[KMS_MAX_FILE_NAME+1];
BuildFullProfilePath( sFullProfileDir,
i_pWorkingDirectory,
i_pProfileName );
char sConfigFile[KMS_MAX_FILE_NAME+1] = "";
strncpy( sConfigFile, sFullProfileDir, KMS_MAX_FILE_NAME );
sConfigFile[KMS_MAX_FILE_NAME] = '\0';
strncat( sConfigFile, PROFILE_CONFIG_FILE, KMS_MAX_FILE_NAME );
// just try to open the file to test if it exists
bool bProfileExists = false;
myFILE* pfFile = fopen( sConfigFile, "rb" );
if ( pfFile != NULL )
{
bProfileExists = true;
fclose(pfFile);
}
return bProfileExists;
}
/*! CreateProfile
*
*/
bool CreateProfile(
KMSClientProfile* const io_pProfile,
const char* const i_pWorkingDirectory,
const char* const i_pProfileName)
{
FATAL_ASSERT( io_pProfile );
FATAL_ASSERT( i_pWorkingDirectory );
FATAL_ASSERT( i_pProfileName );
FATAL_ASSERT( (strlen(i_pProfileName) > 0) );
#if defined(DEBUG_TRACE) && defined(METAWARE)
ECPT_TRACE_ENTRY *trace = NULL;
ECPT_TRACE( trace, CreateProfile );
#endif
bool bSuccess = false;
CAutoMutex oAutoMutex( (K_MUTEX_HANDLE)io_pProfile->m_pLock );
char sFullProfileDir[KMS_MAX_FILE_NAME];
BuildFullProfilePath( sFullProfileDir,
i_pWorkingDirectory,
i_pProfileName );
bSuccess = ( K_CreateDirectory( sFullProfileDir ) == 0 );
if ( !bSuccess )
{
Log(AUDIT_CLIENT_LOAD_PROFILE_CREATE_DIRECTORY_FAILED,
NULL,
NULL,
NULL );
}
strncpy( g_sWorkingDirectory, i_pWorkingDirectory, KMS_MAX_PATH_LENGTH );
bSuccess = StoreConfig( io_pProfile );
if ( !bSuccess )
{
Log(AUDIT_CLIENT_LOAD_PROFILE_CREATE_PROFILE_CONFIG_FAILED,
NULL,
NULL,
NULL );
}
else
{
Log(AUDIT_CLIENT_LOAD_PROFILE_CREATE_PROFILE_CONFIG_SUCCEEDED,
NULL,
NULL,
NULL );
}
return bSuccess;
}
/*! StoreConfig
* Store the configuration to persistent storage
*/
bool StoreConfig(
KMSClientProfile* const i_pProfile )
{
FATAL_ASSERT( i_pProfile );
#if defined(DEBUG_TRACE) && defined(METAWARE)
ECPT_TRACE_ENTRY *trace = NULL;
ECPT_TRACE( trace, StoreConfig ) ;
#endif
char sConfigFile[KMS_MAX_FILE_NAME];
BuildFullProfilePath( sConfigFile,
g_sWorkingDirectory, i_pProfile->m_wsProfileName );
strncat( sConfigFile, PROFILE_CONFIG_FILE, KMS_MAX_FILE_NAME );
return Profile_WriteConfigFile(i_pProfile, sConfigFile );
}
/*! StoreCluster
* Store the cluster to persistent storage
*/
bool StoreCluster(
KMSClientProfile* const i_pProfile )
{
FATAL_ASSERT( i_pProfile );
myFILE *fp;
int sCount;
char *sp = g_sStringbuf;
char sFullProfileDir[KMS_MAX_FILE_NAME+1];
BuildFullProfilePath( sFullProfileDir,
g_sWorkingDirectory, i_pProfile->m_wsProfileName );
char sClusterFile[KMS_MAX_FILE_NAME+1] = "";
strncpy( sClusterFile, sFullProfileDir, KMS_MAX_FILE_NAME );
sClusterFile[KMS_MAX_FILE_NAME] = '\0';
strncat( sClusterFile, PROFILE_CLUSTER_CONFIG_FILE, KMS_MAX_FILE_NAME );
#if defined(DEBUG_TRACE) && defined(METAWARE)
ECPT_TRACE_ENTRY *trace = NULL;
ECPT_TRACE( trace, StoreCluster );
#endif
fp = fopen(sClusterFile, "w");
if (fp == NULL)
{
LogError(i_pProfile,
AUDIT_CLIENT_SAVE_CLUSTER_INFORMATION_OPEN_CLUSTER_FILE_FAILED,
NULL,
NULL,
sClusterFile );
return false;
}
#ifdef K_SOLARIS_PLATFORM
int fd = fileno(fp);
(void) flock_fd(fd, F_WRLCK, &clusterfl, &cluster_mutex);
#endif
sp += K_snprintf(sp, sizeof(g_sStringbuf), "EntitySiteID=%s\n\n", i_pProfile->m_wsEntitySiteID);
for (int i = 0; i < i_pProfile->m_iClusterNum; i++)
{
if ( i > 0 )
{
sp += K_snprintf(sp, sizeof(g_sStringbuf), "\n");
}
if (( sCount = K_snprintf(sp, sizeof(g_sStringbuf),"<StartAppliance>\n")) < 0 )
{
#ifdef K_SOLARIS_PLATFORM
(void) flock_fd(fd, F_UNLCK, &clusterfl, &cluster_mutex);
#endif
fclose(fp);
return false; }
sp += sCount;
#ifdef WIN32
if (( sCount = K_snprintf(sp, sizeof(g_sStringbuf), "ApplianceID=%I64d\n",
i_pProfile->m_aCluster[i].m_lApplianceID)) < 0 )
{ fclose(fp); return false; }
sp += sCount;
#else
if (( sCount = K_snprintf(sp, sizeof(g_sStringbuf), "ApplianceID=%lld\n",
i_pProfile->m_aCluster[i].m_lApplianceID)) < 0 )
{
#ifdef K_SOLARIS_PLATFORM
(void) flock_fd(fd, F_UNLCK, &clusterfl, &cluster_mutex);
#endif
fclose(fp);
return false; }
sp += sCount;
#endif
if (( sCount = K_snprintf(sp, sizeof(g_sStringbuf), "Enabled=%d\n",
i_pProfile->m_aCluster[i].m_iEnabled)) < 0 )
{
#ifdef K_SOLARIS_PLATFORM
(void) flock_fd(fd, F_UNLCK, &clusterfl, &cluster_mutex);
#endif
fclose(fp);
return false; }
sp += sCount;
if (( sCount = K_snprintf(sp, sizeof(g_sStringbuf), "Responding=%d\n",
i_pProfile->m_aCluster[i].m_iResponding)) < 0 )
{
#ifdef K_SOLARIS_PLATFORM
(void) flock_fd(fd, F_UNLCK, &clusterfl, &cluster_mutex);
#endif
fclose(fp);
return false; }
sp += sCount;
if (( sCount = K_snprintf(sp, sizeof(g_sStringbuf), "Load=%lld\n",
i_pProfile->m_aCluster[i].m_lLoad)) < 0 )
{
#ifdef K_SOLARIS_PLATFORM
(void) flock_fd(fd, F_UNLCK, &clusterfl, &cluster_mutex);
#endif
fclose(fp);
return false; }
sp += sCount;
if (( sCount = K_snprintf(sp, sizeof(g_sStringbuf), "ApplianceAlias=%s\n",
i_pProfile->m_aCluster[i].m_wsApplianceAlias)) < 0 )
{
#ifdef K_SOLARIS_PLATFORM
(void) flock_fd(fd, F_UNLCK, &clusterfl, &cluster_mutex);
#endif
fclose(fp);
return false; }
sp += sCount;
if (( sCount = K_snprintf(sp, sizeof(g_sStringbuf), "ApplianceNetworkAddress=%s\n",
i_pProfile->m_aCluster[i].m_wsApplianceNetworkAddress)) < 0 )
{
#ifdef K_SOLARIS_PLATFORM
(void) flock_fd(fd, F_UNLCK, &clusterfl, &cluster_mutex);
#endif
fclose(fp);
return false; }
sp += sCount;
if (( sCount = K_snprintf(sp, sizeof(g_sStringbuf), "ApplianceSiteID=%s\n",
i_pProfile->m_aCluster[i].m_wsApplianceSiteID)) < 0 )
{
#ifdef K_SOLARIS_PLATFORM
(void) flock_fd(fd, F_UNLCK, &clusterfl, &cluster_mutex);
#endif
fclose(fp);
return false; }
sp += sCount;
if (( sCount = K_snprintf(sp, sizeof(g_sStringbuf), "KMAVersion=%s\n",
i_pProfile->m_aCluster[i].m_sKMAVersion)) < 0 )
{
#ifdef K_SOLARIS_PLATFORM
(void) flock_fd(fd, F_UNLCK, &clusterfl, &cluster_mutex);
#endif
fclose(fp);
return false; }
sp += sCount;
if (( sCount = K_snprintf(sp, sizeof(g_sStringbuf), "KMALocked=%d\n",
i_pProfile->m_aCluster[i].m_iKMALocked)) < 0 )
{
#ifdef K_SOLARIS_PLATFORM
(void) flock_fd(fd, F_UNLCK, &clusterfl, &cluster_mutex);
#endif
fclose(fp);
return false; }
sp += sCount;
if (( sCount = K_snprintf(sp, sizeof(g_sStringbuf), "<EndAppliance>\n")) < 0 )
{
#ifdef K_SOLARIS_PLATFORM
(void) flock_fd(fd, F_UNLCK, &clusterfl, &cluster_mutex);
#endif
fclose(fp);
return false; }
sp += sCount;
}
fputs(g_sStringbuf, fp);
#ifdef K_SOLARIS_PLATFORM
(void) flock_fd(fd, F_UNLCK, &clusterfl, &cluster_mutex);
#endif
fclose(fp);
Log(AUDIT_CLIENT_SAVE_CLUSTER_INFORMATION_SUCCEEDED,
NULL,
NULL,
NULL );
return true;
}
/*! GetConfig
* get the configuration file from persistent storage
*/
bool GetConfig(
KMSClientProfile* const io_pProfile )
{
FATAL_ASSERT( io_pProfile );
char sFullProfileDir[KMS_MAX_FILE_NAME+1];
BuildFullProfilePath( sFullProfileDir,
g_sWorkingDirectory,
io_pProfile->m_wsProfileName );
char sConfigFile[KMS_MAX_FILE_NAME+1];
strncpy( sConfigFile, sFullProfileDir, KMS_MAX_FILE_NAME );
sConfigFile[KMS_MAX_FILE_NAME] = '\0';
strncat( sConfigFile, PROFILE_CONFIG_FILE, KMS_MAX_FILE_NAME );
return Profile_ReadConfigFile( io_pProfile, sConfigFile );
}
/** GetCluster
* get the cluster information from persistent storage
*/
bool GetCluster(
KMSClientProfile* const io_pProfile,
int& o_bClusterInformationFound )
{
FATAL_ASSERT( io_pProfile );
const int iMaxLineSize = 1024;
myFILE *fp;
char acBuffer[iMaxLineSize+1];
char sFullProfileDir[KMS_MAX_FILE_NAME+1];
BuildFullProfilePath( sFullProfileDir,
g_sWorkingDirectory,
io_pProfile->m_wsProfileName );
char sClusterFile[KMS_MAX_FILE_NAME+1];
#if defined(DEBUG_TRACE) && defined(METAWARE)
ECPT_TRACE_ENTRY *trace = NULL;
ECPT_TRACE( trace, GetCluster );
#endif
strncpy( sClusterFile, sFullProfileDir, KMS_MAX_FILE_NAME );
sClusterFile[KMS_MAX_FILE_NAME] = '\0';
strncat( sClusterFile, PROFILE_CLUSTER_CONFIG_FILE, KMS_MAX_FILE_NAME );
fp = fopen( sClusterFile, "r" );
if ( fp == NULL )
{
#ifdef METAWARE
// Assume file doesn't exist. This isn't an error (no support for
// errno in metaware).
o_bClusterInformationFound = 0;
return true;
#else
if ( errno == ENOENT )
{
// File doesn't exist. This isn't an error.
o_bClusterInformationFound = 0;
return true;
}
LogError(io_pProfile,
AUDIT_CLIENT_LOAD_CLUSTER_INFORMATION_OPEN_CLUSTER_FILE_FAILED,
NULL,
NULL,
sClusterFile );
return false;
#endif
}
#ifdef K_SOLARIS_PLATFORM
int fd = fileno(fp);
(void) flock_fd(fd, F_WRLCK, &clusterfl, &cluster_mutex);
#endif
o_bClusterInformationFound = 1;
int i;
// KMAVersion is new to Cluster config with 2.1 KMS and will not exist
// in persisted cluster configs from earlier agents
for ( i = 0; i < KMS_MAX_CLUSTER_NUM; i++ )
{
io_pProfile->m_aCluster[i].m_sKMAVersion[0] = '\0';
}
int iClusterNum = 0;
// read file one line by one line
while(1)
{
int i;
char *pName, *pValue;
memset(acBuffer, 0, iMaxLineSize+1);
// get info from the file
if(fgets(acBuffer, iMaxLineSize+1, fp) == NULL)
break;
if(strlen(acBuffer) < 3)
continue;
if(acBuffer[0] == '#' ||
acBuffer[0] == ';' ||
acBuffer[0] == '[') // jump comments
continue;
pName = acBuffer; pValue = NULL;
for(i = 0; acBuffer[i] != '\0'; i++)
{
if(acBuffer[i] == '=')
pValue = acBuffer + i + 1;
if(acBuffer[i] == '=' ||
acBuffer[i] == '\r' ||
acBuffer[i] == '\n')
acBuffer[i] = '\0';
}
if(strcmp(pName, "<StartAppliance>") == 0)
{
continue;
}
if(strcmp(pName, "<EndAppliance>") == 0)
{
iClusterNum++;
}
if(pValue == NULL)
{
if(strcmp(pName,"<StartAppliance>") == 0)
continue;
if(strcmp(pName,"<EndAppliance>") == 0)
continue;
#ifdef K_SOLARIS_PLATFORM
(void) flock_fd(fd, F_UNLCK, &clusterfl, &cluster_mutex);
#endif
fclose(fp);
LogError(io_pProfile,
AUDIT_CLIENT_LOAD_CLUSTER_INFORMATION_INVALID_CLUSTER_FILE_FORMAT,
NULL,
NULL,
sClusterFile );
return false;
}
if(strcmp(pName, "EntitySiteID") == 0)
{
utf8cstr wsValue = pValue;
strncpy(io_pProfile->m_wsEntitySiteID, wsValue, KMS_MAX_ENTITY_SITE_ID);
io_pProfile->m_wsEntitySiteID[KMS_MAX_ENTITY_SITE_ID] = 0;
}
if(strcmp(pName, "ApplianceID") == 0)
{
#ifdef WIN32
sscanf(pValue, "%lld",
&(io_pProfile->m_aCluster[iClusterNum].m_lApplianceID));
#else
sscanf(pValue, "%lld",
&(io_pProfile->m_aCluster[iClusterNum].m_lApplianceID));
#endif
}
if(strcmp(pName, "Enabled") == 0)
{
sscanf(pValue, "%d",
&(io_pProfile->m_aCluster[iClusterNum].m_iEnabled));
}
// assume it is responding by default
io_pProfile->m_aCluster[iClusterNum].
m_iResponding = TRUE;
if(strcmp(pName, "Load") == 0)
{
sscanf(pValue, "%lld",
&(io_pProfile->m_aCluster[iClusterNum].m_lLoad));
}
if(strcmp(pName, "ApplianceAlias") == 0)
{
utf8cstr wsValue = pValue;
strncpy(io_pProfile->m_aCluster[iClusterNum].m_wsApplianceAlias,
wsValue,
KMS_MAX_ENTITY_ID);
io_pProfile->m_aCluster[iClusterNum].
m_wsApplianceAlias[KMS_MAX_ENTITY_ID] = 0;
}
if(strcmp(pName, "ApplianceNetworkAddress") == 0)
{
utf8cstr wsValue = pValue;
strncpy(io_pProfile->m_aCluster[iClusterNum].
m_wsApplianceNetworkAddress,
wsValue,
KMS_MAX_NETWORK_ADDRESS);
io_pProfile->m_aCluster[iClusterNum].
m_wsApplianceNetworkAddress[KMS_MAX_NETWORK_ADDRESS] = 0;
}
if(strcmp(pName, "ApplianceSiteID") == 0)
{
utf8cstr wsValue = pValue;
strncpy(io_pProfile->m_aCluster[iClusterNum].m_wsApplianceSiteID,
wsValue,
KMS_MAX_ENTITY_SITE_ID);
io_pProfile->m_aCluster[iClusterNum].
m_wsApplianceSiteID[KMS_MAX_ENTITY_SITE_ID] = 0;
}
if(strcmp(pName, "KMAVersion") == 0)
{
utf8cstr wsValue = pValue;
strncpy(io_pProfile->m_aCluster[iClusterNum].m_sKMAVersion,
wsValue,
KMS_MAX_VERSION_LENGTH);
io_pProfile->m_aCluster[iClusterNum].
m_sKMAVersion[KMS_MAX_VERSION_LENGTH] = '\0';
}
if(strcmp(pName, "KMALocked") == 0)
{
sscanf(pValue, "%d",
&(io_pProfile->m_aCluster[iClusterNum].m_iKMALocked));
}
}
io_pProfile->m_iClusterNum = iClusterNum;
#ifdef K_SOLARIS_PLATFORM
(void) flock_fd(fd, F_UNLCK, &clusterfl, &cluster_mutex);
#endif
fclose(fp);
return true;
}
/*! DeleteCluster
*
*/
bool DeleteCluster( KMSClientProfile* const io_pProfile )
{
FATAL_ASSERT( io_pProfile );
FATAL_ASSERT( io_pProfile->m_wsProfileName );
#if defined(DEBUG_TRACE) && defined(METAWARE)
ECPT_TRACE_ENTRY *trace = NULL;
ECPT_TRACE( trace, DeleteCluster );
#endif
bool bSuccess = true;
char sFullProfileDir[KMS_MAX_FILE_NAME];
char sClusterInformationFile[KMS_MAX_FILE_NAME];
BuildFullProfilePathWithName( sFullProfileDir, g_sWorkingDirectory,
io_pProfile->m_wsProfileName );
strcpy( sClusterInformationFile, sFullProfileDir );
strncat( sClusterInformationFile, PROFILE_CLUSTER_CONFIG_FILE,
KMS_MAX_FILE_NAME );
myFILE* pfFile = fopen( sClusterInformationFile, "rb" );
if ( pfFile != NULL )
{
fclose(pfFile);
if ( my_unlink(sClusterInformationFile) )
bSuccess = false;
}
return true;
}
/*! StoreCACertificate
* Store CA Certificate to a persistent storage file
* @param i_pProfile
* @param i_pCACertificate
*
* @returns boolean success or failure
*/
bool StoreCACertificate(
KMSClientProfile* const i_pProfile,
CCertificate* const i_pCACertificate )
{
FATAL_ASSERT( i_pProfile );
FATAL_ASSERT( i_pCACertificate );
char sCACertificateFile[KMS_MAX_FILE_NAME];
#if defined(DEBUG_TRACE) && defined(METAWARE)
ECPT_TRACE_ENTRY *trace = NULL;
ECPT_TRACE( trace, StoreCACertificate );
#endif
BuildFullProfilePath( sCACertificateFile,
g_sWorkingDirectory,
i_pProfile->m_wsProfileName );
strncat( sCACertificateFile, CA_CERTIFICATE_FILE, KMS_MAX_FILE_NAME );
// OVERLOADED Save method - 2 parameters means save to a file
if ( !( i_pCACertificate->Save(sCACertificateFile, PKI_FORMAT)) )
{
LogError(i_pProfile,
AUDIT_CLIENT_LOAD_PROFILE_SAVE_CA_CERTIFICATE_FAILED,
NULL,
NULL,
sCACertificateFile );
return false;
}
return true;
}
/*! StoreAgentPKI
* Store Private Keys a persistent storage file
*
*/
#ifndef K_SOLARIS_PLATFORM
static
#endif
bool StoreAgentPKI(
KMSClientProfile* const i_pProfile,
CCertificate* const i_pAgentCertificate,
CPrivateKey* const i_pAgentPrivateKey,
const char* const i_sHexHashedPassphrase )
{
FATAL_ASSERT( i_pProfile );
FATAL_ASSERT( i_pAgentCertificate );
bool bSuccess;
char sClientKeyFile[KMS_MAX_FILE_NAME];
#if defined(DEBUG_TRACE) && defined(METAWARE)
ECPT_TRACE_ENTRY *trace = NULL;
ECPT_TRACE( trace, StoreAgentPKI ) ;
#endif
BuildFullProfilePath( sClientKeyFile,
g_sWorkingDirectory,
i_pProfile->m_wsProfileName );
strncat( sClientKeyFile,
#ifdef KMSUSERPKCS12
CLIENT_PK12_FILE,
#else
CLIENT_KEY_FILE,
#endif
KMS_MAX_FILE_NAME );
CPKI oPKI;
// save Certificate and Private Key to file named sClientKeyFile(CLIENT_KEY_FILE)
bSuccess = oPKI.ExportCertAndKeyToFile(
i_pAgentCertificate,
i_pAgentPrivateKey,
sClientKeyFile,
i_sHexHashedPassphrase,
#ifdef KMSUSERPKCS12
PKCS12_FORMAT
#else
PKI_FORMAT
#endif
);
if ( !bSuccess )
{
LogError(i_pProfile,
AUDIT_CLIENT_LOAD_PROFILE_EXPORT_CERTIFICATE_AND_KEY_FAILED,
NULL,
NULL,
sClientKeyFile );
}
return bSuccess;
}
/*! StorePKIcerts
* Store PKI objects to persistent storage files
*/
bool StorePKIcerts(
KMSClientProfile* const io_pProfile,
CCertificate* const i_pCACertificate,
CCertificate* const i_pAgentCertificate,
CPrivateKey* const i_pAgentPrivateKey,
const char* const i_sHexHashedPassphrase )
{
FATAL_ASSERT( io_pProfile );
FATAL_ASSERT( i_pAgentCertificate );
bool bSuccess = false;
bSuccess = StoreCACertificate( io_pProfile, i_pCACertificate );
if ( bSuccess )
{
bSuccess = StoreAgentPKI( io_pProfile,
i_pAgentCertificate,
i_pAgentPrivateKey,
i_sHexHashedPassphrase );
}
if ( bSuccess )
{
io_pProfile->m_iEnrolled = TRUE;
}
return bSuccess;
}
#ifdef KMSUSERPKCS12
/*
* Test to see if the PKCS12 file exists.
*/
bool ClientKeyP12Exists(char *profileName)
{
bool bSuccess = true;
char sFullProfileDir[KMS_MAX_FILE_NAME+1];
char sAgentPK12File[KMS_MAX_FILE_NAME+1];
struct stat statp;
BuildFullProfilePath(sFullProfileDir,
g_sWorkingDirectory, profileName);
strncpy( sAgentPK12File, sFullProfileDir, KMS_MAX_FILE_NAME );
strncat( sAgentPK12File, CLIENT_PK12_FILE, KMS_MAX_FILE_NAME );
bSuccess = false;
if (stat(sAgentPK12File, &statp) == -1)
bSuccess = false;
else if (statp.st_size > 0)
bSuccess = true;
return (bSuccess);
}
/*
* Load the cert and the private key from the PKCS12 file.
*/
bool GetPKCS12CertAndKey(
KMSClientProfile* const io_pProfile,
utf8char *i_pPassphrase,
CCertificate *i_pEntityCert,
CPrivateKey *i_pEntityPrivateKey)
{
bool bSuccess = true;
char sFullProfileDir[KMS_MAX_FILE_NAME+1];
char sAgentPK12File[KMS_MAX_FILE_NAME+1];
BuildFullProfilePath(sFullProfileDir,
g_sWorkingDirectory, io_pProfile->m_wsProfileName );
strncpy( sAgentPK12File, sFullProfileDir, KMS_MAX_FILE_NAME );
strncat( sAgentPK12File, CLIENT_PK12_FILE, KMS_MAX_FILE_NAME );
bSuccess = i_pEntityCert->LoadPKCS12CertAndKey(
sAgentPK12File, FILE_FORMAT_PKCS12,
i_pEntityPrivateKey, i_pPassphrase);
if (!bSuccess)
io_pProfile->m_iLastErrorCode = KMS_AGENT_LOCAL_AUTH_FAILURE;
return (bSuccess);
}
bool StoreTempAgentPKI(
KMSClientProfile* const i_pProfile,
CCertificate* i_pAgentCertificate,
CPrivateKey* i_pAgentPrivateKey)
{
FATAL_ASSERT( i_pProfile );
FATAL_ASSERT( i_pAgentCertificate );
bool bSuccess;
char sClientKeyFile[KMS_MAX_FILE_NAME];
BuildFullProfilePath( sClientKeyFile,
g_sWorkingDirectory,
i_pProfile->m_wsProfileName );
strncat(sClientKeyFile,
CLIENT_KEY_FILE,
KMS_MAX_FILE_NAME );
CPKI oPKI;
// save Certificate and Private Key to file named sClientKeyFile(CLIENT_KEY_FILE)
bSuccess = oPKI.ExportCertAndKeyToFile(
i_pAgentCertificate,
i_pAgentPrivateKey,
sClientKeyFile,
NULL,
PKI_FORMAT);
if ( !bSuccess )
{
LogError(i_pProfile,
AUDIT_CLIENT_LOAD_PROFILE_EXPORT_CERTIFICATE_AND_KEY_FAILED,
NULL,
NULL,
sClientKeyFile );
}
return bSuccess;
}
void CleanupPrivateKeyFile(KMSClientProfile* const io_pProfile)
{
char sClientKeyFile[KMS_MAX_FILE_NAME];
BuildFullProfilePath( sClientKeyFile,
g_sWorkingDirectory,
io_pProfile->m_wsProfileName );
strncat(sClientKeyFile,
CLIENT_KEY_FILE,
KMS_MAX_FILE_NAME );
(void) unlink(sClientKeyFile);
return;
}
#endif /* PKCS12 */
/**
* GetPKIcerts verifies that CA and Agent certificates are available in
* persistent storage and updates profile with an indicator
*/
bool GetPKIcerts(
KMSClientProfile* const io_pProfile )
{
FATAL_ASSERT( io_pProfile );
bool bSuccess = true;
char sFullProfileDir[KMS_MAX_FILE_NAME+1];
char sCAcertFile[KMS_MAX_FILE_NAME+1];
char sAgentCertFile[KMS_MAX_FILE_NAME+1];
#ifndef K_SOLARIS_PLATFORM
myFILE* pfFile;
#endif
#if defined(DEBUG_TRACE) && defined(METAWARE)
ECPT_TRACE_ENTRY *trace = NULL;
ECPT_TRACE( trace, GetPKIcerts );
#endif
io_pProfile->m_iEnrolled = FALSE;
BuildFullProfilePath( sFullProfileDir,
g_sWorkingDirectory, io_pProfile->m_wsProfileName );
strncpy( sCAcertFile, sFullProfileDir, KMS_MAX_FILE_NAME );
sCAcertFile[KMS_MAX_FILE_NAME] = '\0';
strncat( sCAcertFile, CA_CERTIFICATE_FILE, KMS_MAX_FILE_NAME );
#ifdef K_SOLARIS_PLATFORM
/*
* stat(2) is preferred over fopen(3C)
* fopen for checking if a file is present.
*/
struct stat statp;
if (stat(sCAcertFile, &statp)) {
LogError(io_pProfile,
AUDIT_CLIENT_LOAD_PROFILE_FAILED,
NULL,
NULL,
"Test for presence of CA Certificate failed" );
return false;
}
#else
pfFile = fopen( sCAcertFile, "rb" );
if ( pfFile != NULL )
{
fclose(pfFile);
}
else
{
LogError(io_pProfile,
AUDIT_CLIENT_LOAD_PROFILE_FAILED,
NULL,
NULL,
"Test for presence of CA Certificate failed" );
return false;
}
#endif
// open the file containing client certificate and private key
// checking if the file exists.
strncpy( sAgentCertFile, sFullProfileDir, KMS_MAX_FILE_NAME );
sAgentCertFile[KMS_MAX_FILE_NAME] = '\0';
strncat( sAgentCertFile, CLIENT_KEY_FILE, KMS_MAX_FILE_NAME );
#ifdef K_SOLARIS_PLATFORM
/*
* stat(2) is safer than "fopen" for checking if a file is
* present or not.
*/
if (stat(sAgentCertFile, &statp)) {
LogError(io_pProfile,
AUDIT_CLIENT_LOAD_PROFILE_FAILED,
NULL,
NULL,
"Test for presence of Agent Certificate failed" );
return false;
}
#else
pfFile = fopen( sAgentCertFile, "rb" );
if ( pfFile != NULL )
{
fclose(pfFile);
}
else
{
LogError(io_pProfile,
AUDIT_CLIENT_LOAD_PROFILE_FAILED,
NULL,
NULL,
"Test for presence of Agent Certificate failed" );
return false;
}
#endif
io_pProfile->m_iEnrolled = TRUE;
return bSuccess;
}
/**
* DeleteStorageProfile
*/
bool DeleteStorageProfile(
const char* const i_pName)
{
FATAL_ASSERT( i_pName );
#if defined(DEBUG_TRACE) && defined(METAWARE)
ECPT_TRACE_ENTRY *trace = NULL;
ECPT_TRACE( trace, DeleteStorageProfile );
#endif
bool bSuccess = true;
char sFullProfileDir[KMS_MAX_FILE_NAME+1];
char sConfigFile[KMS_MAX_FILE_NAME+1];
char sClusterInformationFile[KMS_MAX_FILE_NAME+1];
char sCACertificateFile[KMS_MAX_FILE_NAME+1];
char sClientKeyFile[KMS_MAX_FILE_NAME+1];
#ifdef KMSUSERPKCS12
char sClientP12File[KMS_MAX_FILE_NAME+1];
#endif
BuildFullProfilePathWithName( sFullProfileDir,
g_sWorkingDirectory, i_pName );
strncpy( sConfigFile, sFullProfileDir, KMS_MAX_FILE_NAME );
sConfigFile[KMS_MAX_FILE_NAME] = '\0';
strncat( sConfigFile, PROFILE_CONFIG_FILE, KMS_MAX_FILE_NAME );
strncpy( sClusterInformationFile, sFullProfileDir, KMS_MAX_FILE_NAME );
sClusterInformationFile[KMS_MAX_FILE_NAME] = '\0';
strncat( sClusterInformationFile,
PROFILE_CLUSTER_CONFIG_FILE,
KMS_MAX_FILE_NAME );
strncpy( sCACertificateFile, sFullProfileDir, KMS_MAX_FILE_NAME );
sCACertificateFile[KMS_MAX_FILE_NAME] = '\0';
strncat( sCACertificateFile, CA_CERTIFICATE_FILE, KMS_MAX_FILE_NAME );
strncpy( sClientKeyFile, sFullProfileDir, KMS_MAX_FILE_NAME );
sClientKeyFile[KMS_MAX_FILE_NAME] = '\0';
strncat( sClientKeyFile, CLIENT_KEY_FILE, KMS_MAX_FILE_NAME );
myFILE* pfFile = fopen( sConfigFile, "rb" );
if ( pfFile != NULL )
{
fclose(pfFile);
if ( my_unlink(sConfigFile) )
bSuccess = false;
}
pfFile = fopen( sClusterInformationFile, "rb" );
if ( pfFile != NULL )
{
fclose(pfFile);
if ( my_unlink(sClusterInformationFile) )
bSuccess = false;
}
pfFile = fopen( sCACertificateFile, "rb" );
if ( pfFile != NULL )
{
fclose(pfFile);
if ( my_unlink(sCACertificateFile) )
bSuccess = false;
}
pfFile = fopen( sClientKeyFile, "rb" );
if ( pfFile != NULL )
{
fclose(pfFile);
if ( my_unlink(sClientKeyFile) )
bSuccess = false;
}
#ifdef KMSUSERPKCS12
strncpy( sClientP12File, sFullProfileDir, KMS_MAX_FILE_NAME );
sClientP12File[KMS_MAX_FILE_NAME] = '\0';
strncat( sClientP12File, CLIENT_KEY_FILE, KMS_MAX_FILE_NAME );
/* Just unlink, no need to open/close first. */
if ( my_unlink(sClientP12File) )
bSuccess = false;
#endif
pfFile = fopen( sFullProfileDir, "rb" );
if ( pfFile != NULL )
{
fclose(pfFile);
if ( my_rmdir(sFullProfileDir) )
bSuccess = false;
}
return bSuccess;
}
/**
* K_soap_ssl_client_context
* Parse client context and send to soap, either using a soap call
* for openSSL or user implemented call for Treck SSL
*
* @param i_pProfile - pointer to KMSClientProfile
* @param io_pSoap - pointer to soap structure
* @param i_iFlags - input flags (CLIENT or SERVER auth)
*
* @returns 0=success, non-zero=fail
*/
int K_soap_ssl_client_context
( KMSClientProfile* const i_pProfile, // input KMSClientProfile
struct soap * io_pSoap, // i/o soap profile
unsigned short i_iFlags ) // input flags
{
FATAL_ASSERT( i_pProfile );
FATAL_ASSERT( io_pSoap );
#if defined(DEBUG_TRACE) && defined(METAWARE)
ECPT_TRACE_ENTRY *trace = NULL;
ECPT_TRACE( trace, K_soap_ssl_client_context ) ;
#endif
char sCACertificateFile[KMS_MAX_FILE_NAME];
char sClientKeyFile[KMS_MAX_FILE_NAME];
BuildFullProfilePath( sCACertificateFile, // out
g_sWorkingDirectory, // out
i_pProfile->m_wsProfileName ); // in
strncat( sCACertificateFile, // path
CA_CERTIFICATE_FILE, // name
KMS_MAX_FILE_NAME );
switch ( i_iFlags )
{
case SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION:
{
BuildFullProfilePath( sClientKeyFile,
g_sWorkingDirectory,
i_pProfile->m_wsProfileName );
strncat( sClientKeyFile, // path
CLIENT_KEY_FILE, // name
KMS_MAX_FILE_NAME );
// this sends the following to the SSL Layer
#ifdef METAWARE
return K_ssl_client_context(
io_pSoap, // i/o
i_iFlags, // flags
sClientKeyFile, // keyfile - client cert and private key
i_pProfile->m_sHexHashedPassphrase, // password
sCACertificateFile, // cafile - CA certificate
NULL, // capath
NULL ); // randfile
#else
return soap_ssl_client_context(
io_pSoap, // i/o
#ifndef SOAP_SSL_SKIP_HOST_CHECK
i_iFlags, // flags
#else
i_iFlags | SOAP_SSL_SKIP_HOST_CHECK, // flags
#endif
sClientKeyFile, // keyfile - client cert and private key
i_pProfile->m_sHexHashedPassphrase, // password
sCACertificateFile, // cafile - CA certificate
NULL, // capath
NULL ); // randfile
#endif
}
case SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION:
{
#ifdef METAWARE
return K_ssl_client_context(
io_pSoap, // i/o
i_iFlags, // flags
NULL, // keyfile
NULL, // password
sCACertificateFile, // cafile
NULL, // capath
NULL ); // randfile
#else
return soap_ssl_client_context(
io_pSoap, // i/o
#ifndef SOAP_SSL_SKIP_HOST_CHECK
i_iFlags, // flags
#else
i_iFlags | SOAP_SSL_SKIP_HOST_CHECK, // flags
#endif
NULL, // keyfile
NULL, // password
sCACertificateFile, // cafile
NULL, // capath
NULL ); // randfile
#endif
}
default:
// unauthenticated sessions are not supported
return 1;
}
}