1*12720SWyllys.Ingersoll@Sun.COM /* 2*12720SWyllys.Ingersoll@Sun.COM * CDDL HEADER START 3*12720SWyllys.Ingersoll@Sun.COM * 4*12720SWyllys.Ingersoll@Sun.COM * The contents of this file are subject to the terms of the 5*12720SWyllys.Ingersoll@Sun.COM * Common Development and Distribution License (the "License"). 6*12720SWyllys.Ingersoll@Sun.COM * You may not use this file except in compliance with the License. 7*12720SWyllys.Ingersoll@Sun.COM * 8*12720SWyllys.Ingersoll@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*12720SWyllys.Ingersoll@Sun.COM * or http://www.opensolaris.org/os/licensing. 10*12720SWyllys.Ingersoll@Sun.COM * See the License for the specific language governing permissions 11*12720SWyllys.Ingersoll@Sun.COM * and limitations under the License. 12*12720SWyllys.Ingersoll@Sun.COM * 13*12720SWyllys.Ingersoll@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 14*12720SWyllys.Ingersoll@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*12720SWyllys.Ingersoll@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 16*12720SWyllys.Ingersoll@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 17*12720SWyllys.Ingersoll@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 18*12720SWyllys.Ingersoll@Sun.COM * 19*12720SWyllys.Ingersoll@Sun.COM * CDDL HEADER END 20*12720SWyllys.Ingersoll@Sun.COM */ 21*12720SWyllys.Ingersoll@Sun.COM 22*12720SWyllys.Ingersoll@Sun.COM /* 23*12720SWyllys.Ingersoll@Sun.COM * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 24*12720SWyllys.Ingersoll@Sun.COM */ 25*12720SWyllys.Ingersoll@Sun.COM 26*12720SWyllys.Ingersoll@Sun.COM /** 27*12720SWyllys.Ingersoll@Sun.COM * \file KMSAgentLoadBalancer.cpp 28*12720SWyllys.Ingersoll@Sun.COM */ 29*12720SWyllys.Ingersoll@Sun.COM 30*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32 31*12720SWyllys.Ingersoll@Sun.COM #define _WIN32_WINNT 0x0400 32*12720SWyllys.Ingersoll@Sun.COM #include <windows.h> 33*12720SWyllys.Ingersoll@Sun.COM #include <process.h> 34*12720SWyllys.Ingersoll@Sun.COM #endif 35*12720SWyllys.Ingersoll@Sun.COM 36*12720SWyllys.Ingersoll@Sun.COM #include <stdlib.h> 37*12720SWyllys.Ingersoll@Sun.COM 38*12720SWyllys.Ingersoll@Sun.COM #include "KMS_AgentH.h" 39*12720SWyllys.Ingersoll@Sun.COM #include "KMSClientProfile.h" 40*12720SWyllys.Ingersoll@Sun.COM #include "KMSAgentSoapUtilities.h" 41*12720SWyllys.Ingersoll@Sun.COM #include "KMSAgentStringUtilities.h" 42*12720SWyllys.Ingersoll@Sun.COM #include "KMSClientProfileImpl.h" 43*12720SWyllys.Ingersoll@Sun.COM #include "KMSAgent.h" 44*12720SWyllys.Ingersoll@Sun.COM #include "KMSAuditLogger.h" 45*12720SWyllys.Ingersoll@Sun.COM #include "ApplianceParameters.h" 46*12720SWyllys.Ingersoll@Sun.COM #include "KMSAgentCryptoUtilities.h" 47*12720SWyllys.Ingersoll@Sun.COM 48*12720SWyllys.Ingersoll@Sun.COM #ifdef METAWARE 49*12720SWyllys.Ingersoll@Sun.COM #include "debug.h" 50*12720SWyllys.Ingersoll@Sun.COM #include "sizet.h" 51*12720SWyllys.Ingersoll@Sun.COM typedef unsigned char uint8_t; 52*12720SWyllys.Ingersoll@Sun.COM typedef unsigned short uint16_t; 53*12720SWyllys.Ingersoll@Sun.COM typedef unsigned int uint32_t; 54*12720SWyllys.Ingersoll@Sun.COM typedef unsigned long long uint64_t; 55*12720SWyllys.Ingersoll@Sun.COM #endif 56*12720SWyllys.Ingersoll@Sun.COM #include "KMSAgentAESKeyWrap.h" 57*12720SWyllys.Ingersoll@Sun.COM 58*12720SWyllys.Ingersoll@Sun.COM #ifdef METAWARE 59*12720SWyllys.Ingersoll@Sun.COM #include "stdsoap2.h" /* makes fewer platform assumptions 60*12720SWyllys.Ingersoll@Sun.COM than the standard stdsoap2.h */ 61*12720SWyllys.Ingersoll@Sun.COM 62*12720SWyllys.Ingersoll@Sun.COM int time (char *); 63*12720SWyllys.Ingersoll@Sun.COM #include "literals.h" 64*12720SWyllys.Ingersoll@Sun.COM #else 65*12720SWyllys.Ingersoll@Sun.COM #include "stdsoap2.h" 66*12720SWyllys.Ingersoll@Sun.COM #endif 67*12720SWyllys.Ingersoll@Sun.COM 68*12720SWyllys.Ingersoll@Sun.COM #include "AutoMutex.h" 69*12720SWyllys.Ingersoll@Sun.COM 70*12720SWyllys.Ingersoll@Sun.COM // real declaration of soap * 71*12720SWyllys.Ingersoll@Sun.COM #include "KMSAgentDataUnitCache.h" 72*12720SWyllys.Ingersoll@Sun.COM 73*12720SWyllys.Ingersoll@Sun.COM #include "ClientSoapFaultCodes.h" 74*12720SWyllys.Ingersoll@Sun.COM #include "KMSAgentPKICommon.h" 75*12720SWyllys.Ingersoll@Sun.COM #include "KMSAgentLoadBalancer.h" // needs to be after stdsoap2.h to use the 76*12720SWyllys.Ingersoll@Sun.COM 77*12720SWyllys.Ingersoll@Sun.COM CAgentLoadBalancer::CAgentLoadBalancer (KMSClientProfile * const i_pProfile) 78*12720SWyllys.Ingersoll@Sun.COM : m_pProfile (i_pProfile), 79*12720SWyllys.Ingersoll@Sun.COM m_iTransactionStartTimeInMilliseconds (0), 80*12720SWyllys.Ingersoll@Sun.COM m_bFIPS (false), 81*12720SWyllys.Ingersoll@Sun.COM m_iKWKEntryNum (0), 82*12720SWyllys.Ingersoll@Sun.COM m_iLastAttemptedWhenNoneResponding (0) 83*12720SWyllys.Ingersoll@Sun.COM { 84*12720SWyllys.Ingersoll@Sun.COM CAutoMutex oAutoMutex((K_MUTEX_HANDLE) m_pProfile->m_pLock); 85*12720SWyllys.Ingersoll@Sun.COM 86*12720SWyllys.Ingersoll@Sun.COM // initialize the aCluster, let it contain the default appliance 87*12720SWyllys.Ingersoll@Sun.COM m_iClusterNum = 1; 88*12720SWyllys.Ingersoll@Sun.COM memset(&(m_aCluster[0]), 0, sizeof (KMSClusterEntry)); 89*12720SWyllys.Ingersoll@Sun.COM strncpy(m_aCluster[0].m_wsApplianceNetworkAddress, 90*12720SWyllys.Ingersoll@Sun.COM i_pProfile->m_wsApplianceAddress, 91*12720SWyllys.Ingersoll@Sun.COM sizeof(m_aCluster[0].m_wsApplianceNetworkAddress)); 92*12720SWyllys.Ingersoll@Sun.COM m_aCluster[0].m_wsApplianceNetworkAddress[sizeof(m_aCluster[0].m_wsApplianceNetworkAddress)-1] = '\0'; 93*12720SWyllys.Ingersoll@Sun.COM 94*12720SWyllys.Ingersoll@Sun.COM // This may not be known because the initial 95*12720SWyllys.Ingersoll@Sun.COM // appliance's Alias is not yet entered. 96*12720SWyllys.Ingersoll@Sun.COM strcpy(m_aCluster[0].m_wsApplianceAlias, ""); 97*12720SWyllys.Ingersoll@Sun.COM strcpy(m_sURL, ""); 98*12720SWyllys.Ingersoll@Sun.COM memset(m_aKWKEntries, 0, KMS_MAX_CLUSTER_NUM * sizeof(struct KWKEntry *)); 99*12720SWyllys.Ingersoll@Sun.COM } 100*12720SWyllys.Ingersoll@Sun.COM 101*12720SWyllys.Ingersoll@Sun.COM CAgentLoadBalancer::~CAgentLoadBalancer () 102*12720SWyllys.Ingersoll@Sun.COM { 103*12720SWyllys.Ingersoll@Sun.COM // free up KWK entries 104*12720SWyllys.Ingersoll@Sun.COM for( int i=0; i < m_iKWKEntryNum && i < KMS_MAX_CLUSTER_NUM; i++) 105*12720SWyllys.Ingersoll@Sun.COM { 106*12720SWyllys.Ingersoll@Sun.COM if (m_aKWKEntries[i] != NULL) 107*12720SWyllys.Ingersoll@Sun.COM { 108*12720SWyllys.Ingersoll@Sun.COM delete m_aKWKEntries[i]; 109*12720SWyllys.Ingersoll@Sun.COM } 110*12720SWyllys.Ingersoll@Sun.COM } 111*12720SWyllys.Ingersoll@Sun.COM return; 112*12720SWyllys.Ingersoll@Sun.COM } 113*12720SWyllys.Ingersoll@Sun.COM 114*12720SWyllys.Ingersoll@Sun.COM char *CAgentLoadBalancer::GetHTTPSURL (int i_iIndex, int i_iPort) 115*12720SWyllys.Ingersoll@Sun.COM { 116*12720SWyllys.Ingersoll@Sun.COM if (i_iIndex < 0 || i_iIndex >= m_iClusterNum) 117*12720SWyllys.Ingersoll@Sun.COM { 118*12720SWyllys.Ingersoll@Sun.COM strcpy(m_sURL, ""); 119*12720SWyllys.Ingersoll@Sun.COM } 120*12720SWyllys.Ingersoll@Sun.COM else 121*12720SWyllys.Ingersoll@Sun.COM { 122*12720SWyllys.Ingersoll@Sun.COM K_snprintf(m_sURL, KMS_MAX_URL, "https://%s:%d", 123*12720SWyllys.Ingersoll@Sun.COM m_aCluster[i_iIndex].m_wsApplianceNetworkAddress, 124*12720SWyllys.Ingersoll@Sun.COM i_iPort); 125*12720SWyllys.Ingersoll@Sun.COM } 126*12720SWyllys.Ingersoll@Sun.COM 127*12720SWyllys.Ingersoll@Sun.COM return m_sURL; 128*12720SWyllys.Ingersoll@Sun.COM } 129*12720SWyllys.Ingersoll@Sun.COM 130*12720SWyllys.Ingersoll@Sun.COM char *CAgentLoadBalancer::GetHTTPURL (int i_iIndex, int i_iPort) 131*12720SWyllys.Ingersoll@Sun.COM { 132*12720SWyllys.Ingersoll@Sun.COM if (i_iIndex < 0 || i_iIndex >= m_iClusterNum) 133*12720SWyllys.Ingersoll@Sun.COM { 134*12720SWyllys.Ingersoll@Sun.COM strcpy(m_sURL, ""); 135*12720SWyllys.Ingersoll@Sun.COM } 136*12720SWyllys.Ingersoll@Sun.COM else 137*12720SWyllys.Ingersoll@Sun.COM { 138*12720SWyllys.Ingersoll@Sun.COM K_snprintf(m_sURL, KMS_MAX_URL, "http://%s:%d", 139*12720SWyllys.Ingersoll@Sun.COM m_aCluster[i_iIndex].m_wsApplianceNetworkAddress, 140*12720SWyllys.Ingersoll@Sun.COM i_iPort); 141*12720SWyllys.Ingersoll@Sun.COM } 142*12720SWyllys.Ingersoll@Sun.COM 143*12720SWyllys.Ingersoll@Sun.COM return m_sURL; 144*12720SWyllys.Ingersoll@Sun.COM } 145*12720SWyllys.Ingersoll@Sun.COM 146*12720SWyllys.Ingersoll@Sun.COM int CAgentLoadBalancer::Balance () 147*12720SWyllys.Ingersoll@Sun.COM { 148*12720SWyllys.Ingersoll@Sun.COM CAutoMutex oAutoMutex((K_MUTEX_HANDLE) m_pProfile->m_pLock); 149*12720SWyllys.Ingersoll@Sun.COM 150*12720SWyllys.Ingersoll@Sun.COM int i; 151*12720SWyllys.Ingersoll@Sun.COM unsigned int iSelected = 0; 152*12720SWyllys.Ingersoll@Sun.COM unsigned int iSelected2 = 0; 153*12720SWyllys.Ingersoll@Sun.COM 154*12720SWyllys.Ingersoll@Sun.COM // clear the failover attempts 155*12720SWyllys.Ingersoll@Sun.COM m_pProfile->m_iFailoverAttempts = 0; 156*12720SWyllys.Ingersoll@Sun.COM 157*12720SWyllys.Ingersoll@Sun.COM // This assumes Balance()/BalanceBy...() are called at the top of 158*12720SWyllys.Ingersoll@Sun.COM // each Agent Library transaction 159*12720SWyllys.Ingersoll@Sun.COM // m_iTransactionStartTimeInMilliseconds is used to determine if 160*12720SWyllys.Ingersoll@Sun.COM // enough time remains 161*12720SWyllys.Ingersoll@Sun.COM // (vs. KMSClientProfile::m_iTransactionTimeout) to retry a 162*12720SWyllys.Ingersoll@Sun.COM // request if there was a Server Busy error. 163*12720SWyllys.Ingersoll@Sun.COM 164*12720SWyllys.Ingersoll@Sun.COM m_iTransactionStartTimeInMilliseconds = K_GetTickCount(); 165*12720SWyllys.Ingersoll@Sun.COM 166*12720SWyllys.Ingersoll@Sun.COM // if not enabling load balancing, return the default appliance & if 167*12720SWyllys.Ingersoll@Sun.COM // its FIPS compatible when running in FIPS_MODE 168*12720SWyllys.Ingersoll@Sun.COM 169*12720SWyllys.Ingersoll@Sun.COM if (m_pProfile->m_iClusterDiscoveryFrequency == 0) 170*12720SWyllys.Ingersoll@Sun.COM { 171*12720SWyllys.Ingersoll@Sun.COM if (m_bFIPS && !FIPScompatibleKMA(m_aCluster[0].m_sKMAVersion)) 172*12720SWyllys.Ingersoll@Sun.COM { 173*12720SWyllys.Ingersoll@Sun.COM return NO_FIPS_KMA_AVAILABLE; 174*12720SWyllys.Ingersoll@Sun.COM } 175*12720SWyllys.Ingersoll@Sun.COM return 0; 176*12720SWyllys.Ingersoll@Sun.COM } 177*12720SWyllys.Ingersoll@Sun.COM 178*12720SWyllys.Ingersoll@Sun.COM int iCurrentTime = K_GetTickCount() / 1000; 179*12720SWyllys.Ingersoll@Sun.COM 180*12720SWyllys.Ingersoll@Sun.COM // if it is the first time or time to get cluster information 181*12720SWyllys.Ingersoll@Sun.COM if ((!m_pProfile->m_bIsClusterDiscoveryCalled) || 182*12720SWyllys.Ingersoll@Sun.COM ((iCurrentTime - m_pProfile->m_iLastClusterDiscoveryTime) > 183*12720SWyllys.Ingersoll@Sun.COM m_pProfile->m_iClusterDiscoveryFrequency)) 184*12720SWyllys.Ingersoll@Sun.COM { 185*12720SWyllys.Ingersoll@Sun.COM if (!KMSClient_GetClusterInformation(m_pProfile, 186*12720SWyllys.Ingersoll@Sun.COM m_pProfile->m_wsEntitySiteID, 187*12720SWyllys.Ingersoll@Sun.COM sizeof (m_pProfile->m_wsEntitySiteID), 188*12720SWyllys.Ingersoll@Sun.COM &(m_pProfile->m_iClusterNum), 189*12720SWyllys.Ingersoll@Sun.COM m_pProfile->m_aCluster, 190*12720SWyllys.Ingersoll@Sun.COM KMS_MAX_CLUSTER_NUM)) 191*12720SWyllys.Ingersoll@Sun.COM { 192*12720SWyllys.Ingersoll@Sun.COM // if failed due to some error, return default one 193*12720SWyllys.Ingersoll@Sun.COM // KMSClient_GetClusterInformation logs 194*12720SWyllys.Ingersoll@Sun.COM 195*12720SWyllys.Ingersoll@Sun.COM return 0; 196*12720SWyllys.Ingersoll@Sun.COM } 197*12720SWyllys.Ingersoll@Sun.COM 198*12720SWyllys.Ingersoll@Sun.COM m_pProfile->m_bIsClusterDiscoveryCalled = true; 199*12720SWyllys.Ingersoll@Sun.COM 200*12720SWyllys.Ingersoll@Sun.COM // Reset the transaction start time to not include the time spent 201*12720SWyllys.Ingersoll@Sun.COM // calling KMSClient_GetClusterInformation. 202*12720SWyllys.Ingersoll@Sun.COM 203*12720SWyllys.Ingersoll@Sun.COM m_iTransactionStartTimeInMilliseconds = K_GetTickCount(); 204*12720SWyllys.Ingersoll@Sun.COM 205*12720SWyllys.Ingersoll@Sun.COM // reset this index since cluster size may have changed 206*12720SWyllys.Ingersoll@Sun.COM m_iLastAttemptedWhenNoneResponding = 0; 207*12720SWyllys.Ingersoll@Sun.COM 208*12720SWyllys.Ingersoll@Sun.COM // TODO: Adjust timeouts to guarentee a response to the Agent 209*12720SWyllys.Ingersoll@Sun.COM // Library called in m_iTransactionTimeout seconds? This means 210*12720SWyllys.Ingersoll@Sun.COM // not adjusting m_iTransactionStartTimeInMilliseconds, but also 211*12720SWyllys.Ingersoll@Sun.COM // reducing socket timeouts for subsequent calls. 212*12720SWyllys.Ingersoll@Sun.COM } 213*12720SWyllys.Ingersoll@Sun.COM 214*12720SWyllys.Ingersoll@Sun.COM // sort the cluster array by Load 215*12720SWyllys.Ingersoll@Sun.COM 216*12720SWyllys.Ingersoll@Sun.COM KMSClient_SortClusterArray(m_pProfile); 217*12720SWyllys.Ingersoll@Sun.COM 218*12720SWyllys.Ingersoll@Sun.COM // copy all Appliances to this object 219*12720SWyllys.Ingersoll@Sun.COM 220*12720SWyllys.Ingersoll@Sun.COM for (i = 0; i < m_pProfile->m_iClusterNum; i++) 221*12720SWyllys.Ingersoll@Sun.COM { 222*12720SWyllys.Ingersoll@Sun.COM m_aCluster[i] = m_pProfile->m_aCluster[i]; 223*12720SWyllys.Ingersoll@Sun.COM } 224*12720SWyllys.Ingersoll@Sun.COM 225*12720SWyllys.Ingersoll@Sun.COM m_iClusterNum = m_pProfile->m_iClusterNum; 226*12720SWyllys.Ingersoll@Sun.COM 227*12720SWyllys.Ingersoll@Sun.COM int iCandidateAppliances = 0; 228*12720SWyllys.Ingersoll@Sun.COM 229*12720SWyllys.Ingersoll@Sun.COM // the initial set of candidates for load balancing are all enabled, 230*12720SWyllys.Ingersoll@Sun.COM // responding and unlocked KMAs (assumes they are at the top of the sort 231*12720SWyllys.Ingersoll@Sun.COM // order) & FIPS compatible if we're in that mode 232*12720SWyllys.Ingersoll@Sun.COM 233*12720SWyllys.Ingersoll@Sun.COM for (i = 0; i < m_iClusterNum; i++) 234*12720SWyllys.Ingersoll@Sun.COM { 235*12720SWyllys.Ingersoll@Sun.COM if ((m_aCluster[i].m_iResponding == TRUE) && 236*12720SWyllys.Ingersoll@Sun.COM (m_aCluster[i].m_iEnabled == TRUE ) && 237*12720SWyllys.Ingersoll@Sun.COM (m_aCluster[i].m_iKMALocked == FALSE)) 238*12720SWyllys.Ingersoll@Sun.COM { 239*12720SWyllys.Ingersoll@Sun.COM iCandidateAppliances++; 240*12720SWyllys.Ingersoll@Sun.COM } 241*12720SWyllys.Ingersoll@Sun.COM } 242*12720SWyllys.Ingersoll@Sun.COM 243*12720SWyllys.Ingersoll@Sun.COM // check if there are any enabled and responding Appliances in the 244*12720SWyllys.Ingersoll@Sun.COM // same site as this Agent, and if so make those the candidates 245*12720SWyllys.Ingersoll@Sun.COM // (assumes they are at the top of the sort order) 246*12720SWyllys.Ingersoll@Sun.COM 247*12720SWyllys.Ingersoll@Sun.COM int iCandidateAppliancesInSameSite = 0; 248*12720SWyllys.Ingersoll@Sun.COM 249*12720SWyllys.Ingersoll@Sun.COM if (strlen(m_pProfile->m_wsEntitySiteID) > 0) 250*12720SWyllys.Ingersoll@Sun.COM { 251*12720SWyllys.Ingersoll@Sun.COM for (i = 0; i < iCandidateAppliances; i++) 252*12720SWyllys.Ingersoll@Sun.COM { 253*12720SWyllys.Ingersoll@Sun.COM if (strncmp(m_aCluster[i].m_wsApplianceSiteID, 254*12720SWyllys.Ingersoll@Sun.COM m_pProfile->m_wsEntitySiteID, 255*12720SWyllys.Ingersoll@Sun.COM sizeof(m_aCluster[i].m_wsApplianceSiteID)) == 0) 256*12720SWyllys.Ingersoll@Sun.COM { 257*12720SWyllys.Ingersoll@Sun.COM iCandidateAppliancesInSameSite++; 258*12720SWyllys.Ingersoll@Sun.COM } 259*12720SWyllys.Ingersoll@Sun.COM } 260*12720SWyllys.Ingersoll@Sun.COM } 261*12720SWyllys.Ingersoll@Sun.COM 262*12720SWyllys.Ingersoll@Sun.COM // reduce the candidate set to just KMAs within the site 263*12720SWyllys.Ingersoll@Sun.COM if (iCandidateAppliancesInSameSite > 0) 264*12720SWyllys.Ingersoll@Sun.COM { 265*12720SWyllys.Ingersoll@Sun.COM iCandidateAppliances = iCandidateAppliancesInSameSite; 266*12720SWyllys.Ingersoll@Sun.COM } 267*12720SWyllys.Ingersoll@Sun.COM 268*12720SWyllys.Ingersoll@Sun.COM // constrain the candidate set to just FIPS compatible KMAs 269*12720SWyllys.Ingersoll@Sun.COM if (m_bFIPS) 270*12720SWyllys.Ingersoll@Sun.COM { 271*12720SWyllys.Ingersoll@Sun.COM int iCandidateFIPSKMAs = 0; 272*12720SWyllys.Ingersoll@Sun.COM 273*12720SWyllys.Ingersoll@Sun.COM for (i = 0; i < iCandidateAppliances; i++) 274*12720SWyllys.Ingersoll@Sun.COM { 275*12720SWyllys.Ingersoll@Sun.COM if ( FIPScompatibleKMA(m_aCluster[i].m_sKMAVersion )) 276*12720SWyllys.Ingersoll@Sun.COM { 277*12720SWyllys.Ingersoll@Sun.COM iCandidateFIPSKMAs++; 278*12720SWyllys.Ingersoll@Sun.COM } 279*12720SWyllys.Ingersoll@Sun.COM } 280*12720SWyllys.Ingersoll@Sun.COM 281*12720SWyllys.Ingersoll@Sun.COM // select only from FIPS capable KMAs 282*12720SWyllys.Ingersoll@Sun.COM iCandidateAppliances = iCandidateFIPSKMAs; 283*12720SWyllys.Ingersoll@Sun.COM } 284*12720SWyllys.Ingersoll@Sun.COM 285*12720SWyllys.Ingersoll@Sun.COM // if there are no candidate Appliances, use the default Appliance unless 286*12720SWyllys.Ingersoll@Sun.COM // we're in FIPS mode 287*12720SWyllys.Ingersoll@Sun.COM 288*12720SWyllys.Ingersoll@Sun.COM if (!m_bFIPS && iCandidateAppliances <= 1) 289*12720SWyllys.Ingersoll@Sun.COM { 290*12720SWyllys.Ingersoll@Sun.COM return 0; 291*12720SWyllys.Ingersoll@Sun.COM } 292*12720SWyllys.Ingersoll@Sun.COM 293*12720SWyllys.Ingersoll@Sun.COM // FIPS mode 294*12720SWyllys.Ingersoll@Sun.COM else if (iCandidateAppliances <= 0) 295*12720SWyllys.Ingersoll@Sun.COM { 296*12720SWyllys.Ingersoll@Sun.COM return NO_FIPS_KMA_AVAILABLE; 297*12720SWyllys.Ingersoll@Sun.COM } 298*12720SWyllys.Ingersoll@Sun.COM else if (iCandidateAppliances == 1) 299*12720SWyllys.Ingersoll@Sun.COM { 300*12720SWyllys.Ingersoll@Sun.COM return 0; 301*12720SWyllys.Ingersoll@Sun.COM } 302*12720SWyllys.Ingersoll@Sun.COM 303*12720SWyllys.Ingersoll@Sun.COM // randomly select two candidate Appliances and select the one 304*12720SWyllys.Ingersoll@Sun.COM // with the smaller load 305*12720SWyllys.Ingersoll@Sun.COM 306*12720SWyllys.Ingersoll@Sun.COM // choose one random number between 0 -- iCandidateAppliances - 1 307*12720SWyllys.Ingersoll@Sun.COM iSelected = rand() % iCandidateAppliances; 308*12720SWyllys.Ingersoll@Sun.COM iSelected2 = (iSelected + 1) % iCandidateAppliances; 309*12720SWyllys.Ingersoll@Sun.COM 310*12720SWyllys.Ingersoll@Sun.COM // select the one with the smaller load 311*12720SWyllys.Ingersoll@Sun.COM 312*12720SWyllys.Ingersoll@Sun.COM if (m_aCluster[iSelected2].m_lLoad < m_aCluster[iSelected].m_lLoad) 313*12720SWyllys.Ingersoll@Sun.COM { 314*12720SWyllys.Ingersoll@Sun.COM iSelected = iSelected2; 315*12720SWyllys.Ingersoll@Sun.COM } 316*12720SWyllys.Ingersoll@Sun.COM 317*12720SWyllys.Ingersoll@Sun.COM return iSelected; 318*12720SWyllys.Ingersoll@Sun.COM } 319*12720SWyllys.Ingersoll@Sun.COM 320*12720SWyllys.Ingersoll@Sun.COM int CAgentLoadBalancer::BalanceByDataUnitID ( 321*12720SWyllys.Ingersoll@Sun.COM const unsigned char * const i_pDataUnitID, 322*12720SWyllys.Ingersoll@Sun.COM int i_iDataUnitIDMaxLen) 323*12720SWyllys.Ingersoll@Sun.COM { 324*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(i_pDataUnitID); 325*12720SWyllys.Ingersoll@Sun.COM 326*12720SWyllys.Ingersoll@Sun.COM CAutoMutex oAutoMutex((K_MUTEX_HANDLE) m_pProfile->m_pLock); 327*12720SWyllys.Ingersoll@Sun.COM 328*12720SWyllys.Ingersoll@Sun.COM // clear the failover attempts 329*12720SWyllys.Ingersoll@Sun.COM m_pProfile->m_iFailoverAttempts = 0; 330*12720SWyllys.Ingersoll@Sun.COM 331*12720SWyllys.Ingersoll@Sun.COM // This assumes Balance(), or BalanceBy...(), 332*12720SWyllys.Ingersoll@Sun.COM // is called at the top of each Agent Library transaction 333*12720SWyllys.Ingersoll@Sun.COM // m_iTransactionStartTimeInMilliseconds is used to determine if enough time remains 334*12720SWyllys.Ingersoll@Sun.COM // (vs. KMSClientProfile::m_iTransactionTimeout) to retry a request if there was 335*12720SWyllys.Ingersoll@Sun.COM // a Server Busy error. 336*12720SWyllys.Ingersoll@Sun.COM 337*12720SWyllys.Ingersoll@Sun.COM m_iTransactionStartTimeInMilliseconds = K_GetTickCount(); 338*12720SWyllys.Ingersoll@Sun.COM 339*12720SWyllys.Ingersoll@Sun.COM // look in cache 340*12720SWyllys.Ingersoll@Sun.COM 341*12720SWyllys.Ingersoll@Sun.COM CDataUnitCache *pDataUnitCache = (CDataUnitCache *) m_pProfile->m_pDataUnitCache; 342*12720SWyllys.Ingersoll@Sun.COM 343*12720SWyllys.Ingersoll@Sun.COM // if not enabling load balancing, return the default appliance & if 344*12720SWyllys.Ingersoll@Sun.COM // its FIPS compatible when running in FIPS_MODE 345*12720SWyllys.Ingersoll@Sun.COM 346*12720SWyllys.Ingersoll@Sun.COM if (m_pProfile->m_iClusterDiscoveryFrequency == 0) 347*12720SWyllys.Ingersoll@Sun.COM { 348*12720SWyllys.Ingersoll@Sun.COM if (m_bFIPS && !FIPScompatibleKMA(m_aCluster[0].m_sKMAVersion)) 349*12720SWyllys.Ingersoll@Sun.COM { 350*12720SWyllys.Ingersoll@Sun.COM return NO_FIPS_KMA_AVAILABLE; 351*12720SWyllys.Ingersoll@Sun.COM } 352*12720SWyllys.Ingersoll@Sun.COM return 0; 353*12720SWyllys.Ingersoll@Sun.COM } 354*12720SWyllys.Ingersoll@Sun.COM 355*12720SWyllys.Ingersoll@Sun.COM // if the Data Unit ID is in the server affinity cache, use that Appliance 356*12720SWyllys.Ingersoll@Sun.COM 357*12720SWyllys.Ingersoll@Sun.COM utf8char wsApplianceNetworkAddress[KMS_MAX_NETWORK_ADDRESS]; 358*12720SWyllys.Ingersoll@Sun.COM int iIndex = CLIENT_SIDE_ERROR; 359*12720SWyllys.Ingersoll@Sun.COM 360*12720SWyllys.Ingersoll@Sun.COM if (pDataUnitCache->GetApplianceByDataUnitID( 361*12720SWyllys.Ingersoll@Sun.COM i_pDataUnitID, 362*12720SWyllys.Ingersoll@Sun.COM i_iDataUnitIDMaxLen, 363*12720SWyllys.Ingersoll@Sun.COM wsApplianceNetworkAddress, 364*12720SWyllys.Ingersoll@Sun.COM sizeof(wsApplianceNetworkAddress))) 365*12720SWyllys.Ingersoll@Sun.COM { 366*12720SWyllys.Ingersoll@Sun.COM iIndex = FindIndexByNetworkAddress(wsApplianceNetworkAddress); 367*12720SWyllys.Ingersoll@Sun.COM } 368*12720SWyllys.Ingersoll@Sun.COM 369*12720SWyllys.Ingersoll@Sun.COM if (iIndex != CLIENT_SIDE_ERROR) 370*12720SWyllys.Ingersoll@Sun.COM { 371*12720SWyllys.Ingersoll@Sun.COM if (m_bFIPS && !FIPScompatibleKMA(m_aCluster[iIndex].m_sKMAVersion)) 372*12720SWyllys.Ingersoll@Sun.COM { 373*12720SWyllys.Ingersoll@Sun.COM // in spite of caching we need to attempt an alternate KMA due 374*12720SWyllys.Ingersoll@Sun.COM // to the FIPS mode setting 375*12720SWyllys.Ingersoll@Sun.COM return Balance(); 376*12720SWyllys.Ingersoll@Sun.COM } 377*12720SWyllys.Ingersoll@Sun.COM return iIndex; 378*12720SWyllys.Ingersoll@Sun.COM } 379*12720SWyllys.Ingersoll@Sun.COM 380*12720SWyllys.Ingersoll@Sun.COM // normal balancing 381*12720SWyllys.Ingersoll@Sun.COM return Balance(); 382*12720SWyllys.Ingersoll@Sun.COM } 383*12720SWyllys.Ingersoll@Sun.COM 384*12720SWyllys.Ingersoll@Sun.COM int CAgentLoadBalancer::BalanceByDataUnitKeyID ( 385*12720SWyllys.Ingersoll@Sun.COM const unsigned char * const i_pDataUnitKeyID, 386*12720SWyllys.Ingersoll@Sun.COM int i_iDataUnitKeyIDMaxLen) 387*12720SWyllys.Ingersoll@Sun.COM { 388*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(i_pDataUnitKeyID); 389*12720SWyllys.Ingersoll@Sun.COM 390*12720SWyllys.Ingersoll@Sun.COM CAutoMutex oAutoMutex((K_MUTEX_HANDLE) m_pProfile->m_pLock); 391*12720SWyllys.Ingersoll@Sun.COM 392*12720SWyllys.Ingersoll@Sun.COM // clear the failover attempts 393*12720SWyllys.Ingersoll@Sun.COM m_pProfile->m_iFailoverAttempts = 0; 394*12720SWyllys.Ingersoll@Sun.COM 395*12720SWyllys.Ingersoll@Sun.COM // This assumes Balance()/BalanceBy...() 396*12720SWyllys.Ingersoll@Sun.COM // are called at the top of each Agent Library transaction 397*12720SWyllys.Ingersoll@Sun.COM // m_iTransactionStartTimeInMilliseconds is used to determine if enough time remains 398*12720SWyllys.Ingersoll@Sun.COM // (vs. KMSClientProfile::m_iTransactionTimeout) to retry a request if there was 399*12720SWyllys.Ingersoll@Sun.COM // a Server Busy error. 400*12720SWyllys.Ingersoll@Sun.COM 401*12720SWyllys.Ingersoll@Sun.COM m_iTransactionStartTimeInMilliseconds = K_GetTickCount(); 402*12720SWyllys.Ingersoll@Sun.COM 403*12720SWyllys.Ingersoll@Sun.COM // look in cache 404*12720SWyllys.Ingersoll@Sun.COM 405*12720SWyllys.Ingersoll@Sun.COM CDataUnitCache *pDataUnitCache = (CDataUnitCache *) m_pProfile->m_pDataUnitCache; 406*12720SWyllys.Ingersoll@Sun.COM 407*12720SWyllys.Ingersoll@Sun.COM // if not enabling load balancing, return the default appliance & if 408*12720SWyllys.Ingersoll@Sun.COM // its FIPS compatible when running in FIPS_MODE 409*12720SWyllys.Ingersoll@Sun.COM 410*12720SWyllys.Ingersoll@Sun.COM if (m_pProfile->m_iClusterDiscoveryFrequency == 0) 411*12720SWyllys.Ingersoll@Sun.COM { 412*12720SWyllys.Ingersoll@Sun.COM if (m_bFIPS && !FIPScompatibleKMA(m_aCluster[0].m_sKMAVersion)) 413*12720SWyllys.Ingersoll@Sun.COM { 414*12720SWyllys.Ingersoll@Sun.COM return NO_FIPS_KMA_AVAILABLE; 415*12720SWyllys.Ingersoll@Sun.COM } 416*12720SWyllys.Ingersoll@Sun.COM return 0; 417*12720SWyllys.Ingersoll@Sun.COM } 418*12720SWyllys.Ingersoll@Sun.COM 419*12720SWyllys.Ingersoll@Sun.COM // if the Data Unit Key ID is in the server affinity cache, use that Appliance 420*12720SWyllys.Ingersoll@Sun.COM 421*12720SWyllys.Ingersoll@Sun.COM utf8char sApplianceNetworkAddress[KMS_MAX_NETWORK_ADDRESS]; 422*12720SWyllys.Ingersoll@Sun.COM int iIndex = CLIENT_SIDE_ERROR; 423*12720SWyllys.Ingersoll@Sun.COM 424*12720SWyllys.Ingersoll@Sun.COM if (pDataUnitCache->GetApplianceByDataUnitKeyID( 425*12720SWyllys.Ingersoll@Sun.COM i_pDataUnitKeyID, 426*12720SWyllys.Ingersoll@Sun.COM i_iDataUnitKeyIDMaxLen, 427*12720SWyllys.Ingersoll@Sun.COM sApplianceNetworkAddress, 428*12720SWyllys.Ingersoll@Sun.COM sizeof(sApplianceNetworkAddress))) 429*12720SWyllys.Ingersoll@Sun.COM { 430*12720SWyllys.Ingersoll@Sun.COM iIndex = FindIndexByNetworkAddress(sApplianceNetworkAddress); 431*12720SWyllys.Ingersoll@Sun.COM } 432*12720SWyllys.Ingersoll@Sun.COM 433*12720SWyllys.Ingersoll@Sun.COM if (iIndex != CLIENT_SIDE_ERROR) 434*12720SWyllys.Ingersoll@Sun.COM { 435*12720SWyllys.Ingersoll@Sun.COM if (m_bFIPS && !FIPScompatibleKMA(m_aCluster[iIndex].m_sKMAVersion)) 436*12720SWyllys.Ingersoll@Sun.COM { 437*12720SWyllys.Ingersoll@Sun.COM // in spite of caching we need to attempt an alternate KMA due 438*12720SWyllys.Ingersoll@Sun.COM // to the FIPS mode setting 439*12720SWyllys.Ingersoll@Sun.COM return Balance(); 440*12720SWyllys.Ingersoll@Sun.COM } 441*12720SWyllys.Ingersoll@Sun.COM return iIndex; 442*12720SWyllys.Ingersoll@Sun.COM } 443*12720SWyllys.Ingersoll@Sun.COM 444*12720SWyllys.Ingersoll@Sun.COM // normal balancing 445*12720SWyllys.Ingersoll@Sun.COM return Balance(); 446*12720SWyllys.Ingersoll@Sun.COM } 447*12720SWyllys.Ingersoll@Sun.COM 448*12720SWyllys.Ingersoll@Sun.COM int CAgentLoadBalancer::FindIndexByNetworkAddress 449*12720SWyllys.Ingersoll@Sun.COM (char * i_wsApplianceNetworkAddress) 450*12720SWyllys.Ingersoll@Sun.COM { 451*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(i_wsApplianceNetworkAddress); 452*12720SWyllys.Ingersoll@Sun.COM 453*12720SWyllys.Ingersoll@Sun.COM for (int i = 0; i < m_iClusterNum; i++) 454*12720SWyllys.Ingersoll@Sun.COM { 455*12720SWyllys.Ingersoll@Sun.COM 456*12720SWyllys.Ingersoll@Sun.COM if ((strncmp(m_aCluster[i].m_wsApplianceNetworkAddress, 457*12720SWyllys.Ingersoll@Sun.COM i_wsApplianceNetworkAddress, 458*12720SWyllys.Ingersoll@Sun.COM sizeof(m_aCluster[i].m_wsApplianceNetworkAddress)) == 0) && 459*12720SWyllys.Ingersoll@Sun.COM m_aCluster[i].m_iEnabled == TRUE && 460*12720SWyllys.Ingersoll@Sun.COM m_aCluster[i].m_iResponding == TRUE) 461*12720SWyllys.Ingersoll@Sun.COM { 462*12720SWyllys.Ingersoll@Sun.COM return i; 463*12720SWyllys.Ingersoll@Sun.COM } 464*12720SWyllys.Ingersoll@Sun.COM 465*12720SWyllys.Ingersoll@Sun.COM } 466*12720SWyllys.Ingersoll@Sun.COM 467*12720SWyllys.Ingersoll@Sun.COM return CLIENT_SIDE_ERROR; 468*12720SWyllys.Ingersoll@Sun.COM } 469*12720SWyllys.Ingersoll@Sun.COM 470*12720SWyllys.Ingersoll@Sun.COM char* CAgentLoadBalancer::GetApplianceNetworkAddress (int i_iIndex) 471*12720SWyllys.Ingersoll@Sun.COM { 472*12720SWyllys.Ingersoll@Sun.COM if (i_iIndex < 0 || i_iIndex >= m_iClusterNum) 473*12720SWyllys.Ingersoll@Sun.COM { 474*12720SWyllys.Ingersoll@Sun.COM return (char *)""; 475*12720SWyllys.Ingersoll@Sun.COM } 476*12720SWyllys.Ingersoll@Sun.COM 477*12720SWyllys.Ingersoll@Sun.COM return m_aCluster[i_iIndex].m_wsApplianceNetworkAddress; 478*12720SWyllys.Ingersoll@Sun.COM } 479*12720SWyllys.Ingersoll@Sun.COM 480*12720SWyllys.Ingersoll@Sun.COM bool CAgentLoadBalancer::FailOverLimit (void) 481*12720SWyllys.Ingersoll@Sun.COM { 482*12720SWyllys.Ingersoll@Sun.COM if (m_pProfile->m_iFailoverLimit >= 0 && 483*12720SWyllys.Ingersoll@Sun.COM m_pProfile->m_iFailoverAttempts > m_pProfile->m_iFailoverLimit) 484*12720SWyllys.Ingersoll@Sun.COM return true; 485*12720SWyllys.Ingersoll@Sun.COM else 486*12720SWyllys.Ingersoll@Sun.COM return false; 487*12720SWyllys.Ingersoll@Sun.COM } 488*12720SWyllys.Ingersoll@Sun.COM 489*12720SWyllys.Ingersoll@Sun.COM int CAgentLoadBalancer::FailOver (int i_iFailedApplianceIndex, 490*12720SWyllys.Ingersoll@Sun.COM struct soap *i_pstSoap) 491*12720SWyllys.Ingersoll@Sun.COM { 492*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(i_pstSoap); 493*12720SWyllys.Ingersoll@Sun.COM 494*12720SWyllys.Ingersoll@Sun.COM CAutoMutex oAutoMutex((K_MUTEX_HANDLE) m_pProfile->m_pLock); 495*12720SWyllys.Ingersoll@Sun.COM 496*12720SWyllys.Ingersoll@Sun.COM const char *strError = GET_SOAP_FAULTSTRING(i_pstSoap); 497*12720SWyllys.Ingersoll@Sun.COM int iSoapErrno = i_pstSoap->errnum; 498*12720SWyllys.Ingersoll@Sun.COM int iErrorCode = GET_FAULT_CODE(strError); 499*12720SWyllys.Ingersoll@Sun.COM int i; 500*12720SWyllys.Ingersoll@Sun.COM 501*12720SWyllys.Ingersoll@Sun.COM if ( m_bFIPS && 502*12720SWyllys.Ingersoll@Sun.COM KMSClient_NoFIPSCompatibleKMAs(m_pProfile)) 503*12720SWyllys.Ingersoll@Sun.COM { 504*12720SWyllys.Ingersoll@Sun.COM return NO_FIPS_KMA_AVAILABLE; 505*12720SWyllys.Ingersoll@Sun.COM } 506*12720SWyllys.Ingersoll@Sun.COM 507*12720SWyllys.Ingersoll@Sun.COM m_pProfile->m_iFailoverAttempts++; 508*12720SWyllys.Ingersoll@Sun.COM 509*12720SWyllys.Ingersoll@Sun.COM /* 510*12720SWyllys.Ingersoll@Sun.COM * if KWK is not registered, or mismatched, most likely KMA lost its key due to a service 511*12720SWyllys.Ingersoll@Sun.COM * restart. Call RegisterKWK to re-register the KWK. 512*12720SWyllys.Ingersoll@Sun.COM * If RegisterKWK fails proceed from here with new failover info 513*12720SWyllys.Ingersoll@Sun.COM */ 514*12720SWyllys.Ingersoll@Sun.COM if ( iErrorCode == CLIENT_ERROR_AGENT_KWK_NOT_REGISTERED || 515*12720SWyllys.Ingersoll@Sun.COM iErrorCode == CLIENT_ERROR_AGENT_KWK_ID_MISMATCH ) 516*12720SWyllys.Ingersoll@Sun.COM { 517*12720SWyllys.Ingersoll@Sun.COM LogError(m_pProfile, 518*12720SWyllys.Ingersoll@Sun.COM AGENT_LOADBALANCER_FAILOVER, 519*12720SWyllys.Ingersoll@Sun.COM NULL, 520*12720SWyllys.Ingersoll@Sun.COM m_aCluster[i_iFailedApplianceIndex].m_wsApplianceNetworkAddress, 521*12720SWyllys.Ingersoll@Sun.COM "KWK not registered or ID mismatch - registering"); 522*12720SWyllys.Ingersoll@Sun.COM // delete the KWK entry since the KMA no longer has it 523*12720SWyllys.Ingersoll@Sun.COM DeleteKWKEntry( GetKMAID(i_iFailedApplianceIndex)); 524*12720SWyllys.Ingersoll@Sun.COM 525*12720SWyllys.Ingersoll@Sun.COM return i_iFailedApplianceIndex; 526*12720SWyllys.Ingersoll@Sun.COM } 527*12720SWyllys.Ingersoll@Sun.COM 528*12720SWyllys.Ingersoll@Sun.COM bool bServerError = false; 529*12720SWyllys.Ingersoll@Sun.COM 530*12720SWyllys.Ingersoll@Sun.COM // if the request failed due to a Server Busy error, and if 531*12720SWyllys.Ingersoll@Sun.COM // - transaction timeout has not been exceeded OR 532*12720SWyllys.Ingersoll@Sun.COM // - failover attempts remain 533*12720SWyllys.Ingersoll@Sun.COM // then failover 534*12720SWyllys.Ingersoll@Sun.COM 535*12720SWyllys.Ingersoll@Sun.COM if (iErrorCode == CLIENT_ERROR_SERVER_BUSY && 536*12720SWyllys.Ingersoll@Sun.COM (K_GetTickCount() < m_iTransactionStartTimeInMilliseconds + (m_pProfile->m_iTransactionTimeout * 1000) || 537*12720SWyllys.Ingersoll@Sun.COM !CAgentLoadBalancer::FailOverLimit())) 538*12720SWyllys.Ingersoll@Sun.COM { 539*12720SWyllys.Ingersoll@Sun.COM LogError(m_pProfile, 540*12720SWyllys.Ingersoll@Sun.COM AGENT_LOADBALANCER_FAILOVER, 541*12720SWyllys.Ingersoll@Sun.COM NULL, 542*12720SWyllys.Ingersoll@Sun.COM m_aCluster[i_iFailedApplianceIndex].m_wsApplianceNetworkAddress, 543*12720SWyllys.Ingersoll@Sun.COM "Server Busy - failing over"); 544*12720SWyllys.Ingersoll@Sun.COM bServerError = true; 545*12720SWyllys.Ingersoll@Sun.COM } 546*12720SWyllys.Ingersoll@Sun.COM else if (ServerError(strError,iSoapErrno)) 547*12720SWyllys.Ingersoll@Sun.COM { 548*12720SWyllys.Ingersoll@Sun.COM bServerError = true; 549*12720SWyllys.Ingersoll@Sun.COM } 550*12720SWyllys.Ingersoll@Sun.COM else 551*12720SWyllys.Ingersoll@Sun.COM { 552*12720SWyllys.Ingersoll@Sun.COM if (i_iFailedApplianceIndex == AES_KEY_WRAP_SETUP_ERROR) 553*12720SWyllys.Ingersoll@Sun.COM { 554*12720SWyllys.Ingersoll@Sun.COM return AES_KEY_WRAP_SETUP_ERROR; 555*12720SWyllys.Ingersoll@Sun.COM } 556*12720SWyllys.Ingersoll@Sun.COM else 557*12720SWyllys.Ingersoll@Sun.COM { 558*12720SWyllys.Ingersoll@Sun.COM return CLIENT_SIDE_ERROR; // it is a client side problem, don't fail over 559*12720SWyllys.Ingersoll@Sun.COM } 560*12720SWyllys.Ingersoll@Sun.COM } 561*12720SWyllys.Ingersoll@Sun.COM 562*12720SWyllys.Ingersoll@Sun.COM // disable the failed Appliance in the profile, and 563*12720SWyllys.Ingersoll@Sun.COM // re-sort the cluster array, so transactions in other threads 564*12720SWyllys.Ingersoll@Sun.COM // will not send requests to the same failed Appliance 565*12720SWyllys.Ingersoll@Sun.COM #if defined(METAWARE) 566*12720SWyllys.Ingersoll@Sun.COM log_cond_printf(ECPT_LOG_AGENT, "CAgentLoadBalancer::Failover(): FailoverAttempts=%d\n", 567*12720SWyllys.Ingersoll@Sun.COM m_pProfile->m_iFailoverAttempts); 568*12720SWyllys.Ingersoll@Sun.COM #endif 569*12720SWyllys.Ingersoll@Sun.COM for (i = 0; i < m_pProfile->m_iClusterNum; i++) 570*12720SWyllys.Ingersoll@Sun.COM { 571*12720SWyllys.Ingersoll@Sun.COM if (m_pProfile->m_aCluster[i].m_lApplianceID == 572*12720SWyllys.Ingersoll@Sun.COM m_aCluster[i_iFailedApplianceIndex].m_lApplianceID) 573*12720SWyllys.Ingersoll@Sun.COM { 574*12720SWyllys.Ingersoll@Sun.COM m_pProfile->m_aCluster[i].m_iResponding = FALSE; 575*12720SWyllys.Ingersoll@Sun.COM break; 576*12720SWyllys.Ingersoll@Sun.COM } 577*12720SWyllys.Ingersoll@Sun.COM } 578*12720SWyllys.Ingersoll@Sun.COM 579*12720SWyllys.Ingersoll@Sun.COM KMSClient_SortClusterArray(m_pProfile); 580*12720SWyllys.Ingersoll@Sun.COM 581*12720SWyllys.Ingersoll@Sun.COM // mark the failed Appliance as not responding (unlike the case 582*12720SWyllys.Ingersoll@Sun.COM // above which is conditional on bServerError, this marking is 583*12720SWyllys.Ingersoll@Sun.COM // only local to this transaction; it must be done to ensure that 584*12720SWyllys.Ingersoll@Sun.COM // this transaction does not cycle in its fail-over loop.) 585*12720SWyllys.Ingersoll@Sun.COM 586*12720SWyllys.Ingersoll@Sun.COM m_aCluster[i_iFailedApplianceIndex].m_iResponding = FALSE; 587*12720SWyllys.Ingersoll@Sun.COM 588*12720SWyllys.Ingersoll@Sun.COM if (!CAgentLoadBalancer::FailOverLimit()) 589*12720SWyllys.Ingersoll@Sun.COM { 590*12720SWyllys.Ingersoll@Sun.COM // now try to fail over to all other Appliances that are 591*12720SWyllys.Ingersoll@Sun.COM // apparently enabled and responding 592*12720SWyllys.Ingersoll@Sun.COM 593*12720SWyllys.Ingersoll@Sun.COM for (i = 0; i < m_iClusterNum; i++) 594*12720SWyllys.Ingersoll@Sun.COM { 595*12720SWyllys.Ingersoll@Sun.COM if (m_aCluster[i].m_iEnabled == TRUE && 596*12720SWyllys.Ingersoll@Sun.COM m_aCluster[i].m_iResponding == TRUE && 597*12720SWyllys.Ingersoll@Sun.COM m_aCluster[i].m_iKMALocked == FALSE) 598*12720SWyllys.Ingersoll@Sun.COM { 599*12720SWyllys.Ingersoll@Sun.COM Log(AGENT_LOADBALANCER_FAILOVER, 600*12720SWyllys.Ingersoll@Sun.COM NULL, 601*12720SWyllys.Ingersoll@Sun.COM m_aCluster[i].m_wsApplianceNetworkAddress, 602*12720SWyllys.Ingersoll@Sun.COM "Failing over to this addr"); 603*12720SWyllys.Ingersoll@Sun.COM 604*12720SWyllys.Ingersoll@Sun.COM return i; 605*12720SWyllys.Ingersoll@Sun.COM } 606*12720SWyllys.Ingersoll@Sun.COM } 607*12720SWyllys.Ingersoll@Sun.COM 608*12720SWyllys.Ingersoll@Sun.COM // now retry KMAs previously reported as not responding 609*12720SWyllys.Ingersoll@Sun.COM 610*12720SWyllys.Ingersoll@Sun.COM m_iLastAttemptedWhenNoneResponding++; 611*12720SWyllys.Ingersoll@Sun.COM 612*12720SWyllys.Ingersoll@Sun.COM if (m_iLastAttemptedWhenNoneResponding >= m_iClusterNum) 613*12720SWyllys.Ingersoll@Sun.COM { 614*12720SWyllys.Ingersoll@Sun.COM m_iLastAttemptedWhenNoneResponding = m_iLastAttemptedWhenNoneResponding % m_iClusterNum; 615*12720SWyllys.Ingersoll@Sun.COM } 616*12720SWyllys.Ingersoll@Sun.COM 617*12720SWyllys.Ingersoll@Sun.COM Log(AGENT_LOADBALANCER_FAILOVER, 618*12720SWyllys.Ingersoll@Sun.COM NULL, 619*12720SWyllys.Ingersoll@Sun.COM m_aCluster[m_iLastAttemptedWhenNoneResponding].m_wsApplianceNetworkAddress, 620*12720SWyllys.Ingersoll@Sun.COM "Failing over to retry this addr"); 621*12720SWyllys.Ingersoll@Sun.COM 622*12720SWyllys.Ingersoll@Sun.COM return m_iLastAttemptedWhenNoneResponding; 623*12720SWyllys.Ingersoll@Sun.COM } 624*12720SWyllys.Ingersoll@Sun.COM else 625*12720SWyllys.Ingersoll@Sun.COM { 626*12720SWyllys.Ingersoll@Sun.COM Log(AGENT_LOADBALANCER_FAILOVER, 627*12720SWyllys.Ingersoll@Sun.COM NULL, 628*12720SWyllys.Ingersoll@Sun.COM NULL, 629*12720SWyllys.Ingersoll@Sun.COM "Failover limit reached"); 630*12720SWyllys.Ingersoll@Sun.COM } 631*12720SWyllys.Ingersoll@Sun.COM 632*12720SWyllys.Ingersoll@Sun.COM return m_bFIPS ? NO_FIPS_KMA_AVAILABLE : NO_KMA_AVAILABLE; 633*12720SWyllys.Ingersoll@Sun.COM } 634*12720SWyllys.Ingersoll@Sun.COM 635*12720SWyllys.Ingersoll@Sun.COM void CAgentLoadBalancer::UpdateResponseStatus(int i_iIndex) 636*12720SWyllys.Ingersoll@Sun.COM { 637*12720SWyllys.Ingersoll@Sun.COM bool bStatusChanged = false; 638*12720SWyllys.Ingersoll@Sun.COM 639*12720SWyllys.Ingersoll@Sun.COM CAutoMutex oAutoMutex((K_MUTEX_HANDLE) m_pProfile->m_pLock); 640*12720SWyllys.Ingersoll@Sun.COM 641*12720SWyllys.Ingersoll@Sun.COM // enable the responding Appliance in the profile, and 642*12720SWyllys.Ingersoll@Sun.COM // re-sort the cluster array, so transactions in other threads 643*12720SWyllys.Ingersoll@Sun.COM // will not send requests to the same failed Appliance 644*12720SWyllys.Ingersoll@Sun.COM 645*12720SWyllys.Ingersoll@Sun.COM for (int i = 0; i < m_pProfile->m_iClusterNum; i++) 646*12720SWyllys.Ingersoll@Sun.COM { 647*12720SWyllys.Ingersoll@Sun.COM if (m_pProfile->m_aCluster[i].m_lApplianceID == 648*12720SWyllys.Ingersoll@Sun.COM m_aCluster[i_iIndex].m_lApplianceID) 649*12720SWyllys.Ingersoll@Sun.COM { 650*12720SWyllys.Ingersoll@Sun.COM if (m_pProfile->m_aCluster[i].m_iResponding == FALSE) 651*12720SWyllys.Ingersoll@Sun.COM { 652*12720SWyllys.Ingersoll@Sun.COM bStatusChanged = true; 653*12720SWyllys.Ingersoll@Sun.COM } 654*12720SWyllys.Ingersoll@Sun.COM m_pProfile->m_aCluster[i].m_iResponding = TRUE; 655*12720SWyllys.Ingersoll@Sun.COM break; 656*12720SWyllys.Ingersoll@Sun.COM } 657*12720SWyllys.Ingersoll@Sun.COM } 658*12720SWyllys.Ingersoll@Sun.COM 659*12720SWyllys.Ingersoll@Sun.COM // only resort if the responding status actually changed 660*12720SWyllys.Ingersoll@Sun.COM if (bStatusChanged) 661*12720SWyllys.Ingersoll@Sun.COM { 662*12720SWyllys.Ingersoll@Sun.COM KMSClient_SortClusterArray(m_pProfile); 663*12720SWyllys.Ingersoll@Sun.COM } 664*12720SWyllys.Ingersoll@Sun.COM 665*12720SWyllys.Ingersoll@Sun.COM // mark the Appliance as now responding 666*12720SWyllys.Ingersoll@Sun.COM m_aCluster[i_iIndex].m_iResponding = TRUE; 667*12720SWyllys.Ingersoll@Sun.COM 668*12720SWyllys.Ingersoll@Sun.COM return; 669*12720SWyllys.Ingersoll@Sun.COM } 670*12720SWyllys.Ingersoll@Sun.COM 671*12720SWyllys.Ingersoll@Sun.COM Long64 CAgentLoadBalancer::GetKMAID ( 672*12720SWyllys.Ingersoll@Sun.COM int i_iIndex) 673*12720SWyllys.Ingersoll@Sun.COM { 674*12720SWyllys.Ingersoll@Sun.COM if (i_iIndex < 0 || i_iIndex >= m_iClusterNum) 675*12720SWyllys.Ingersoll@Sun.COM { 676*12720SWyllys.Ingersoll@Sun.COM return -1; 677*12720SWyllys.Ingersoll@Sun.COM } 678*12720SWyllys.Ingersoll@Sun.COM 679*12720SWyllys.Ingersoll@Sun.COM return m_aCluster[i_iIndex].m_lApplianceID; 680*12720SWyllys.Ingersoll@Sun.COM } 681*12720SWyllys.Ingersoll@Sun.COM 682*12720SWyllys.Ingersoll@Sun.COM CAgentLoadBalancer::KWKEntry *CAgentLoadBalancer::GetKWK ( 683*12720SWyllys.Ingersoll@Sun.COM Long64 i_lKMAID) 684*12720SWyllys.Ingersoll@Sun.COM { 685*12720SWyllys.Ingersoll@Sun.COM if (i_lKMAID == -1) 686*12720SWyllys.Ingersoll@Sun.COM { 687*12720SWyllys.Ingersoll@Sun.COM return NULL; 688*12720SWyllys.Ingersoll@Sun.COM } 689*12720SWyllys.Ingersoll@Sun.COM 690*12720SWyllys.Ingersoll@Sun.COM for (int i = 0; i < m_iKWKEntryNum && i < KMS_MAX_CLUSTER_NUM; i++) 691*12720SWyllys.Ingersoll@Sun.COM { 692*12720SWyllys.Ingersoll@Sun.COM if (m_aKWKEntries[i] != NULL && 693*12720SWyllys.Ingersoll@Sun.COM m_aKWKEntries[i]->m_lKMAID == i_lKMAID ) 694*12720SWyllys.Ingersoll@Sun.COM { 695*12720SWyllys.Ingersoll@Sun.COM return m_aKWKEntries[i]; 696*12720SWyllys.Ingersoll@Sun.COM } 697*12720SWyllys.Ingersoll@Sun.COM } 698*12720SWyllys.Ingersoll@Sun.COM 699*12720SWyllys.Ingersoll@Sun.COM return NULL; 700*12720SWyllys.Ingersoll@Sun.COM } 701*12720SWyllys.Ingersoll@Sun.COM 702*12720SWyllys.Ingersoll@Sun.COM CAgentLoadBalancer::KWKEntry *CAgentLoadBalancer::CreateKWK ( 703*12720SWyllys.Ingersoll@Sun.COM Long64 i_lKMAID, 704*12720SWyllys.Ingersoll@Sun.COM struct soap * const i_pstSoap, 705*12720SWyllys.Ingersoll@Sun.COM const char * const i_sURL, 706*12720SWyllys.Ingersoll@Sun.COM bool * const o_pbClientAESKeyWrapSetupError) 707*12720SWyllys.Ingersoll@Sun.COM { 708*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(i_pstSoap); 709*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(i_sURL); 710*12720SWyllys.Ingersoll@Sun.COM 711*12720SWyllys.Ingersoll@Sun.COM int bSuccess = FALSE; 712*12720SWyllys.Ingersoll@Sun.COM KWKEntry *oKWKEntry = new KWKEntry; 713*12720SWyllys.Ingersoll@Sun.COM 714*12720SWyllys.Ingersoll@Sun.COM oKWKEntry->m_lKMAID = i_lKMAID; 715*12720SWyllys.Ingersoll@Sun.COM *o_pbClientAESKeyWrapSetupError = false; 716*12720SWyllys.Ingersoll@Sun.COM 717*12720SWyllys.Ingersoll@Sun.COM bSuccess = GetPseudorandomBytes(sizeof (oKWKEntry->m_acKWK), 718*12720SWyllys.Ingersoll@Sun.COM oKWKEntry->m_acKWK); 719*12720SWyllys.Ingersoll@Sun.COM if (!bSuccess) 720*12720SWyllys.Ingersoll@Sun.COM { 721*12720SWyllys.Ingersoll@Sun.COM Log(AUDIT_CLIENT_AGENT_CREATE_KWK_RNG_ERROR, 722*12720SWyllys.Ingersoll@Sun.COM NULL, 723*12720SWyllys.Ingersoll@Sun.COM NULL, 724*12720SWyllys.Ingersoll@Sun.COM "Error from RNG"); 725*12720SWyllys.Ingersoll@Sun.COM *o_pbClientAESKeyWrapSetupError = true; 726*12720SWyllys.Ingersoll@Sun.COM delete(oKWKEntry); 727*12720SWyllys.Ingersoll@Sun.COM return NULL; 728*12720SWyllys.Ingersoll@Sun.COM } 729*12720SWyllys.Ingersoll@Sun.COM 730*12720SWyllys.Ingersoll@Sun.COM #if defined(DEBUG) 731*12720SWyllys.Ingersoll@Sun.COM char sHexKWK[2*KMS_MAX_KEY_SIZE+1]; 732*12720SWyllys.Ingersoll@Sun.COM ConvertBinaryToUTF8HexString( sHexKWK, oKWKEntry->m_acKWK, sizeof (oKWKEntry->m_acKWK)); 733*12720SWyllys.Ingersoll@Sun.COM #if defined(METAWARE) 734*12720SWyllys.Ingersoll@Sun.COM log_printf("CAgentLoadBalancer::CreateKWK(): KWK hex=%s\n", 735*12720SWyllys.Ingersoll@Sun.COM sHexKWK); 736*12720SWyllys.Ingersoll@Sun.COM #else 737*12720SWyllys.Ingersoll@Sun.COM // printf("CAgentLoadBalancer::CreateKWK(): KWK hex=%s\n", 738*12720SWyllys.Ingersoll@Sun.COM // sHexKWK); 739*12720SWyllys.Ingersoll@Sun.COM #endif 740*12720SWyllys.Ingersoll@Sun.COM #endif 741*12720SWyllys.Ingersoll@Sun.COM 742*12720SWyllys.Ingersoll@Sun.COM CPublicKey oPublicKEK; 743*12720SWyllys.Ingersoll@Sun.COM 744*12720SWyllys.Ingersoll@Sun.COM bSuccess = GetKWKWrappingKey(i_pstSoap, i_sURL, &oPublicKEK); 745*12720SWyllys.Ingersoll@Sun.COM 746*12720SWyllys.Ingersoll@Sun.COM if (!bSuccess) 747*12720SWyllys.Ingersoll@Sun.COM { 748*12720SWyllys.Ingersoll@Sun.COM // GetKWKWrappingKey logs errors 749*12720SWyllys.Ingersoll@Sun.COM 750*12720SWyllys.Ingersoll@Sun.COM if (!ServerError(GET_SOAP_FAULTSTRING(i_pstSoap),i_pstSoap->errnum)) 751*12720SWyllys.Ingersoll@Sun.COM { 752*12720SWyllys.Ingersoll@Sun.COM *o_pbClientAESKeyWrapSetupError = true; 753*12720SWyllys.Ingersoll@Sun.COM } 754*12720SWyllys.Ingersoll@Sun.COM delete(oKWKEntry); 755*12720SWyllys.Ingersoll@Sun.COM return NULL; 756*12720SWyllys.Ingersoll@Sun.COM } 757*12720SWyllys.Ingersoll@Sun.COM 758*12720SWyllys.Ingersoll@Sun.COM unsigned char acWrappedKWK[MAX_RSA_PUB_KEY_LENGTH]; 759*12720SWyllys.Ingersoll@Sun.COM int iWrappedKWKLength; 760*12720SWyllys.Ingersoll@Sun.COM bSuccess = oPublicKEK.Encrypt(sizeof (oKWKEntry->m_acKWK), 761*12720SWyllys.Ingersoll@Sun.COM oKWKEntry->m_acKWK, (unsigned char *) acWrappedKWK, &iWrappedKWKLength); 762*12720SWyllys.Ingersoll@Sun.COM 763*12720SWyllys.Ingersoll@Sun.COM if (!bSuccess) 764*12720SWyllys.Ingersoll@Sun.COM { 765*12720SWyllys.Ingersoll@Sun.COM Log(AUDIT_CLIENT_AGENT_CREATE_KWK_PUBLIC_ENCRYPT_ERROR, 766*12720SWyllys.Ingersoll@Sun.COM NULL, 767*12720SWyllys.Ingersoll@Sun.COM NULL, 768*12720SWyllys.Ingersoll@Sun.COM "Error encrypting KWK with KMA public key"); 769*12720SWyllys.Ingersoll@Sun.COM *o_pbClientAESKeyWrapSetupError = true; 770*12720SWyllys.Ingersoll@Sun.COM delete(oKWKEntry); 771*12720SWyllys.Ingersoll@Sun.COM return NULL; 772*12720SWyllys.Ingersoll@Sun.COM } 773*12720SWyllys.Ingersoll@Sun.COM //#if defined(DEBUG) && !defined(METAWARE) 774*12720SWyllys.Ingersoll@Sun.COM // char sHexWrappedKWK[2*MAX_RSA_PUB_KEY_LENGTH+1]; 775*12720SWyllys.Ingersoll@Sun.COM // ConvertBinaryToUTF8HexString( sHexWrappedKWK, acWrappedKWK, iWrappedKWKLength); 776*12720SWyllys.Ingersoll@Sun.COM // printf("CAgentLoadBalancer::CreateKWK(): wrapped KWK hex=%s\n", 777*12720SWyllys.Ingersoll@Sun.COM // sHexWrappedKWK); 778*12720SWyllys.Ingersoll@Sun.COM //#endif 779*12720SWyllys.Ingersoll@Sun.COM 780*12720SWyllys.Ingersoll@Sun.COM // register the new KWK 781*12720SWyllys.Ingersoll@Sun.COM bSuccess = RegisterKWK(iWrappedKWKLength, acWrappedKWK, i_pstSoap, 782*12720SWyllys.Ingersoll@Sun.COM i_sURL, oKWKEntry->m_acKWKID); 783*12720SWyllys.Ingersoll@Sun.COM 784*12720SWyllys.Ingersoll@Sun.COM if (!bSuccess) 785*12720SWyllys.Ingersoll@Sun.COM { 786*12720SWyllys.Ingersoll@Sun.COM // RegisterKWK logs errors 787*12720SWyllys.Ingersoll@Sun.COM if (!ServerError(GET_SOAP_FAULTSTRING(i_pstSoap), i_pstSoap->error)) 788*12720SWyllys.Ingersoll@Sun.COM { 789*12720SWyllys.Ingersoll@Sun.COM *o_pbClientAESKeyWrapSetupError = true; 790*12720SWyllys.Ingersoll@Sun.COM } 791*12720SWyllys.Ingersoll@Sun.COM delete(oKWKEntry); 792*12720SWyllys.Ingersoll@Sun.COM return NULL; 793*12720SWyllys.Ingersoll@Sun.COM } 794*12720SWyllys.Ingersoll@Sun.COM 795*12720SWyllys.Ingersoll@Sun.COM // save the new KWK entry in an empty slot in the array 796*12720SWyllys.Ingersoll@Sun.COM for (int i=0; i < m_iKWKEntryNum && i < KMS_MAX_CLUSTER_NUM; i++) 797*12720SWyllys.Ingersoll@Sun.COM { 798*12720SWyllys.Ingersoll@Sun.COM if (m_aKWKEntries[i] == NULL) 799*12720SWyllys.Ingersoll@Sun.COM { 800*12720SWyllys.Ingersoll@Sun.COM m_aKWKEntries[i] = oKWKEntry; 801*12720SWyllys.Ingersoll@Sun.COM return oKWKEntry; 802*12720SWyllys.Ingersoll@Sun.COM } 803*12720SWyllys.Ingersoll@Sun.COM } 804*12720SWyllys.Ingersoll@Sun.COM 805*12720SWyllys.Ingersoll@Sun.COM // no empty slots so add it to the end 806*12720SWyllys.Ingersoll@Sun.COM m_aKWKEntries[m_iKWKEntryNum++] = oKWKEntry; 807*12720SWyllys.Ingersoll@Sun.COM 808*12720SWyllys.Ingersoll@Sun.COM return oKWKEntry; 809*12720SWyllys.Ingersoll@Sun.COM } 810*12720SWyllys.Ingersoll@Sun.COM 811*12720SWyllys.Ingersoll@Sun.COM void CAgentLoadBalancer::DeleteKWKEntry(Long64 i_lKMAID) 812*12720SWyllys.Ingersoll@Sun.COM { 813*12720SWyllys.Ingersoll@Sun.COM for (int i=0; i < m_iKWKEntryNum && i < KMS_MAX_CLUSTER_NUM; i++) 814*12720SWyllys.Ingersoll@Sun.COM { 815*12720SWyllys.Ingersoll@Sun.COM if (m_aKWKEntries[i] && m_aKWKEntries[i]->m_lKMAID == i_lKMAID) 816*12720SWyllys.Ingersoll@Sun.COM { 817*12720SWyllys.Ingersoll@Sun.COM delete(m_aKWKEntries[i]); 818*12720SWyllys.Ingersoll@Sun.COM m_aKWKEntries[i] = NULL; 819*12720SWyllys.Ingersoll@Sun.COM return; 820*12720SWyllys.Ingersoll@Sun.COM } 821*12720SWyllys.Ingersoll@Sun.COM } 822*12720SWyllys.Ingersoll@Sun.COM // should not occur 823*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(0); 824*12720SWyllys.Ingersoll@Sun.COM return; 825*12720SWyllys.Ingersoll@Sun.COM } 826*12720SWyllys.Ingersoll@Sun.COM 827*12720SWyllys.Ingersoll@Sun.COM bool CAgentLoadBalancer::AESKeyWrapSupported (int i_iIndex) 828*12720SWyllys.Ingersoll@Sun.COM { 829*12720SWyllys.Ingersoll@Sun.COM if (i_iIndex < 0 || i_iIndex >= m_iClusterNum) 830*12720SWyllys.Ingersoll@Sun.COM { 831*12720SWyllys.Ingersoll@Sun.COM return false; 832*12720SWyllys.Ingersoll@Sun.COM } 833*12720SWyllys.Ingersoll@Sun.COM return (strcmp(m_aCluster[i_iIndex].m_sKMAVersion, 834*12720SWyllys.Ingersoll@Sun.COM FIPS_COMPATIBLE_KMA_VERSION) >= 0); 835*12720SWyllys.Ingersoll@Sun.COM } 836*12720SWyllys.Ingersoll@Sun.COM 837*12720SWyllys.Ingersoll@Sun.COM int CAgentLoadBalancer::GetKWKID ( 838*12720SWyllys.Ingersoll@Sun.COM int i_Index, 839*12720SWyllys.Ingersoll@Sun.COM Long64 i_lKMAID, 840*12720SWyllys.Ingersoll@Sun.COM struct soap * const i_pstSoap, 841*12720SWyllys.Ingersoll@Sun.COM UTF8_KEYID o_pKWKID, 842*12720SWyllys.Ingersoll@Sun.COM bool * const o_pbClientAESKeyWrapSetupError) 843*12720SWyllys.Ingersoll@Sun.COM { 844*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(i_Index >= 0 && i_Index <= m_iClusterNum); 845*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(i_lKMAID != 0); 846*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(i_pstSoap); 847*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(o_pKWKID); 848*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(o_pbClientAESKeyWrapSetupError); 849*12720SWyllys.Ingersoll@Sun.COM 850*12720SWyllys.Ingersoll@Sun.COM *o_pbClientAESKeyWrapSetupError = false; 851*12720SWyllys.Ingersoll@Sun.COM 852*12720SWyllys.Ingersoll@Sun.COM // check if the KMA for this cluster index is at a version supporting 853*12720SWyllys.Ingersoll@Sun.COM // AES key wrap 854*12720SWyllys.Ingersoll@Sun.COM if (!AESKeyWrapSupported(i_Index)) 855*12720SWyllys.Ingersoll@Sun.COM { 856*12720SWyllys.Ingersoll@Sun.COM strcpy(o_pKWKID, ""); 857*12720SWyllys.Ingersoll@Sun.COM return TRUE; 858*12720SWyllys.Ingersoll@Sun.COM } 859*12720SWyllys.Ingersoll@Sun.COM 860*12720SWyllys.Ingersoll@Sun.COM // AES Key Wrap Mode 861*12720SWyllys.Ingersoll@Sun.COM 862*12720SWyllys.Ingersoll@Sun.COM struct KWKEntry* pKWKentry = GetKWK(i_lKMAID); 863*12720SWyllys.Ingersoll@Sun.COM 864*12720SWyllys.Ingersoll@Sun.COM if (pKWKentry == NULL) 865*12720SWyllys.Ingersoll@Sun.COM { 866*12720SWyllys.Ingersoll@Sun.COM const char* sURL = GetHTTPSURL( 867*12720SWyllys.Ingersoll@Sun.COM i_Index, 868*12720SWyllys.Ingersoll@Sun.COM m_pProfile->m_iPortForAgentService); 869*12720SWyllys.Ingersoll@Sun.COM 870*12720SWyllys.Ingersoll@Sun.COM pKWKentry = CreateKWK(i_lKMAID, i_pstSoap, sURL, o_pbClientAESKeyWrapSetupError); 871*12720SWyllys.Ingersoll@Sun.COM 872*12720SWyllys.Ingersoll@Sun.COM if (pKWKentry == NULL) 873*12720SWyllys.Ingersoll@Sun.COM { 874*12720SWyllys.Ingersoll@Sun.COM return FALSE; 875*12720SWyllys.Ingersoll@Sun.COM } 876*12720SWyllys.Ingersoll@Sun.COM } 877*12720SWyllys.Ingersoll@Sun.COM 878*12720SWyllys.Ingersoll@Sun.COM #if defined(DEBUG) && defined(METAWARE) 879*12720SWyllys.Ingersoll@Sun.COM log_printf("CAgentLoadBalancer::GetKWKID(): KWK IDhex=%s\n", 880*12720SWyllys.Ingersoll@Sun.COM pKWKentry->m_acKWKID, 881*12720SWyllys.Ingersoll@Sun.COM sizeof (UTF8_KEYID)); 882*12720SWyllys.Ingersoll@Sun.COM #endif 883*12720SWyllys.Ingersoll@Sun.COM 884*12720SWyllys.Ingersoll@Sun.COM strncpy(o_pKWKID, pKWKentry->m_acKWKID, sizeof(UTF8_KEYID)); 885*12720SWyllys.Ingersoll@Sun.COM o_pKWKID[sizeof(UTF8_KEYID)-1] = '\0'; 886*12720SWyllys.Ingersoll@Sun.COM 887*12720SWyllys.Ingersoll@Sun.COM return TRUE; 888*12720SWyllys.Ingersoll@Sun.COM }; 889*12720SWyllys.Ingersoll@Sun.COM 890*12720SWyllys.Ingersoll@Sun.COM int CAgentLoadBalancer::GetKWKWrappingKey ( 891*12720SWyllys.Ingersoll@Sun.COM struct soap * const i_pstSoap, 892*12720SWyllys.Ingersoll@Sun.COM const char * const i_sURL, 893*12720SWyllys.Ingersoll@Sun.COM CPublicKey * const o_opPublicKEK) 894*12720SWyllys.Ingersoll@Sun.COM { 895*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(i_pstSoap); 896*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(i_sURL); 897*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(o_opPublicKEK); 898*12720SWyllys.Ingersoll@Sun.COM 899*12720SWyllys.Ingersoll@Sun.COM int bSuccess = TRUE; 900*12720SWyllys.Ingersoll@Sun.COM struct KMS_Agent::KMS_Agent__GetAgentKWKPublicKeyResponse oResponse; 901*12720SWyllys.Ingersoll@Sun.COM char sSoapFaultMsg[g_iMAX_SOAP_FAULT_MESSAGE_LENGTH]; 902*12720SWyllys.Ingersoll@Sun.COM char sKmaAddress[g_iMAX_PEER_NETWORK_ADDRESS_LENGTH]; 903*12720SWyllys.Ingersoll@Sun.COM 904*12720SWyllys.Ingersoll@Sun.COM bSuccess = KMS_Agent::soap_call_KMS_Agent__GetAgentKWKPublicKey( 905*12720SWyllys.Ingersoll@Sun.COM const_cast<struct soap *> (i_pstSoap), 906*12720SWyllys.Ingersoll@Sun.COM i_sURL, 907*12720SWyllys.Ingersoll@Sun.COM NULL, 908*12720SWyllys.Ingersoll@Sun.COM oResponse) == SOAP_OK; 909*12720SWyllys.Ingersoll@Sun.COM 910*12720SWyllys.Ingersoll@Sun.COM if (!bSuccess) 911*12720SWyllys.Ingersoll@Sun.COM { 912*12720SWyllys.Ingersoll@Sun.COM GetSoapFault(sSoapFaultMsg, const_cast<struct soap *> (i_pstSoap)); 913*12720SWyllys.Ingersoll@Sun.COM GetPeerNetworkAddress(sKmaAddress, const_cast<struct soap *> (i_pstSoap)); 914*12720SWyllys.Ingersoll@Sun.COM 915*12720SWyllys.Ingersoll@Sun.COM LogError(m_pProfile, 916*12720SWyllys.Ingersoll@Sun.COM AUDIT_CLIENT_GET_KWK_WRAPPING_KEY_SOAP_ERROR, 917*12720SWyllys.Ingersoll@Sun.COM NULL, 918*12720SWyllys.Ingersoll@Sun.COM sKmaAddress, 919*12720SWyllys.Ingersoll@Sun.COM sSoapFaultMsg); 920*12720SWyllys.Ingersoll@Sun.COM 921*12720SWyllys.Ingersoll@Sun.COM return FALSE; 922*12720SWyllys.Ingersoll@Sun.COM } 923*12720SWyllys.Ingersoll@Sun.COM 924*12720SWyllys.Ingersoll@Sun.COM // Validate the response structure 925*12720SWyllys.Ingersoll@Sun.COM if (bSuccess) 926*12720SWyllys.Ingersoll@Sun.COM { 927*12720SWyllys.Ingersoll@Sun.COM if (oResponse.KWKPublicKey.__ptr == NULL 928*12720SWyllys.Ingersoll@Sun.COM || oResponse.KWKPublicKey.__size < 1) 929*12720SWyllys.Ingersoll@Sun.COM { 930*12720SWyllys.Ingersoll@Sun.COM bSuccess = FALSE; 931*12720SWyllys.Ingersoll@Sun.COM 932*12720SWyllys.Ingersoll@Sun.COM GetPeerNetworkAddress(sKmaAddress, const_cast<struct soap *> (i_pstSoap)); 933*12720SWyllys.Ingersoll@Sun.COM 934*12720SWyllys.Ingersoll@Sun.COM LogError(m_pProfile, 935*12720SWyllys.Ingersoll@Sun.COM AUDIT_CLIENT_GET_KWK_WRAPPING_KEY_INVALID_KEY_RESPONSE, 936*12720SWyllys.Ingersoll@Sun.COM NULL, 937*12720SWyllys.Ingersoll@Sun.COM sKmaAddress, 938*12720SWyllys.Ingersoll@Sun.COM NULL); 939*12720SWyllys.Ingersoll@Sun.COM } 940*12720SWyllys.Ingersoll@Sun.COM else 941*12720SWyllys.Ingersoll@Sun.COM { 942*12720SWyllys.Ingersoll@Sun.COM bSuccess = o_opPublicKEK->Load(oResponse.KWKPublicKey.__ptr, 943*12720SWyllys.Ingersoll@Sun.COM oResponse.KWKPublicKey.__size, PKI_FORMAT); 944*12720SWyllys.Ingersoll@Sun.COM if (!bSuccess) 945*12720SWyllys.Ingersoll@Sun.COM { 946*12720SWyllys.Ingersoll@Sun.COM GetPeerNetworkAddress(sKmaAddress, const_cast<struct soap *> (i_pstSoap)); 947*12720SWyllys.Ingersoll@Sun.COM 948*12720SWyllys.Ingersoll@Sun.COM LogError(m_pProfile, 949*12720SWyllys.Ingersoll@Sun.COM AUDIT_CLIENT_GET_KWK_WRAPPING_KEY_INVALID_RSA_PUB_KEY, 950*12720SWyllys.Ingersoll@Sun.COM NULL, 951*12720SWyllys.Ingersoll@Sun.COM sKmaAddress, 952*12720SWyllys.Ingersoll@Sun.COM NULL); 953*12720SWyllys.Ingersoll@Sun.COM } 954*12720SWyllys.Ingersoll@Sun.COM } 955*12720SWyllys.Ingersoll@Sun.COM } 956*12720SWyllys.Ingersoll@Sun.COM 957*12720SWyllys.Ingersoll@Sun.COM // Note: no SOAP cleanup as caller's environment will get destroyed 958*12720SWyllys.Ingersoll@Sun.COM 959*12720SWyllys.Ingersoll@Sun.COM return bSuccess; 960*12720SWyllys.Ingersoll@Sun.COM }; 961*12720SWyllys.Ingersoll@Sun.COM 962*12720SWyllys.Ingersoll@Sun.COM int CAgentLoadBalancer::RegisterKWK ( 963*12720SWyllys.Ingersoll@Sun.COM int i_iWrappedKWKSize, 964*12720SWyllys.Ingersoll@Sun.COM const unsigned char * const i_acWrappedKWK, 965*12720SWyllys.Ingersoll@Sun.COM struct soap * const i_pstSoap, 966*12720SWyllys.Ingersoll@Sun.COM const char * const i_sURL, 967*12720SWyllys.Ingersoll@Sun.COM UTF8_KEYID o_acUTF8KeyID) 968*12720SWyllys.Ingersoll@Sun.COM { 969*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(i_iWrappedKWKSize > 0); 970*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(i_acWrappedKWK); 971*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(i_pstSoap); 972*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(i_sURL); 973*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(o_acUTF8KeyID); 974*12720SWyllys.Ingersoll@Sun.COM 975*12720SWyllys.Ingersoll@Sun.COM int bSuccess; 976*12720SWyllys.Ingersoll@Sun.COM 977*12720SWyllys.Ingersoll@Sun.COM struct KMS_Agent::xsd__hexBinary oKWK; 978*12720SWyllys.Ingersoll@Sun.COM 979*12720SWyllys.Ingersoll@Sun.COM #if defined(DEBUG) && defined(METAWARE) 980*12720SWyllys.Ingersoll@Sun.COM char sHexWrappedKWK[512]; 981*12720SWyllys.Ingersoll@Sun.COM ConvertBinaryToUTF8HexString( sHexWrappedKWK, i_acWrappedKWK, i_iWrappedKWKSize); 982*12720SWyllys.Ingersoll@Sun.COM log_printf("CAgentLoadBalancer::RegisterKWK(): Wrapped KWK hex=%s, len=%d\n", 983*12720SWyllys.Ingersoll@Sun.COM sHexWrappedKWK, i_iWrappedKWKSize); 984*12720SWyllys.Ingersoll@Sun.COM #endif 985*12720SWyllys.Ingersoll@Sun.COM 986*12720SWyllys.Ingersoll@Sun.COM if (!PutBinaryIntoSoapBinary(i_pstSoap, 987*12720SWyllys.Ingersoll@Sun.COM i_acWrappedKWK, 988*12720SWyllys.Ingersoll@Sun.COM i_iWrappedKWKSize, 989*12720SWyllys.Ingersoll@Sun.COM oKWK.__ptr, 990*12720SWyllys.Ingersoll@Sun.COM oKWK.__size)) 991*12720SWyllys.Ingersoll@Sun.COM { 992*12720SWyllys.Ingersoll@Sun.COM return FALSE; 993*12720SWyllys.Ingersoll@Sun.COM } 994*12720SWyllys.Ingersoll@Sun.COM 995*12720SWyllys.Ingersoll@Sun.COM char sSoapFaultMsg[g_iMAX_SOAP_FAULT_MESSAGE_LENGTH]; 996*12720SWyllys.Ingersoll@Sun.COM char sKmaAddress[g_iMAX_PEER_NETWORK_ADDRESS_LENGTH]; 997*12720SWyllys.Ingersoll@Sun.COM struct KMS_Agent::KMS_Agent__RegisterAgentKWKResponse oResponse; 998*12720SWyllys.Ingersoll@Sun.COM 999*12720SWyllys.Ingersoll@Sun.COM bSuccess = KMS_Agent::soap_call_KMS_Agent__RegisterAgentKWK( 1000*12720SWyllys.Ingersoll@Sun.COM const_cast<struct soap *> (i_pstSoap), 1001*12720SWyllys.Ingersoll@Sun.COM i_sURL, NULL, oKWK, oResponse) == SOAP_OK; 1002*12720SWyllys.Ingersoll@Sun.COM 1003*12720SWyllys.Ingersoll@Sun.COM if (bSuccess) 1004*12720SWyllys.Ingersoll@Sun.COM { 1005*12720SWyllys.Ingersoll@Sun.COM // verify response 1006*12720SWyllys.Ingersoll@Sun.COM if (oResponse.AgentKWKID && 1007*12720SWyllys.Ingersoll@Sun.COM strlen(oResponse.AgentKWKID) == 2 * KMS_KWK_KEY_ID_SIZE) 1008*12720SWyllys.Ingersoll@Sun.COM { 1009*12720SWyllys.Ingersoll@Sun.COM #if defined(DEBUG) && defined(METAWARE) 1010*12720SWyllys.Ingersoll@Sun.COM log_printf("CAgentLoadBalancer::RegisterKWK(): KWK ID hex=%s\n", 1011*12720SWyllys.Ingersoll@Sun.COM oResponse.AgentKWKID, 1012*12720SWyllys.Ingersoll@Sun.COM sizeof (UTF8_KEYID)); 1013*12720SWyllys.Ingersoll@Sun.COM #endif 1014*12720SWyllys.Ingersoll@Sun.COM strncpy(o_acUTF8KeyID, oResponse.AgentKWKID, sizeof(UTF8_KEYID)); 1015*12720SWyllys.Ingersoll@Sun.COM o_acUTF8KeyID[sizeof(UTF8_KEYID)-1] = '\0'; 1016*12720SWyllys.Ingersoll@Sun.COM } 1017*12720SWyllys.Ingersoll@Sun.COM else 1018*12720SWyllys.Ingersoll@Sun.COM { 1019*12720SWyllys.Ingersoll@Sun.COM GetPeerNetworkAddress(sKmaAddress, const_cast<struct soap *> (i_pstSoap)); 1020*12720SWyllys.Ingersoll@Sun.COM GetSoapFault(sSoapFaultMsg, const_cast<struct soap *> (i_pstSoap)); 1021*12720SWyllys.Ingersoll@Sun.COM 1022*12720SWyllys.Ingersoll@Sun.COM Log(AUDIT_CLIENT_AGENT_REGISTER_KWK_INVALID_KEYID_RESPONSE, 1023*12720SWyllys.Ingersoll@Sun.COM NULL, 1024*12720SWyllys.Ingersoll@Sun.COM sKmaAddress, 1025*12720SWyllys.Ingersoll@Sun.COM sSoapFaultMsg); 1026*12720SWyllys.Ingersoll@Sun.COM bSuccess = FALSE; 1027*12720SWyllys.Ingersoll@Sun.COM } 1028*12720SWyllys.Ingersoll@Sun.COM } 1029*12720SWyllys.Ingersoll@Sun.COM else 1030*12720SWyllys.Ingersoll@Sun.COM { 1031*12720SWyllys.Ingersoll@Sun.COM GetPeerNetworkAddress(sKmaAddress, const_cast<struct soap *> (i_pstSoap)); 1032*12720SWyllys.Ingersoll@Sun.COM GetSoapFault(sSoapFaultMsg, const_cast<struct soap *> (i_pstSoap)); 1033*12720SWyllys.Ingersoll@Sun.COM 1034*12720SWyllys.Ingersoll@Sun.COM Log(AUDIT_CLIENT_AGENT_REGISTER_KWK_ERROR, 1035*12720SWyllys.Ingersoll@Sun.COM NULL, 1036*12720SWyllys.Ingersoll@Sun.COM sKmaAddress, 1037*12720SWyllys.Ingersoll@Sun.COM sSoapFaultMsg); 1038*12720SWyllys.Ingersoll@Sun.COM bSuccess = FALSE; 1039*12720SWyllys.Ingersoll@Sun.COM } 1040*12720SWyllys.Ingersoll@Sun.COM 1041*12720SWyllys.Ingersoll@Sun.COM // Note: Clean up SOAP must happen in caller, not here 1042*12720SWyllys.Ingersoll@Sun.COM 1043*12720SWyllys.Ingersoll@Sun.COM return bSuccess; 1044*12720SWyllys.Ingersoll@Sun.COM 1045*12720SWyllys.Ingersoll@Sun.COM }; 1046*12720SWyllys.Ingersoll@Sun.COM 1047*12720SWyllys.Ingersoll@Sun.COM bool CAgentLoadBalancer::AESKeyUnwrap ( 1048*12720SWyllys.Ingersoll@Sun.COM int * const io_pIndex, 1049*12720SWyllys.Ingersoll@Sun.COM const WRAPPED_KEY i_pAESWrappedKey, 1050*12720SWyllys.Ingersoll@Sun.COM KEY o_pPlainTextKey) 1051*12720SWyllys.Ingersoll@Sun.COM { 1052*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(io_pIndex); 1053*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(*io_pIndex >= 0); 1054*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(o_pPlainTextKey); 1055*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(i_pAESWrappedKey); 1056*12720SWyllys.Ingersoll@Sun.COM 1057*12720SWyllys.Ingersoll@Sun.COM struct KWKEntry * pKWKEntry = GetKWK(GetKMAID(*io_pIndex)); 1058*12720SWyllys.Ingersoll@Sun.COM 1059*12720SWyllys.Ingersoll@Sun.COM if (pKWKEntry == NULL) 1060*12720SWyllys.Ingersoll@Sun.COM { 1061*12720SWyllys.Ingersoll@Sun.COM Log(AGENT_LOADBALANCER_AESKEYUNWRAP_GETKWK_RETURNED_NULL, 1062*12720SWyllys.Ingersoll@Sun.COM NULL, 1063*12720SWyllys.Ingersoll@Sun.COM m_aCluster[*io_pIndex].m_wsApplianceNetworkAddress, 1064*12720SWyllys.Ingersoll@Sun.COM NULL); 1065*12720SWyllys.Ingersoll@Sun.COM *io_pIndex = CAgentLoadBalancer::AES_KEY_UNWRAP_ERROR; 1066*12720SWyllys.Ingersoll@Sun.COM 1067*12720SWyllys.Ingersoll@Sun.COM return false; 1068*12720SWyllys.Ingersoll@Sun.COM } 1069*12720SWyllys.Ingersoll@Sun.COM 1070*12720SWyllys.Ingersoll@Sun.COM #if defined(DEBUG) && defined(METAWARE) 1071*12720SWyllys.Ingersoll@Sun.COM char sHexKWK[2*KMS_MAX_KEY_SIZE+1]; 1072*12720SWyllys.Ingersoll@Sun.COM ConvertBinaryToUTF8HexString( sHexKWK, pKWKEntry->m_acKWK, sizeof (pKWKEntry->m_acKWK)); 1073*12720SWyllys.Ingersoll@Sun.COM log_printf("CAgentLoadBalancer::AESKeyUnwrap(): KWK hex=%s\n", 1074*12720SWyllys.Ingersoll@Sun.COM sHexKWK); 1075*12720SWyllys.Ingersoll@Sun.COM #endif 1076*12720SWyllys.Ingersoll@Sun.COM 1077*12720SWyllys.Ingersoll@Sun.COM if (aes_key_unwrap(pKWKEntry->m_acKWK, 1078*12720SWyllys.Ingersoll@Sun.COM sizeof (pKWKEntry->m_acKWK), 1079*12720SWyllys.Ingersoll@Sun.COM i_pAESWrappedKey, 1080*12720SWyllys.Ingersoll@Sun.COM o_pPlainTextKey, 4) != 0) 1081*12720SWyllys.Ingersoll@Sun.COM { 1082*12720SWyllys.Ingersoll@Sun.COM Log(AGENT_LOADBALANCER_AESKEYUNWRAP_KEY_UNWRAP_FAILED, 1083*12720SWyllys.Ingersoll@Sun.COM NULL, 1084*12720SWyllys.Ingersoll@Sun.COM m_aCluster[*io_pIndex].m_wsApplianceNetworkAddress, 1085*12720SWyllys.Ingersoll@Sun.COM NULL); 1086*12720SWyllys.Ingersoll@Sun.COM *io_pIndex = CAgentLoadBalancer::AES_KEY_UNWRAP_ERROR; 1087*12720SWyllys.Ingersoll@Sun.COM return false; 1088*12720SWyllys.Ingersoll@Sun.COM } 1089*12720SWyllys.Ingersoll@Sun.COM 1090*12720SWyllys.Ingersoll@Sun.COM return true; 1091*12720SWyllys.Ingersoll@Sun.COM } 1092*12720SWyllys.Ingersoll@Sun.COM 1093*12720SWyllys.Ingersoll@Sun.COM /*--------------------------------------------------------------------------- 1094*12720SWyllys.Ingersoll@Sun.COM * Function: KMSClient_SortClusterArray 1095*12720SWyllys.Ingersoll@Sun.COM * 1096*12720SWyllys.Ingersoll@Sun.COM *--------------------------------------------------------------------------*/ 1097*12720SWyllys.Ingersoll@Sun.COM void CAgentLoadBalancer::KMSClient_SortClusterArray (KMSClientProfile * const i_pProfile) 1098*12720SWyllys.Ingersoll@Sun.COM { 1099*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT(i_pProfile); 1100*12720SWyllys.Ingersoll@Sun.COM 1101*12720SWyllys.Ingersoll@Sun.COM CAutoMutex oAutoMutex((K_MUTEX_HANDLE) i_pProfile->m_pLock); 1102*12720SWyllys.Ingersoll@Sun.COM 1103*12720SWyllys.Ingersoll@Sun.COM int i; 1104*12720SWyllys.Ingersoll@Sun.COM 1105*12720SWyllys.Ingersoll@Sun.COM 1106*12720SWyllys.Ingersoll@Sun.COM // adjust loads according to availability, site and FIPS compatibility 1107*12720SWyllys.Ingersoll@Sun.COM for (i = 0; i < i_pProfile->m_iClusterNum; i++) 1108*12720SWyllys.Ingersoll@Sun.COM { 1109*12720SWyllys.Ingersoll@Sun.COM if ((i_pProfile->m_aCluster[i].m_iEnabled == FALSE 1110*12720SWyllys.Ingersoll@Sun.COM || i_pProfile->m_aCluster[i].m_iResponding == FALSE 1111*12720SWyllys.Ingersoll@Sun.COM || i_pProfile->m_aCluster[i].m_iKMALocked)) 1112*12720SWyllys.Ingersoll@Sun.COM { 1113*12720SWyllys.Ingersoll@Sun.COM ((unsigned char*) &(i_pProfile->m_aCluster[i].m_lLoad))[sizeof (int)+1] = 1; 1114*12720SWyllys.Ingersoll@Sun.COM } 1115*12720SWyllys.Ingersoll@Sun.COM else 1116*12720SWyllys.Ingersoll@Sun.COM { 1117*12720SWyllys.Ingersoll@Sun.COM ((unsigned char*) &(i_pProfile->m_aCluster[i].m_lLoad))[sizeof (int)+1] = 0; 1118*12720SWyllys.Ingersoll@Sun.COM } 1119*12720SWyllys.Ingersoll@Sun.COM 1120*12720SWyllys.Ingersoll@Sun.COM if (strcmp(i_pProfile->m_aCluster[i].m_wsApplianceSiteID, 1121*12720SWyllys.Ingersoll@Sun.COM i_pProfile->m_wsEntitySiteID) != 0) 1122*12720SWyllys.Ingersoll@Sun.COM { 1123*12720SWyllys.Ingersoll@Sun.COM ((unsigned char*) &(i_pProfile->m_aCluster[i].m_lLoad))[sizeof (int)] = 1; 1124*12720SWyllys.Ingersoll@Sun.COM } 1125*12720SWyllys.Ingersoll@Sun.COM else 1126*12720SWyllys.Ingersoll@Sun.COM { 1127*12720SWyllys.Ingersoll@Sun.COM ((unsigned char*) &(i_pProfile->m_aCluster[i].m_lLoad))[sizeof (int)] = 0; 1128*12720SWyllys.Ingersoll@Sun.COM } 1129*12720SWyllys.Ingersoll@Sun.COM 1130*12720SWyllys.Ingersoll@Sun.COM if ( m_bFIPS && 1131*12720SWyllys.Ingersoll@Sun.COM !FIPScompatibleKMA(i_pProfile->m_aCluster[i].m_sKMAVersion)) 1132*12720SWyllys.Ingersoll@Sun.COM { 1133*12720SWyllys.Ingersoll@Sun.COM ((unsigned char*) &(i_pProfile->m_aCluster[i].m_lLoad))[sizeof (int)+2] = 1; 1134*12720SWyllys.Ingersoll@Sun.COM } 1135*12720SWyllys.Ingersoll@Sun.COM else 1136*12720SWyllys.Ingersoll@Sun.COM { 1137*12720SWyllys.Ingersoll@Sun.COM ((unsigned char*) &(i_pProfile->m_aCluster[i].m_lLoad))[sizeof (int)+2] = 0; 1138*12720SWyllys.Ingersoll@Sun.COM } 1139*12720SWyllys.Ingersoll@Sun.COM } 1140*12720SWyllys.Ingersoll@Sun.COM 1141*12720SWyllys.Ingersoll@Sun.COM // sort ascending by load 1142*12720SWyllys.Ingersoll@Sun.COM 1143*12720SWyllys.Ingersoll@Sun.COM // gnome sort: the simplest sort algoritm 1144*12720SWyllys.Ingersoll@Sun.COM // http://www.cs.vu.nl/~dick/gnomesort.html 1145*12720SWyllys.Ingersoll@Sun.COM 1146*12720SWyllys.Ingersoll@Sun.COM //void gnomesort(int n, int ar[]) { 1147*12720SWyllys.Ingersoll@Sun.COM // int i = 0; 1148*12720SWyllys.Ingersoll@Sun.COM // 1149*12720SWyllys.Ingersoll@Sun.COM // while (i < n) { 1150*12720SWyllys.Ingersoll@Sun.COM // if (i == 0 || ar[i-1] <= ar[i]) i++; 1151*12720SWyllys.Ingersoll@Sun.COM // else {int tmp = ar[i]; ar[i] = ar[i-1]; ar[--i] = tmp;} 1152*12720SWyllys.Ingersoll@Sun.COM // } 1153*12720SWyllys.Ingersoll@Sun.COM //} 1154*12720SWyllys.Ingersoll@Sun.COM 1155*12720SWyllys.Ingersoll@Sun.COM i = 0; 1156*12720SWyllys.Ingersoll@Sun.COM while (i < i_pProfile->m_iClusterNum) 1157*12720SWyllys.Ingersoll@Sun.COM { 1158*12720SWyllys.Ingersoll@Sun.COM if (i == 0 || i_pProfile->m_aCluster[i - 1].m_lLoad <= i_pProfile->m_aCluster[i].m_lLoad) 1159*12720SWyllys.Ingersoll@Sun.COM { 1160*12720SWyllys.Ingersoll@Sun.COM i++; 1161*12720SWyllys.Ingersoll@Sun.COM } 1162*12720SWyllys.Ingersoll@Sun.COM else 1163*12720SWyllys.Ingersoll@Sun.COM { 1164*12720SWyllys.Ingersoll@Sun.COM KMSClusterEntry tmp = i_pProfile->m_aCluster[i]; 1165*12720SWyllys.Ingersoll@Sun.COM i_pProfile->m_aCluster[i] = i_pProfile->m_aCluster[i - 1]; 1166*12720SWyllys.Ingersoll@Sun.COM i_pProfile->m_aCluster[--i] = tmp; 1167*12720SWyllys.Ingersoll@Sun.COM } 1168*12720SWyllys.Ingersoll@Sun.COM } 1169*12720SWyllys.Ingersoll@Sun.COM } 1170