xref: /onnv-gate/usr/src/lib/libkmsagent/common/KMSAgent.cpp (revision 12720:3db6e0082404)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 /**
27  * \file KMSAgent.cpp
28  */
29 
30 #ifdef WIN32
31 #define _WIN32_WINNT 0x0400
32 #include <windows.h>
33 #include <process.h>
34 #endif
35 
36 #include <stdlib.h>
37 
38 #include "KMSClientProfile.h"
39 
40 #include "KMS_AgentStub.h"
41 #include "KMS_DiscoveryStub.h"
42 
43 #include "KMSClientProfileImpl.h"
44 #include "KMSAgent.h"
45 #include "KMSAuditLogger.h"
46 #include "KMSAgentSoapUtilities.h"
47 #include "KMSAgentStringUtilities.h"
48 #include "KMSAgentPKICommon.h"
49 #include "KMSAgentLoadBalancer.h"
50 
51 #include "KMSAgentWebServiceNamespaces.h"
52 #include "k_setupssl.h"
53 
54 #include "ApplianceParameters.h"
55 
56 #include "AutoMutex.h"
57 #include "KMSAgentKeyCallout.h"
58 
59 #include "KMSAgentLoadBalancer.h"
60 #include "KMSAgentDataUnitCache.h"
61 
62 #ifdef K_SOLARIS_PLATFORM
63 #include "KMSAgentStorage.h"
64 #endif
65 
66 #include "ClientSoapFaultCodes.h"
67 
68 #ifdef METAWARE
69 #include "debug.h"
70 #include "sizet.h"
71 typedef unsigned char		uint8_t;
72 typedef unsigned short		uint16_t;
73 typedef unsigned int		uint32_t;
74 typedef unsigned long long	uint64_t;
75 #endif
76 
77 #include "KMSAgentAESKeyWrap.h"
78 #include "KMSAgentKnownAnswerTests.h"
79 
80 #if defined(METAWARE) && defined(DEBUG_RETURNS)
81 extern "C" void ecpt_trace_msg (ECPT_TRACE_ENTRY*, char*, ...);
82 
83 #define RETURN(a) { ecpt_trace_msg( trace,"(returned=%x)",(a));  return(a);  }
84 
85 #else
86 #define RETURN(a) return(a)
87 #endif
88 
89 /* KMS_AGENT_VERSION_STRING  gets passed in via compilation flags */
90 extern "C" const char KMSAgent_Version[KMS_MAX_VERSION_LENGTH + 1] = KMS_AGENT_VERSION_STRING;
91 
92 
93 /* The following enum and structs are used for QueryParameters in
94  * ListKeyGroup. Since they are only used in implementation code,
95  * so they are not in the header file in order to hide these details
96  */
97 
98 
99 /*---------------------------Start Query Parameters Declartion -------- */
100 
101 #define KMS_MAX_AGENT_FILTER_PARAMETERS     10
102 
103 enum KMSAgent_SortOrder
104 {
105     SORT_ORDER_ASCENDING = 0,
106     SORT_ORDER_DESCENDING
107 };
108 
109 enum KMSAgent_FilterOperator
110 {
111     FILTER_OPERATOR_EQUAL = 0,
112     FILTER_OPERATOR_NOT_EQUAL,
113     FILTER_OPERATOR_GREATER_THAN,
114     FILTER_OPERATOR_LESS_THAN,
115     FILTER_OPERATOR_GREATER_THAN_OR_EQUAL,
116     FILTER_OPERATOR_LESS_THAN_OR_EQUAL,
117     FILTER_OPERATOR_STARTS_WITH
118 };
119 
120 struct KMSAgent_FilterParameters
121 {
122     utf8char m_wsFieldName[KMS_MAX_FIELD_NAME + 1];
123     enum KMSAgent_FilterOperator m_eFilterOperator;
124     utf8char m_wsFieldValue[KMS_MAX_FIELD_VALUE + 1];
125 };
126 
127 struct KMSAgent_QueryParameters
128 {
129     utf8char m_wsSortFieldName[KMS_MAX_FIELD_NAME + 1];
130     enum KMSAgent_SortOrder m_eSortOrder;
131 
132     struct KMSAgent_FilterParameters m_aFilterParameters[KMS_MAX_AGENT_FILTER_PARAMETERS];
133     int m_iSizeFilterParameters;
134 
135     utf8char m_wsPreviousPageLastIDValue[KMS_MAX_ID + 1];
136     utf8char m_wsPreviousPageLastSortFieldValue[KMS_MAX_FIELD_VALUE + 1];
137 };
138 
139 /*---------------------------End Of Query Parameters Declaration -------- */
140 
141 #ifdef METAWARE
142 int CAgentLoadBalancer::FailOver (int i_iFailedApplianceIndex,
143                                   struct soap *i_pstSoap);
144 #endif
145 
KMSAgent_GetVersion()146 extern const char * KMSAgent_GetVersion ()
147 {
148     return (KMSAgent_Version);
149 }
150 
CopyQueryParametersFromRequest(struct soap * i_pstSoap,int i_iPageSize,struct KMS_Agent::KMS_Agent__QueryParameters * i_pQueryParameters,struct KMSAgent_QueryParameters * i_pSourceQueryParameters)151 static bool CopyQueryParametersFromRequest
152 (
153  struct soap *i_pstSoap,
154  int i_iPageSize,
155  struct KMS_Agent::KMS_Agent__QueryParameters *i_pQueryParameters,
156  struct KMSAgent_QueryParameters *i_pSourceQueryParameters
157  )
158 {
159 
160     // set page size
161     i_pQueryParameters->NextPageSize = i_iPageSize;
162 
163     // copy sort field name
164     i_pQueryParameters->SortFieldName = (char *)
165             soap_malloc(i_pstSoap,
166             sizeof (i_pSourceQueryParameters->m_wsSortFieldName));
167     if (i_pQueryParameters->SortFieldName == NULL)
168     {
169         return (false);
170     }
171     strncpy(i_pQueryParameters->SortFieldName,
172             i_pSourceQueryParameters->m_wsSortFieldName,
173             sizeof (i_pSourceQueryParameters->m_wsSortFieldName));
174     i_pQueryParameters->SortFieldName[sizeof (i_pSourceQueryParameters->m_wsSortFieldName)-1] = 0;
175 
176     // sort order
177     i_pQueryParameters->SortOrder =
178             (enum KMS_Agent::KMS_Agent__SortOrder)i_pSourceQueryParameters->m_eSortOrder;
179 
180     // copy filter parameters
181     i_pQueryParameters->FilterParameters.__size =
182             i_pSourceQueryParameters->m_iSizeFilterParameters;
183 
184     if (i_pQueryParameters->FilterParameters.__size > 0)
185     {
186         i_pQueryParameters->
187                 FilterParameters.__ptr =
188                 (struct KMS_Agent::KMS_Agent__FilterParameters *)soap_malloc
189                 (i_pstSoap,
190                 sizeof (KMS_Agent::KMS_Agent__FilterParameters) *
191                 i_pQueryParameters->FilterParameters.__size);
192 
193         if (i_pQueryParameters->FilterParameters.__ptr == NULL)
194         {
195             return (false);
196         }
197     }
198     else
199     {
200         i_pQueryParameters->FilterParameters.__ptr = NULL;
201     }
202 
203     for (int i = 0; i < i_pSourceQueryParameters->m_iSizeFilterParameters; i++)
204     {
205         struct KMS_Agent::KMS_Agent__FilterParameters *pParameters;
206 
207         pParameters = &(i_pQueryParameters->FilterParameters.__ptr[i]);
208 
209         // copy field name
210         pParameters->FieldName = (
211                 utf8cstr) soap_malloc(i_pstSoap,
212                 sizeof (i_pSourceQueryParameters->
213                 m_aFilterParameters[i].m_wsFieldName));
214         if (pParameters->FieldName == NULL)
215         {
216             return (false);
217         }
218 
219         strncpy(pParameters->FieldName,
220                 i_pSourceQueryParameters->m_aFilterParameters[i].m_wsFieldName,
221                 sizeof (i_pSourceQueryParameters->
222                     m_aFilterParameters[i].m_wsFieldName));
223         pParameters->FieldName[sizeof (i_pSourceQueryParameters->
224                     m_aFilterParameters[i].m_wsFieldName)-1] = '\0';
225 
226         // copy field value
227         pParameters->FieldValue =
228                 (utf8cstr) soap_malloc
229                 (i_pstSoap,
230                 sizeof (i_pSourceQueryParameters->m_aFilterParameters[i].m_wsFieldValue));
231         if (pParameters->FieldValue == NULL)
232         {
233             return (false);
234         }
235 
236         strncpy(pParameters->FieldValue,
237                 i_pSourceQueryParameters->m_aFilterParameters[i].m_wsFieldValue,
238                 sizeof (i_pSourceQueryParameters->m_aFilterParameters[i].m_wsFieldValue));
239         pParameters->FieldValue[sizeof (i_pSourceQueryParameters->m_aFilterParameters[i].m_wsFieldValue)-1] = '\0';
240 
241         // copy FilterOperator
242         pParameters->FilterOperator =
243                 (KMS_Agent::KMS_Agent__FilterOperator)
244                 i_pSourceQueryParameters->m_aFilterParameters[i].m_eFilterOperator;
245     }
246 
247     // copy PreviousPageLastIDValue
248     i_pQueryParameters->PreviousPageLastIDValue =
249             (utf8cstr) soap_malloc(i_pstSoap,
250             sizeof (i_pSourceQueryParameters->m_wsPreviousPageLastIDValue));
251     if (i_pQueryParameters->PreviousPageLastIDValue == NULL)
252     {
253         return (false);
254     }
255     strncpy(i_pQueryParameters->PreviousPageLastIDValue,
256             i_pSourceQueryParameters->m_wsPreviousPageLastIDValue,
257             sizeof (i_pSourceQueryParameters->m_wsPreviousPageLastIDValue));
258     i_pQueryParameters->PreviousPageLastIDValue[sizeof (i_pSourceQueryParameters->m_wsPreviousPageLastIDValue)-1] = '\0';
259 
260     // copy PreviousPageLastIDValue
261     i_pQueryParameters->PreviousPageLastSortFieldValue =
262             (utf8cstr) soap_malloc(i_pstSoap,
263             sizeof (i_pSourceQueryParameters->
264             m_wsPreviousPageLastSortFieldValue));
265     if (i_pQueryParameters->PreviousPageLastSortFieldValue == NULL)
266     {
267         return (false);
268     }
269     strncpy(i_pQueryParameters->PreviousPageLastSortFieldValue,
270             i_pSourceQueryParameters->m_wsPreviousPageLastSortFieldValue,
271             sizeof (i_pSourceQueryParameters->
272             m_wsPreviousPageLastSortFieldValue));
273     i_pQueryParameters->PreviousPageLastSortFieldValue[sizeof (i_pSourceQueryParameters->
274             m_wsPreviousPageLastSortFieldValue)-1] = 0;
275 
276     return (true);
277 }
278 
CopyQueryParametersFromResponse(struct KMSAgent_QueryParameters * i_pQueryParameters,struct KMS_Agent::KMS_Agent__QueryParameters * i_pSourceQueryParameters)279 static void CopyQueryParametersFromResponse (
280                                              struct KMSAgent_QueryParameters *i_pQueryParameters,
281                                              struct KMS_Agent::KMS_Agent__QueryParameters *i_pSourceQueryParameters)
282 {
283 
284     // copy sort field name
285     if (i_pSourceQueryParameters->SortFieldName)
286     {
287         strncpy(i_pQueryParameters->m_wsSortFieldName,
288                 i_pSourceQueryParameters->SortFieldName,
289                 sizeof(i_pQueryParameters->m_wsSortFieldName));
290         i_pQueryParameters->m_wsSortFieldName[sizeof(i_pQueryParameters->m_wsSortFieldName)-1] = '\0';
291     }
292 
293     // copy order
294     i_pQueryParameters->m_eSortOrder =
295             (KMSAgent_SortOrder) i_pSourceQueryParameters->SortOrder;
296 
297     // copy filter parameters
298     i_pQueryParameters->m_iSizeFilterParameters =
299             i_pSourceQueryParameters->FilterParameters.__size;
300 
301     // we only accept this amount of parameters
302     if (i_pQueryParameters->m_iSizeFilterParameters >= KMS_MAX_AGENT_FILTER_PARAMETERS)
303     {
304         // this should not happen, but just for defending the code
305         i_pQueryParameters->m_iSizeFilterParameters = KMS_MAX_AGENT_FILTER_PARAMETERS;
306     }
307 
308     for (int i = 0; i < i_pQueryParameters->m_iSizeFilterParameters; i++)
309     {
310         struct KMS_Agent::KMS_Agent__FilterParameters *pParameters;
311 
312         pParameters = i_pSourceQueryParameters->FilterParameters.__ptr + i;
313 
314         i_pQueryParameters->m_aFilterParameters[i].m_eFilterOperator
315                 = (KMSAgent_FilterOperator) pParameters->FilterOperator;
316 
317         if (pParameters->FieldName)
318         {
319             strncpy(i_pQueryParameters->m_aFilterParameters[i].m_wsFieldName,
320                     pParameters->FieldName,
321                     sizeof (i_pQueryParameters->m_aFilterParameters[i].m_wsFieldName));
322             i_pQueryParameters->
323                     m_aFilterParameters[i].m_wsFieldName[sizeof (i_pQueryParameters->m_aFilterParameters[i].m_wsFieldName) - 1] = '\0';
324         }
325 
326         if (pParameters->FieldValue)
327         {
328             strncpy(i_pQueryParameters->m_aFilterParameters[i].m_wsFieldValue,
329                     pParameters->FieldValue,
330                     sizeof(i_pQueryParameters->m_aFilterParameters[i].m_wsFieldValue));
331             i_pQueryParameters->
332                     m_aFilterParameters[i].m_wsFieldValue[sizeof(i_pQueryParameters->m_aFilterParameters[i].m_wsFieldValue)-1] = '\0';
333         }
334     }
335     // copy PreviousPageLastIDValue
336     if (i_pSourceQueryParameters->PreviousPageLastIDValue)
337     {
338         strncpy(i_pQueryParameters->m_wsPreviousPageLastIDValue,
339                 i_pSourceQueryParameters->PreviousPageLastIDValue,
340                 sizeof(i_pQueryParameters->m_wsPreviousPageLastIDValue));
341         i_pQueryParameters->m_wsPreviousPageLastIDValue[sizeof(i_pQueryParameters->m_wsPreviousPageLastIDValue)-1] = '\0';
342     }
343 
344     // copy PreviousPageLastSortFieldValue
345     if (i_pSourceQueryParameters->PreviousPageLastSortFieldValue)
346     {
347         strncpy(i_pQueryParameters->m_wsPreviousPageLastSortFieldValue,
348                 i_pSourceQueryParameters->PreviousPageLastSortFieldValue,
349                 sizeof(i_pQueryParameters->m_wsPreviousPageLastSortFieldValue));
350         i_pQueryParameters->m_wsPreviousPageLastSortFieldValue[sizeof(i_pQueryParameters->m_wsPreviousPageLastSortFieldValue)-1] = '\0';
351     }
352 
353 }
354 
355 /**
356  *  copies data unit to the soap data unit structure, placing the xsd_string types on the
357  *  gsoap heap.
358  *  @return(false if soap_malloc fails
359  */
CopyDataUnitFromRequest(struct soap * i_pstSoap,struct KMS_Agent::KMS_Agent__DataUnit * i_pDataUnit,const KMSAgent_DataUnit * const i_pSourceDataUnit)360 static bool CopyDataUnitFromRequest (struct soap *i_pstSoap,
361                                      struct KMS_Agent::KMS_Agent__DataUnit *i_pDataUnit,
362                                      const KMSAgent_DataUnit * const i_pSourceDataUnit)
363 {
364 
365     if (i_pSourceDataUnit)
366     {
367         // copy field name
368         i_pDataUnit->DataUnitID =
369                 (utf8cstr) soap_malloc(i_pstSoap,
370                 2 * sizeof (i_pSourceDataUnit->m_acDataUnitID) + 1);
371         if (i_pDataUnit->DataUnitID == NULL)
372         {
373             return (false);
374         }
375 
376         ConvertBinaryToUTF8HexString(i_pDataUnit->DataUnitID,
377                 i_pSourceDataUnit->m_acDataUnitID,
378                 KMS_DATA_UNIT_ID_SIZE);
379     }
380     else
381     {
382         strcpy(i_pDataUnit->DataUnitID, "");
383     }
384 
385     i_pDataUnit->ExternalUniqueID = (utf8cstr) soap_malloc(i_pstSoap,
386             2 * sizeof (i_pSourceDataUnit->m_acExternalUniqueID) + 1);
387     if (i_pDataUnit->ExternalUniqueID == NULL)
388     {
389         return (false);
390     }
391 
392     if (i_pSourceDataUnit->m_iExternalUniqueIDLength > 0 &&
393         i_pSourceDataUnit->m_iExternalUniqueIDLength <= KMS_MAX_EXTERNAL_UNIQUE_ID_SIZE)
394     {
395         ConvertBinaryToUTF8HexString(i_pDataUnit->ExternalUniqueID,
396                 i_pSourceDataUnit->m_acExternalUniqueID,
397                 i_pSourceDataUnit->m_iExternalUniqueIDLength);
398     }
399     else
400     {
401         strcpy(i_pDataUnit->ExternalUniqueID, "");
402     }
403 
404     i_pDataUnit->ExternalTag = (utf8cstr) soap_malloc(i_pstSoap, sizeof (i_pSourceDataUnit->m_acExternalTag));
405     if (i_pDataUnit->ExternalTag == NULL)
406     {
407         return (false);
408     }
409 
410     if (strlen(i_pSourceDataUnit->m_acExternalTag) <= sizeof (i_pSourceDataUnit->m_acExternalTag))
411     {
412         strncpy(i_pDataUnit->ExternalTag,
413                 i_pSourceDataUnit->m_acExternalTag,
414                 sizeof (i_pSourceDataUnit->m_acExternalTag));
415         i_pDataUnit->ExternalTag[sizeof (i_pSourceDataUnit->m_acExternalTag)-1] = '\0';
416     }
417     else
418     {
419         strcpy(i_pDataUnit->ExternalTag, "");
420     }
421 
422     i_pDataUnit->Description = (utf8cstr) soap_malloc(i_pstSoap, sizeof (i_pSourceDataUnit->m_acDescription));
423     if (i_pDataUnit->Description == NULL)
424     {
425         return (false);
426     }
427     if (strlen(i_pSourceDataUnit->m_acDescription) <= sizeof (i_pSourceDataUnit->m_acDescription))
428     {
429         strncpy(i_pDataUnit->Description,
430                 i_pSourceDataUnit->m_acDescription,
431                 sizeof (i_pSourceDataUnit->m_acDescription));
432         i_pDataUnit->Description[sizeof (i_pSourceDataUnit->m_acDescription)-1] = '\0';
433     }
434     else
435     {
436         strcpy(i_pDataUnit->Description, "");
437     }
438 
439     i_pDataUnit->DataUnitState = (KMS_Agent::KMS_Agent__DataUnitState) i_pSourceDataUnit->m_iDataUnitState;
440 
441     return (true);
442 }
443 
444 /**
445  *  Converts an ExternalUniqueID value to UTF8Hexstring value from gSoap managed heap storage
446  *  @param  i_pstSoap pointer to gSoap runtime
447  *  @param  i_pExternalUniqueID non-NULL pointer to an external unique id to be converted
448  *  @return(NULL if memory cannot be allocated
449  */
ConvertBinaryDataFromRequest(struct soap * i_pstSoap,const unsigned char * i_pBinaryData,int i_iBinaryDataLen)450 static char * ConvertBinaryDataFromRequest (struct soap *i_pstSoap,
451                                             const unsigned char * i_pBinaryData,
452                                             int i_iBinaryDataLen)
453 {
454     char * pBinaryData = (char *) soap_malloc(i_pstSoap, 2 * i_iBinaryDataLen + 1);
455     if (pBinaryData != NULL)
456     {
457         ConvertBinaryToUTF8HexString(pBinaryData,
458                 i_pBinaryData,
459                 i_iBinaryDataLen);
460     }
461     return (pBinaryData);
462 }
463 
464 /**
465  *  Converts a UTF8 char string value to a fixed length array from
466  *  gSoap managed heap storage
467  *  @param  pointer to gSoap runtime
468  *  @param  i_pUTF8string non-NULL pointer to a null terminated UTF8 string
469  *  @param  i_iLen size of arrray to be allocated
470  *  @return(NULL if gSoap allocated storage could not be obtained
471  */
ConvertUTF8StringFromRequest(struct soap * i_pstSoap,const char * const i_pUTF8string,size_t i_iLen)472 static char * ConvertUTF8StringFromRequest (struct soap *i_pstSoap,
473                                             const char * const i_pUTF8string,
474                                             size_t i_iLen)
475 {
476     char * pUTF8string = NULL;
477     pUTF8string = (char *) soap_malloc(i_pstSoap, i_iLen);
478     if (pUTF8string != NULL)
479     {
480         strncpy(pUTF8string, i_pUTF8string, i_iLen);
481         pUTF8string[i_iLen-1] = '\0';
482     }
483     return (pUTF8string);
484 }
485 
CopyKeyGroupsResponse(struct KMS_Agent::KMS_Agent__ArrayOfKeyGroups * i_pKeyGroupsResponse)486 static KMSAgent_ArrayOfKeyGroups * CopyKeyGroupsResponse
487 (
488  struct KMS_Agent::KMS_Agent__ArrayOfKeyGroups *i_pKeyGroupsResponse
489  )
490 {
491     // alloc memory for result
492     KMSAgent_ArrayOfKeyGroups *pResult =
493             (KMSAgent_ArrayOfKeyGroups *) calloc(1, sizeof (KMSAgent_ArrayOfKeyGroups));
494 
495     // no memory, return
496     if (pResult == NULL)
497     {
498         return (NULL);
499     }
500 
501     // copy size
502     pResult->m_iSize = i_pKeyGroupsResponse->__size;
503 
504     // if the size is 0, return(an empty result
505     if (pResult->m_iSize == 0)
506     {
507         return (pResult);
508     }
509 
510     // alloc memory for all key groups
511     pResult->m_pKeyGroups = (KMSAgent_KeyGroup*)
512             calloc(1, sizeof (KMSAgent_KeyGroup) * pResult->m_iSize);
513 
514     if (pResult->m_pKeyGroups == NULL)
515     {
516         free(pResult);
517         return (NULL);
518     }
519 
520     for (int i = 0; i < pResult->m_iSize; i++)
521     {
522         KMSAgent_KeyGroup *pKeyGroup;
523 
524         pKeyGroup = &(pResult->m_pKeyGroups[i]);
525 
526         strncpy(pKeyGroup->m_acKeyGroupID,
527                 i_pKeyGroupsResponse->__ptr[i].KeyGroupID,
528                 sizeof(pKeyGroup->m_acKeyGroupID));
529         pKeyGroup->m_acKeyGroupID[sizeof(pKeyGroup->m_acKeyGroupID)-1] = '\0';
530 
531         strncpy(pKeyGroup->m_acDescription,
532                 i_pKeyGroupsResponse->__ptr[i].Description,
533                 sizeof(pKeyGroup->m_acDescription));
534         pKeyGroup->m_acDescription[sizeof(pKeyGroup->m_acDescription)-1] = '\0';
535     }
536 
537     return (pResult);
538 }
539 /**
540  *  allocate storage for the KMSAgent_ArrayOfKeys struct and the array of keys returned in the
541  *  soap response.
542  *  @param  i_pProfile pointer to profile
543  *  @param  io_pClusterIndex pointer to the cluster index value which is used
544  *      by AES Key Unwrap to access the KWK for the KMA corresponding to the
545  *      cluster index.
546  *  @param  i_pKeysResponse pointer to the soap response' array of keys struct
547  *  @return(pointer to allocated KMSAgent_ArrayOfKeys and the corresponding keys, returns NULL
548  *  on any error and frees any allocated storage before returning.  For response data validation errors a
549  *  message will be logged.
550  */
CopyDataUnitKeysResponse(KMSClientProfile * i_pProfile,int * const io_pClusterIndex,struct KMS_Agent::KMS_Agent__ArrayOfKeys * i_pKeysResponse)551 static KMSAgent_ArrayOfKeys * CopyDataUnitKeysResponse (
552                     KMSClientProfile *i_pProfile,
553                     int * const io_pClusterIndex,
554                     struct KMS_Agent::KMS_Agent__ArrayOfKeys *i_pKeysResponse)
555 {
556     KMSAgent_ArrayOfKeys * pResult =
557             (KMSAgent_ArrayOfKeys *) calloc(1, sizeof (KMSAgent_ArrayOfKeys));
558 
559     if (pResult == NULL)
560     {
561         return (NULL);
562     }
563 
564     // if the size is 0, return(an empty result
565     if (i_pKeysResponse->__size == 0)
566     {
567         return (pResult);
568     }
569 
570     if (i_pKeysResponse->__size > KMS_MAX_PAGE_SIZE)
571     {
572         free(pResult);
573         LogError(i_pProfile,
574                 AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_KEY_ARRAY_SIZE_RESPONSE,
575                 NULL,
576                 NULL,
577                 NULL);
578         return (NULL);
579     }
580 
581     pResult->m_iSize = i_pKeysResponse->__size;
582 
583     // alloc memory for all keys returned
584     pResult->m_pKeys = (KMSAgent_Key*)
585             calloc(1, sizeof (KMSAgent_Key) * i_pKeysResponse->__size);
586 
587     if (pResult->m_pKeys == NULL)
588     {
589         free(pResult);
590         return (NULL);
591         // no memory, don't log
592     }
593 
594     // copy keys from response
595     for (int i = 0; i < i_pKeysResponse->__size; i++)
596     {
597         if (KMS_KEY_ID_SIZE != ConvertUTF8HexStringToBinary(
598             i_pKeysResponse->__ptr[i].KeyID, NULL))
599         {
600             free(pResult->m_pKeys);
601             free(pResult);
602 
603             LogError(i_pProfile,
604                     AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_KEY_RESPONSE,
605                     NULL,
606                     NULL,
607                     NULL);
608             return (NULL);
609         }
610 
611         ConvertUTF8HexStringToBinary(
612                 i_pKeysResponse->__ptr[i].KeyID, pResult->m_pKeys[i].m_acKeyID);
613 
614         if ((KMS_AGENT_KEY_STATE) i_pKeysResponse->__ptr[i].KeyState < KMS_KEY_STATE_ACTIVE_PROTECT_AND_PROCESS ||
615             (KMS_AGENT_KEY_STATE) i_pKeysResponse->__ptr[i].KeyState > KMS_KEY_STATE_COMPROMISED)
616         {
617             free(pResult->m_pKeys);
618             free(pResult);
619             LogError(i_pProfile,
620                     AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_KEY_STATE_RESPONSE,
621                     NULL,
622                     NULL,
623                     NULL);
624             return (NULL);
625         }
626         pResult->m_pKeys[i].m_iKeyState = (KMS_AGENT_KEY_STATE) i_pKeysResponse->__ptr[i].KeyState;
627 
628         if ((KMS_KEY_TYPE) i_pKeysResponse->__ptr[i].KeyType != (KMS_KEY_TYPE)KMS_KEY_TYPE_AES_256)
629         {
630             free(pResult->m_pKeys);
631             free(pResult);
632             LogError(i_pProfile,
633                     AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_KEY_TYPE_RESPONSE,
634                     NULL,
635                     NULL,
636                     NULL);
637             return (NULL);
638         }
639         pResult->m_pKeys[i].m_iKeyType = (KMS_KEY_TYPE) i_pKeysResponse->__ptr[i].KeyType;
640 
641         strncpy(pResult->m_pKeys[i].m_acKeyGroupID,
642                 i_pKeysResponse->__ptr[i].KeyGroupID,
643                 sizeof(pResult->m_pKeys[i].m_acKeyGroupID));
644         pResult->m_pKeys[i].m_acKeyGroupID[sizeof(pResult->m_pKeys[i].m_acKeyGroupID)-1] = '\0';
645 
646         CAgentLoadBalancer *pAgentLoadBalancer = reinterpret_cast
647                 <CAgentLoadBalancer *> (i_pProfile->m_pAgentLoadBalancer);
648 
649         if (pAgentLoadBalancer->AESKeyWrapSupported(*io_pClusterIndex))
650         {
651             if (i_pKeysResponse->__ptr[i].Key.__size != KMS_MAX_WRAPPED_KEY_SIZE)
652             {
653                 free(pResult->m_pKeys);
654                 free(pResult);
655                 LogError(i_pProfile,
656                         AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_WRAPPED_KEY_LENGTH_RESPONSE,
657                         NULL,
658                         NULL,
659                         NULL);
660                 return (NULL);
661             }
662             else
663             {
664                 if (pAgentLoadBalancer->AESKeyUnwrap(io_pClusterIndex,
665                     i_pKeysResponse->__ptr[i].Key.__ptr,
666                     pResult->m_pKeys[i].m_acKey) == false)
667                 {
668                     free(pResult->m_pKeys);
669                     free(pResult);
670                     LogError(i_pProfile,
671                             AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_AESKEYUNWRAP_ERROR,
672                             NULL,
673                             NULL,
674                             NULL);
675 
676                     return (NULL);
677                 }
678             }
679         }
680         else  // non-AES Key Wrap
681         {
682             if (i_pKeysResponse->__ptr[i].Key.__size != KMS_MAX_KEY_SIZE)
683             {
684                 free(pResult->m_pKeys);
685                 free(pResult);
686                 LogError(i_pProfile,
687                         AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_KEY_LENGTH_RESPONSE,
688                         NULL,
689                         NULL,
690                         NULL);
691                 return (NULL);
692             }
693 
694             memcpy(pResult->m_pKeys[i].m_acKey,
695                     i_pKeysResponse->__ptr[i].Key.__ptr,
696                     KMS_MAX_KEY_SIZE);
697         }
698 
699         pResult->m_pKeys[i].m_iKeyLength = KMS_MAX_KEY_SIZE;
700 
701         if (KMSAgentKeyCallout(pResult->m_pKeys[i].m_acKey) != 0)
702         {
703             free(pResult->m_pKeys);
704             free(pResult);
705             LogError(i_pProfile,
706                     AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_KEY_CALLOUT_ERROR,
707                     NULL,
708                     NULL,
709                     NULL);
710             return (NULL);
711         }
712     }
713 
714     return (pResult);
715 }
716 
717 /**
718  *  This function returns the API status code based upon the error string in the profile and
719  *  availability of KMAs. KMA availability determination is based upon the i_iKMAFailoverReturnCode
720  *  parameter and the size of the cluster.  A cluster size of 0 is an indicator that there are
721  *  no KMAs available, unless cluster discovery is disabled by the profile's cluster discovery
722  *  frequency.
723  *
724  *  @param i_pProfile  pointer to the profile
725  *  @param i_iKMAFailoverReturnCode the return(code from CAgentLoadBalancer::Failover() or 0
726  *  if it was not called.  This is used to for determining if KMS_AGENT_STATUS_KMS_UNAVAILABLE
727  *  needs to be returned.
728  *  @returns KMS_AGENT_STATUS_GENERIC_ERROR
729  *  unless the profile's last error message field contains a message substring matching one of the
730  *  KMSAgent service soap fault strings.
731  *
732  */
KMSAgent_GetLastStatusCode(KMSClientProfile * i_pProfile,int i_iKMAFailoverReturnCode)733 static KMS_AGENT_STATUS KMSAgent_GetLastStatusCode (KMSClientProfile *i_pProfile,
734                                                     int i_iKMAFailoverReturnCode)
735 {
736     bool bServerError = false;
737 
738     FATAL_ASSERT(i_pProfile);
739 
740     // see KMSAgentLoadBalancer.h for return codes from Failover
741 
742     if (i_iKMAFailoverReturnCode == CAgentLoadBalancer::NO_FIPS_KMA_AVAILABLE)
743     {
744         return (KMS_AGENT_STATUS_NO_FIPS_KMAS_AVAILABLE);
745     }
746 
747     // parse for server errors -
748     // when KMAs have no ready keys we want to inform the client, vs reporting that the KMS is unavailable
749     bServerError = ServerError(i_pProfile->m_wsErrorString, 0);
750 
751     // parse for Soap errors
752     const char* sFaultstringStart = strstr(i_pProfile->m_wsErrorString, "SoapFaultString=");
753 
754     int iErrorCode = INVALID_CLIENT_ERROR; // initially
755 
756 
757     // if there is a Soap error
758     if (sFaultstringStart)
759     {
760         if (SSL_InvalidCertificate(sFaultstringStart))
761         {
762             // this can be caused by the KMS invalidating the agent's cert
763             return (KMS_AGENT_STATUS_ACCESS_DENIED);
764         }
765         iErrorCode = GET_FAULT_CODE(sFaultstringStart + strlen("SoapFaultString="));
766     }
767 
768 
769 #ifdef METAWARE
770     // log the failure code/cause to the event log
771     LogToFile(i_iKMAFailoverReturnCode, i_pProfile->m_wsErrorString);
772     LogToFile(iErrorCode, "error code");
773 #endif
774 
775 
776     // parse return code passed in from last call to FailOver, Balance or BalanceByDataUnitKeyID
777     // if failover reported no kma and there is a valid server error and client couldn't get keys
778     if (i_iKMAFailoverReturnCode == CAgentLoadBalancer::NO_KMA_AVAILABLE &&
779         bServerError &&
780         iErrorCode == CLIENT_ERROR_AGENT_NO_READY_KEYS)
781     {
782         return (KMS_AGENT_STATUS_KMS_UNAVAILABLE);
783     }
784 
785     // if there is a server error and we are doing discovery
786     if (bServerError &&
787         ((i_pProfile->m_iClusterDiscoveryFrequency > 0 &&
788         i_pProfile->m_iClusterNum == 0)
789         || iErrorCode == CLIENT_ERROR_AGENT_APPLIANCE_LOCKED))
790     {
791         return (KMS_AGENT_STATUS_KMS_UNAVAILABLE);
792     }
793 
794     if (bServerError && i_iKMAFailoverReturnCode == CAgentLoadBalancer::NO_KMA_AVAILABLE)
795     {
796         return (KMS_AGENT_STATUS_KMS_UNAVAILABLE);
797     }
798 
799     if ( i_iKMAFailoverReturnCode == CAgentLoadBalancer::AES_KEY_UNWRAP_ERROR )
800         return (KMS_AGENT_AES_KEY_UNWRAP_ERROR);
801     if ( i_iKMAFailoverReturnCode == CAgentLoadBalancer::AES_KEY_WRAP_SETUP_ERROR )
802         return (KMS_AGENT_AES_KEY_WRAP_SETUP_ERROR);
803 
804     if (iErrorCode == CLIENT_ERROR_ACCESS_DENIED)
805         return (KMS_AGENT_STATUS_ACCESS_DENIED);
806     if (iErrorCode == CLIENT_ERROR_SERVER_BUSY)
807         return (KMS_AGENT_STATUS_SERVER_BUSY);
808     if (iErrorCode == CLIENT_ERROR_AGENT_INVALID_PARAMETERS)
809         return (KMS_AGENT_STATUS_INVALID_PARAMETER);
810     if (iErrorCode == CLIENT_ERROR_AGENT_KEY_DOES_NOT_EXIST)
811         return (KMS_AGENT_STATUS_KEY_DOES_NOT_EXIST);
812     if (iErrorCode == CLIENT_ERROR_AGENT_KEY_DESTROYED)
813         return (KMS_AGENT_STATUS_KEY_DESTROYED);
814     if (iErrorCode == CLIENT_ERROR_AGENT_DATA_UNIT_ID_NOT_FOUND_EXTERNAL_ID_EXISTS)
815         return (KMS_AGENT_STATUS_DATA_UNIT_ID_NOT_FOUND_EXTERNAL_ID_EXISTS);
816     if (iErrorCode == CLIENT_ERROR_AGENT_DUPLICATE_EXTERNAL_ID)
817         return (KMS_AGENT_STATUS_EXTERNAL_UNIQUE_ID_EXISTS);
818     if (iErrorCode == CLIENT_ERROR_AGENT_NO_READY_KEYS)
819         return (KMS_AGENT_STATUS_KMS_NO_READY_KEYS);
820 
821     // this check is made last to allow other specific errors that may have occurred to take precedence,
822     // e.g. return access denied before reporting No FIPS KMAs
823     if (i_pProfile->m_eKMSmode == FIPS_MODE &&
824         KMSClient_NoFIPSCompatibleKMAs(i_pProfile))
825     {
826         return (KMS_AGENT_STATUS_NO_FIPS_KMAS_AVAILABLE);
827     }
828 
829     return (KMS_AGENT_STATUS_GENERIC_ERROR);
830 }
831 
832 /*---------------------------------------------------------------------------
833  * Function: KMSAgent_InitializeLibrary
834  *--------------------------------------------------------------------------*/
835 #include "KMSAuditLogger.h"
836 
837 extern "C"
KMSAgent_InitializeLibrary(utf8cstr const i_pWorkingDirectory,int i_bUseFileLog)838 KMS_AGENT_STATUS KMSAgent_InitializeLibrary (utf8cstr const i_pWorkingDirectory,
839                                              int i_bUseFileLog)
840 
841 {
842     bool bSuccess;
843 
844 #if defined(METAWARE)
845 #warn "debug timing is on"
846     ECPT_TRACE_ENTRY *trace = NULL;
847     ECPT_TRACE(trace, KMSAgent_InitializeLibrary);
848 #endif
849 
850 #if defined(DEBUG) && defined(METAWARE)
851     log_printf("KMSAgent_InitializeLibrary : Entered");
852 #endif
853 
854     bSuccess = KMSClient_InitializeLibrary(
855             i_pWorkingDirectory,
856             i_bUseFileLog);
857 
858     if (bSuccess)
859     {
860         RETURN(KMS_AGENT_STATUS_OK);
861     }
862 
863     RETURN(KMS_AGENT_STATUS_GENERIC_ERROR);
864 }
865 
866 /*---------------------------------------------------------------------------
867  * Function: KMSAgent_KnownAnswerTests
868  *
869  *--------------------------------------------------------------------------*/
KMSAgent_KnownAnswerTests()870 KMS_AGENT_STATUS KMSAgent_KnownAnswerTests()
871 {
872 #if defined(METAWARE)
873     ECPT_TRACE_ENTRY *trace = NULL;
874     ECPT_TRACE(trace, KMSAgent_KnownAnswerTests);
875 #endif
876 
877    // Known Answer Test on AES Key Wrap code
878    if ( KnownAnswerTestAESKeyWrap() != 0 )
879    {
880        RETURN(KMS_AGENT_STATUS_FIPS_KAT_AES_KEYWRAP_ERROR);
881    }
882 
883    if ( KnownAnswerTestAESECB() != 0 )
884    {
885        RETURN(KMS_AGENT_STATUS_FIPS_KAT_AES_ECB_ERROR);
886    }
887 
888    if ( KnownAnswerTestHMACSHA1() != 0 )
889    {
890        RETURN(KMS_AGENT_STATUS_FIPS_KAT_HMAC_SHA1_ERROR);
891    }
892 
893    RETURN(KMS_AGENT_STATUS_OK);
894 
895 }
896 
897 /*---------------------------------------------------------------------------
898  * Function: KMSAgent_FinalizeLibrary
899  *
900  *--------------------------------------------------------------------------*/
901 
902 extern "C"
KMSAgent_FinalizeLibrary()903 KMS_AGENT_STATUS KMSAgent_FinalizeLibrary ()
904 {
905     bool bSuccess;
906 
907 #if defined(METAWARE)
908     ECPT_TRACE_ENTRY *trace = NULL;
909     ECPT_TRACE(trace, KMSAgent_FinalizeLibrary);
910 #endif
911 
912     bSuccess = KMSClient_FinalizeLibrary();
913 
914     if (bSuccess)
915     {
916         RETURN(KMS_AGENT_STATUS_OK);
917     }
918 
919     RETURN(KMS_AGENT_STATUS_GENERIC_ERROR);
920 }
921 
922 /*---------------------------------------------------------------------------
923  * Function: KMSAgent_GetLastErrorMessage
924  *
925  *--------------------------------------------------------------------------*/
926 
927 extern "C"
KMSAgent_GetLastErrorMessage(KMSClientProfile * i_pProfile)928 utf8cstr KMSAgent_GetLastErrorMessage (KMSClientProfile* i_pProfile)
929 {
930 #if defined(METAWARE)
931     ECPT_TRACE_ENTRY *trace = NULL;
932     ECPT_TRACE(trace, KMSAgent_GetLastErrorMessage);
933 #endif
934 
935     if (i_pProfile == NULL)
936     {
937         RETURN(NULL);
938     }
939 
940     RETURN(KMSClient_GetLastErrorMessage(i_pProfile));
941 }
942 
943 /*---------------------------------------------------------------------------
944  * Function: KMSAgent_GetClusterInformation
945  *
946  *--------------------------------------------------------------------------*/
947 extern "C"
KMSAgent_GetClusterInformation(KMSClientProfile * const i_pProfile,int i_iEntitySiteIDSize,int i_iClusterEntryArraySize,utf8cstr const o_pEntitySiteID,int * const o_pApplianceNum,KMSClusterEntry * const o_pClusterEntryArray)948 KMS_AGENT_STATUS KMSAgent_GetClusterInformation (
949                                                  KMSClientProfile * const i_pProfile,
950                                                  int i_iEntitySiteIDSize,
951                                                  int i_iClusterEntryArraySize,
952                                                  utf8cstr const o_pEntitySiteID,
953                                                  int * const o_pApplianceNum,
954                                                  KMSClusterEntry * const o_pClusterEntryArray)
955 {
956     bool bSuccess;
957 #if defined(METAWARE)
958     ECPT_TRACE_ENTRY *trace = NULL;
959     ECPT_TRACE(trace, KMSAgent_GetClusterInformation);
960 #endif
961 
962     if (!i_pProfile)
963     {
964         Log(AUDIT_CLIENT_AGENT_GET_CLUSTER_INFORMATION_INVALID_PARAMETERS,
965                 NULL,
966                 NULL,
967                 "Profile arg");
968         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
969     }
970 
971     if (!o_pEntitySiteID || (i_iEntitySiteIDSize <= (KMS_MAX_ENTITY_SITE_ID)))
972     {
973         Log(AUDIT_CLIENT_AGENT_GET_CLUSTER_INFORMATION_INVALID_PARAMETERS,
974                 NULL,
975                 NULL,
976                 "EntitySiteIDSize arg");
977         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
978     }
979 
980     if (i_iClusterEntryArraySize > KMS_MAX_CLUSTER_NUM)
981     {
982         Log(AUDIT_CLIENT_AGENT_GET_CLUSTER_INFORMATION_INVALID_PARAMETERS,
983                 NULL,
984                 NULL,
985                 "i_iClusterEntryArraySize exceeds KMS_MAX_CLUSTER_NUM");
986         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
987     }
988 
989     if (!o_pApplianceNum)
990     {
991         Log(AUDIT_CLIENT_AGENT_GET_CLUSTER_INFORMATION_INVALID_PARAMETERS,
992                 NULL,
993                 NULL,
994                 "ApplianceNum arg");
995         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
996     }
997 
998     if (!o_pClusterEntryArray ||
999         (i_iClusterEntryArraySize <= 0))
1000     {
1001         Log(AUDIT_CLIENT_AGENT_GET_CLUSTER_INFORMATION_INVALID_PARAMETERS,
1002                 NULL,
1003                 NULL,
1004                 "ClusterEntry or Size arg");
1005         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
1006     }
1007 
1008     if (!KMSClient_ProfileLoaded(i_pProfile))
1009     {
1010         RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
1011     }
1012 
1013     CAutoMutex oAutoMutex((K_MUTEX_HANDLE) i_pProfile->m_pLock);
1014 
1015     bSuccess = KMSClient_GetClusterInformation(
1016             i_pProfile,
1017             o_pEntitySiteID,
1018             i_iEntitySiteIDSize,
1019             o_pApplianceNum,
1020             o_pClusterEntryArray,
1021             i_iClusterEntryArraySize);
1022 
1023     // KMSClient_GetClusterInformation logs if there was an error
1024 
1025     if (bSuccess)
1026     {
1027         RETURN(KMS_AGENT_STATUS_OK);
1028     }
1029 
1030     RETURN(KMSAgent_GetLastStatusCode(i_pProfile, 0));
1031 }
1032 
1033 extern "C"
KMSAgent_SelectAppliance(KMSClientProfile * const i_pProfile,utf8cstr const i_pApplianceAddress)1034 KMS_AGENT_STATUS KMSAgent_SelectAppliance (
1035                                            KMSClientProfile * const i_pProfile,
1036                                            utf8cstr const i_pApplianceAddress)
1037 {
1038     bool bSuccess;
1039 #if defined(METAWARE)
1040     ECPT_TRACE_ENTRY *trace = NULL;
1041     ECPT_TRACE(trace, KMSAgent_SelectAppliance);
1042 #endif
1043 
1044     if (!i_pProfile)
1045     {
1046         Log(AUDIT_CLIENT_AGENT_SELECT_APPLIANCE_INVALID_PARAMETERS,
1047                 NULL,
1048                 NULL,
1049                 "Profile arg");
1050         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
1051     }
1052     if (!i_pApplianceAddress)
1053     {
1054         Log(AUDIT_CLIENT_AGENT_GET_CLUSTER_INFORMATION_INVALID_PARAMETERS,
1055                 NULL,
1056                 NULL,
1057                 "ApplianceAddress arg");
1058         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
1059     }
1060 
1061     if (!KMSClient_ProfileLoaded(i_pProfile))
1062     {
1063         RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
1064     }
1065 
1066     // All modes are supported by this function.
1067 
1068     bSuccess = KMSClient_SelectAppliance(i_pProfile, i_pApplianceAddress);
1069 
1070     if (bSuccess)
1071     {
1072         RETURN(KMS_AGENT_STATUS_OK);
1073     }
1074 
1075     RETURN(KMSAgent_GetLastStatusCode(i_pProfile, 0));
1076 }
1077 
1078 /*---------------------------------------------------------------------------
1079  * Function: KMSAgent_LoadProfile
1080  *
1081  *--------------------------------------------------------------------------*/
1082 extern "C"
KMSAgent_LoadProfile(KMSClientProfile * const io_pProfile,utf8cstr const i_pProfileName,utf8cstr const i_pAgentID,utf8cstr const i_pPassphrase,utf8cstr const i_pInitialApplianceAddress,int i_iTransactionTimeout,int i_iFailOverLimit,int i_iClusterDiscoveryFrequency,int i_eKMSmode)1083 KMS_AGENT_STATUS KMSAgent_LoadProfile (
1084                                        KMSClientProfile * const io_pProfile,
1085                                        utf8cstr const i_pProfileName,
1086                                        utf8cstr const i_pAgentID,
1087                                        utf8cstr const i_pPassphrase,
1088                                        utf8cstr const i_pInitialApplianceAddress,
1089                                        int i_iTransactionTimeout,
1090                                        int i_iFailOverLimit,
1091                                        int i_iClusterDiscoveryFrequency,
1092                                        int i_eKMSmode)
1093 {
1094     bool bSuccess;
1095 #if defined(METAWARE)
1096     ECPT_TRACE_ENTRY *trace = NULL;
1097     ECPT_TRACE(trace, KMSAgent_LoadProfile);
1098 #endif
1099 
1100 #if defined(DEBUG) && defined(METAWARE)
1101     log_printf("KMSAgent_LoadProfile : Entered");
1102 #endif
1103     if (!io_pProfile ||
1104         !i_pProfileName || (strlen(i_pProfileName) <= 0))
1105     {
1106         Log(AUDIT_CLIENT_AGENT_LOAD_PROFILE_INVALID_PARAMETERS,
1107                 NULL,
1108                 NULL,
1109                 "Profile or Name arg");
1110         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
1111     }
1112     if (!i_pInitialApplianceAddress || (strlen(i_pInitialApplianceAddress) <= 0))
1113     {
1114         Log(AUDIT_CLIENT_AGENT_LOAD_PROFILE_INVALID_PARAMETERS,
1115                 NULL,
1116                 NULL,
1117                 "InitialApplianceAddress arg");
1118         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
1119     }
1120 
1121     if (i_iTransactionTimeout <= 0)
1122     {
1123         Log(AUDIT_CLIENT_AGENT_LOAD_PROFILE_INVALID_PARAMETERS,
1124                 NULL,
1125                 NULL,
1126                 "TransactionTimeout arg");
1127         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
1128     }
1129     if (i_iClusterDiscoveryFrequency < 0)
1130     {
1131         Log(AUDIT_CLIENT_AGENT_LOAD_PROFILE_INVALID_PARAMETERS,
1132                 NULL,
1133                 NULL,
1134                 "ClusterDiscoveryFrequency arg");
1135         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
1136     }
1137 
1138     // for enrollment both arguments are required
1139     if ((i_pAgentID && !i_pPassphrase) || (i_pPassphrase && !i_pAgentID))
1140     {
1141         Log(AUDIT_CLIENT_AGENT_LOAD_PROFILE_INVALID_PARAMETERS,
1142                 NULL,
1143                 NULL,
1144                 "Enrollment requires AgentID & Passphrase");
1145         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
1146     }
1147 
1148     if (i_pAgentID && (strlen(i_pAgentID) <= 0))
1149     {
1150         Log(AUDIT_CLIENT_AGENT_LOAD_PROFILE_INVALID_PARAMETERS,
1151                 NULL,
1152                 NULL,
1153                 "AgentID arg");
1154         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
1155     }
1156 
1157     if (i_pPassphrase && (strlen(i_pPassphrase) <= 0))
1158     {
1159         Log(AUDIT_CLIENT_AGENT_LOAD_PROFILE_INVALID_PARAMETERS,
1160                 NULL,
1161                 NULL,
1162                 "Passphrase arg");
1163         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
1164     }
1165 
1166     if ( i_eKMSmode != DEFAULT_MODE && i_eKMSmode != FIPS_MODE )
1167     {
1168         Log(AUDIT_CLIENT_AGENT_LOAD_PROFILE_INVALID_PARAMETERS,
1169                 NULL,
1170                 NULL,
1171                 "KMS security mode arg");
1172         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
1173     }
1174 
1175     if (KMSClient_ProfileLoaded(io_pProfile))
1176     {
1177         Log(AUDIT_CLIENT_AGENT_LOAD_PROFILE_PROFILE_ALREADY_LOADED,
1178                 NULL,
1179                 NULL,
1180                 "profile is already loaded and should be unloaded first");
1181         RETURN(KMS_AGENT_STATUS_PROFILE_ALREADY_LOADED);
1182     }
1183 
1184     memset(io_pProfile, 0, sizeof (KMSClientProfile));
1185     char sInitialApplianceAddress[KMS_MAX_NETWORK_ADDRESS+1];
1186     strncpy(sInitialApplianceAddress, i_pInitialApplianceAddress, sizeof(sInitialApplianceAddress));
1187     sInitialApplianceAddress[sizeof(sInitialApplianceAddress)-1] = '\0';
1188 
1189     // Convert to lower case
1190 
1191     for ( size_t i = 0; i < strlen( sInitialApplianceAddress ); i++ )
1192     {
1193         if ( isupper( sInitialApplianceAddress[i] ) )
1194         {
1195             sInitialApplianceAddress[i] = tolower( sInitialApplianceAddress[i] );
1196         }
1197     }
1198 
1199     bSuccess = KMSClient_LoadProfile(
1200                             io_pProfile,
1201                             i_pProfileName,
1202                             i_pAgentID,
1203                             i_pPassphrase,
1204                             sInitialApplianceAddress,
1205                             i_iTransactionTimeout,
1206                             i_iFailOverLimit,
1207                             i_iClusterDiscoveryFrequency,
1208                             i_eKMSmode);
1209 
1210     if (bSuccess)
1211     {
1212 #if defined(DEBUG) && defined(METAWARE)
1213         log_printf("KMSAgent_LoadProfile : Returned ok");
1214 #endif
1215         RETURN(KMS_AGENT_STATUS_OK);
1216     }
1217 
1218     // when not enrolling & cluster discovery is disabled there are no
1219     // soap transactions so failover would not have occurred
1220     bool bEnrolling = i_pAgentID && i_pPassphrase;
1221 
1222     if (!bEnrolling &&
1223         i_iClusterDiscoveryFrequency == 0)
1224     {
1225         RETURN(KMSAgent_GetLastStatusCode(io_pProfile, 0));
1226     }
1227     else
1228     {
1229 //        if (i_eKMSmode == FIPS_MODE &&
1230 //            KMSClient_NoFIPSCompatibleKMAs(io_pProfile))
1231 //        {
1232 //            RETURN(KMSAgent_GetLastStatusCode(io_pProfile,
1233 //                CAgentLoadBalancer::NO_FIPS_KMA_AVAILABLE));
1234 //        }
1235 
1236         RETURN(KMSAgent_GetLastStatusCode(io_pProfile,
1237             CAgentLoadBalancer::NO_KMA_AVAILABLE));
1238     }
1239 }
1240 
1241 /*---------------------------------------------------------------------------
1242  * Function: KMSAgent_UnloadProfile
1243  *
1244  *--------------------------------------------------------------------------*/
1245 extern "C"
KMSAgent_UnloadProfile(KMSClientProfile * const i_pProfile)1246 KMS_AGENT_STATUS KMSAgent_UnloadProfile (KMSClientProfile * const i_pProfile)
1247 {
1248     bool bSuccess;
1249 #if defined(METAWARE)
1250     ECPT_TRACE_ENTRY *trace = NULL;
1251     ECPT_TRACE(trace, KMSAgent_UnloadProfile);
1252 #endif
1253 
1254     if (!i_pProfile)
1255     {
1256         Log(AUDIT_CLIENT_AGENT_UNLOAD_PROFILE_INVALID_PARAMETERS,
1257                 NULL,
1258                 NULL,
1259                 "Profile arg");
1260         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
1261     }
1262 
1263     if (!KMSClient_ProfileLoaded(i_pProfile))
1264     {
1265         RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
1266     }
1267 
1268     bSuccess = KMSClient_UnloadProfile(i_pProfile);
1269 
1270     if (bSuccess)
1271     {
1272         RETURN(KMS_AGENT_STATUS_OK);
1273     }
1274 
1275     RETURN(KMSAgent_GetLastStatusCode(i_pProfile, 0));
1276 }
1277 
1278 /*---------------------------------------------------------------------------
1279  * Function: KMSAgent_DeleteProfile
1280  *
1281  *--------------------------------------------------------------------------*/
1282 extern "C"
KMSAgent_DeleteProfile(utf8cstr i_pProfileName)1283 KMS_AGENT_STATUS KMSAgent_DeleteProfile (utf8cstr i_pProfileName)
1284 {
1285     bool bSuccess;
1286 #if defined(METAWARE)
1287     ECPT_TRACE_ENTRY *trace = NULL;
1288     ECPT_TRACE(trace, KMSAgent_DeleteProfile);
1289 #endif
1290 
1291     if (!i_pProfileName || (strlen(i_pProfileName) <= 0))
1292     {
1293         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
1294     }
1295 
1296     bSuccess = KMSClient_DeleteProfile(i_pProfileName);
1297 
1298     if (bSuccess)
1299     {
1300         RETURN(KMS_AGENT_STATUS_OK);
1301     }
1302 
1303     RETURN(KMS_AGENT_STATUS_GENERIC_ERROR);
1304 }
1305 
1306 /*---------------------------------------------------------------------------
1307  * Function: KMSAgent_ListKeyGroups
1308  *
1309  *--------------------------------------------------------------------------*/
1310 
1311 extern "C"
KMSAgent_ListKeyGroups(KMSClientProfile * const i_pProfile,KMSAgent_ArrayOfKeyGroups ** const o_ppKeyGroups)1312 KMS_AGENT_STATUS KMSAgent_ListKeyGroups (
1313                                          KMSClientProfile * const i_pProfile,
1314                                          KMSAgent_ArrayOfKeyGroups* * const o_ppKeyGroups)
1315 {
1316     bool bSuccess;
1317 #if defined(METAWARE)
1318     ECPT_TRACE_ENTRY *trace = NULL;
1319     ECPT_TRACE(trace, KMSAgent_ListKeyGroups);
1320 #endif
1321 
1322     int bIsLastPage;
1323     struct KMSAgent_QueryParameters stQueryParameters;
1324 
1325     if (!i_pProfile)
1326     {
1327         Log(AUDIT_CLIENT_AGENT_LIST_KEY_GROUPS_INVALID_PARAMETERS,
1328                 NULL,
1329                 NULL,
1330                 "Profile arg");
1331         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
1332     }
1333     if (!o_ppKeyGroups)
1334     {
1335         Log(AUDIT_CLIENT_AGENT_LIST_KEY_GROUPS_INVALID_PARAMETERS,
1336                 NULL,
1337                 NULL,
1338                 "KeyGroups arg");
1339         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
1340     }
1341 
1342     if (!KMSClient_ProfileLoaded(i_pProfile))
1343     {
1344         RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
1345     }
1346 
1347     CAutoMutex oAutoMutex((K_MUTEX_HANDLE) i_pProfile->m_pLock);
1348 
1349     struct soap *pstSoap = (struct soap *) i_pProfile->m_pvSoap;
1350 
1351     // Get Key Groups
1352     memset(&stQueryParameters, 0, sizeof (stQueryParameters));
1353 
1354     struct KMS_Agent::KMS_Agent__QueryParameters oQueryParameters;
1355     struct KMS_Agent::KMS_Agent__ListKeyGroupsResponse oResponse;
1356 
1357     memset(&oQueryParameters, 0, sizeof (oQueryParameters));
1358 
1359     bSuccess = CopyQueryParametersFromRequest(pstSoap,
1360             KMS_MAX_LIST_KEY_GROUPS,
1361             &oQueryParameters,
1362             &stQueryParameters);
1363     if (!bSuccess)
1364     {
1365         soap_destroy(pstSoap);
1366         soap_end(pstSoap);
1367         // no memory, don't log
1368         RETURN(KMS_AGENT_STATUS_NO_MEMORY);
1369     }
1370 
1371     CAgentLoadBalancer *pLoadBalancer =
1372             (CAgentLoadBalancer *) i_pProfile->m_pAgentLoadBalancer;
1373 
1374     int iIndex = pLoadBalancer->Balance();
1375 
1376     if ( iIndex >= 0 )
1377     {
1378         do
1379         {
1380             const char* sURL =
1381                     pLoadBalancer->GetHTTPSURL(iIndex, i_pProfile->m_iPortForAgentService);
1382             strncpy(i_pProfile->m_sURL, sURL, sizeof(i_pProfile->m_sURL));
1383             i_pProfile->m_sURL[sizeof(i_pProfile->m_sURL)-1] = '\0';
1384 
1385             bSuccess = KMS_Agent::soap_call_KMS_Agent__ListKeyGroups(
1386                     pstSoap,
1387                     sURL,
1388                     NULL,
1389                     oQueryParameters,
1390                     oResponse) == SOAP_OK;
1391 
1392             if (!bSuccess)
1393             {
1394                 iIndex = pLoadBalancer->FailOver(iIndex, pstSoap);
1395 
1396                 char sKmaAddress[g_iMAX_PEER_NETWORK_ADDRESS_LENGTH];
1397                 char sSoapFaultMsg[g_iMAX_SOAP_FAULT_MESSAGE_LENGTH];
1398 
1399                 GetPeerNetworkAddress(sKmaAddress, pstSoap);
1400                 GetSoapFault(sSoapFaultMsg, pstSoap);
1401 
1402                 LogError(i_pProfile, AUDIT_CLIENT_AGENT_LIST_KEY_GROUPS_SOAP_ERROR,
1403                         NULL,
1404                         sKmaAddress,
1405                         sSoapFaultMsg);
1406             }
1407             else
1408             {
1409                 pLoadBalancer->UpdateResponseStatus(iIndex);
1410             }
1411         }
1412         while (iIndex >= 0 && (!bSuccess));
1413     }
1414     else
1415     {
1416         bSuccess = false;
1417     }
1418 
1419     if (bSuccess)
1420     {
1421         bIsLastPage = oResponse.LastPage;
1422 
1423         *o_ppKeyGroups = CopyKeyGroupsResponse(&oResponse.KeyGroups);
1424         if (*o_ppKeyGroups == NULL)
1425         {
1426             bSuccess = false;
1427             // no memory, don't log
1428         }
1429 
1430         CopyQueryParametersFromResponse(&stQueryParameters,
1431                 &oResponse.NextPageQueryParameters);
1432     }
1433 
1434     // free allocated memory for output if error condition
1435     // Clean up SOAP
1436 
1437     soap_destroy(pstSoap);
1438     soap_end(pstSoap);
1439 
1440     if (bSuccess)
1441         RETURN(KMS_AGENT_STATUS_OK);
1442 
1443     RETURN(KMSAgent_GetLastStatusCode(i_pProfile, iIndex));
1444 }
1445 
1446 /*---------------------------------------------------------------------------
1447  * Function: KMSAgent_FreeArrayOfKeyGroups
1448  *
1449  *--------------------------------------------------------------------------*/
1450 
1451 extern "C"
KMSAgent_FreeArrayOfKeyGroups(struct KMSAgent_ArrayOfKeyGroups * i_pArrayOfKeyGroups)1452 void KMSAgent_FreeArrayOfKeyGroups (
1453                                     struct KMSAgent_ArrayOfKeyGroups *i_pArrayOfKeyGroups)
1454 {
1455 #if defined(METAWARE)
1456     ECPT_TRACE_ENTRY *trace = NULL;
1457     ECPT_TRACE(trace, KMSAgent_FreeArrayOfKeyGroups);
1458 #endif
1459     if (!i_pArrayOfKeyGroups)
1460     {
1461         return;
1462     }
1463 
1464     // free memory for all information groups
1465     if (i_pArrayOfKeyGroups->m_pKeyGroups)
1466     {
1467         free(i_pArrayOfKeyGroups->m_pKeyGroups);
1468     }
1469 
1470     free(i_pArrayOfKeyGroups);
1471 }
1472 
1473 extern "C"
KMSAgent_CreateKey(KMSClientProfile * const i_pProfile,const KMSAgent_DataUnit * const i_pDataUnit,KEY_GROUP_ID const i_pKeyGroupID,KMSAgent_Key * const o_pKey)1474 KMS_AGENT_STATUS KMSAgent_CreateKey (
1475                                      KMSClientProfile * const i_pProfile,
1476                                      const KMSAgent_DataUnit * const i_pDataUnit,
1477                                      KEY_GROUP_ID const i_pKeyGroupID,
1478                                      KMSAgent_Key * const o_pKey)
1479 {
1480     bool bSuccess;
1481 #if defined(METAWARE)
1482     ECPT_TRACE_ENTRY *trace = NULL;
1483     ECPT_TRACE(trace, KMSAgent_CreateKey);
1484 #endif
1485 
1486     if (!i_pProfile)
1487     {
1488         Log(AUDIT_CLIENT_AGENT_CREATE_KEY_INVALID_PARAMETERS,
1489                 NULL,
1490                 NULL,
1491                 "Profile arg");
1492         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
1493     }
1494     if (!o_pKey)
1495     {
1496         Log(AUDIT_CLIENT_AGENT_CREATE_KEY_INVALID_PARAMETERS,
1497                 NULL,
1498                 NULL,
1499                 "Key arg");
1500         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
1501     }
1502 
1503     if (!KMSClient_ProfileLoaded(i_pProfile))
1504     {
1505         RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
1506     }
1507 
1508     if (i_pKeyGroupID &&
1509         strlen(i_pKeyGroupID) > KMS_MAX_KEY_GROUP_ID_SIZE)
1510     {
1511         Log(AUDIT_CLIENT_AGENT_CREATE_KEY_INVALID_PARAMETERS,
1512                 NULL,
1513                 NULL,
1514                 "GroupID arg");
1515         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
1516     }
1517 
1518     CAutoMutex oAutoMutex((K_MUTEX_HANDLE) i_pProfile->m_pLock);
1519 
1520     struct KMS_Agent::KMS_Agent__DataUnit
1521                         stDataUnit = {"", "", "", "",
1522                             (KMS_Agent::KMS_Agent__DataUnitState) 0};
1523 
1524     struct soap *pstSoap = (struct soap *) i_pProfile->m_pvSoap;
1525     struct KMS_Agent::KMS_Agent__CreateKeyResponse oResponse;
1526 
1527     if (i_pDataUnit != NULL)
1528     {
1529         if (!CopyDataUnitFromRequest(pstSoap,
1530             &stDataUnit,
1531             i_pDataUnit))
1532         {
1533             soap_destroy(pstSoap);
1534             soap_end(pstSoap);
1535             // no memory dont' log
1536             RETURN(KMS_AGENT_STATUS_NO_MEMORY);
1537         }
1538     }
1539 
1540     char * pKeyGroupID = NULL;
1541     if (i_pKeyGroupID)
1542     {
1543         pKeyGroupID = ConvertUTF8StringFromRequest(pstSoap,
1544                 i_pKeyGroupID,
1545                 KMS_MAX_KEY_GROUP_ID_SIZE + 1);
1546         if (pKeyGroupID == NULL)
1547         {
1548             soap_destroy(pstSoap);
1549             soap_end(pstSoap);
1550             // no memory dont' log
1551             RETURN(KMS_AGENT_STATUS_NO_MEMORY);
1552         }
1553     }
1554 
1555     CAgentLoadBalancer *pLoadBalancer =
1556             (CAgentLoadBalancer *) i_pProfile->m_pAgentLoadBalancer;
1557 
1558     char sKmaAddress[g_iMAX_PEER_NETWORK_ADDRESS_LENGTH];
1559     char sSoapFaultMsg[g_iMAX_SOAP_FAULT_MESSAGE_LENGTH];
1560 
1561     int iIndex;
1562     UTF8_KEYID acKWKID;
1563     bool bClientAESKeyWrapSetupError = false;
1564 
1565     if (i_pDataUnit)
1566     {
1567         // attempt to maintain affinity with KMA for specified DU ID
1568         iIndex = pLoadBalancer->BalanceByDataUnitID(
1569                 i_pDataUnit->m_acDataUnitID,
1570                 KMS_DATA_UNIT_ID_SIZE);
1571     }
1572     else
1573     {
1574         iIndex = pLoadBalancer->Balance();
1575     }
1576 
1577     if (iIndex >= 0)
1578     {
1579         do
1580         {
1581             bSuccess = true;
1582             const char* sURL = pLoadBalancer->GetHTTPSURL(
1583                     iIndex,
1584                     i_pProfile->m_iPortForAgentService);
1585 
1586             strncpy(i_pProfile->m_sURL, sURL, sizeof(i_pProfile->m_sURL));
1587 
1588             i_pProfile->m_sURL[sizeof(i_pProfile->m_sURL)-1] = '\0';
1589 
1590             Long64 lKMAID = pLoadBalancer->GetKMAID(iIndex);
1591 
1592             if (bSuccess && pLoadBalancer->AESKeyWrapSupported(iIndex))
1593             {
1594                 // if this fails we want to utilize normal failover logic, GetKWKID
1595                 // logs error
1596                 bSuccess = pLoadBalancer->GetKWKID(iIndex, lKMAID, pstSoap,
1597 					acKWKID, &bClientAESKeyWrapSetupError) ? true : false;
1598                 if (bSuccess)
1599                 {
1600                     bSuccess = KMS_Agent::soap_call_KMS_Agent__CreateKey2(
1601                             pstSoap,
1602                             sURL,
1603                             NULL,
1604                             stDataUnit,
1605                             i_pKeyGroupID ? pKeyGroupID : (char *) "",
1606                             acKWKID,
1607                             //NOTE: this is ugly but the soap response struct's are the same for both flavors of CreateKey
1608                             *(reinterpret_cast<struct KMS_Agent::KMS_Agent__CreateKey2Response *>(&oResponse))) == SOAP_OK;
1609                 }
1610             }
1611             else  if (bSuccess) // NO AES Key Wrap
1612             {
1613                 bSuccess = KMS_Agent::soap_call_KMS_Agent__CreateKey(
1614                         pstSoap,
1615                         sURL,
1616                         NULL,
1617                         stDataUnit,
1618                         i_pKeyGroupID ? pKeyGroupID : (char *) "",
1619                         oResponse) == SOAP_OK;
1620             }
1621 
1622             // don'f failover for Client side AES Key Wrap setup problems
1623             if (!bSuccess && !bClientAESKeyWrapSetupError)
1624             {
1625                 iIndex = pLoadBalancer->FailOver(iIndex, pstSoap);
1626 
1627                 GetPeerNetworkAddress(sKmaAddress, pstSoap);
1628                 GetSoapFault(sSoapFaultMsg, pstSoap);
1629 
1630                 LogError(i_pProfile,
1631                         AUDIT_CLIENT_AGENT_CREATE_KEY_SOAP_ERROR,
1632                         NULL,
1633                         sKmaAddress,
1634                         sSoapFaultMsg);
1635             }
1636             if (bSuccess)
1637             {
1638                 pLoadBalancer->UpdateResponseStatus(iIndex);
1639             }
1640         }
1641         while (iIndex >= 0 && (!bSuccess) && (!bClientAESKeyWrapSetupError));
1642     }
1643     else
1644     {
1645         bSuccess = false;
1646     }
1647 
1648 
1649 #if defined(DEBUG) && defined(METAWARE)
1650     log_printf("CreateKey gets keyID %s (size %x) \n",
1651             oResponse.Key.KeyID,
1652             sizeof (oResponse.Key.KeyID));
1653 #endif
1654 
1655 
1656     if (bSuccess)
1657     {
1658         if (KMS_KEY_ID_SIZE != ConvertUTF8HexStringToBinary(
1659             oResponse.Key.KeyID, NULL))
1660         {
1661             GetPeerNetworkAddress(sKmaAddress, pstSoap);
1662             LogError(i_pProfile,
1663                     AUDIT_CLIENT_AGENT_CREATE_KEY_INVALID_KEYID_RESPONSE,
1664                     NULL,
1665                     sKmaAddress,
1666                     NULL);
1667             bSuccess = false;
1668         }
1669 
1670         ConvertUTF8HexStringToBinary(
1671                 oResponse.Key.KeyID, // in
1672                 o_pKey->m_acKeyID); // out
1673 
1674 #if defined(DEBUG) && defined(METAWARE)
1675         log_printf("CreateKey gets keyState %x (size %x) \n",
1676                 oResponse.Key.KeyState,
1677                 sizeof (oResponse.Key.KeyState));
1678 #endif
1679 
1680         if ((KMS_AGENT_KEY_STATE) oResponse.Key.KeyState < KMS_KEY_STATE_ACTIVE_PROTECT_AND_PROCESS ||
1681             (KMS_AGENT_KEY_STATE) oResponse.Key.KeyState > KMS_KEY_STATE_COMPROMISED)
1682         {
1683             GetPeerNetworkAddress(sKmaAddress, pstSoap);
1684             LogError(i_pProfile,
1685                     AUDIT_CLIENT_AGENT_CREATE_KEY_INVALID_KEY_STATE_RESPONSE,
1686                     NULL,
1687                     sKmaAddress,
1688                     NULL);
1689             bSuccess = false;
1690         }
1691 
1692         o_pKey->m_iKeyState = (KMS_AGENT_KEY_STATE) oResponse.Key.KeyState;
1693 
1694 #if defined(DEBUG) && defined(METAWARE)
1695         log_printf("CreateKey o_pKey->m_iKeyState %x (size %x) = "
1696                 "(KMS_AGENT_KEY_STATE) oResponse.Key.KeyState %x (size %x)\n",
1697                 o_pKey->m_iKeyState,
1698                 sizeof (o_pKey->m_iKeyState),
1699                 oResponse.Key.KeyState,
1700                 sizeof (oResponse.Key.KeyState));
1701 #endif
1702 
1703 
1704         if ((KMS_KEY_TYPE) oResponse.Key.KeyType != KMS_KEY_TYPE_AES_256)
1705         {
1706             GetPeerNetworkAddress(sKmaAddress, pstSoap);
1707             LogError(i_pProfile,
1708                     AUDIT_CLIENT_AGENT_CREATE_KEY_INVALID_KEY_TYPE_RESPONSE,
1709                     NULL,
1710                     sKmaAddress,
1711                     NULL);
1712             bSuccess = false;
1713         }
1714         o_pKey->m_iKeyType = (KMS_KEY_TYPE) oResponse.Key.KeyType;
1715 
1716         if (strlen(oResponse.Key.KeyGroupID) > KMS_MAX_KEY_GROUP_ID_SIZE)
1717         {
1718             GetPeerNetworkAddress(sKmaAddress, pstSoap);
1719             LogError(i_pProfile,
1720                     AUDIT_CLIENT_AGENT_CREATE_KEY_INVALID_KEY_GROUP_ID_LENGTH_RESPONSE,
1721                     NULL,
1722                     sKmaAddress,
1723                     NULL);
1724             bSuccess = false;
1725         }
1726         else
1727         {
1728             strncpy(o_pKey->m_acKeyGroupID,
1729                     oResponse.Key.KeyGroupID,
1730                     sizeof(o_pKey->m_acKeyGroupID));
1731             o_pKey->m_acKeyGroupID[sizeof(o_pKey->m_acKeyGroupID)-1] = '\0';
1732         }
1733 
1734         if ( bSuccess && pLoadBalancer->AESKeyWrapSupported(iIndex))
1735         {
1736             // verify KWK ID matches what was registered
1737             if (oResponse.Key.Key.__size != KMS_MAX_WRAPPED_KEY_SIZE)
1738             {
1739                 GetPeerNetworkAddress(sKmaAddress, pstSoap);
1740                 LogError(i_pProfile,
1741                         AUDIT_CLIENT_AGENT_CREATE_KEY_INVALID_WRAPPED_KEY_LENGTH_RESPONSE,
1742                         NULL,
1743                         sKmaAddress,
1744                         NULL);
1745                 bSuccess = false;
1746             }
1747             else
1748             {
1749                 if (pLoadBalancer->AESKeyUnwrap(&iIndex, oResponse.Key.Key.__ptr,
1750                     o_pKey->m_acKey) == false)
1751                 {
1752                     GetPeerNetworkAddress(sKmaAddress, pstSoap);
1753                     LogError(i_pProfile,
1754                             AUDIT_CLIENT_AGENT_CREATE_KEY_AESKEYUNWRAP_ERROR,
1755                             NULL,
1756                             sKmaAddress,
1757                             NULL);
1758 
1759                     bSuccess = false;
1760                 }
1761             }
1762         }
1763         else if (bSuccess) // non-AES key wrap
1764         {
1765             if (oResponse.Key.Key.__size != KMS_MAX_KEY_SIZE)
1766             {
1767                 GetPeerNetworkAddress(sKmaAddress, pstSoap);
1768                 LogError(i_pProfile,
1769                         AUDIT_CLIENT_AGENT_CREATE_KEY_INVALID_KEY_LENGTH_RESPONSE,
1770                         NULL,
1771                         sKmaAddress,
1772                         NULL);
1773                 bSuccess = false;
1774             }
1775             else
1776             {
1777                 memcpy(o_pKey->m_acKey,
1778                         oResponse.Key.Key.__ptr,
1779                         KMS_MAX_KEY_SIZE);
1780             }
1781         }
1782 
1783         if (bSuccess)
1784         {
1785             o_pKey->m_iKeyLength = KMS_MAX_KEY_SIZE;
1786 
1787             if (KMSAgentKeyCallout(o_pKey->m_acKey) != 0)
1788             {
1789                 LogError(i_pProfile,
1790                         AUDIT_CLIENT_AGENT_CREATE_KEY_KEY_CALLOUT_ERROR,
1791                         NULL,
1792                         NULL,
1793                         NULL);
1794                 bSuccess = false;
1795             }
1796         }
1797     }
1798 
1799     if (bSuccess)
1800     {
1801         // add Key ID and the creating KMA IP address to the DU cache
1802         CDataUnitCache* pDataUnitCache = (CDataUnitCache*) i_pProfile->m_pDataUnitCache;
1803 
1804         if (i_pProfile->m_iClusterDiscoveryFrequency != 0) // load balancing enabled
1805         {
1806             bSuccess = pDataUnitCache->Insert(
1807                     NULL,
1808                     0,
1809                     o_pKey->m_acKeyID,
1810                     KMS_KEY_ID_SIZE,
1811                     pLoadBalancer->GetApplianceNetworkAddress(iIndex));
1812         }
1813     }
1814     // free allocated memory for output if error condition
1815     // Clean up SOAP
1816 
1817     soap_destroy(pstSoap);
1818     soap_end(pstSoap);
1819 
1820     if (bSuccess)
1821     {
1822         RETURN(KMS_AGENT_STATUS_OK);
1823     }
1824 
1825     RETURN(KMSAgent_GetLastStatusCode(i_pProfile,
1826             bClientAESKeyWrapSetupError ?
1827                 CAgentLoadBalancer::AES_KEY_WRAP_SETUP_ERROR : iIndex));
1828 }
1829 
1830 extern "C"
KMSAgent_CreateDataUnit(KMSClientProfile * const i_pProfile,const unsigned char * i_pExternalUniqueID,int i_iExternalUniqueIDIDLen,utf8cstr const i_pExternalTag,utf8cstr const i_pDescription,KMSAgent_DataUnit * const o_pDataUnit)1831 KMS_AGENT_STATUS KMSAgent_CreateDataUnit (
1832                                           KMSClientProfile * const i_pProfile,
1833                                           const unsigned char * i_pExternalUniqueID,
1834                                           int i_iExternalUniqueIDIDLen,
1835                                           utf8cstr const i_pExternalTag,
1836                                           utf8cstr const i_pDescription,
1837                                           KMSAgent_DataUnit * const o_pDataUnit)
1838 {
1839     bool bSuccess;
1840 #if defined(METAWARE)
1841     ECPT_TRACE_ENTRY *trace = NULL;
1842     ECPT_TRACE(trace, KMSAgent_CreateDataUnit);
1843 #endif
1844 
1845 #if defined(DEBUG) && defined(METAWARE)
1846 #warn "debug Create Data Unit is on"
1847     log_printf("KMSAgent_CreateDataUnit entered\n");
1848     log_printf("KMSAgent_CreateDataUnit profile=%x\n", i_pProfile);
1849 #endif
1850 
1851     if (!i_pProfile)
1852     {
1853         Log(AUDIT_CLIENT_AGENT_CREATE_DATA_UNIT_INVALID_PARAMETERS,
1854                 NULL,
1855                 NULL,
1856                 "Profile arg");
1857         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
1858     }
1859     if (!o_pDataUnit)
1860     {
1861         Log(AUDIT_CLIENT_AGENT_CREATE_DATA_UNIT_INVALID_PARAMETERS,
1862                 NULL,
1863                 NULL,
1864                 "DataUnit arg");
1865         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
1866     }
1867 
1868     if (!KMSClient_ProfileLoaded(i_pProfile))
1869     {
1870         RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
1871     }
1872 
1873     CAutoMutex oAutoMutex((K_MUTEX_HANDLE) i_pProfile->m_pLock);
1874 
1875     // validate input parms
1876 
1877     if (i_pExternalUniqueID &&
1878         (i_iExternalUniqueIDIDLen <= 0 ||
1879         i_iExternalUniqueIDIDLen > KMS_MAX_EXTERNAL_UNIQUE_ID_SIZE))
1880     {
1881         Log(AUDIT_CLIENT_AGENT_CREATE_DATA_UNIT_INVALID_PARAMETERS,
1882                 NULL,
1883                 NULL,
1884                 "ExternalUniqueID arg");
1885         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
1886     }
1887 
1888     if (i_pExternalTag && strlen(i_pExternalTag) > KMS_MAX_EXTERNAL_TAG)
1889     {
1890         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
1891     }
1892 
1893     if (i_pDescription && strlen(i_pDescription) > KMS_MAX_DESCRIPTION)
1894     {
1895         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
1896     }
1897 
1898     struct soap *pstSoap = (struct soap *) i_pProfile->m_pvSoap;
1899     struct KMS_Agent::KMS_Agent__CreateDataUnitResponse oResponse;
1900 
1901     char * pExternalUniqueID = NULL;
1902     if (i_pExternalUniqueID)
1903     {
1904         pExternalUniqueID = ConvertBinaryDataFromRequest(pstSoap,
1905                 i_pExternalUniqueID,
1906                 i_iExternalUniqueIDIDLen);
1907         if (pExternalUniqueID == NULL)
1908         {
1909             soap_destroy(pstSoap);
1910             soap_end(pstSoap);
1911             // no memory dont' log
1912             RETURN(KMS_AGENT_STATUS_NO_MEMORY);
1913         }
1914     }
1915 
1916     char * pExternalTag = NULL;
1917     if (i_pExternalTag)
1918     {
1919         pExternalTag = ConvertUTF8StringFromRequest(pstSoap,
1920                 i_pExternalTag,
1921                 strlen(i_pExternalTag) + 1);
1922         if (pExternalTag == NULL)
1923         {
1924             soap_destroy(pstSoap);
1925             soap_end(pstSoap);
1926             // no memory dont' log
1927             RETURN(KMS_AGENT_STATUS_NO_MEMORY);
1928         }
1929     }
1930 
1931     char * pDescription = NULL;
1932     if (i_pDescription)
1933     {
1934         pDescription = ConvertUTF8StringFromRequest(pstSoap,
1935                 i_pDescription,
1936                 strlen(i_pDescription) + 1);
1937         if (pDescription == NULL)
1938         {
1939             soap_destroy(pstSoap);
1940             soap_end(pstSoap);
1941             // no memory dont' log
1942             RETURN(KMS_AGENT_STATUS_NO_MEMORY);
1943         }
1944     }
1945 
1946     CAgentLoadBalancer *pLoadBalancer =
1947             (CAgentLoadBalancer *) i_pProfile->m_pAgentLoadBalancer;
1948     int iIndex = pLoadBalancer->Balance();
1949 
1950     if (iIndex >= 0)
1951     {
1952         do
1953         {
1954             const char* sURL = pLoadBalancer->GetHTTPSURL(
1955                     iIndex,
1956                     i_pProfile->m_iPortForAgentService);
1957 
1958             strncpy(i_pProfile->m_sURL, sURL, sizeof(i_pProfile->m_sURL));
1959 
1960             i_pProfile->m_sURL[sizeof(i_pProfile->m_sURL)-1] = '\0';
1961 
1962             bSuccess = KMS_Agent::soap_call_KMS_Agent__CreateDataUnit(
1963                     pstSoap,
1964                     sURL,
1965                     NULL,
1966                     i_pExternalUniqueID ? pExternalUniqueID : (char *) "",
1967                     i_pExternalTag ? pExternalTag : (char *) "",
1968                     i_pDescription ? pDescription : (char *) "",
1969                     oResponse) == SOAP_OK;
1970 
1971             if (!bSuccess)
1972             {
1973                 iIndex = pLoadBalancer->FailOver(iIndex, pstSoap);
1974 
1975                 char sKmaAddress[g_iMAX_PEER_NETWORK_ADDRESS_LENGTH];
1976                 char sSoapFaultMsg[g_iMAX_SOAP_FAULT_MESSAGE_LENGTH];
1977 
1978                 GetPeerNetworkAddress(sKmaAddress, pstSoap);
1979                 GetSoapFault(sSoapFaultMsg, pstSoap);
1980 
1981                 LogError(i_pProfile,
1982                         AUDIT_CLIENT_AGENT_CREATE_DATA_UNIT_SOAP_ERROR,
1983                         NULL,
1984                         sKmaAddress,
1985                         sSoapFaultMsg);
1986             }
1987             else
1988             {
1989                 pLoadBalancer->UpdateResponseStatus(iIndex);
1990             }
1991 
1992         }
1993         while (iIndex >= 0 && (!bSuccess));
1994     }
1995     else
1996     {
1997         bSuccess = false;
1998     }
1999 
2000     if (bSuccess)
2001     {
2002         int iDataUnitIDLength;
2003         iDataUnitIDLength = ConvertUTF8HexStringToBinary(
2004                 oResponse.DataUnit.DataUnitID, o_pDataUnit->m_acDataUnitID);
2005 
2006         if (iDataUnitIDLength != KMS_DATA_UNIT_ID_SIZE)
2007         {
2008 #if defined(DEBUG) && defined(METAWARE)
2009             log_printf("iDataUnitIDLength (%x) != KMS_DATA_UNIT_ID_SIZE (%x)",
2010                     iDataUnitIDLength,
2011                     KMS_DATA_UNIT_ID_SIZE);
2012 #endif
2013             LogError(i_pProfile,
2014                     AUDIT_CLIENT_AGENT_CREATE_DATA_UNIT_RESPONSE_INVALID_DU_ID_LENGTH,
2015                     NULL,
2016                     NULL,
2017                     NULL);
2018             bSuccess = false;
2019         }
2020         o_pDataUnit->m_iExternalUniqueIDLength = ConvertUTF8HexStringToBinary(
2021                 oResponse.DataUnit.ExternalUniqueID, o_pDataUnit->m_acExternalUniqueID);
2022 
2023         if (strlen(oResponse.DataUnit.ExternalTag) > KMS_MAX_EXTERNAL_TAG)
2024         {
2025             LogError(i_pProfile,
2026                     AUDIT_CLIENT_AGENT_CREATE_DATA_UNIT_RESPONSE_INVALID_EXTERNAL_TAG_LENGTH,
2027                     NULL,
2028                     NULL,
2029                     NULL);
2030             bSuccess = false;
2031         }
2032         else
2033         {
2034             strncpy(o_pDataUnit->m_acExternalTag,
2035                     oResponse.DataUnit.ExternalTag,
2036                     sizeof(o_pDataUnit->m_acExternalTag));
2037             o_pDataUnit->m_acExternalTag[sizeof(o_pDataUnit->m_acExternalTag)-1] = '\0';
2038         }
2039 
2040         if (strlen(oResponse.DataUnit.Description) > KMS_MAX_DESCRIPTION)
2041         {
2042             LogError(i_pProfile,
2043                     AUDIT_CLIENT_AGENT_CREATE_DATA_UNIT_RESPONSE_INVALID_DESCRIPTION_LENGTH,
2044                     NULL,
2045                     NULL,
2046                     NULL);
2047             bSuccess = false;
2048         }
2049         else
2050         {
2051             strcpy(o_pDataUnit->m_acDescription,
2052                     oResponse.DataUnit.Description);
2053         }
2054 
2055         o_pDataUnit->m_iDataUnitState =
2056                 (KMS_AGENT_DATA_UNIT_STATE) oResponse.DataUnit.DataUnitState;
2057     }
2058 
2059     if (bSuccess)
2060     {
2061         // add data unit ID and the creating KMA IP address to the DU cache
2062         CDataUnitCache* pDataUnitCache = (CDataUnitCache*) i_pProfile->m_pDataUnitCache;
2063 
2064         if (i_pProfile->m_iClusterDiscoveryFrequency != 0) // load balancing enabled
2065         {
2066             bSuccess = pDataUnitCache->Insert(
2067                     o_pDataUnit->m_acDataUnitID,
2068                     KMS_DATA_UNIT_ID_SIZE,
2069                     NULL, 0,
2070                     pLoadBalancer->GetApplianceNetworkAddress(iIndex));
2071         }
2072     }
2073 
2074     // free allocated memory for output if error condition
2075     // Clean up SOAP
2076 
2077     soap_destroy(pstSoap);
2078     soap_end(pstSoap);
2079 
2080     if (bSuccess)
2081     {
2082         RETURN(KMS_AGENT_STATUS_OK);
2083     }
2084 
2085     RETURN(KMSAgent_GetLastStatusCode(i_pProfile, iIndex));
2086 }
2087 
2088 extern "C"
KMSAgent_DisassociateDataUnitKeys(KMSClientProfile * const i_pProfile,const KMSAgent_DataUnit * const i_pDataUnit)2089 KMS_AGENT_STATUS KMSAgent_DisassociateDataUnitKeys (
2090                                                     KMSClientProfile * const i_pProfile,
2091                                                     const KMSAgent_DataUnit * const i_pDataUnit)
2092 {
2093     bool bSuccess;
2094 #if defined(METAWARE)
2095     ECPT_TRACE_ENTRY *trace = NULL;
2096     ECPT_TRACE(trace, KMSAgent_DisassociateDataUnitKeys);
2097 #endif
2098 
2099     if (!i_pProfile)
2100     {
2101         Log(AUDIT_CLIENT_AGENT_DISASSOCIATE_DATA_UNIT_KEYS_INVALID_PARAMETERS,
2102                 NULL,
2103                 NULL,
2104                 "Profile arg");
2105         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
2106     }
2107 
2108     if (!i_pDataUnit)
2109     {
2110         Log(AUDIT_CLIENT_AGENT_DISASSOCIATE_DATA_UNIT_KEYS_INVALID_PARAMETERS,
2111                 NULL,
2112                 NULL,
2113                 "DataUnit arg");
2114         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
2115     }
2116     if (!KMSClient_ProfileLoaded(i_pProfile))
2117     {
2118         RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
2119     }
2120 
2121     CAutoMutex oAutoMutex((K_MUTEX_HANDLE) i_pProfile->m_pLock);
2122 
2123     struct KMS_Agent::KMS_Agent__DataUnit stDataUnit = {"", "", "", "",
2124         (KMS_Agent::KMS_Agent__DataUnitState) 0};
2125 
2126     struct soap *pstSoap = (struct soap *) i_pProfile->m_pvSoap;
2127     struct KMS_Agent::KMS_Agent__DisassociateDataUnitKeysResponse oResponse;
2128 
2129     if (!CopyDataUnitFromRequest(pstSoap,
2130         &stDataUnit,
2131         i_pDataUnit))
2132     {
2133         soap_destroy(pstSoap);
2134         soap_end(pstSoap);
2135         // no memory dont' log
2136         RETURN(KMS_AGENT_STATUS_NO_MEMORY);
2137     }
2138 
2139     CAgentLoadBalancer *pLoadBalancer =
2140             (CAgentLoadBalancer *) i_pProfile->m_pAgentLoadBalancer;
2141     int iIndex = pLoadBalancer->BalanceByDataUnitID(
2142             i_pDataUnit->m_acDataUnitID,
2143             KMS_DATA_UNIT_ID_SIZE);
2144 
2145     if (iIndex >= 0)
2146     {
2147         do
2148         {
2149             const char* sURL = pLoadBalancer->GetHTTPSURL(
2150                     iIndex,
2151                     i_pProfile->m_iPortForAgentService);
2152 
2153             strncpy(i_pProfile->m_sURL, sURL, sizeof(i_pProfile->m_sURL));
2154 
2155             i_pProfile->m_sURL[sizeof(i_pProfile->m_sURL)-1] = '\0';
2156 
2157             bSuccess = KMS_Agent::soap_call_KMS_Agent__DisassociateDataUnitKeys(
2158                     pstSoap,
2159                     sURL,
2160                     NULL,
2161                     stDataUnit,
2162                     oResponse) == SOAP_OK;
2163 
2164             if (!bSuccess)
2165             {
2166                 iIndex = pLoadBalancer->FailOver(iIndex, pstSoap);
2167 
2168                 char sKmaAddress[g_iMAX_PEER_NETWORK_ADDRESS_LENGTH];
2169                 char sSoapFaultMsg[g_iMAX_SOAP_FAULT_MESSAGE_LENGTH];
2170 
2171                 GetPeerNetworkAddress(sKmaAddress, pstSoap);
2172                 GetSoapFault(sSoapFaultMsg, pstSoap);
2173 
2174                 LogError(i_pProfile,
2175                         AUDIT_CLIENT_AGENT_DISASSOCIATE_DATA_UNIT_KEYS_SOAP_ERROR,
2176                         NULL,
2177                         sKmaAddress,
2178                         sSoapFaultMsg);
2179             }
2180             else
2181             {
2182                 pLoadBalancer->UpdateResponseStatus(iIndex);
2183             }
2184         }
2185         while (iIndex >= 0 && (!bSuccess));
2186     }
2187     else
2188     {
2189         bSuccess = false;
2190     }
2191 
2192     // no response data for this transaction
2193 
2194     // free allocated memory for output if error condition
2195     // Clean up SOAP
2196 
2197     soap_destroy(pstSoap);
2198     soap_end(pstSoap);
2199 
2200     if (bSuccess)
2201     {
2202         RETURN(KMS_AGENT_STATUS_OK);
2203     }
2204 
2205     RETURN(KMSAgent_GetLastStatusCode(i_pProfile, iIndex));
2206 }
2207 
2208 extern "C"
KMSAgent_RetrieveKey(KMSClientProfile * const i_pProfile,const unsigned char * const i_pKeyID,const KMSAgent_DataUnit * const i_pDataUnit,utf8cstr const i_pKeyGroupID,KMSAgent_Key * const o_pKey)2209 KMS_AGENT_STATUS KMSAgent_RetrieveKey (
2210                                        KMSClientProfile * const i_pProfile,
2211                                        const unsigned char * const i_pKeyID,
2212                                        const KMSAgent_DataUnit * const i_pDataUnit,
2213                                        utf8cstr const i_pKeyGroupID,
2214                                        KMSAgent_Key * const o_pKey)
2215 {
2216     bool bSuccess;
2217 
2218 #if defined(METAWARE)
2219     ECPT_TRACE_ENTRY *trace = NULL;
2220     ECPT_TRACE(trace, KMSAgent_RetrieveKey);
2221 #endif
2222 
2223     if (!i_pProfile)
2224     {
2225         Log(AUDIT_CLIENT_AGENT_RETRIEVE_KEY_INVALID_PARAMETERS,
2226                 NULL,
2227                 NULL,
2228                 "Profile arg");
2229         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
2230     }
2231     if (!i_pKeyID)
2232     {
2233         Log(AUDIT_CLIENT_AGENT_RETRIEVE_KEY_INVALID_PARAMETERS,
2234                 NULL,
2235                 NULL,
2236                 "KeyID arg");
2237         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
2238     }
2239     if (!o_pKey)
2240     {
2241         Log(AUDIT_CLIENT_AGENT_RETRIEVE_KEY_INVALID_PARAMETERS,
2242                 NULL,
2243                 NULL,
2244                 "Key arg");
2245         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
2246     }
2247 
2248     if (!KMSClient_ProfileLoaded(i_pProfile))
2249     {
2250         RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
2251     }
2252 
2253     CAutoMutex oAutoMutex((K_MUTEX_HANDLE) i_pProfile->m_pLock);
2254 
2255     if (i_pKeyGroupID &&
2256         strlen(i_pKeyGroupID) > KMS_MAX_KEY_GROUP_ID_SIZE)
2257     {
2258         Log(AUDIT_CLIENT_AGENT_RETRIEVE_KEY_INVALID_PARAMETERS,
2259                 NULL,
2260                 NULL,
2261                 "GroupID arg");
2262         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
2263     }
2264 
2265     struct KMS_Agent::KMS_Agent__DataUnit stDataUnit = {"", "", "", "",
2266         (KMS_Agent::KMS_Agent__DataUnitState) 0};
2267 
2268     struct soap *pstSoap = (struct soap *) i_pProfile->m_pvSoap;
2269     struct KMS_Agent::KMS_Agent__RetrieveKeyResponse oResponse;
2270 
2271     char * pKeyID = NULL;
2272     pKeyID = ConvertBinaryDataFromRequest(pstSoap,
2273             i_pKeyID,
2274             KMS_KEY_ID_SIZE);
2275     if (pKeyID == NULL)
2276     {
2277         soap_destroy(pstSoap);
2278         soap_end(pstSoap);
2279         // no memory dont' log
2280         RETURN(KMS_AGENT_STATUS_NO_MEMORY);
2281     }
2282 
2283     if (i_pDataUnit != NULL)
2284     {
2285         if (!CopyDataUnitFromRequest(pstSoap,
2286             &stDataUnit,
2287             i_pDataUnit))
2288         {
2289             soap_destroy(pstSoap);
2290             soap_end(pstSoap);
2291             // no memory dont' log
2292             RETURN(KMS_AGENT_STATUS_NO_MEMORY);
2293         }
2294     }
2295 
2296     char * pKeyGroupID = NULL;
2297     if (i_pKeyGroupID)
2298     {
2299         pKeyGroupID = ConvertUTF8StringFromRequest(pstSoap,
2300                 i_pKeyGroupID,
2301                 KMS_MAX_KEY_GROUP_ID_SIZE + 1);
2302         if (pKeyGroupID == NULL)
2303         {
2304             soap_destroy(pstSoap);
2305             soap_end(pstSoap);
2306             // no memory dont' log
2307             RETURN(KMS_AGENT_STATUS_NO_MEMORY);
2308         }
2309     }
2310 
2311     UTF8_KEYID acKWKID;
2312 
2313     char sKmaAddress[g_iMAX_PEER_NETWORK_ADDRESS_LENGTH];
2314     char sSoapFaultMsg[g_iMAX_SOAP_FAULT_MESSAGE_LENGTH];
2315     bool bClientAESKeyWrapSetupError = false;
2316 
2317     CAgentLoadBalancer *pLoadBalancer =
2318             (CAgentLoadBalancer *) i_pProfile->m_pAgentLoadBalancer;
2319     int iIndex = pLoadBalancer->BalanceByDataUnitKeyID(i_pKeyID, KMS_KEY_ID_SIZE);
2320 
2321     if (iIndex >= 0)
2322     {
2323         do
2324         {
2325             bSuccess = true;
2326             const char* sURL = pLoadBalancer->GetHTTPSURL(
2327                     iIndex,
2328                     i_pProfile->m_iPortForAgentService);
2329 
2330             strncpy(i_pProfile->m_sURL, sURL, sizeof(i_pProfile->m_sURL));
2331 
2332             i_pProfile->m_sURL[sizeof(i_pProfile->m_sURL)-1] = '\0';
2333 
2334             Long64 lKMAID = pLoadBalancer->GetKMAID(iIndex);
2335 
2336             if (bSuccess && pLoadBalancer->AESKeyWrapSupported(iIndex))
2337             {
2338                 // if this fails we want to utilize normal failover logic, GetKWKID
2339                 // logs error
2340                 bSuccess = pLoadBalancer->GetKWKID(iIndex, lKMAID, pstSoap,
2341 					acKWKID, &bClientAESKeyWrapSetupError) ? true : false;
2342                 if (bSuccess)
2343                 {
2344                     bSuccess = KMS_Agent::soap_call_KMS_Agent__RetrieveKey2(
2345                             pstSoap,
2346                             sURL,
2347                             NULL,
2348                             pKeyID,
2349                             stDataUnit,
2350                             i_pKeyGroupID ? i_pKeyGroupID : (char *) "",
2351                             acKWKID,
2352                             //NOTE: this is ugly but the soap response struct's are the same for both flavors of CreateKey
2353                             *(reinterpret_cast<struct KMS_Agent::KMS_Agent__RetrieveKey2Response *>(&oResponse))) == SOAP_OK;
2354                 }
2355             }
2356             else if (bSuccess)  // NO AES Key Wrap
2357             {
2358                     bSuccess = KMS_Agent::soap_call_KMS_Agent__RetrieveKey(
2359                             pstSoap,
2360                             sURL,
2361                             NULL,
2362                             pKeyID,
2363                             stDataUnit,
2364                             i_pKeyGroupID ? i_pKeyGroupID : (char *) "",
2365                             oResponse) == SOAP_OK;
2366             }
2367 
2368             // don'f failover for Client side AES Key Wrap setup problems
2369             if (!bSuccess && !bClientAESKeyWrapSetupError)
2370             {
2371                 iIndex = pLoadBalancer->FailOver(iIndex, pstSoap);
2372 
2373                 GetPeerNetworkAddress(sKmaAddress, pstSoap);
2374                 GetSoapFault(sSoapFaultMsg, pstSoap);
2375 
2376                 LogError(i_pProfile,
2377                         AUDIT_CLIENT_AGENT_RETRIEVE_KEY_SOAP_ERROR,
2378                         NULL,
2379                         sKmaAddress,
2380                         sSoapFaultMsg);
2381             }
2382             if (bSuccess)
2383             {
2384                 pLoadBalancer->UpdateResponseStatus(iIndex);
2385             }
2386         }
2387         while (iIndex >= 0 && (!bSuccess) && (!bClientAESKeyWrapSetupError));
2388     }
2389     else
2390     {
2391         bSuccess = false;
2392     }
2393 
2394     if (bSuccess)
2395     {
2396         if (KMS_KEY_ID_SIZE != ConvertUTF8HexStringToBinary(
2397             oResponse.Key.KeyID, NULL))
2398         {
2399             GetPeerNetworkAddress(sKmaAddress, pstSoap);
2400             LogError(i_pProfile,
2401                     AUDIT_CLIENT_AGENT_RETRIEVE_KEY_INVALID_KEYID_RESPONSE,
2402                     NULL,
2403                     sKmaAddress,
2404                     NULL);
2405             bSuccess = false;
2406         }
2407     }
2408 
2409     if (bSuccess)
2410     {
2411         ConvertUTF8HexStringToBinary(
2412                 oResponse.Key.KeyID, o_pKey->m_acKeyID);
2413 
2414         //if ( oResponse.Key.KeyState < (KMS_Agent__KeyState)KMS_KEY_STATE_ACTIVE_PROTECT_AND_PROCESS ||
2415         //    oResponse.Key.KeyState > (KMS_Agent__KeyState)KMS_KEY_STATE_COMPROMISED )
2416         if ((KMS_AGENT_KEY_STATE) oResponse.Key.KeyState < KMS_KEY_STATE_ACTIVE_PROTECT_AND_PROCESS ||
2417             (KMS_AGENT_KEY_STATE) oResponse.Key.KeyState > KMS_KEY_STATE_COMPROMISED)
2418         {
2419             GetPeerNetworkAddress(sKmaAddress, pstSoap);
2420             LogError(i_pProfile,
2421                     AUDIT_CLIENT_AGENT_RETRIEVE_KEY_INVALID_KEY_STATE_RESPONSE,
2422                     NULL,
2423                     sKmaAddress,
2424                     NULL);
2425             bSuccess = false;
2426         }
2427 
2428         o_pKey->m_iKeyState = (KMS_AGENT_KEY_STATE) oResponse.Key.KeyState;
2429 
2430         if ((KMS_KEY_TYPE) oResponse.Key.KeyType != KMS_KEY_TYPE_AES_256)
2431         {
2432             GetPeerNetworkAddress(sKmaAddress, pstSoap);
2433             LogError(i_pProfile,
2434                     AUDIT_CLIENT_AGENT_RETRIEVE_KEY_INVALID_KEY_TYPE_RESPONSE,
2435                     NULL,
2436                     sKmaAddress,
2437                     NULL);
2438             bSuccess = false;
2439         }
2440 
2441         o_pKey->m_iKeyType = (KMS_KEY_TYPE) oResponse.Key.KeyType;
2442 
2443         if (strlen(oResponse.Key.KeyGroupID) > KMS_MAX_KEY_GROUP_ID_SIZE)
2444         {
2445             GetPeerNetworkAddress(sKmaAddress, pstSoap);
2446             LogError(i_pProfile,
2447                     AUDIT_CLIENT_AGENT_RETRIEVE_KEY_INVALID_KEY_GROUP_ID_LENGTH_RESPONSE,
2448                     NULL,
2449                     sKmaAddress,
2450                     NULL);
2451             bSuccess = false;
2452         }
2453         else
2454         {
2455             strncpy(o_pKey->m_acKeyGroupID,
2456                     oResponse.Key.KeyGroupID,
2457                     sizeof(o_pKey->m_acKeyGroupID));
2458             o_pKey->m_acKeyGroupID[sizeof(o_pKey->m_acKeyGroupID)-1] = '\0';
2459         }
2460 
2461         if ( bSuccess && pLoadBalancer->AESKeyWrapSupported(iIndex))
2462         {
2463             // verify KWK ID matches what was registered
2464             if (oResponse.Key.Key.__size != KMS_MAX_WRAPPED_KEY_SIZE)
2465             {
2466                 GetPeerNetworkAddress(sKmaAddress, pstSoap);
2467                 LogError(i_pProfile,
2468                         AUDIT_CLIENT_AGENT_RETRIEVE_KEY_INVALID_WRAPPED_KEY_LENGTH_RESPONSE,
2469                         NULL,
2470                         sKmaAddress,
2471                         NULL);
2472                 bSuccess = false;
2473             }
2474             else
2475             {
2476                 if (pLoadBalancer->AESKeyUnwrap(&iIndex, oResponse.Key.Key.__ptr,
2477                     o_pKey->m_acKey) == false)
2478                 {
2479                     GetPeerNetworkAddress(sKmaAddress, pstSoap);
2480                     LogError(i_pProfile,
2481                             AUDIT_CLIENT_AGENT_RETRIEVE_KEY_AESKEYUNWRAP_ERROR,
2482                             NULL,
2483                             sKmaAddress,
2484                             NULL);
2485 
2486                     bSuccess = false;
2487                 }
2488             }
2489         }
2490         else if (bSuccess) // non-AES key wrap
2491         {
2492             if (oResponse.Key.Key.__size != KMS_MAX_KEY_SIZE)
2493             {
2494                 GetPeerNetworkAddress(sKmaAddress, pstSoap);
2495                 LogError(i_pProfile,
2496                         AUDIT_CLIENT_AGENT_RETRIEVE_KEY_INVALID_KEY_LENGTH_RESPONSE,
2497                         NULL,
2498                         sKmaAddress,
2499                         NULL);
2500                 bSuccess = false;
2501             }
2502             else
2503             {
2504                 memcpy(o_pKey->m_acKey,
2505                         oResponse.Key.Key.__ptr,
2506                         KMS_MAX_KEY_SIZE);
2507             }
2508         }
2509 
2510         if (bSuccess)
2511         {
2512             o_pKey->m_iKeyLength = KMS_MAX_KEY_SIZE;
2513 
2514             if (KMSAgentKeyCallout(o_pKey->m_acKey) != 0)
2515             {
2516                 LogError(i_pProfile,
2517                         AUDIT_CLIENT_AGENT_RETRIEVE_KEY_KEY_CALLOUT_ERROR,
2518                         NULL,
2519                         NULL,
2520                         NULL);
2521                 bSuccess = false;
2522             }
2523         }
2524     }
2525 
2526     // free allocated memory for output if error condition
2527     // Clean up SOAP
2528 
2529     soap_destroy(pstSoap);
2530     soap_end(pstSoap);
2531 
2532     if (bSuccess)
2533     {
2534         RETURN(KMS_AGENT_STATUS_OK);
2535     }
2536 
2537     RETURN(KMSAgent_GetLastStatusCode(i_pProfile,
2538             bClientAESKeyWrapSetupError ?
2539                 CAgentLoadBalancer::AES_KEY_WRAP_SETUP_ERROR : iIndex));
2540 }
2541 
2542 extern "C"
KMSAgent_RetrieveDataUnit(KMSClientProfile * const i_pProfile,const unsigned char * const i_pDataUnitID,const unsigned char * const i_pExternalUniqueID,int i_iExternalUniqueIDLen,utf8cstr const i_pExternalTag,utf8cstr const i_pDescription,KMSAgent_DataUnit * const o_pDataUnit)2543 KMS_AGENT_STATUS KMSAgent_RetrieveDataUnit (
2544                                             KMSClientProfile * const i_pProfile,
2545                                             const unsigned char * const i_pDataUnitID,
2546                                             const unsigned char * const i_pExternalUniqueID,
2547                                             int i_iExternalUniqueIDLen,
2548                                             utf8cstr const i_pExternalTag,
2549                                             utf8cstr const i_pDescription,
2550                                             KMSAgent_DataUnit * const o_pDataUnit)
2551 {
2552     bool bSuccess;
2553 #if defined(METAWARE)
2554     ECPT_TRACE_ENTRY *trace = NULL;
2555     ECPT_TRACE(trace, KMSAgent_RetrieveDataUnit);
2556 #endif
2557 
2558 #if defined(DEBUG) && defined(METAWARE)
2559     log_printf("KMSAgent_RetrieveDataUnit entered\n");
2560 #endif
2561 
2562     // required parms
2563     if (!i_pProfile)
2564     {
2565         Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_INVALID_PARAMETERS,
2566                 NULL,
2567                 NULL,
2568                 "Profile arg");
2569         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
2570     }
2571     if (!i_pDataUnitID)
2572     {
2573         Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_INVALID_PARAMETERS,
2574                 NULL,
2575                 NULL,
2576                 "DataUnitID arg");
2577         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
2578     }
2579     if (!o_pDataUnit)
2580     {
2581         Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_INVALID_PARAMETERS,
2582                 NULL,
2583                 NULL,
2584                 "DataUnit arg");
2585         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
2586     }
2587 
2588 
2589 
2590     if (!KMSClient_ProfileLoaded(i_pProfile))
2591     {
2592 #if defined(DEBUG) && defined(METAWARE)
2593         log_printf("KMSAgent_RetrieveDataUnit profile not loaded\n");
2594 #endif
2595         RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
2596     }
2597 
2598     CAutoMutex oAutoMutex((K_MUTEX_HANDLE) i_pProfile->m_pLock);
2599 
2600     // validate input parms
2601 
2602     if (i_pExternalUniqueID &&
2603         (i_iExternalUniqueIDLen <= 0 ||
2604         i_iExternalUniqueIDLen > KMS_MAX_EXTERNAL_UNIQUE_ID_SIZE))
2605     {
2606         Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_INVALID_PARAMETERS,
2607                 NULL,
2608                 NULL,
2609                 "ExternalUniqueID arg");
2610         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
2611     }
2612 
2613     if (i_pExternalTag && strlen(i_pExternalTag) > KMS_MAX_EXTERNAL_TAG)
2614     {
2615         Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_INVALID_PARAMETERS,
2616                 NULL,
2617                 NULL,
2618                 "ExternalTag arg");
2619         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
2620     }
2621 
2622     if (i_pDescription &&
2623         strlen(i_pDescription) > KMS_MAX_DESCRIPTION)
2624     {
2625         Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_INVALID_PARAMETERS,
2626                 NULL,
2627                 NULL,
2628                 "Description arg");
2629         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
2630     }
2631 
2632     // prepare args to soap transaction
2633 
2634     struct soap *pstSoap = (struct soap *) i_pProfile->m_pvSoap;
2635     struct KMS_Agent::KMS_Agent__RetrieveDataUnitResponse oResponse;
2636 
2637     char * pDataUnitID = NULL;
2638     pDataUnitID = ConvertBinaryDataFromRequest(pstSoap,
2639             i_pDataUnitID,
2640             KMS_DATA_UNIT_ID_SIZE);
2641     //sizeof(DATA_UNIT_ID) );
2642     if (pDataUnitID == NULL)
2643     {
2644         soap_destroy(pstSoap);
2645         soap_end(pstSoap);
2646         // no memory dont' log
2647         RETURN(KMS_AGENT_STATUS_NO_MEMORY);
2648     }
2649 
2650     char * pExternalUniqueID = NULL;
2651     if (i_pExternalUniqueID)
2652     {
2653         pExternalUniqueID = ConvertBinaryDataFromRequest(pstSoap,
2654                 i_pExternalUniqueID,
2655                 i_iExternalUniqueIDLen);
2656         if (pExternalUniqueID == NULL)
2657         {
2658             soap_destroy(pstSoap);
2659             soap_end(pstSoap);
2660             // no memory dont' log
2661             RETURN(KMS_AGENT_STATUS_NO_MEMORY);
2662         }
2663     }
2664 
2665     char * pExternalTag = NULL;
2666     if (i_pExternalTag)
2667     {
2668         pExternalTag = ConvertUTF8StringFromRequest(pstSoap,
2669                 i_pExternalTag,
2670                 KMS_MAX_EXTERNAL_TAG + 1);
2671         if (pExternalTag == NULL)
2672         {
2673             soap_destroy(pstSoap);
2674             soap_end(pstSoap);
2675             // no memory dont' log
2676             RETURN(KMS_AGENT_STATUS_NO_MEMORY);
2677         }
2678     }
2679 
2680     char * pDescription = NULL;
2681     if (i_pDescription)
2682     {
2683         pDescription = ConvertUTF8StringFromRequest(pstSoap,
2684                 i_pDescription,
2685                 KMS_MAX_DESCRIPTION + 1);
2686         if (pDescription == NULL)
2687         {
2688             soap_destroy(pstSoap);
2689             soap_end(pstSoap);
2690             // no memory dont' log
2691             RETURN(KMS_AGENT_STATUS_NO_MEMORY);
2692         }
2693     }
2694 
2695     CAgentLoadBalancer *pLoadBalancer =
2696             (CAgentLoadBalancer *) i_pProfile->m_pAgentLoadBalancer;
2697     int iIndex = pLoadBalancer->BalanceByDataUnitID(i_pDataUnitID,
2698             KMS_DATA_UNIT_ID_SIZE);
2699 
2700     if ( iIndex >= 0 )
2701     {
2702         do
2703         {
2704             const char* sURL = pLoadBalancer->GetHTTPSURL(
2705                     iIndex,
2706                     i_pProfile->m_iPortForAgentService);
2707 
2708             strncpy(i_pProfile->m_sURL, sURL, sizeof(i_pProfile->m_sURL));
2709 
2710             i_pProfile->m_sURL[sizeof(i_pProfile->m_sURL)-1] = '\0';
2711 
2712             bSuccess = KMS_Agent::soap_call_KMS_Agent__RetrieveDataUnit(
2713                     pstSoap,
2714                     sURL,
2715                     NULL,
2716                     pDataUnitID,
2717                     i_pExternalUniqueID ? pExternalUniqueID : (char *) "",
2718                     i_pExternalTag ? pExternalTag : (char *) "",
2719                     i_pDescription ? pDescription : (char *) "",
2720                     oResponse) == SOAP_OK;
2721 
2722             if (!bSuccess)
2723             {
2724                 iIndex = pLoadBalancer->FailOver(iIndex, pstSoap);
2725 
2726                 char sKmaAddress[g_iMAX_PEER_NETWORK_ADDRESS_LENGTH];
2727                 char sSoapFaultMsg[g_iMAX_SOAP_FAULT_MESSAGE_LENGTH];
2728 
2729                 GetPeerNetworkAddress(sKmaAddress, pstSoap);
2730                 GetSoapFault(sSoapFaultMsg, pstSoap);
2731 
2732                 LogError(i_pProfile,
2733                         AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_SOAP_ERROR,
2734                         NULL,
2735                         sKmaAddress,
2736                         sSoapFaultMsg);
2737             }
2738             else
2739             {
2740                 pLoadBalancer->UpdateResponseStatus(iIndex);
2741             }
2742         }
2743         while (iIndex >= 0 && (!bSuccess));
2744     }
2745     else
2746     {
2747         bSuccess = false;
2748     }
2749 
2750     if (bSuccess)
2751     {
2752         ConvertUTF8HexStringToBinary(
2753                 oResponse.DataUnit.DataUnitID, o_pDataUnit->m_acDataUnitID);
2754 
2755         o_pDataUnit->m_iExternalUniqueIDLength = ConvertUTF8HexStringToBinary(
2756                 oResponse.DataUnit.ExternalUniqueID, o_pDataUnit->m_acExternalUniqueID);
2757 
2758         if (strlen(oResponse.DataUnit.ExternalTag) > KMS_MAX_EXTERNAL_TAG)
2759         {
2760             LogError(i_pProfile,
2761                     AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_RESPONSE_INVALID_EXTERNAL_TAG_LENGTH,
2762                     NULL,
2763                     NULL,
2764                     NULL);
2765             bSuccess = false;
2766         }
2767         else
2768         {
2769             strncpy(o_pDataUnit->m_acExternalTag,
2770                     oResponse.DataUnit.ExternalTag,
2771                     sizeof(o_pDataUnit->m_acExternalTag));
2772             o_pDataUnit->m_acExternalTag[sizeof(o_pDataUnit->m_acExternalTag)-1] = '\0';
2773         }
2774 
2775         if (strlen(oResponse.DataUnit.Description) > KMS_MAX_DESCRIPTION)
2776         {
2777             LogError(i_pProfile,
2778                     AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_RESPONSE_INVALID_DESCRIPTION_LENGTH,
2779                     NULL,
2780                     NULL,
2781                     NULL);
2782             bSuccess = false;
2783         }
2784         else
2785         {
2786             strcpy(o_pDataUnit->m_acDescription,
2787                     oResponse.DataUnit.Description);
2788         }
2789 
2790         o_pDataUnit->m_iDataUnitState =
2791                 (KMS_AGENT_DATA_UNIT_STATE) oResponse.DataUnit.DataUnitState;
2792     }
2793 
2794     // free allocated memory for output if error condition
2795     // Clean up SOAP
2796 
2797     soap_destroy(pstSoap);
2798     soap_end(pstSoap);
2799 
2800     if (bSuccess)
2801     {
2802         RETURN(KMS_AGENT_STATUS_OK);
2803     }
2804 
2805     RETURN(KMSAgent_GetLastStatusCode(i_pProfile, iIndex));
2806 }
2807 
2808 extern "C"
KMSAgent_RetrieveDataUnitByExternalUniqueID(KMSClientProfile * const i_pProfile,const unsigned char * const i_pExternalUniqueID,int i_iExternalUniqueIDLen,utf8cstr const i_pExternalTag,utf8cstr const i_pDescription,KMSAgent_DataUnit * const o_pDataUnit)2809 KMS_AGENT_STATUS KMSAgent_RetrieveDataUnitByExternalUniqueID (
2810                                                               KMSClientProfile * const i_pProfile,
2811                                                               const unsigned char* const i_pExternalUniqueID,
2812                                                               int i_iExternalUniqueIDLen,
2813                                                               utf8cstr const i_pExternalTag,
2814                                                               utf8cstr const i_pDescription,
2815                                                               KMSAgent_DataUnit * const o_pDataUnit)
2816 {
2817     bool bSuccess;
2818 #if defined(METAWARE)
2819     ECPT_TRACE_ENTRY *trace = NULL;
2820     ECPT_TRACE(trace, KMSAgent_RetrieveDataUnitByExternalUniqueID);
2821 #endif
2822 
2823     // required parms
2824     if (!i_pProfile)
2825     {
2826         Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_BY_EXTERNAL_UNIQUE_ID_INVALID_PARAMETERS,
2827                 NULL,
2828                 NULL,
2829                 "Profile arg");
2830         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
2831     }
2832     if (!i_pExternalUniqueID)
2833     {
2834         Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_BY_EXTERNAL_UNIQUE_ID_INVALID_PARAMETERS,
2835                 NULL,
2836                 NULL,
2837                 "ExternalUniqueID arg");
2838         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
2839     }
2840     if (!o_pDataUnit)
2841     {
2842         Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_BY_EXTERNAL_UNIQUE_ID_INVALID_PARAMETERS,
2843                 NULL,
2844                 NULL,
2845                 "DataUnit arg");
2846         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
2847     }
2848 
2849     if (!KMSClient_ProfileLoaded(i_pProfile))
2850     {
2851         RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
2852     }
2853 
2854     CAutoMutex oAutoMutex((K_MUTEX_HANDLE) i_pProfile->m_pLock);
2855 
2856     // validate input parms
2857 
2858     if (i_iExternalUniqueIDLen <= 0 ||
2859         i_iExternalUniqueIDLen > KMS_MAX_EXTERNAL_UNIQUE_ID_SIZE)
2860     {
2861         Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_BY_EXTERNAL_UNIQUE_ID_INVALID_PARAMETERS,
2862                 NULL,
2863                 NULL,
2864                 "ExternalUniqueIDLen arg");
2865         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
2866     }
2867 
2868     if (i_pExternalTag && strlen(i_pExternalTag) > KMS_MAX_EXTERNAL_TAG)
2869     {
2870         Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_BY_EXTERNAL_UNIQUE_ID_INVALID_PARAMETERS,
2871                 NULL,
2872                 NULL,
2873                 "ExternalTag arg");
2874         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
2875     }
2876 
2877     if (i_pDescription &&
2878         strlen(i_pDescription) > KMS_MAX_DESCRIPTION)
2879     {
2880         Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_BY_EXTERNAL_UNIQUE_ID_INVALID_PARAMETERS,
2881                 NULL,
2882                 NULL,
2883                 "Description arg");
2884         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
2885     }
2886 
2887     // prepare args to soap transaction
2888 
2889     struct soap *pstSoap = (struct soap *) i_pProfile->m_pvSoap;
2890     struct KMS_Agent::KMS_Agent__RetrieveDataUnitByExternalUniqueIDResponse oResponse;
2891 
2892     char * pExternalUniqueID = NULL;
2893     pExternalUniqueID = ConvertBinaryDataFromRequest(pstSoap,
2894             i_pExternalUniqueID,
2895             i_iExternalUniqueIDLen);
2896     if (pExternalUniqueID == NULL)
2897     {
2898         soap_destroy(pstSoap);
2899         soap_end(pstSoap);
2900         // no memory dont' log
2901         RETURN(KMS_AGENT_STATUS_NO_MEMORY);
2902     }
2903 
2904     char * pExternalTag = NULL;
2905     if (i_pExternalTag)
2906     {
2907         pExternalTag = ConvertUTF8StringFromRequest(pstSoap,
2908                 i_pExternalTag,
2909                 KMS_MAX_EXTERNAL_TAG + 1);
2910         if (pExternalTag == NULL)
2911         {
2912             soap_destroy(pstSoap);
2913             soap_end(pstSoap);
2914             // no memory dont' log
2915             RETURN(KMS_AGENT_STATUS_NO_MEMORY);
2916         }
2917     }
2918 
2919     char * pDescription = NULL;
2920     if (i_pDescription)
2921     {
2922         pDescription = ConvertUTF8StringFromRequest(pstSoap,
2923                 i_pDescription,
2924                 KMS_MAX_DESCRIPTION + 1);
2925         if (pDescription == NULL)
2926         {
2927             soap_destroy(pstSoap);
2928             soap_end(pstSoap);
2929             // no memory dont' log
2930             RETURN(KMS_AGENT_STATUS_NO_MEMORY);
2931         }
2932     }
2933 
2934     CAgentLoadBalancer *pLoadBalancer =
2935             (CAgentLoadBalancer *) i_pProfile->m_pAgentLoadBalancer;
2936     int iIndex = pLoadBalancer->Balance();
2937 
2938     if ( iIndex >= 0 )
2939     {
2940         do
2941         {
2942             const char* sURL = pLoadBalancer->GetHTTPSURL(
2943                     iIndex,
2944                     i_pProfile->m_iPortForAgentService);
2945 
2946             strncpy(i_pProfile->m_sURL, sURL, sizeof(i_pProfile->m_sURL));
2947 
2948             i_pProfile->m_sURL[sizeof(i_pProfile->m_sURL)-1] = '\0';
2949 
2950             bSuccess = KMS_Agent::
2951                     soap_call_KMS_Agent__RetrieveDataUnitByExternalUniqueID(
2952                     pstSoap,
2953                     sURL,
2954                     NULL,
2955                     pExternalUniqueID,
2956                     i_pExternalTag ? pExternalTag : (char *) "",
2957                     i_pDescription ? pDescription : (char *) "",
2958                     oResponse) == SOAP_OK;
2959 
2960             if (!bSuccess)
2961             {
2962                 iIndex = pLoadBalancer->FailOver(iIndex, pstSoap);
2963 
2964                 char sKmaAddress[g_iMAX_PEER_NETWORK_ADDRESS_LENGTH];
2965                 char sSoapFaultMsg[g_iMAX_SOAP_FAULT_MESSAGE_LENGTH];
2966 
2967                 GetPeerNetworkAddress(sKmaAddress, pstSoap);
2968                 GetSoapFault(sSoapFaultMsg, pstSoap);
2969 
2970                 LogError(i_pProfile,
2971                         AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_BY_EXTERNAL_UNIQUE_ID_SOAP_ERROR,
2972                         NULL,
2973                         sKmaAddress,
2974                         sSoapFaultMsg);
2975             }
2976             else
2977             {
2978                 pLoadBalancer->UpdateResponseStatus(iIndex);
2979             }
2980         }
2981         while (iIndex >= 0 && (!bSuccess));
2982     }
2983     else
2984     {
2985         bSuccess = false;
2986     }
2987 
2988     if (bSuccess)
2989     {
2990         ConvertUTF8HexStringToBinary(
2991                 oResponse.DataUnit.DataUnitID, o_pDataUnit->m_acDataUnitID);
2992 
2993         o_pDataUnit->m_iExternalUniqueIDLength = ConvertUTF8HexStringToBinary(
2994                 oResponse.DataUnit.ExternalUniqueID,
2995                 o_pDataUnit->m_acExternalUniqueID);
2996 
2997         if (strlen(oResponse.DataUnit.ExternalTag) > KMS_MAX_EXTERNAL_TAG)
2998         {
2999             LogError(i_pProfile,
3000                     AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_BY_EXTERNAL_UNIQUE_ID_RESPONSE_INVALID_EXTERNAL_TAG_LENGTH,
3001                     NULL,
3002                     NULL,
3003                     NULL);
3004             bSuccess = false;
3005         }
3006         else
3007         {
3008             strncpy(o_pDataUnit->m_acExternalTag,
3009                     oResponse.DataUnit.ExternalTag,
3010                     sizeof(o_pDataUnit->m_acExternalTag));
3011             o_pDataUnit->m_acExternalTag[sizeof(o_pDataUnit->m_acExternalTag)-1] = '\0';
3012         }
3013 
3014         if (strlen(oResponse.DataUnit.Description) > KMS_MAX_DESCRIPTION)
3015         {
3016             LogError(i_pProfile,
3017                     AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_BY_EXTERNAL_UNIQUE_ID_RESPONSE_INVALID_DESCRIPTION_LENGTH,
3018                     NULL,
3019                     NULL,
3020                     NULL);
3021             bSuccess = false;
3022         }
3023         else
3024         {
3025             strcpy(o_pDataUnit->m_acDescription,
3026                     oResponse.DataUnit.Description);
3027         }
3028 
3029         o_pDataUnit->m_iDataUnitState =
3030                 (KMS_AGENT_DATA_UNIT_STATE) oResponse.DataUnit.DataUnitState;
3031 
3032         if (bSuccess)
3033         {
3034             // RetrieveDataUnitByExternalUniqueID may create a DU so add data unit ID
3035             // and the KMA IP address to the DU cache
3036             CDataUnitCache* pDataUnitCache = (CDataUnitCache*) i_pProfile->m_pDataUnitCache;
3037 
3038             if (i_pProfile->m_iClusterDiscoveryFrequency != 0) // load balancing enabled
3039             {
3040                 bSuccess = pDataUnitCache->Insert(
3041                         o_pDataUnit->m_acDataUnitID,
3042                         KMS_DATA_UNIT_ID_SIZE,
3043                         NULL, 0,
3044                         pLoadBalancer->GetApplianceNetworkAddress(iIndex));
3045             }
3046         }
3047     }
3048 
3049     // free allocated memory for output if error condition
3050     // Clean up SOAP
3051 
3052     soap_destroy(pstSoap);
3053     soap_end(pstSoap);
3054 
3055     if (bSuccess)
3056     {
3057         RETURN(KMS_AGENT_STATUS_OK);
3058     }
3059 
3060     RETURN(KMSAgent_GetLastStatusCode(i_pProfile, iIndex));
3061 }
3062 
3063 extern "C"
KMSAgent_RetrieveDataUnitKeys(KMSClientProfile * const i_pProfile,const KMSAgent_DataUnit * const i_pDataUnit,int i_iPageSize,int i_iPageOffset,int * const o_piKeysRemaining,const unsigned char * const i_pKeyID,KMSAgent_ArrayOfKeys ** const o_ppKeys)3064 KMS_AGENT_STATUS KMSAgent_RetrieveDataUnitKeys (
3065                                                 KMSClientProfile * const i_pProfile,
3066                                                 const KMSAgent_DataUnit * const i_pDataUnit,
3067                                                 int i_iPageSize,
3068                                                 int i_iPageOffset,
3069                                                 int* const o_piKeysRemaining,
3070                                                 const unsigned char * const i_pKeyID,
3071                                                 KMSAgent_ArrayOfKeys* * const o_ppKeys)
3072 {
3073     bool bSuccess;
3074 #if defined(METAWARE)
3075     ECPT_TRACE_ENTRY *trace = NULL;
3076     ECPT_TRACE(trace, KMSAgent_RetrieveDataUnitKeys);
3077 #endif
3078 
3079     if (!i_pProfile)
3080     {
3081         Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_PARAMETERS,
3082                 NULL,
3083                 NULL,
3084                 "Profile arg");
3085         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
3086     }
3087     if (!i_pDataUnit)
3088     {
3089         Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_PARAMETERS,
3090                 NULL,
3091                 NULL,
3092                 "DataUnit arg");
3093         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
3094     }
3095     if (!o_piKeysRemaining)
3096     {
3097         Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_PARAMETERS,
3098                 NULL,
3099                 NULL,
3100                 "KeysRemaining arg");
3101         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
3102     }
3103     if (!o_ppKeys)
3104     {
3105         Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_PARAMETERS,
3106                 NULL,
3107                 NULL,
3108                 "Keys arg");
3109         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
3110     }
3111     if (i_pKeyID && i_iPageOffset != 0)
3112     {
3113         Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_PARAMETERS,
3114                 NULL,
3115                 NULL,
3116                 "KeyID and PageOffset are mutually exclusive");
3117         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
3118     }
3119 
3120     if (!KMSClient_ProfileLoaded(i_pProfile))
3121     {
3122         RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
3123     }
3124 
3125     CAutoMutex oAutoMutex((K_MUTEX_HANDLE) i_pProfile->m_pLock);
3126 
3127     // validate input parms
3128 
3129     if (i_iPageSize <= 0 || i_iPageSize > KMS_MAX_PAGE_SIZE)
3130     {
3131         Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_PARAMETERS,
3132                 NULL,
3133                 NULL,
3134                 "PageSize arg");
3135         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
3136     }
3137 
3138     if (i_iPageOffset < 0)
3139     {
3140         Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_PARAMETERS,
3141                 NULL,
3142                 NULL,
3143                 "PageOffset arg");
3144         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
3145     }
3146 
3147     // prepare args to soap transaction
3148 
3149     struct KMS_Agent::KMS_Agent__DataUnit stDataUnit = {"", "", "", "",
3150         (KMS_Agent::KMS_Agent__DataUnitState) 0};
3151 
3152     struct soap *pstSoap = (struct soap *) i_pProfile->m_pvSoap;
3153     struct KMS_Agent::KMS_Agent__RetrieveDataUnitKeysResponse oResponse;
3154 
3155     if (!CopyDataUnitFromRequest(pstSoap,
3156         &stDataUnit,
3157         i_pDataUnit))
3158     {
3159         soap_destroy(pstSoap);
3160         soap_end(pstSoap);
3161         // no memory dont' log
3162         RETURN(KMS_AGENT_STATUS_NO_MEMORY);
3163     }
3164 
3165     char * pKeyID = NULL;
3166     if (i_pKeyID)
3167     {
3168         pKeyID = ConvertBinaryDataFromRequest(pstSoap,
3169                 i_pKeyID,
3170                 KMS_KEY_ID_SIZE);
3171         if (pKeyID == NULL)
3172         {
3173             soap_destroy(pstSoap);
3174             soap_end(pstSoap);
3175             // no memory dont' log
3176             RETURN(KMS_AGENT_STATUS_NO_MEMORY);
3177         }
3178     }
3179 
3180     UTF8_KEYID acKWKID;
3181     char sKmaAddress[g_iMAX_PEER_NETWORK_ADDRESS_LENGTH];
3182     char sSoapFaultMsg[g_iMAX_SOAP_FAULT_MESSAGE_LENGTH];
3183     bool bClientAESKeyWrapSetupError = false;
3184 
3185     CAgentLoadBalancer *pLoadBalancer =
3186             (CAgentLoadBalancer *) i_pProfile->m_pAgentLoadBalancer;
3187 
3188     int iIndex = pLoadBalancer->BalanceByDataUnitID(i_pDataUnit->m_acDataUnitID,
3189             KMS_DATA_UNIT_ID_SIZE);
3190 
3191     if (iIndex >= 0)
3192     {
3193         do
3194         {
3195             bSuccess = true;
3196 
3197             const char* sURL = pLoadBalancer->GetHTTPSURL(
3198                     iIndex,
3199                     i_pProfile->m_iPortForAgentService);
3200 
3201             strncpy(i_pProfile->m_sURL, sURL, sizeof(i_pProfile->m_sURL));
3202 
3203             i_pProfile->m_sURL[sizeof(i_pProfile->m_sURL)-1] = 0;
3204 
3205             Long64 lKMAID = pLoadBalancer->GetKMAID(iIndex);
3206 
3207             if (bSuccess && pLoadBalancer->AESKeyWrapSupported(iIndex))
3208             {
3209                 // if this fails we want to utilize normal failover logic, GetKWKID
3210                 // logs error
3211                 bSuccess = pLoadBalancer->GetKWKID(iIndex, lKMAID, pstSoap,
3212 					acKWKID, &bClientAESKeyWrapSetupError) ? true : false;
3213                 if (bSuccess)
3214                 {
3215                     bSuccess = KMS_Agent::soap_call_KMS_Agent__RetrieveDataUnitKeys2(
3216                             pstSoap,
3217                             sURL,
3218                             NULL,
3219                             stDataUnit,
3220                             i_iPageSize,
3221                             i_iPageOffset,
3222                             pKeyID,
3223                             acKWKID,
3224                             *(reinterpret_cast<struct KMS_Agent::KMS_Agent__RetrieveDataUnitKeys2Response *>(&oResponse))) == SOAP_OK;
3225                 }
3226             }
3227             else if (bSuccess)  // No AES Key Wrap
3228             {
3229                     bSuccess = KMS_Agent::soap_call_KMS_Agent__RetrieveDataUnitKeys(
3230                             pstSoap,
3231                             sURL,
3232                             NULL,
3233                             stDataUnit,
3234                             i_iPageSize,
3235                             i_iPageOffset,
3236                             pKeyID,
3237                             oResponse) == SOAP_OK;
3238             }
3239 
3240             // don'f failover for Client side AES Key Wrap setup problems
3241             if (!bSuccess && !bClientAESKeyWrapSetupError)
3242             {
3243                 iIndex = pLoadBalancer->FailOver(iIndex, pstSoap);
3244 
3245                 GetPeerNetworkAddress(sKmaAddress, pstSoap);
3246                 GetSoapFault(sSoapFaultMsg, pstSoap);
3247 
3248                 LogError(i_pProfile,
3249                         AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_SOAP_ERROR,
3250                         NULL,
3251                         sKmaAddress,
3252                         sSoapFaultMsg);
3253             }
3254             if (bSuccess)
3255             {
3256                 pLoadBalancer->UpdateResponseStatus(iIndex);
3257             }
3258         }
3259         while (iIndex >= 0 && (!bSuccess) && (!bClientAESKeyWrapSetupError));
3260     }
3261     else
3262     {
3263         bSuccess = false;
3264     }
3265 
3266     // validate response
3267 
3268     if (bSuccess && oResponse.KeysRemaining < 0)
3269     {
3270         LogError(i_pProfile,
3271                 AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_KEYS_REMAINING_RESPONSE,
3272                 NULL,
3273                 NULL,
3274                 NULL);
3275         bSuccess = false;
3276     }
3277 
3278     if (bSuccess &&
3279         (oResponse.Keys.__size < 0 ||
3280         oResponse.Keys.__size > i_iPageSize))
3281     {
3282         LogError(i_pProfile,
3283                 AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_KEYS_SIZE_RESPONSE,
3284                 NULL,
3285                 NULL,
3286                 NULL);
3287         bSuccess = false;
3288     }
3289 
3290     if ( bSuccess && pLoadBalancer->AESKeyWrapSupported(iIndex))
3291     {
3292         // verify KWK ID matches what was registered
3293     }
3294 
3295     if (bSuccess)
3296     {
3297         *o_ppKeys = CopyDataUnitKeysResponse(i_pProfile, &iIndex, &oResponse.Keys);
3298 
3299         if (*o_ppKeys == NULL)
3300         {
3301             // CopyDataUnitKeysResponse logs errors
3302             bSuccess = false;
3303         }
3304         *o_piKeysRemaining = (int) oResponse.KeysRemaining;
3305     }
3306 
3307     // free allocated memory for output if error condition
3308     // Clean up SOAP
3309 
3310     soap_destroy(pstSoap);
3311     soap_end(pstSoap);
3312 
3313     if (bSuccess)
3314     {
3315         RETURN(KMS_AGENT_STATUS_OK);
3316     }
3317 
3318     RETURN(KMSAgent_GetLastStatusCode(i_pProfile,
3319             bClientAESKeyWrapSetupError ?
3320                 CAgentLoadBalancer::AES_KEY_WRAP_SETUP_ERROR : iIndex));
3321 }
3322 
3323 extern "C"
KMSAgent_RetrieveProtectAndProcessKey(KMSClientProfile * const i_pProfile,const KMSAgent_DataUnit * const i_pDataUnit,utf8cstr const i_pKeyGroupID,KMSAgent_Key * const o_pKey)3324 KMS_AGENT_STATUS KMSAgent_RetrieveProtectAndProcessKey (
3325                                                         KMSClientProfile * const i_pProfile,
3326                                                         const KMSAgent_DataUnit * const i_pDataUnit,
3327                                                         utf8cstr const i_pKeyGroupID,
3328                                                         KMSAgent_Key * const o_pKey)
3329 {
3330     bool bSuccess;
3331 #if defined(METAWARE)
3332     ECPT_TRACE_ENTRY *trace = NULL;
3333     ECPT_TRACE(trace, KMSAgent_RetrieveProtectAndProcessKey);
3334 #endif
3335 
3336     if (!i_pProfile || !i_pDataUnit || !o_pKey)
3337     {
3338         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
3339     }
3340 
3341     if (!i_pProfile)
3342     {
3343         Log(AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_INVALID_PARAMETERS,
3344                 NULL,
3345                 NULL,
3346                 "Profile arg");
3347         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
3348     }
3349     if (!i_pDataUnit)
3350     {
3351         Log(AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_INVALID_PARAMETERS,
3352                 NULL,
3353                 NULL,
3354                 "DataUnit arg");
3355         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
3356     }
3357     if (!o_pKey)
3358     {
3359         Log(AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_INVALID_PARAMETERS,
3360                 NULL,
3361                 NULL,
3362                 "Key arg");
3363         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
3364     }
3365 
3366     if (i_pKeyGroupID &&
3367         strlen(i_pKeyGroupID) > KMS_MAX_KEY_GROUP_ID_SIZE)
3368     {
3369         Log(AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_INVALID_PARAMETERS,
3370                 NULL,
3371                 NULL,
3372                 "GroupID arg");
3373         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
3374     }
3375 
3376     if (!KMSClient_ProfileLoaded(i_pProfile))
3377     {
3378         RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
3379     }
3380 
3381     CAutoMutex oAutoMutex((K_MUTEX_HANDLE) i_pProfile->m_pLock);
3382 
3383     struct KMS_Agent::KMS_Agent__DataUnit stDataUnit ={"", "", "", "",
3384         (KMS_Agent::KMS_Agent__DataUnitState) 0};
3385 
3386     struct soap *pstSoap = (struct soap *) i_pProfile->m_pvSoap;
3387     struct KMS_Agent::KMS_Agent__RetrieveProtectAndProcessKeyResponse oResponse;
3388 
3389     if (i_pDataUnit != NULL)
3390     {
3391         if (!CopyDataUnitFromRequest(pstSoap,
3392             &stDataUnit,
3393             i_pDataUnit))
3394         {
3395             soap_destroy(pstSoap);
3396             soap_end(pstSoap);
3397             // no memory dont' log
3398             RETURN(KMS_AGENT_STATUS_NO_MEMORY);
3399         }
3400     }
3401 
3402     char * pKeyGroupID = NULL;
3403     if (i_pKeyGroupID)
3404     {
3405         pKeyGroupID = ConvertUTF8StringFromRequest(pstSoap,
3406                 i_pKeyGroupID,
3407                 KMS_MAX_KEY_GROUP_ID_SIZE + 1);
3408         if (pKeyGroupID == NULL)
3409         {
3410             soap_destroy(pstSoap);
3411             soap_end(pstSoap);
3412             // no memory dont' log
3413             RETURN(KMS_AGENT_STATUS_NO_MEMORY);
3414         }
3415     }
3416 
3417     char sKmaAddress[g_iMAX_PEER_NETWORK_ADDRESS_LENGTH];
3418     char sSoapFaultMsg[g_iMAX_SOAP_FAULT_MESSAGE_LENGTH];
3419     bool bClientAESKeyWrapSetupError = false;
3420     UTF8_KEYID acKWKID;
3421 
3422     CAgentLoadBalancer *pLoadBalancer = (CAgentLoadBalancer *) i_pProfile->m_pAgentLoadBalancer;
3423     int iIndex = pLoadBalancer->BalanceByDataUnitID(i_pDataUnit->m_acDataUnitID,
3424                                                     KMS_DATA_UNIT_ID_SIZE);
3425 
3426     if (iIndex >= 0)
3427     {
3428         do
3429         {
3430             bSuccess = true;
3431             const char* sURL = pLoadBalancer->GetHTTPSURL(
3432                     iIndex,
3433                     i_pProfile->m_iPortForAgentService);
3434 
3435             strncpy(i_pProfile->m_sURL, sURL, sizeof(i_pProfile->m_sURL));
3436 
3437             i_pProfile->m_sURL[sizeof(i_pProfile->m_sURL)-1] = '\0';
3438 
3439             Long64 lKMAID = pLoadBalancer->GetKMAID(iIndex);
3440 
3441             if (bSuccess && pLoadBalancer->AESKeyWrapSupported(iIndex))
3442             {
3443                 // if this fails we want to utilize normal failover logic, GetKWKID
3444                 // logs error
3445                 bSuccess = pLoadBalancer->GetKWKID(iIndex, lKMAID, pstSoap,
3446                                             acKWKID, &bClientAESKeyWrapSetupError)
3447 											? true : false;
3448                 if (bSuccess)
3449                 {
3450                     bSuccess = KMS_Agent::soap_call_KMS_Agent__RetrieveProtectAndProcessKey2(
3451                             pstSoap,
3452                             sURL,
3453                             NULL,
3454                             stDataUnit,
3455                             i_pKeyGroupID ? i_pKeyGroupID : (char *) "",
3456                             acKWKID,
3457                             *(reinterpret_cast<struct KMS_Agent::KMS_Agent__RetrieveProtectAndProcessKey2Response *>(&oResponse))) == SOAP_OK;
3458                 }
3459             }
3460             else if (bSuccess)  // No AES Key Wrap
3461             {
3462                     bSuccess = KMS_Agent::soap_call_KMS_Agent__RetrieveProtectAndProcessKey(
3463                             pstSoap,
3464                             sURL,
3465                             NULL,
3466                             stDataUnit,
3467                             i_pKeyGroupID ? i_pKeyGroupID : (char *) "",
3468                             oResponse) == SOAP_OK;
3469             }
3470 
3471             // don'f failover for Client side AES Key Wrap setup problems
3472             if (!bSuccess && !bClientAESKeyWrapSetupError)
3473             {
3474                 iIndex = pLoadBalancer->FailOver(iIndex, pstSoap);
3475 
3476                 GetPeerNetworkAddress(sKmaAddress, pstSoap);
3477                 GetSoapFault(sSoapFaultMsg, pstSoap);
3478 
3479                 LogError(i_pProfile,
3480                         AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_SOAP_ERROR,
3481                         NULL,
3482                         sKmaAddress,
3483                         sSoapFaultMsg);
3484             }
3485             else
3486             {
3487                 pLoadBalancer->UpdateResponseStatus(iIndex);
3488             }
3489         }
3490         while (iIndex >= 0 && (!bSuccess) && (!bClientAESKeyWrapSetupError));
3491     }
3492     else
3493     {
3494         bSuccess = false;
3495     }
3496 
3497     if (bSuccess)
3498     {
3499         if (KMS_KEY_ID_SIZE != ConvertUTF8HexStringToBinary(
3500             oResponse.Key.KeyID, NULL))
3501         {
3502             GetPeerNetworkAddress(sKmaAddress, pstSoap);
3503             LogError(i_pProfile,
3504                     AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_INVALID_KEYID_RESPONSE,
3505                     NULL,
3506                     sKmaAddress,
3507                     NULL);
3508             bSuccess = false;
3509         }
3510     }
3511 
3512     if (bSuccess)
3513     {
3514         ConvertUTF8HexStringToBinary(
3515                 oResponse.Key.KeyID, o_pKey->m_acKeyID);
3516 
3517         if ((KMS_AGENT_KEY_STATE) oResponse.Key.KeyState < KMS_KEY_STATE_ACTIVE_PROTECT_AND_PROCESS ||
3518             (KMS_AGENT_KEY_STATE) oResponse.Key.KeyState > KMS_KEY_STATE_COMPROMISED)
3519         {
3520             GetPeerNetworkAddress(sKmaAddress, pstSoap);
3521             LogError(i_pProfile,
3522                     AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_INVALID_KEY_STATE_RESPONSE,
3523                     NULL,
3524                     sKmaAddress,
3525                     NULL);
3526             bSuccess = false;
3527         }
3528 
3529         o_pKey->m_iKeyState = (KMS_AGENT_KEY_STATE) oResponse.Key.KeyState;
3530 
3531         if ((KMS_KEY_TYPE) oResponse.Key.KeyType != KMS_KEY_TYPE_AES_256)
3532         {
3533             GetPeerNetworkAddress(sKmaAddress, pstSoap);
3534             LogError(i_pProfile,
3535                     AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_INVALID_KEY_TYPE_RESPONSE,
3536                     NULL,
3537                     sKmaAddress,
3538                     NULL);
3539             bSuccess = false;
3540         }
3541 
3542         o_pKey->m_iKeyType = (KMS_KEY_TYPE) oResponse.Key.KeyType;
3543 
3544         if (strlen(oResponse.Key.KeyGroupID) > KMS_MAX_KEY_GROUP_ID_SIZE)
3545         {
3546             GetPeerNetworkAddress(sKmaAddress, pstSoap);
3547             LogError(i_pProfile,
3548                     AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_INVALID_KEY_GROUP_ID_LENGTH_RESPONSE,
3549                     NULL,
3550                     sKmaAddress,
3551                     NULL);
3552             bSuccess = false;
3553         }
3554         else
3555         {
3556             strncpy(o_pKey->m_acKeyGroupID,
3557                     oResponse.Key.KeyGroupID,
3558                     sizeof(o_pKey->m_acKeyGroupID));
3559             o_pKey->m_acKeyGroupID[sizeof(o_pKey->m_acKeyGroupID)-1] = '\0';
3560         }
3561 
3562         if ( bSuccess && pLoadBalancer->AESKeyWrapSupported(iIndex))
3563         {
3564             // verify KWK ID matches what was registered
3565             if (oResponse.Key.Key.__size != KMS_MAX_WRAPPED_KEY_SIZE)
3566             {
3567                 GetPeerNetworkAddress(sKmaAddress, pstSoap);
3568                 LogError(i_pProfile,
3569                         AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_INVALID_WRAPPED_KEY_LENGTH_RESPONSE,
3570                         NULL,
3571                         sKmaAddress,
3572                         NULL);
3573                 bSuccess = false;
3574             }
3575             else
3576             {
3577                 if (pLoadBalancer->AESKeyUnwrap(&iIndex, oResponse.Key.Key.__ptr,
3578                     o_pKey->m_acKey) == false)
3579                 {
3580                     GetPeerNetworkAddress(sKmaAddress, pstSoap);
3581                     LogError(i_pProfile,
3582                             AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_AESKEYUNWRAP_ERROR,
3583                             NULL,
3584                             sKmaAddress,
3585                             NULL);
3586 
3587                     bSuccess = false;
3588                 }
3589             }
3590         }
3591         else if (bSuccess) // non-AES key wrap
3592         {
3593             if (oResponse.Key.Key.__size != KMS_MAX_KEY_SIZE)
3594             {
3595                 GetPeerNetworkAddress(sKmaAddress, pstSoap);
3596                 LogError(i_pProfile,
3597                         AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_INVALID_KEY_LENGTH_RESPONSE,
3598                         NULL,
3599                         sKmaAddress,
3600                         NULL);
3601                 bSuccess = false;
3602             }
3603             else
3604             {
3605                 memcpy(o_pKey->m_acKey,
3606                         oResponse.Key.Key.__ptr,
3607                         KMS_MAX_KEY_SIZE);
3608             }
3609         }
3610 
3611         if (bSuccess)
3612         {
3613             o_pKey->m_iKeyLength = KMS_MAX_KEY_SIZE;
3614 
3615             if (KMSAgentKeyCallout(o_pKey->m_acKey) != 0)
3616             {
3617                 LogError(i_pProfile,
3618                         AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_KEY_CALLOUT_ERROR,
3619                         NULL,
3620                         NULL,
3621                         NULL);
3622                 bSuccess = false;
3623             }
3624         }
3625     }
3626 
3627     if (bSuccess)
3628     {
3629         // add Key ID and the creating KMA IP address to the DU cache
3630         CDataUnitCache* pDataUnitCache = (CDataUnitCache*) i_pProfile->m_pDataUnitCache;
3631 
3632         if (i_pProfile->m_iClusterDiscoveryFrequency != 0) // load balancing enabled
3633         {
3634             bSuccess = pDataUnitCache->Insert(
3635                     NULL,
3636                     0,
3637                     o_pKey->m_acKeyID,
3638                     KMS_KEY_ID_SIZE,
3639                     pLoadBalancer->GetApplianceNetworkAddress(iIndex));
3640         }
3641     }
3642 
3643     // free allocated memory for output if error condition
3644     // Clean up SOAP
3645 
3646     soap_destroy(pstSoap);
3647     soap_end(pstSoap);
3648 
3649     if (bSuccess)
3650     {
3651         RETURN(KMS_AGENT_STATUS_OK);
3652     }
3653 
3654     RETURN(KMSAgent_GetLastStatusCode(i_pProfile,
3655             bClientAESKeyWrapSetupError ?
3656                 CAgentLoadBalancer::AES_KEY_WRAP_SETUP_ERROR : iIndex));
3657 }
3658 
3659 extern "C"
KMSAgent_FreeArrayOfKeys(KMSAgent_ArrayOfKeys * i_pArrayOfKeys)3660 void KMSAgent_FreeArrayOfKeys (
3661                                KMSAgent_ArrayOfKeys* i_pArrayOfKeys)
3662 {
3663 #if defined(METAWARE)
3664     ECPT_TRACE_ENTRY *trace = NULL;
3665     ECPT_TRACE(trace, KMSAgent_FreeArrayOfKeys);
3666 #endif
3667     if (!i_pArrayOfKeys)
3668     {
3669         return;
3670     }
3671 
3672     // free memory for all information groups
3673     if (i_pArrayOfKeys->m_pKeys)
3674     {
3675         free(i_pArrayOfKeys->m_pKeys);
3676     }
3677 
3678     free(i_pArrayOfKeys);
3679 }
3680 
3681 /*---------------------------------------------------------------------------
3682  * Function: KMSAgent_CreateAuditLog
3683  *
3684  *--------------------------------------------------------------------------*/
3685 extern "C"
KMSAgent_CreateAuditLog(KMSClientProfile * i_pProfile,enum KMS_AUDIT_LOG_RETENTION i_iRetention,enum KMS_AUDIT_LOG_CONDITION i_iCondition,int i_bIssueAlert,utf8cstr i_pMessage)3686 KMS_AGENT_STATUS KMSAgent_CreateAuditLog (
3687                                           KMSClientProfile* i_pProfile,
3688                                           enum KMS_AUDIT_LOG_RETENTION i_iRetention,
3689                                           enum KMS_AUDIT_LOG_CONDITION i_iCondition,
3690                                           int i_bIssueAlert,
3691                                           utf8cstr i_pMessage)
3692 {
3693     bool bSuccess = true;
3694 #ifdef DEBUG_TIMING
3695     ECPT_TRACE_ENTRY *trace = NULL;
3696     ECPT_TRACE(trace, KMSAgent_CreateAuditLog);
3697 #endif
3698 
3699     //   START_STACK_CHECK;
3700 
3701     if (!i_pProfile)
3702     {
3703         Log(AUDIT_CLIENT_AGENT_CREATED_AUDIT_LOG_INVALID_PARAMETERS,
3704                 NULL,
3705                 NULL,
3706                 "Profile arg");
3707 
3708         //        END_STACK_CHECK;
3709 
3710         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
3711     }
3712 
3713     // check arguments
3714     if (i_iRetention > KMS_AUDIT_LOG_SHORT_TERM_RETENTION)
3715     {
3716         Log(AUDIT_CLIENT_AGENT_CREATE_AUDIT_LOG_INVALID_PARAMETERS,
3717                 NULL,
3718                 NULL,
3719                 "Retention arg");
3720         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
3721     }
3722 
3723     if (i_iCondition > KMS_AUDIT_LOG_WARNING_CONDITION)
3724     {
3725         Log(AUDIT_CLIENT_AGENT_CREATE_AUDIT_LOG_INVALID_PARAMETERS,
3726                 NULL,
3727                 NULL,
3728                 "Condition arg");
3729         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
3730     }
3731 
3732     if (!i_pMessage || (strlen(i_pMessage) <= 0))
3733     {
3734         Log(AUDIT_CLIENT_AGENT_CREATE_AUDIT_LOG_INVALID_PARAMETERS,
3735                 NULL,
3736                 NULL,
3737                 "Message arg");
3738         //       END_STACK_CHECK;
3739         RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
3740     }
3741     if (!KMSClient_ProfileLoaded(i_pProfile))
3742     {
3743         //        END_STACK_CHECK;
3744         RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
3745     }
3746 
3747     CAutoMutex oAutoMutex((K_MUTEX_HANDLE) i_pProfile->m_pLock);
3748 
3749     struct soap* pstSoap = (struct soap*) i_pProfile->m_pvSoap;
3750 
3751     // Create Audit Log
3752 
3753     KMS_Agent::KMS_Agent__CreateAuditLogResponse oResponse;
3754 
3755     CAgentLoadBalancer *pLoadBalancer =
3756             (CAgentLoadBalancer *) i_pProfile->m_pAgentLoadBalancer;
3757 
3758     int iIndex = pLoadBalancer->Balance();
3759     if (iIndex >= 0)
3760     {
3761         do
3762         {
3763             const char* sURL = pLoadBalancer->
3764                     GetHTTPSURL(iIndex, i_pProfile->m_iPortForAgentService);
3765             strncpy(i_pProfile->m_sURL, sURL, sizeof(i_pProfile->m_sURL));
3766             i_pProfile->m_sURL[sizeof(i_pProfile->m_sURL)-1] = '\0';
3767 
3768             bSuccess = KMS_Agent::soap_call_KMS_Agent__CreateAuditLog(
3769                     pstSoap,
3770                     sURL,
3771                     NULL,
3772                     (enum KMS_Agent::KMS_Agent__AuditLogRetention)i_iRetention,
3773                     (enum KMS_Agent::KMS_Agent__AuditLogCondition)i_iCondition,
3774                     i_bIssueAlert ? true : false,
3775                     i_pMessage,
3776                     oResponse) == SOAP_OK;
3777 
3778 
3779             if (!bSuccess)
3780             {
3781                 char sSoapFaultMsg[g_iMAX_SOAP_FAULT_MESSAGE_LENGTH];
3782                 char sKmaAddress[g_iMAX_PEER_NETWORK_ADDRESS_LENGTH];
3783 
3784                 GetSoapFault(sSoapFaultMsg, pstSoap);
3785                 GetPeerNetworkAddress(sKmaAddress, pstSoap);
3786 
3787                 iIndex = pLoadBalancer->FailOver(iIndex, pstSoap);
3788 
3789                 LogError(i_pProfile, AUDIT_CLIENT_AGENT_CREATE_AUDIT_LOG_SOAP_ERROR,
3790                         NULL,
3791                         sKmaAddress,
3792                         sSoapFaultMsg);
3793             }
3794             else
3795             {
3796                 pLoadBalancer->UpdateResponseStatus(iIndex);
3797             }
3798         }
3799         while (iIndex >= 0 && (!bSuccess));
3800     }
3801     else
3802     {
3803         bSuccess = false;
3804     }
3805 
3806     // free allocated memory for output if error condition
3807     // Clean up SOAP
3808 
3809     soap_destroy(pstSoap);
3810     soap_end(pstSoap);
3811 
3812     if (bSuccess)
3813     {
3814         //      END_STACK_CHECK;
3815         RETURN(KMS_AGENT_STATUS_OK);
3816     }
3817 
3818     //   END_STACK_CHECK;
3819     RETURN(KMSAgent_GetLastStatusCode(i_pProfile, iIndex));
3820 }
3821 
3822 #ifdef KMSUSERPKCS12
3823 /*
3824  * This function allows the user to change the PIN on the PKCS12
3825  * file that holds the clients private key and cert.
3826  */
3827 extern "C"
KMSAgent_ChangeLocalPWD(KMSClientProfile * i_pProfile,utf8cstr const i_pOldPassphrase,utf8cstr const i_pNewPassphrase)3828 KMS_AGENT_STATUS KMSAgent_ChangeLocalPWD(
3829 	KMSClientProfile* i_pProfile,
3830 	utf8cstr const i_pOldPassphrase,
3831 	utf8cstr const i_pNewPassphrase)
3832 {
3833 	CCertificate *pCert;
3834 	CPrivateKey *pKey;
3835 	bool bSuccess;
3836 
3837 	pCert = new CCertificate;
3838 	pKey = new CPrivateKey;
3839 
3840 	bSuccess = GetPKCS12CertAndKey(i_pProfile, i_pOldPassphrase,
3841 		pCert, pKey);
3842 	if (!bSuccess)
3843     		return(KMSAgent_GetLastStatusCode(i_pProfile, 0));
3844 
3845 	bSuccess = StoreAgentPKI(i_pProfile, pCert, pKey, i_pNewPassphrase);
3846 	if (!bSuccess)
3847     		return(KMSAgent_GetLastStatusCode(i_pProfile, 0));
3848 
3849 	return (KMS_AGENT_STATUS_OK);
3850 }
3851 #endif /* KMSUSERPKCS12 */
3852