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
CAgentLoadBalancer(KMSClientProfile * const i_pProfile)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
~CAgentLoadBalancer()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
GetHTTPSURL(int i_iIndex,int i_iPort)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
GetHTTPURL(int i_iIndex,int i_iPort)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
Balance()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
BalanceByDataUnitID(const unsigned char * const i_pDataUnitID,int i_iDataUnitIDMaxLen)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
BalanceByDataUnitKeyID(const unsigned char * const i_pDataUnitKeyID,int i_iDataUnitKeyIDMaxLen)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
FindIndexByNetworkAddress(char * i_wsApplianceNetworkAddress)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
GetApplianceNetworkAddress(int i_iIndex)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
FailOverLimit(void)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
FailOver(int i_iFailedApplianceIndex,struct soap * i_pstSoap)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
UpdateResponseStatus(int i_iIndex)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
GetKMAID(int i_iIndex)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
GetKWK(Long64 i_lKMAID)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
CreateKWK(Long64 i_lKMAID,struct soap * const i_pstSoap,const char * const i_sURL,bool * const o_pbClientAESKeyWrapSetupError)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
DeleteKWKEntry(Long64 i_lKMAID)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
AESKeyWrapSupported(int i_iIndex)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
GetKWKID(int i_Index,Long64 i_lKMAID,struct soap * const i_pstSoap,UTF8_KEYID o_pKWKID,bool * const o_pbClientAESKeyWrapSetupError)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
GetKWKWrappingKey(struct soap * const i_pstSoap,const char * const i_sURL,CPublicKey * const o_opPublicKEK)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
RegisterKWK(int i_iWrappedKWKSize,const unsigned char * const i_acWrappedKWK,struct soap * const i_pstSoap,const char * const i_sURL,UTF8_KEYID o_acUTF8KeyID)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
AESKeyUnwrap(int * const io_pIndex,const WRAPPED_KEY i_pAESWrappedKey,KEY o_pPlainTextKey)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 *--------------------------------------------------------------------------*/
KMSClient_SortClusterArray(KMSClientProfile * const i_pProfile)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