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