summaryrefslogtreecommitdiff
path: root/usr/src/lib/libkmsagent/common/KMSAgent.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libkmsagent/common/KMSAgent.cpp')
-rw-r--r--usr/src/lib/libkmsagent/common/KMSAgent.cpp3851
1 files changed, 3851 insertions, 0 deletions
diff --git a/usr/src/lib/libkmsagent/common/KMSAgent.cpp b/usr/src/lib/libkmsagent/common/KMSAgent.cpp
new file mode 100644
index 0000000000..3d34ea571f
--- /dev/null
+++ b/usr/src/lib/libkmsagent/common/KMSAgent.cpp
@@ -0,0 +1,3851 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/**
+ * \file KMSAgent.cpp
+ */
+
+#ifdef WIN32
+#define _WIN32_WINNT 0x0400
+#include <windows.h>
+#include <process.h>
+#endif
+
+#include <stdlib.h>
+
+#include "KMSClientProfile.h"
+
+#include "KMS_AgentStub.h"
+#include "KMS_DiscoveryStub.h"
+
+#include "KMSClientProfileImpl.h"
+#include "KMSAgent.h"
+#include "KMSAuditLogger.h"
+#include "KMSAgentSoapUtilities.h"
+#include "KMSAgentStringUtilities.h"
+#include "KMSAgentPKICommon.h"
+#include "KMSAgentLoadBalancer.h"
+
+#include "KMSAgentWebServiceNamespaces.h"
+#include "k_setupssl.h"
+
+#include "ApplianceParameters.h"
+
+#include "AutoMutex.h"
+#include "KMSAgentKeyCallout.h"
+
+#include "KMSAgentLoadBalancer.h"
+#include "KMSAgentDataUnitCache.h"
+
+#ifdef K_SOLARIS_PLATFORM
+#include "KMSAgentStorage.h"
+#endif
+
+#include "ClientSoapFaultCodes.h"
+
+#ifdef METAWARE
+#include "debug.h"
+#include "sizet.h"
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+#endif
+
+#include "KMSAgentAESKeyWrap.h"
+#include "KMSAgentKnownAnswerTests.h"
+
+#if defined(METAWARE) && defined(DEBUG_RETURNS)
+extern "C" void ecpt_trace_msg (ECPT_TRACE_ENTRY*, char*, ...);
+
+#define RETURN(a) { ecpt_trace_msg( trace,"(returned=%x)",(a)); return(a); }
+
+#else
+#define RETURN(a) return(a)
+#endif
+
+/* KMS_AGENT_VERSION_STRING gets passed in via compilation flags */
+extern "C" const char KMSAgent_Version[KMS_MAX_VERSION_LENGTH + 1] = KMS_AGENT_VERSION_STRING;
+
+
+/* The following enum and structs are used for QueryParameters in
+ * ListKeyGroup. Since they are only used in implementation code,
+ * so they are not in the header file in order to hide these details
+ */
+
+
+/*---------------------------Start Query Parameters Declartion -------- */
+
+#define KMS_MAX_AGENT_FILTER_PARAMETERS 10
+
+enum KMSAgent_SortOrder
+{
+ SORT_ORDER_ASCENDING = 0,
+ SORT_ORDER_DESCENDING
+};
+
+enum KMSAgent_FilterOperator
+{
+ FILTER_OPERATOR_EQUAL = 0,
+ FILTER_OPERATOR_NOT_EQUAL,
+ FILTER_OPERATOR_GREATER_THAN,
+ FILTER_OPERATOR_LESS_THAN,
+ FILTER_OPERATOR_GREATER_THAN_OR_EQUAL,
+ FILTER_OPERATOR_LESS_THAN_OR_EQUAL,
+ FILTER_OPERATOR_STARTS_WITH
+};
+
+struct KMSAgent_FilterParameters
+{
+ utf8char m_wsFieldName[KMS_MAX_FIELD_NAME + 1];
+ enum KMSAgent_FilterOperator m_eFilterOperator;
+ utf8char m_wsFieldValue[KMS_MAX_FIELD_VALUE + 1];
+};
+
+struct KMSAgent_QueryParameters
+{
+ utf8char m_wsSortFieldName[KMS_MAX_FIELD_NAME + 1];
+ enum KMSAgent_SortOrder m_eSortOrder;
+
+ struct KMSAgent_FilterParameters m_aFilterParameters[KMS_MAX_AGENT_FILTER_PARAMETERS];
+ int m_iSizeFilterParameters;
+
+ utf8char m_wsPreviousPageLastIDValue[KMS_MAX_ID + 1];
+ utf8char m_wsPreviousPageLastSortFieldValue[KMS_MAX_FIELD_VALUE + 1];
+};
+
+/*---------------------------End Of Query Parameters Declaration -------- */
+
+#ifdef METAWARE
+int CAgentLoadBalancer::FailOver (int i_iFailedApplianceIndex,
+ struct soap *i_pstSoap);
+#endif
+
+extern const char * KMSAgent_GetVersion ()
+{
+ return (KMSAgent_Version);
+}
+
+static bool CopyQueryParametersFromRequest
+(
+ struct soap *i_pstSoap,
+ int i_iPageSize,
+ struct KMS_Agent::KMS_Agent__QueryParameters *i_pQueryParameters,
+ struct KMSAgent_QueryParameters *i_pSourceQueryParameters
+ )
+{
+
+ // set page size
+ i_pQueryParameters->NextPageSize = i_iPageSize;
+
+ // copy sort field name
+ i_pQueryParameters->SortFieldName = (char *)
+ soap_malloc(i_pstSoap,
+ sizeof (i_pSourceQueryParameters->m_wsSortFieldName));
+ if (i_pQueryParameters->SortFieldName == NULL)
+ {
+ return (false);
+ }
+ strncpy(i_pQueryParameters->SortFieldName,
+ i_pSourceQueryParameters->m_wsSortFieldName,
+ sizeof (i_pSourceQueryParameters->m_wsSortFieldName));
+ i_pQueryParameters->SortFieldName[sizeof (i_pSourceQueryParameters->m_wsSortFieldName)-1] = 0;
+
+ // sort order
+ i_pQueryParameters->SortOrder =
+ (enum KMS_Agent::KMS_Agent__SortOrder)i_pSourceQueryParameters->m_eSortOrder;
+
+ // copy filter parameters
+ i_pQueryParameters->FilterParameters.__size =
+ i_pSourceQueryParameters->m_iSizeFilterParameters;
+
+ if (i_pQueryParameters->FilterParameters.__size > 0)
+ {
+ i_pQueryParameters->
+ FilterParameters.__ptr =
+ (struct KMS_Agent::KMS_Agent__FilterParameters *)soap_malloc
+ (i_pstSoap,
+ sizeof (KMS_Agent::KMS_Agent__FilterParameters) *
+ i_pQueryParameters->FilterParameters.__size);
+
+ if (i_pQueryParameters->FilterParameters.__ptr == NULL)
+ {
+ return (false);
+ }
+ }
+ else
+ {
+ i_pQueryParameters->FilterParameters.__ptr = NULL;
+ }
+
+ for (int i = 0; i < i_pSourceQueryParameters->m_iSizeFilterParameters; i++)
+ {
+ struct KMS_Agent::KMS_Agent__FilterParameters *pParameters;
+
+ pParameters = &(i_pQueryParameters->FilterParameters.__ptr[i]);
+
+ // copy field name
+ pParameters->FieldName = (
+ utf8cstr) soap_malloc(i_pstSoap,
+ sizeof (i_pSourceQueryParameters->
+ m_aFilterParameters[i].m_wsFieldName));
+ if (pParameters->FieldName == NULL)
+ {
+ return (false);
+ }
+
+ strncpy(pParameters->FieldName,
+ i_pSourceQueryParameters->m_aFilterParameters[i].m_wsFieldName,
+ sizeof (i_pSourceQueryParameters->
+ m_aFilterParameters[i].m_wsFieldName));
+ pParameters->FieldName[sizeof (i_pSourceQueryParameters->
+ m_aFilterParameters[i].m_wsFieldName)-1] = '\0';
+
+ // copy field value
+ pParameters->FieldValue =
+ (utf8cstr) soap_malloc
+ (i_pstSoap,
+ sizeof (i_pSourceQueryParameters->m_aFilterParameters[i].m_wsFieldValue));
+ if (pParameters->FieldValue == NULL)
+ {
+ return (false);
+ }
+
+ strncpy(pParameters->FieldValue,
+ i_pSourceQueryParameters->m_aFilterParameters[i].m_wsFieldValue,
+ sizeof (i_pSourceQueryParameters->m_aFilterParameters[i].m_wsFieldValue));
+ pParameters->FieldValue[sizeof (i_pSourceQueryParameters->m_aFilterParameters[i].m_wsFieldValue)-1] = '\0';
+
+ // copy FilterOperator
+ pParameters->FilterOperator =
+ (KMS_Agent::KMS_Agent__FilterOperator)
+ i_pSourceQueryParameters->m_aFilterParameters[i].m_eFilterOperator;
+ }
+
+ // copy PreviousPageLastIDValue
+ i_pQueryParameters->PreviousPageLastIDValue =
+ (utf8cstr) soap_malloc(i_pstSoap,
+ sizeof (i_pSourceQueryParameters->m_wsPreviousPageLastIDValue));
+ if (i_pQueryParameters->PreviousPageLastIDValue == NULL)
+ {
+ return (false);
+ }
+ strncpy(i_pQueryParameters->PreviousPageLastIDValue,
+ i_pSourceQueryParameters->m_wsPreviousPageLastIDValue,
+ sizeof (i_pSourceQueryParameters->m_wsPreviousPageLastIDValue));
+ i_pQueryParameters->PreviousPageLastIDValue[sizeof (i_pSourceQueryParameters->m_wsPreviousPageLastIDValue)-1] = '\0';
+
+ // copy PreviousPageLastIDValue
+ i_pQueryParameters->PreviousPageLastSortFieldValue =
+ (utf8cstr) soap_malloc(i_pstSoap,
+ sizeof (i_pSourceQueryParameters->
+ m_wsPreviousPageLastSortFieldValue));
+ if (i_pQueryParameters->PreviousPageLastSortFieldValue == NULL)
+ {
+ return (false);
+ }
+ strncpy(i_pQueryParameters->PreviousPageLastSortFieldValue,
+ i_pSourceQueryParameters->m_wsPreviousPageLastSortFieldValue,
+ sizeof (i_pSourceQueryParameters->
+ m_wsPreviousPageLastSortFieldValue));
+ i_pQueryParameters->PreviousPageLastSortFieldValue[sizeof (i_pSourceQueryParameters->
+ m_wsPreviousPageLastSortFieldValue)-1] = 0;
+
+ return (true);
+}
+
+static void CopyQueryParametersFromResponse (
+ struct KMSAgent_QueryParameters *i_pQueryParameters,
+ struct KMS_Agent::KMS_Agent__QueryParameters *i_pSourceQueryParameters)
+{
+
+ // copy sort field name
+ if (i_pSourceQueryParameters->SortFieldName)
+ {
+ strncpy(i_pQueryParameters->m_wsSortFieldName,
+ i_pSourceQueryParameters->SortFieldName,
+ sizeof(i_pQueryParameters->m_wsSortFieldName));
+ i_pQueryParameters->m_wsSortFieldName[sizeof(i_pQueryParameters->m_wsSortFieldName)-1] = '\0';
+ }
+
+ // copy order
+ i_pQueryParameters->m_eSortOrder =
+ (KMSAgent_SortOrder) i_pSourceQueryParameters->SortOrder;
+
+ // copy filter parameters
+ i_pQueryParameters->m_iSizeFilterParameters =
+ i_pSourceQueryParameters->FilterParameters.__size;
+
+ // we only accept this amount of parameters
+ if (i_pQueryParameters->m_iSizeFilterParameters >= KMS_MAX_AGENT_FILTER_PARAMETERS)
+ {
+ // this should not happen, but just for defending the code
+ i_pQueryParameters->m_iSizeFilterParameters = KMS_MAX_AGENT_FILTER_PARAMETERS;
+ }
+
+ for (int i = 0; i < i_pQueryParameters->m_iSizeFilterParameters; i++)
+ {
+ struct KMS_Agent::KMS_Agent__FilterParameters *pParameters;
+
+ pParameters = i_pSourceQueryParameters->FilterParameters.__ptr + i;
+
+ i_pQueryParameters->m_aFilterParameters[i].m_eFilterOperator
+ = (KMSAgent_FilterOperator) pParameters->FilterOperator;
+
+ if (pParameters->FieldName)
+ {
+ strncpy(i_pQueryParameters->m_aFilterParameters[i].m_wsFieldName,
+ pParameters->FieldName,
+ sizeof (i_pQueryParameters->m_aFilterParameters[i].m_wsFieldName));
+ i_pQueryParameters->
+ m_aFilterParameters[i].m_wsFieldName[sizeof (i_pQueryParameters->m_aFilterParameters[i].m_wsFieldName) - 1] = '\0';
+ }
+
+ if (pParameters->FieldValue)
+ {
+ strncpy(i_pQueryParameters->m_aFilterParameters[i].m_wsFieldValue,
+ pParameters->FieldValue,
+ sizeof(i_pQueryParameters->m_aFilterParameters[i].m_wsFieldValue));
+ i_pQueryParameters->
+ m_aFilterParameters[i].m_wsFieldValue[sizeof(i_pQueryParameters->m_aFilterParameters[i].m_wsFieldValue)-1] = '\0';
+ }
+ }
+ // copy PreviousPageLastIDValue
+ if (i_pSourceQueryParameters->PreviousPageLastIDValue)
+ {
+ strncpy(i_pQueryParameters->m_wsPreviousPageLastIDValue,
+ i_pSourceQueryParameters->PreviousPageLastIDValue,
+ sizeof(i_pQueryParameters->m_wsPreviousPageLastIDValue));
+ i_pQueryParameters->m_wsPreviousPageLastIDValue[sizeof(i_pQueryParameters->m_wsPreviousPageLastIDValue)-1] = '\0';
+ }
+
+ // copy PreviousPageLastSortFieldValue
+ if (i_pSourceQueryParameters->PreviousPageLastSortFieldValue)
+ {
+ strncpy(i_pQueryParameters->m_wsPreviousPageLastSortFieldValue,
+ i_pSourceQueryParameters->PreviousPageLastSortFieldValue,
+ sizeof(i_pQueryParameters->m_wsPreviousPageLastSortFieldValue));
+ i_pQueryParameters->m_wsPreviousPageLastSortFieldValue[sizeof(i_pQueryParameters->m_wsPreviousPageLastSortFieldValue)-1] = '\0';
+ }
+
+}
+
+/**
+ * copies data unit to the soap data unit structure, placing the xsd_string types on the
+ * gsoap heap.
+ * @return(false if soap_malloc fails
+ */
+static bool CopyDataUnitFromRequest (struct soap *i_pstSoap,
+ struct KMS_Agent::KMS_Agent__DataUnit *i_pDataUnit,
+ const KMSAgent_DataUnit * const i_pSourceDataUnit)
+{
+
+ if (i_pSourceDataUnit)
+ {
+ // copy field name
+ i_pDataUnit->DataUnitID =
+ (utf8cstr) soap_malloc(i_pstSoap,
+ 2 * sizeof (i_pSourceDataUnit->m_acDataUnitID) + 1);
+ if (i_pDataUnit->DataUnitID == NULL)
+ {
+ return (false);
+ }
+
+ ConvertBinaryToUTF8HexString(i_pDataUnit->DataUnitID,
+ i_pSourceDataUnit->m_acDataUnitID,
+ KMS_DATA_UNIT_ID_SIZE);
+ }
+ else
+ {
+ strcpy(i_pDataUnit->DataUnitID, "");
+ }
+
+ i_pDataUnit->ExternalUniqueID = (utf8cstr) soap_malloc(i_pstSoap,
+ 2 * sizeof (i_pSourceDataUnit->m_acExternalUniqueID) + 1);
+ if (i_pDataUnit->ExternalUniqueID == NULL)
+ {
+ return (false);
+ }
+
+ if (i_pSourceDataUnit->m_iExternalUniqueIDLength > 0 &&
+ i_pSourceDataUnit->m_iExternalUniqueIDLength <= KMS_MAX_EXTERNAL_UNIQUE_ID_SIZE)
+ {
+ ConvertBinaryToUTF8HexString(i_pDataUnit->ExternalUniqueID,
+ i_pSourceDataUnit->m_acExternalUniqueID,
+ i_pSourceDataUnit->m_iExternalUniqueIDLength);
+ }
+ else
+ {
+ strcpy(i_pDataUnit->ExternalUniqueID, "");
+ }
+
+ i_pDataUnit->ExternalTag = (utf8cstr) soap_malloc(i_pstSoap, sizeof (i_pSourceDataUnit->m_acExternalTag));
+ if (i_pDataUnit->ExternalTag == NULL)
+ {
+ return (false);
+ }
+
+ if (strlen(i_pSourceDataUnit->m_acExternalTag) <= sizeof (i_pSourceDataUnit->m_acExternalTag))
+ {
+ strncpy(i_pDataUnit->ExternalTag,
+ i_pSourceDataUnit->m_acExternalTag,
+ sizeof (i_pSourceDataUnit->m_acExternalTag));
+ i_pDataUnit->ExternalTag[sizeof (i_pSourceDataUnit->m_acExternalTag)-1] = '\0';
+ }
+ else
+ {
+ strcpy(i_pDataUnit->ExternalTag, "");
+ }
+
+ i_pDataUnit->Description = (utf8cstr) soap_malloc(i_pstSoap, sizeof (i_pSourceDataUnit->m_acDescription));
+ if (i_pDataUnit->Description == NULL)
+ {
+ return (false);
+ }
+ if (strlen(i_pSourceDataUnit->m_acDescription) <= sizeof (i_pSourceDataUnit->m_acDescription))
+ {
+ strncpy(i_pDataUnit->Description,
+ i_pSourceDataUnit->m_acDescription,
+ sizeof (i_pSourceDataUnit->m_acDescription));
+ i_pDataUnit->Description[sizeof (i_pSourceDataUnit->m_acDescription)-1] = '\0';
+ }
+ else
+ {
+ strcpy(i_pDataUnit->Description, "");
+ }
+
+ i_pDataUnit->DataUnitState = (KMS_Agent::KMS_Agent__DataUnitState) i_pSourceDataUnit->m_iDataUnitState;
+
+ return (true);
+}
+
+/**
+ * Converts an ExternalUniqueID value to UTF8Hexstring value from gSoap managed heap storage
+ * @param i_pstSoap pointer to gSoap runtime
+ * @param i_pExternalUniqueID non-NULL pointer to an external unique id to be converted
+ * @return(NULL if memory cannot be allocated
+ */
+static char * ConvertBinaryDataFromRequest (struct soap *i_pstSoap,
+ const unsigned char * i_pBinaryData,
+ int i_iBinaryDataLen)
+{
+ char * pBinaryData = (char *) soap_malloc(i_pstSoap, 2 * i_iBinaryDataLen + 1);
+ if (pBinaryData != NULL)
+ {
+ ConvertBinaryToUTF8HexString(pBinaryData,
+ i_pBinaryData,
+ i_iBinaryDataLen);
+ }
+ return (pBinaryData);
+}
+
+/**
+ * Converts a UTF8 char string value to a fixed length array from
+ * gSoap managed heap storage
+ * @param pointer to gSoap runtime
+ * @param i_pUTF8string non-NULL pointer to a null terminated UTF8 string
+ * @param i_iLen size of arrray to be allocated
+ * @return(NULL if gSoap allocated storage could not be obtained
+ */
+static char * ConvertUTF8StringFromRequest (struct soap *i_pstSoap,
+ const char * const i_pUTF8string,
+ size_t i_iLen)
+{
+ char * pUTF8string = NULL;
+ pUTF8string = (char *) soap_malloc(i_pstSoap, i_iLen);
+ if (pUTF8string != NULL)
+ {
+ strncpy(pUTF8string, i_pUTF8string, i_iLen);
+ pUTF8string[i_iLen-1] = '\0';
+ }
+ return (pUTF8string);
+}
+
+static KMSAgent_ArrayOfKeyGroups * CopyKeyGroupsResponse
+(
+ struct KMS_Agent::KMS_Agent__ArrayOfKeyGroups *i_pKeyGroupsResponse
+ )
+{
+ // alloc memory for result
+ KMSAgent_ArrayOfKeyGroups *pResult =
+ (KMSAgent_ArrayOfKeyGroups *) calloc(1, sizeof (KMSAgent_ArrayOfKeyGroups));
+
+ // no memory, return
+ if (pResult == NULL)
+ {
+ return (NULL);
+ }
+
+ // copy size
+ pResult->m_iSize = i_pKeyGroupsResponse->__size;
+
+ // if the size is 0, return(an empty result
+ if (pResult->m_iSize == 0)
+ {
+ return (pResult);
+ }
+
+ // alloc memory for all key groups
+ pResult->m_pKeyGroups = (KMSAgent_KeyGroup*)
+ calloc(1, sizeof (KMSAgent_KeyGroup) * pResult->m_iSize);
+
+ if (pResult->m_pKeyGroups == NULL)
+ {
+ free(pResult);
+ return (NULL);
+ }
+
+ for (int i = 0; i < pResult->m_iSize; i++)
+ {
+ KMSAgent_KeyGroup *pKeyGroup;
+
+ pKeyGroup = &(pResult->m_pKeyGroups[i]);
+
+ strncpy(pKeyGroup->m_acKeyGroupID,
+ i_pKeyGroupsResponse->__ptr[i].KeyGroupID,
+ sizeof(pKeyGroup->m_acKeyGroupID));
+ pKeyGroup->m_acKeyGroupID[sizeof(pKeyGroup->m_acKeyGroupID)-1] = '\0';
+
+ strncpy(pKeyGroup->m_acDescription,
+ i_pKeyGroupsResponse->__ptr[i].Description,
+ sizeof(pKeyGroup->m_acDescription));
+ pKeyGroup->m_acDescription[sizeof(pKeyGroup->m_acDescription)-1] = '\0';
+ }
+
+ return (pResult);
+}
+/**
+ * allocate storage for the KMSAgent_ArrayOfKeys struct and the array of keys returned in the
+ * soap response.
+ * @param i_pProfile pointer to profile
+ * @param io_pClusterIndex pointer to the cluster index value which is used
+ * by AES Key Unwrap to access the KWK for the KMA corresponding to the
+ * cluster index.
+ * @param i_pKeysResponse pointer to the soap response' array of keys struct
+ * @return(pointer to allocated KMSAgent_ArrayOfKeys and the corresponding keys, returns NULL
+ * on any error and frees any allocated storage before returning. For response data validation errors a
+ * message will be logged.
+ */
+static KMSAgent_ArrayOfKeys * CopyDataUnitKeysResponse (
+ KMSClientProfile *i_pProfile,
+ int * const io_pClusterIndex,
+ struct KMS_Agent::KMS_Agent__ArrayOfKeys *i_pKeysResponse)
+{
+ KMSAgent_ArrayOfKeys * pResult =
+ (KMSAgent_ArrayOfKeys *) calloc(1, sizeof (KMSAgent_ArrayOfKeys));
+
+ if (pResult == NULL)
+ {
+ return (NULL);
+ }
+
+ // if the size is 0, return(an empty result
+ if (i_pKeysResponse->__size == 0)
+ {
+ return (pResult);
+ }
+
+ if (i_pKeysResponse->__size > KMS_MAX_PAGE_SIZE)
+ {
+ free(pResult);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_KEY_ARRAY_SIZE_RESPONSE,
+ NULL,
+ NULL,
+ NULL);
+ return (NULL);
+ }
+
+ pResult->m_iSize = i_pKeysResponse->__size;
+
+ // alloc memory for all keys returned
+ pResult->m_pKeys = (KMSAgent_Key*)
+ calloc(1, sizeof (KMSAgent_Key) * i_pKeysResponse->__size);
+
+ if (pResult->m_pKeys == NULL)
+ {
+ free(pResult);
+ return (NULL);
+ // no memory, don't log
+ }
+
+ // copy keys from response
+ for (int i = 0; i < i_pKeysResponse->__size; i++)
+ {
+ if (KMS_KEY_ID_SIZE != ConvertUTF8HexStringToBinary(
+ i_pKeysResponse->__ptr[i].KeyID, NULL))
+ {
+ free(pResult->m_pKeys);
+ free(pResult);
+
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_KEY_RESPONSE,
+ NULL,
+ NULL,
+ NULL);
+ return (NULL);
+ }
+
+ ConvertUTF8HexStringToBinary(
+ i_pKeysResponse->__ptr[i].KeyID, pResult->m_pKeys[i].m_acKeyID);
+
+ if ((KMS_AGENT_KEY_STATE) i_pKeysResponse->__ptr[i].KeyState < KMS_KEY_STATE_ACTIVE_PROTECT_AND_PROCESS ||
+ (KMS_AGENT_KEY_STATE) i_pKeysResponse->__ptr[i].KeyState > KMS_KEY_STATE_COMPROMISED)
+ {
+ free(pResult->m_pKeys);
+ free(pResult);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_KEY_STATE_RESPONSE,
+ NULL,
+ NULL,
+ NULL);
+ return (NULL);
+ }
+ pResult->m_pKeys[i].m_iKeyState = (KMS_AGENT_KEY_STATE) i_pKeysResponse->__ptr[i].KeyState;
+
+ if ((KMS_KEY_TYPE) i_pKeysResponse->__ptr[i].KeyType != (KMS_KEY_TYPE)KMS_KEY_TYPE_AES_256)
+ {
+ free(pResult->m_pKeys);
+ free(pResult);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_KEY_TYPE_RESPONSE,
+ NULL,
+ NULL,
+ NULL);
+ return (NULL);
+ }
+ pResult->m_pKeys[i].m_iKeyType = (KMS_KEY_TYPE) i_pKeysResponse->__ptr[i].KeyType;
+
+ strncpy(pResult->m_pKeys[i].m_acKeyGroupID,
+ i_pKeysResponse->__ptr[i].KeyGroupID,
+ sizeof(pResult->m_pKeys[i].m_acKeyGroupID));
+ pResult->m_pKeys[i].m_acKeyGroupID[sizeof(pResult->m_pKeys[i].m_acKeyGroupID)-1] = '\0';
+
+ CAgentLoadBalancer *pAgentLoadBalancer = reinterpret_cast
+ <CAgentLoadBalancer *> (i_pProfile->m_pAgentLoadBalancer);
+
+ if (pAgentLoadBalancer->AESKeyWrapSupported(*io_pClusterIndex))
+ {
+ if (i_pKeysResponse->__ptr[i].Key.__size != KMS_MAX_WRAPPED_KEY_SIZE)
+ {
+ free(pResult->m_pKeys);
+ free(pResult);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_WRAPPED_KEY_LENGTH_RESPONSE,
+ NULL,
+ NULL,
+ NULL);
+ return (NULL);
+ }
+ else
+ {
+ if (pAgentLoadBalancer->AESKeyUnwrap(io_pClusterIndex,
+ i_pKeysResponse->__ptr[i].Key.__ptr,
+ pResult->m_pKeys[i].m_acKey) == false)
+ {
+ free(pResult->m_pKeys);
+ free(pResult);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_AESKEYUNWRAP_ERROR,
+ NULL,
+ NULL,
+ NULL);
+
+ return (NULL);
+ }
+ }
+ }
+ else // non-AES Key Wrap
+ {
+ if (i_pKeysResponse->__ptr[i].Key.__size != KMS_MAX_KEY_SIZE)
+ {
+ free(pResult->m_pKeys);
+ free(pResult);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_KEY_LENGTH_RESPONSE,
+ NULL,
+ NULL,
+ NULL);
+ return (NULL);
+ }
+
+ memcpy(pResult->m_pKeys[i].m_acKey,
+ i_pKeysResponse->__ptr[i].Key.__ptr,
+ KMS_MAX_KEY_SIZE);
+ }
+
+ pResult->m_pKeys[i].m_iKeyLength = KMS_MAX_KEY_SIZE;
+
+ if (KMSAgentKeyCallout(pResult->m_pKeys[i].m_acKey) != 0)
+ {
+ free(pResult->m_pKeys);
+ free(pResult);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_KEY_CALLOUT_ERROR,
+ NULL,
+ NULL,
+ NULL);
+ return (NULL);
+ }
+ }
+
+ return (pResult);
+}
+
+/**
+ * This function returns the API status code based upon the error string in the profile and
+ * availability of KMAs. KMA availability determination is based upon the i_iKMAFailoverReturnCode
+ * parameter and the size of the cluster. A cluster size of 0 is an indicator that there are
+ * no KMAs available, unless cluster discovery is disabled by the profile's cluster discovery
+ * frequency.
+ *
+ * @param i_pProfile pointer to the profile
+ * @param i_iKMAFailoverReturnCode the return(code from CAgentLoadBalancer::Failover() or 0
+ * if it was not called. This is used to for determining if KMS_AGENT_STATUS_KMS_UNAVAILABLE
+ * needs to be returned.
+ * @returns KMS_AGENT_STATUS_GENERIC_ERROR
+ * unless the profile's last error message field contains a message substring matching one of the
+ * KMSAgent service soap fault strings.
+ *
+ */
+static KMS_AGENT_STATUS KMSAgent_GetLastStatusCode (KMSClientProfile *i_pProfile,
+ int i_iKMAFailoverReturnCode)
+{
+ bool bServerError = false;
+
+ FATAL_ASSERT(i_pProfile);
+
+ // see KMSAgentLoadBalancer.h for return codes from Failover
+
+ if (i_iKMAFailoverReturnCode == CAgentLoadBalancer::NO_FIPS_KMA_AVAILABLE)
+ {
+ return (KMS_AGENT_STATUS_NO_FIPS_KMAS_AVAILABLE);
+ }
+
+ // parse for server errors -
+ // when KMAs have no ready keys we want to inform the client, vs reporting that the KMS is unavailable
+ bServerError = ServerError(i_pProfile->m_wsErrorString, 0);
+
+ // parse for Soap errors
+ const char* sFaultstringStart = strstr(i_pProfile->m_wsErrorString, "SoapFaultString=");
+
+ int iErrorCode = INVALID_CLIENT_ERROR; // initially
+
+
+ // if there is a Soap error
+ if (sFaultstringStart)
+ {
+ if (SSL_InvalidCertificate(sFaultstringStart))
+ {
+ // this can be caused by the KMS invalidating the agent's cert
+ return (KMS_AGENT_STATUS_ACCESS_DENIED);
+ }
+ iErrorCode = GET_FAULT_CODE(sFaultstringStart + strlen("SoapFaultString="));
+ }
+
+
+#ifdef METAWARE
+ // log the failure code/cause to the event log
+ LogToFile(i_iKMAFailoverReturnCode, i_pProfile->m_wsErrorString);
+ LogToFile(iErrorCode, "error code");
+#endif
+
+
+ // parse return code passed in from last call to FailOver, Balance or BalanceByDataUnitKeyID
+ // if failover reported no kma and there is a valid server error and client couldn't get keys
+ if (i_iKMAFailoverReturnCode == CAgentLoadBalancer::NO_KMA_AVAILABLE &&
+ bServerError &&
+ iErrorCode == CLIENT_ERROR_AGENT_NO_READY_KEYS)
+ {
+ return (KMS_AGENT_STATUS_KMS_UNAVAILABLE);
+ }
+
+ // if there is a server error and we are doing discovery
+ if (bServerError &&
+ ((i_pProfile->m_iClusterDiscoveryFrequency > 0 &&
+ i_pProfile->m_iClusterNum == 0)
+ || iErrorCode == CLIENT_ERROR_AGENT_APPLIANCE_LOCKED))
+ {
+ return (KMS_AGENT_STATUS_KMS_UNAVAILABLE);
+ }
+
+ if (bServerError && i_iKMAFailoverReturnCode == CAgentLoadBalancer::NO_KMA_AVAILABLE)
+ {
+ return (KMS_AGENT_STATUS_KMS_UNAVAILABLE);
+ }
+
+ if ( i_iKMAFailoverReturnCode == CAgentLoadBalancer::AES_KEY_UNWRAP_ERROR )
+ return (KMS_AGENT_AES_KEY_UNWRAP_ERROR);
+ if ( i_iKMAFailoverReturnCode == CAgentLoadBalancer::AES_KEY_WRAP_SETUP_ERROR )
+ return (KMS_AGENT_AES_KEY_WRAP_SETUP_ERROR);
+
+ if (iErrorCode == CLIENT_ERROR_ACCESS_DENIED)
+ return (KMS_AGENT_STATUS_ACCESS_DENIED);
+ if (iErrorCode == CLIENT_ERROR_SERVER_BUSY)
+ return (KMS_AGENT_STATUS_SERVER_BUSY);
+ if (iErrorCode == CLIENT_ERROR_AGENT_INVALID_PARAMETERS)
+ return (KMS_AGENT_STATUS_INVALID_PARAMETER);
+ if (iErrorCode == CLIENT_ERROR_AGENT_KEY_DOES_NOT_EXIST)
+ return (KMS_AGENT_STATUS_KEY_DOES_NOT_EXIST);
+ if (iErrorCode == CLIENT_ERROR_AGENT_KEY_DESTROYED)
+ return (KMS_AGENT_STATUS_KEY_DESTROYED);
+ if (iErrorCode == CLIENT_ERROR_AGENT_DATA_UNIT_ID_NOT_FOUND_EXTERNAL_ID_EXISTS)
+ return (KMS_AGENT_STATUS_DATA_UNIT_ID_NOT_FOUND_EXTERNAL_ID_EXISTS);
+ if (iErrorCode == CLIENT_ERROR_AGENT_DUPLICATE_EXTERNAL_ID)
+ return (KMS_AGENT_STATUS_EXTERNAL_UNIQUE_ID_EXISTS);
+ if (iErrorCode == CLIENT_ERROR_AGENT_NO_READY_KEYS)
+ return (KMS_AGENT_STATUS_KMS_NO_READY_KEYS);
+
+ // this check is made last to allow other specific errors that may have occurred to take precedence,
+ // e.g. return access denied before reporting No FIPS KMAs
+ if (i_pProfile->m_eKMSmode == FIPS_MODE &&
+ KMSClient_NoFIPSCompatibleKMAs(i_pProfile))
+ {
+ return (KMS_AGENT_STATUS_NO_FIPS_KMAS_AVAILABLE);
+ }
+
+ return (KMS_AGENT_STATUS_GENERIC_ERROR);
+}
+
+/*---------------------------------------------------------------------------
+ * Function: KMSAgent_InitializeLibrary
+ *--------------------------------------------------------------------------*/
+#include "KMSAuditLogger.h"
+
+extern "C"
+KMS_AGENT_STATUS KMSAgent_InitializeLibrary (utf8cstr const i_pWorkingDirectory,
+ int i_bUseFileLog)
+
+{
+ bool bSuccess;
+
+#if defined(METAWARE)
+#warn "debug timing is on"
+ ECPT_TRACE_ENTRY *trace = NULL;
+ ECPT_TRACE(trace, KMSAgent_InitializeLibrary);
+#endif
+
+#if defined(DEBUG) && defined(METAWARE)
+ log_printf("KMSAgent_InitializeLibrary : Entered");
+#endif
+
+ bSuccess = KMSClient_InitializeLibrary(
+ i_pWorkingDirectory,
+ i_bUseFileLog);
+
+ if (bSuccess)
+ {
+ RETURN(KMS_AGENT_STATUS_OK);
+ }
+
+ RETURN(KMS_AGENT_STATUS_GENERIC_ERROR);
+}
+
+/*---------------------------------------------------------------------------
+ * Function: KMSAgent_KnownAnswerTests
+ *
+ *--------------------------------------------------------------------------*/
+KMS_AGENT_STATUS KMSAgent_KnownAnswerTests()
+{
+#if defined(METAWARE)
+ ECPT_TRACE_ENTRY *trace = NULL;
+ ECPT_TRACE(trace, KMSAgent_KnownAnswerTests);
+#endif
+
+ // Known Answer Test on AES Key Wrap code
+ if ( KnownAnswerTestAESKeyWrap() != 0 )
+ {
+ RETURN(KMS_AGENT_STATUS_FIPS_KAT_AES_KEYWRAP_ERROR);
+ }
+
+ if ( KnownAnswerTestAESECB() != 0 )
+ {
+ RETURN(KMS_AGENT_STATUS_FIPS_KAT_AES_ECB_ERROR);
+ }
+
+ if ( KnownAnswerTestHMACSHA1() != 0 )
+ {
+ RETURN(KMS_AGENT_STATUS_FIPS_KAT_HMAC_SHA1_ERROR);
+ }
+
+ RETURN(KMS_AGENT_STATUS_OK);
+
+}
+
+/*---------------------------------------------------------------------------
+ * Function: KMSAgent_FinalizeLibrary
+ *
+ *--------------------------------------------------------------------------*/
+
+extern "C"
+KMS_AGENT_STATUS KMSAgent_FinalizeLibrary ()
+{
+ bool bSuccess;
+
+#if defined(METAWARE)
+ ECPT_TRACE_ENTRY *trace = NULL;
+ ECPT_TRACE(trace, KMSAgent_FinalizeLibrary);
+#endif
+
+ bSuccess = KMSClient_FinalizeLibrary();
+
+ if (bSuccess)
+ {
+ RETURN(KMS_AGENT_STATUS_OK);
+ }
+
+ RETURN(KMS_AGENT_STATUS_GENERIC_ERROR);
+}
+
+/*---------------------------------------------------------------------------
+ * Function: KMSAgent_GetLastErrorMessage
+ *
+ *--------------------------------------------------------------------------*/
+
+extern "C"
+utf8cstr KMSAgent_GetLastErrorMessage (KMSClientProfile* i_pProfile)
+{
+#if defined(METAWARE)
+ ECPT_TRACE_ENTRY *trace = NULL;
+ ECPT_TRACE(trace, KMSAgent_GetLastErrorMessage);
+#endif
+
+ if (i_pProfile == NULL)
+ {
+ RETURN(NULL);
+ }
+
+ RETURN(KMSClient_GetLastErrorMessage(i_pProfile));
+}
+
+/*---------------------------------------------------------------------------
+ * Function: KMSAgent_GetClusterInformation
+ *
+ *--------------------------------------------------------------------------*/
+extern "C"
+KMS_AGENT_STATUS KMSAgent_GetClusterInformation (
+ KMSClientProfile * const i_pProfile,
+ int i_iEntitySiteIDSize,
+ int i_iClusterEntryArraySize,
+ utf8cstr const o_pEntitySiteID,
+ int * const o_pApplianceNum,
+ KMSClusterEntry * const o_pClusterEntryArray)
+{
+ bool bSuccess;
+#if defined(METAWARE)
+ ECPT_TRACE_ENTRY *trace = NULL;
+ ECPT_TRACE(trace, KMSAgent_GetClusterInformation);
+#endif
+
+ if (!i_pProfile)
+ {
+ Log(AUDIT_CLIENT_AGENT_GET_CLUSTER_INFORMATION_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Profile arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (!o_pEntitySiteID || (i_iEntitySiteIDSize <= (KMS_MAX_ENTITY_SITE_ID)))
+ {
+ Log(AUDIT_CLIENT_AGENT_GET_CLUSTER_INFORMATION_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "EntitySiteIDSize arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (i_iClusterEntryArraySize > KMS_MAX_CLUSTER_NUM)
+ {
+ Log(AUDIT_CLIENT_AGENT_GET_CLUSTER_INFORMATION_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "i_iClusterEntryArraySize exceeds KMS_MAX_CLUSTER_NUM");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (!o_pApplianceNum)
+ {
+ Log(AUDIT_CLIENT_AGENT_GET_CLUSTER_INFORMATION_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "ApplianceNum arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (!o_pClusterEntryArray ||
+ (i_iClusterEntryArraySize <= 0))
+ {
+ Log(AUDIT_CLIENT_AGENT_GET_CLUSTER_INFORMATION_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "ClusterEntry or Size arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (!KMSClient_ProfileLoaded(i_pProfile))
+ {
+ RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
+ }
+
+ CAutoMutex oAutoMutex((K_MUTEX_HANDLE) i_pProfile->m_pLock);
+
+ bSuccess = KMSClient_GetClusterInformation(
+ i_pProfile,
+ o_pEntitySiteID,
+ i_iEntitySiteIDSize,
+ o_pApplianceNum,
+ o_pClusterEntryArray,
+ i_iClusterEntryArraySize);
+
+ // KMSClient_GetClusterInformation logs if there was an error
+
+ if (bSuccess)
+ {
+ RETURN(KMS_AGENT_STATUS_OK);
+ }
+
+ RETURN(KMSAgent_GetLastStatusCode(i_pProfile, 0));
+}
+
+extern "C"
+KMS_AGENT_STATUS KMSAgent_SelectAppliance (
+ KMSClientProfile * const i_pProfile,
+ utf8cstr const i_pApplianceAddress)
+{
+ bool bSuccess;
+#if defined(METAWARE)
+ ECPT_TRACE_ENTRY *trace = NULL;
+ ECPT_TRACE(trace, KMSAgent_SelectAppliance);
+#endif
+
+ if (!i_pProfile)
+ {
+ Log(AUDIT_CLIENT_AGENT_SELECT_APPLIANCE_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Profile arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+ if (!i_pApplianceAddress)
+ {
+ Log(AUDIT_CLIENT_AGENT_GET_CLUSTER_INFORMATION_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "ApplianceAddress arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (!KMSClient_ProfileLoaded(i_pProfile))
+ {
+ RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
+ }
+
+ // All modes are supported by this function.
+
+ bSuccess = KMSClient_SelectAppliance(i_pProfile, i_pApplianceAddress);
+
+ if (bSuccess)
+ {
+ RETURN(KMS_AGENT_STATUS_OK);
+ }
+
+ RETURN(KMSAgent_GetLastStatusCode(i_pProfile, 0));
+}
+
+/*---------------------------------------------------------------------------
+ * Function: KMSAgent_LoadProfile
+ *
+ *--------------------------------------------------------------------------*/
+extern "C"
+KMS_AGENT_STATUS 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)
+{
+ bool bSuccess;
+#if defined(METAWARE)
+ ECPT_TRACE_ENTRY *trace = NULL;
+ ECPT_TRACE(trace, KMSAgent_LoadProfile);
+#endif
+
+#if defined(DEBUG) && defined(METAWARE)
+ log_printf("KMSAgent_LoadProfile : Entered");
+#endif
+ if (!io_pProfile ||
+ !i_pProfileName || (strlen(i_pProfileName) <= 0))
+ {
+ Log(AUDIT_CLIENT_AGENT_LOAD_PROFILE_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Profile or Name arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+ if (!i_pInitialApplianceAddress || (strlen(i_pInitialApplianceAddress) <= 0))
+ {
+ Log(AUDIT_CLIENT_AGENT_LOAD_PROFILE_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "InitialApplianceAddress arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (i_iTransactionTimeout <= 0)
+ {
+ Log(AUDIT_CLIENT_AGENT_LOAD_PROFILE_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "TransactionTimeout arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+ if (i_iClusterDiscoveryFrequency < 0)
+ {
+ Log(AUDIT_CLIENT_AGENT_LOAD_PROFILE_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "ClusterDiscoveryFrequency arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ // for enrollment both arguments are required
+ if ((i_pAgentID && !i_pPassphrase) || (i_pPassphrase && !i_pAgentID))
+ {
+ Log(AUDIT_CLIENT_AGENT_LOAD_PROFILE_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Enrollment requires AgentID & Passphrase");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (i_pAgentID && (strlen(i_pAgentID) <= 0))
+ {
+ Log(AUDIT_CLIENT_AGENT_LOAD_PROFILE_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "AgentID arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (i_pPassphrase && (strlen(i_pPassphrase) <= 0))
+ {
+ Log(AUDIT_CLIENT_AGENT_LOAD_PROFILE_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Passphrase arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if ( i_eKMSmode != DEFAULT_MODE && i_eKMSmode != FIPS_MODE )
+ {
+ Log(AUDIT_CLIENT_AGENT_LOAD_PROFILE_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "KMS security mode arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (KMSClient_ProfileLoaded(io_pProfile))
+ {
+ Log(AUDIT_CLIENT_AGENT_LOAD_PROFILE_PROFILE_ALREADY_LOADED,
+ NULL,
+ NULL,
+ "profile is already loaded and should be unloaded first");
+ RETURN(KMS_AGENT_STATUS_PROFILE_ALREADY_LOADED);
+ }
+
+ memset(io_pProfile, 0, sizeof (KMSClientProfile));
+ char sInitialApplianceAddress[KMS_MAX_NETWORK_ADDRESS+1];
+ strncpy(sInitialApplianceAddress, i_pInitialApplianceAddress, sizeof(sInitialApplianceAddress));
+ sInitialApplianceAddress[sizeof(sInitialApplianceAddress)-1] = '\0';
+
+ // Convert to lower case
+
+ for ( size_t i = 0; i < strlen( sInitialApplianceAddress ); i++ )
+ {
+ if ( isupper( sInitialApplianceAddress[i] ) )
+ {
+ sInitialApplianceAddress[i] = tolower( sInitialApplianceAddress[i] );
+ }
+ }
+
+ bSuccess = KMSClient_LoadProfile(
+ io_pProfile,
+ i_pProfileName,
+ i_pAgentID,
+ i_pPassphrase,
+ sInitialApplianceAddress,
+ i_iTransactionTimeout,
+ i_iFailOverLimit,
+ i_iClusterDiscoveryFrequency,
+ i_eKMSmode);
+
+ if (bSuccess)
+ {
+#if defined(DEBUG) && defined(METAWARE)
+ log_printf("KMSAgent_LoadProfile : Returned ok");
+#endif
+ RETURN(KMS_AGENT_STATUS_OK);
+ }
+
+ // when not enrolling & cluster discovery is disabled there are no
+ // soap transactions so failover would not have occurred
+ bool bEnrolling = i_pAgentID && i_pPassphrase;
+
+ if (!bEnrolling &&
+ i_iClusterDiscoveryFrequency == 0)
+ {
+ RETURN(KMSAgent_GetLastStatusCode(io_pProfile, 0));
+ }
+ else
+ {
+// if (i_eKMSmode == FIPS_MODE &&
+// KMSClient_NoFIPSCompatibleKMAs(io_pProfile))
+// {
+// RETURN(KMSAgent_GetLastStatusCode(io_pProfile,
+// CAgentLoadBalancer::NO_FIPS_KMA_AVAILABLE));
+// }
+
+ RETURN(KMSAgent_GetLastStatusCode(io_pProfile,
+ CAgentLoadBalancer::NO_KMA_AVAILABLE));
+ }
+}
+
+/*---------------------------------------------------------------------------
+ * Function: KMSAgent_UnloadProfile
+ *
+ *--------------------------------------------------------------------------*/
+extern "C"
+KMS_AGENT_STATUS KMSAgent_UnloadProfile (KMSClientProfile * const i_pProfile)
+{
+ bool bSuccess;
+#if defined(METAWARE)
+ ECPT_TRACE_ENTRY *trace = NULL;
+ ECPT_TRACE(trace, KMSAgent_UnloadProfile);
+#endif
+
+ if (!i_pProfile)
+ {
+ Log(AUDIT_CLIENT_AGENT_UNLOAD_PROFILE_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Profile arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (!KMSClient_ProfileLoaded(i_pProfile))
+ {
+ RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
+ }
+
+ bSuccess = KMSClient_UnloadProfile(i_pProfile);
+
+ if (bSuccess)
+ {
+ RETURN(KMS_AGENT_STATUS_OK);
+ }
+
+ RETURN(KMSAgent_GetLastStatusCode(i_pProfile, 0));
+}
+
+/*---------------------------------------------------------------------------
+ * Function: KMSAgent_DeleteProfile
+ *
+ *--------------------------------------------------------------------------*/
+extern "C"
+KMS_AGENT_STATUS KMSAgent_DeleteProfile (utf8cstr i_pProfileName)
+{
+ bool bSuccess;
+#if defined(METAWARE)
+ ECPT_TRACE_ENTRY *trace = NULL;
+ ECPT_TRACE(trace, KMSAgent_DeleteProfile);
+#endif
+
+ if (!i_pProfileName || (strlen(i_pProfileName) <= 0))
+ {
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ bSuccess = KMSClient_DeleteProfile(i_pProfileName);
+
+ if (bSuccess)
+ {
+ RETURN(KMS_AGENT_STATUS_OK);
+ }
+
+ RETURN(KMS_AGENT_STATUS_GENERIC_ERROR);
+}
+
+/*---------------------------------------------------------------------------
+ * Function: KMSAgent_ListKeyGroups
+ *
+ *--------------------------------------------------------------------------*/
+
+extern "C"
+KMS_AGENT_STATUS KMSAgent_ListKeyGroups (
+ KMSClientProfile * const i_pProfile,
+ KMSAgent_ArrayOfKeyGroups* * const o_ppKeyGroups)
+{
+ bool bSuccess;
+#if defined(METAWARE)
+ ECPT_TRACE_ENTRY *trace = NULL;
+ ECPT_TRACE(trace, KMSAgent_ListKeyGroups);
+#endif
+
+ int bIsLastPage;
+ struct KMSAgent_QueryParameters stQueryParameters;
+
+ if (!i_pProfile)
+ {
+ Log(AUDIT_CLIENT_AGENT_LIST_KEY_GROUPS_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Profile arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+ if (!o_ppKeyGroups)
+ {
+ Log(AUDIT_CLIENT_AGENT_LIST_KEY_GROUPS_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "KeyGroups arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (!KMSClient_ProfileLoaded(i_pProfile))
+ {
+ RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
+ }
+
+ CAutoMutex oAutoMutex((K_MUTEX_HANDLE) i_pProfile->m_pLock);
+
+ struct soap *pstSoap = (struct soap *) i_pProfile->m_pvSoap;
+
+ // Get Key Groups
+ memset(&stQueryParameters, 0, sizeof (stQueryParameters));
+
+ struct KMS_Agent::KMS_Agent__QueryParameters oQueryParameters;
+ struct KMS_Agent::KMS_Agent__ListKeyGroupsResponse oResponse;
+
+ memset(&oQueryParameters, 0, sizeof (oQueryParameters));
+
+ bSuccess = CopyQueryParametersFromRequest(pstSoap,
+ KMS_MAX_LIST_KEY_GROUPS,
+ &oQueryParameters,
+ &stQueryParameters);
+ if (!bSuccess)
+ {
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+ // no memory, don't log
+ RETURN(KMS_AGENT_STATUS_NO_MEMORY);
+ }
+
+ CAgentLoadBalancer *pLoadBalancer =
+ (CAgentLoadBalancer *) i_pProfile->m_pAgentLoadBalancer;
+
+ int iIndex = pLoadBalancer->Balance();
+
+ if ( iIndex >= 0 )
+ {
+ do
+ {
+ const char* sURL =
+ pLoadBalancer->GetHTTPSURL(iIndex, i_pProfile->m_iPortForAgentService);
+ strncpy(i_pProfile->m_sURL, sURL, sizeof(i_pProfile->m_sURL));
+ i_pProfile->m_sURL[sizeof(i_pProfile->m_sURL)-1] = '\0';
+
+ bSuccess = KMS_Agent::soap_call_KMS_Agent__ListKeyGroups(
+ pstSoap,
+ sURL,
+ NULL,
+ oQueryParameters,
+ oResponse) == SOAP_OK;
+
+ if (!bSuccess)
+ {
+ iIndex = pLoadBalancer->FailOver(iIndex, pstSoap);
+
+ char sKmaAddress[g_iMAX_PEER_NETWORK_ADDRESS_LENGTH];
+ char sSoapFaultMsg[g_iMAX_SOAP_FAULT_MESSAGE_LENGTH];
+
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ GetSoapFault(sSoapFaultMsg, pstSoap);
+
+ LogError(i_pProfile, AUDIT_CLIENT_AGENT_LIST_KEY_GROUPS_SOAP_ERROR,
+ NULL,
+ sKmaAddress,
+ sSoapFaultMsg);
+ }
+ else
+ {
+ pLoadBalancer->UpdateResponseStatus(iIndex);
+ }
+ }
+ while (iIndex >= 0 && (!bSuccess));
+ }
+ else
+ {
+ bSuccess = false;
+ }
+
+ if (bSuccess)
+ {
+ bIsLastPage = oResponse.LastPage;
+
+ *o_ppKeyGroups = CopyKeyGroupsResponse(&oResponse.KeyGroups);
+ if (*o_ppKeyGroups == NULL)
+ {
+ bSuccess = false;
+ // no memory, don't log
+ }
+
+ CopyQueryParametersFromResponse(&stQueryParameters,
+ &oResponse.NextPageQueryParameters);
+ }
+
+ // free allocated memory for output if error condition
+ // Clean up SOAP
+
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+
+ if (bSuccess)
+ RETURN(KMS_AGENT_STATUS_OK);
+
+ RETURN(KMSAgent_GetLastStatusCode(i_pProfile, iIndex));
+}
+
+/*---------------------------------------------------------------------------
+ * Function: KMSAgent_FreeArrayOfKeyGroups
+ *
+ *--------------------------------------------------------------------------*/
+
+extern "C"
+void KMSAgent_FreeArrayOfKeyGroups (
+ struct KMSAgent_ArrayOfKeyGroups *i_pArrayOfKeyGroups)
+{
+#if defined(METAWARE)
+ ECPT_TRACE_ENTRY *trace = NULL;
+ ECPT_TRACE(trace, KMSAgent_FreeArrayOfKeyGroups);
+#endif
+ if (!i_pArrayOfKeyGroups)
+ {
+ return;
+ }
+
+ // free memory for all information groups
+ if (i_pArrayOfKeyGroups->m_pKeyGroups)
+ {
+ free(i_pArrayOfKeyGroups->m_pKeyGroups);
+ }
+
+ free(i_pArrayOfKeyGroups);
+}
+
+extern "C"
+KMS_AGENT_STATUS KMSAgent_CreateKey (
+ KMSClientProfile * const i_pProfile,
+ const KMSAgent_DataUnit * const i_pDataUnit,
+ KEY_GROUP_ID const i_pKeyGroupID,
+ KMSAgent_Key * const o_pKey)
+{
+ bool bSuccess;
+#if defined(METAWARE)
+ ECPT_TRACE_ENTRY *trace = NULL;
+ ECPT_TRACE(trace, KMSAgent_CreateKey);
+#endif
+
+ if (!i_pProfile)
+ {
+ Log(AUDIT_CLIENT_AGENT_CREATE_KEY_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Profile arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+ if (!o_pKey)
+ {
+ Log(AUDIT_CLIENT_AGENT_CREATE_KEY_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Key arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (!KMSClient_ProfileLoaded(i_pProfile))
+ {
+ RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
+ }
+
+ if (i_pKeyGroupID &&
+ strlen(i_pKeyGroupID) > KMS_MAX_KEY_GROUP_ID_SIZE)
+ {
+ Log(AUDIT_CLIENT_AGENT_CREATE_KEY_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "GroupID arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ CAutoMutex oAutoMutex((K_MUTEX_HANDLE) i_pProfile->m_pLock);
+
+ struct KMS_Agent::KMS_Agent__DataUnit
+ stDataUnit = {"", "", "", "",
+ (KMS_Agent::KMS_Agent__DataUnitState) 0};
+
+ struct soap *pstSoap = (struct soap *) i_pProfile->m_pvSoap;
+ struct KMS_Agent::KMS_Agent__CreateKeyResponse oResponse;
+
+ if (i_pDataUnit != NULL)
+ {
+ if (!CopyDataUnitFromRequest(pstSoap,
+ &stDataUnit,
+ i_pDataUnit))
+ {
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+ // no memory dont' log
+ RETURN(KMS_AGENT_STATUS_NO_MEMORY);
+ }
+ }
+
+ char * pKeyGroupID = NULL;
+ if (i_pKeyGroupID)
+ {
+ pKeyGroupID = ConvertUTF8StringFromRequest(pstSoap,
+ i_pKeyGroupID,
+ KMS_MAX_KEY_GROUP_ID_SIZE + 1);
+ if (pKeyGroupID == NULL)
+ {
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+ // no memory dont' log
+ RETURN(KMS_AGENT_STATUS_NO_MEMORY);
+ }
+ }
+
+ CAgentLoadBalancer *pLoadBalancer =
+ (CAgentLoadBalancer *) i_pProfile->m_pAgentLoadBalancer;
+
+ char sKmaAddress[g_iMAX_PEER_NETWORK_ADDRESS_LENGTH];
+ char sSoapFaultMsg[g_iMAX_SOAP_FAULT_MESSAGE_LENGTH];
+
+ int iIndex;
+ UTF8_KEYID acKWKID;
+ bool bClientAESKeyWrapSetupError = false;
+
+ if (i_pDataUnit)
+ {
+ // attempt to maintain affinity with KMA for specified DU ID
+ iIndex = pLoadBalancer->BalanceByDataUnitID(
+ i_pDataUnit->m_acDataUnitID,
+ KMS_DATA_UNIT_ID_SIZE);
+ }
+ else
+ {
+ iIndex = pLoadBalancer->Balance();
+ }
+
+ if (iIndex >= 0)
+ {
+ do
+ {
+ bSuccess = true;
+ const char* sURL = pLoadBalancer->GetHTTPSURL(
+ iIndex,
+ i_pProfile->m_iPortForAgentService);
+
+ strncpy(i_pProfile->m_sURL, sURL, sizeof(i_pProfile->m_sURL));
+
+ i_pProfile->m_sURL[sizeof(i_pProfile->m_sURL)-1] = '\0';
+
+ Long64 lKMAID = pLoadBalancer->GetKMAID(iIndex);
+
+ if (bSuccess && pLoadBalancer->AESKeyWrapSupported(iIndex))
+ {
+ // if this fails we want to utilize normal failover logic, GetKWKID
+ // logs error
+ bSuccess = pLoadBalancer->GetKWKID(iIndex, lKMAID, pstSoap,
+ acKWKID, &bClientAESKeyWrapSetupError) ? true : false;
+ if (bSuccess)
+ {
+ bSuccess = KMS_Agent::soap_call_KMS_Agent__CreateKey2(
+ pstSoap,
+ sURL,
+ NULL,
+ stDataUnit,
+ i_pKeyGroupID ? pKeyGroupID : (char *) "",
+ acKWKID,
+ //NOTE: this is ugly but the soap response struct's are the same for both flavors of CreateKey
+ *(reinterpret_cast<struct KMS_Agent::KMS_Agent__CreateKey2Response *>(&oResponse))) == SOAP_OK;
+ }
+ }
+ else if (bSuccess) // NO AES Key Wrap
+ {
+ bSuccess = KMS_Agent::soap_call_KMS_Agent__CreateKey(
+ pstSoap,
+ sURL,
+ NULL,
+ stDataUnit,
+ i_pKeyGroupID ? pKeyGroupID : (char *) "",
+ oResponse) == SOAP_OK;
+ }
+
+ // don'f failover for Client side AES Key Wrap setup problems
+ if (!bSuccess && !bClientAESKeyWrapSetupError)
+ {
+ iIndex = pLoadBalancer->FailOver(iIndex, pstSoap);
+
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ GetSoapFault(sSoapFaultMsg, pstSoap);
+
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_CREATE_KEY_SOAP_ERROR,
+ NULL,
+ sKmaAddress,
+ sSoapFaultMsg);
+ }
+ if (bSuccess)
+ {
+ pLoadBalancer->UpdateResponseStatus(iIndex);
+ }
+ }
+ while (iIndex >= 0 && (!bSuccess) && (!bClientAESKeyWrapSetupError));
+ }
+ else
+ {
+ bSuccess = false;
+ }
+
+
+#if defined(DEBUG) && defined(METAWARE)
+ log_printf("CreateKey gets keyID %s (size %x) \n",
+ oResponse.Key.KeyID,
+ sizeof (oResponse.Key.KeyID));
+#endif
+
+
+ if (bSuccess)
+ {
+ if (KMS_KEY_ID_SIZE != ConvertUTF8HexStringToBinary(
+ oResponse.Key.KeyID, NULL))
+ {
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_CREATE_KEY_INVALID_KEYID_RESPONSE,
+ NULL,
+ sKmaAddress,
+ NULL);
+ bSuccess = false;
+ }
+
+ ConvertUTF8HexStringToBinary(
+ oResponse.Key.KeyID, // in
+ o_pKey->m_acKeyID); // out
+
+#if defined(DEBUG) && defined(METAWARE)
+ log_printf("CreateKey gets keyState %x (size %x) \n",
+ oResponse.Key.KeyState,
+ sizeof (oResponse.Key.KeyState));
+#endif
+
+ if ((KMS_AGENT_KEY_STATE) oResponse.Key.KeyState < KMS_KEY_STATE_ACTIVE_PROTECT_AND_PROCESS ||
+ (KMS_AGENT_KEY_STATE) oResponse.Key.KeyState > KMS_KEY_STATE_COMPROMISED)
+ {
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_CREATE_KEY_INVALID_KEY_STATE_RESPONSE,
+ NULL,
+ sKmaAddress,
+ NULL);
+ bSuccess = false;
+ }
+
+ o_pKey->m_iKeyState = (KMS_AGENT_KEY_STATE) oResponse.Key.KeyState;
+
+#if defined(DEBUG) && defined(METAWARE)
+ log_printf("CreateKey o_pKey->m_iKeyState %x (size %x) = "
+ "(KMS_AGENT_KEY_STATE) oResponse.Key.KeyState %x (size %x)\n",
+ o_pKey->m_iKeyState,
+ sizeof (o_pKey->m_iKeyState),
+ oResponse.Key.KeyState,
+ sizeof (oResponse.Key.KeyState));
+#endif
+
+
+ if ((KMS_KEY_TYPE) oResponse.Key.KeyType != KMS_KEY_TYPE_AES_256)
+ {
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_CREATE_KEY_INVALID_KEY_TYPE_RESPONSE,
+ NULL,
+ sKmaAddress,
+ NULL);
+ bSuccess = false;
+ }
+ o_pKey->m_iKeyType = (KMS_KEY_TYPE) oResponse.Key.KeyType;
+
+ if (strlen(oResponse.Key.KeyGroupID) > KMS_MAX_KEY_GROUP_ID_SIZE)
+ {
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_CREATE_KEY_INVALID_KEY_GROUP_ID_LENGTH_RESPONSE,
+ NULL,
+ sKmaAddress,
+ NULL);
+ bSuccess = false;
+ }
+ else
+ {
+ strncpy(o_pKey->m_acKeyGroupID,
+ oResponse.Key.KeyGroupID,
+ sizeof(o_pKey->m_acKeyGroupID));
+ o_pKey->m_acKeyGroupID[sizeof(o_pKey->m_acKeyGroupID)-1] = '\0';
+ }
+
+ if ( bSuccess && pLoadBalancer->AESKeyWrapSupported(iIndex))
+ {
+ // verify KWK ID matches what was registered
+ if (oResponse.Key.Key.__size != KMS_MAX_WRAPPED_KEY_SIZE)
+ {
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_CREATE_KEY_INVALID_WRAPPED_KEY_LENGTH_RESPONSE,
+ NULL,
+ sKmaAddress,
+ NULL);
+ bSuccess = false;
+ }
+ else
+ {
+ if (pLoadBalancer->AESKeyUnwrap(&iIndex, oResponse.Key.Key.__ptr,
+ o_pKey->m_acKey) == false)
+ {
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_CREATE_KEY_AESKEYUNWRAP_ERROR,
+ NULL,
+ sKmaAddress,
+ NULL);
+
+ bSuccess = false;
+ }
+ }
+ }
+ else if (bSuccess) // non-AES key wrap
+ {
+ if (oResponse.Key.Key.__size != KMS_MAX_KEY_SIZE)
+ {
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_CREATE_KEY_INVALID_KEY_LENGTH_RESPONSE,
+ NULL,
+ sKmaAddress,
+ NULL);
+ bSuccess = false;
+ }
+ else
+ {
+ memcpy(o_pKey->m_acKey,
+ oResponse.Key.Key.__ptr,
+ KMS_MAX_KEY_SIZE);
+ }
+ }
+
+ if (bSuccess)
+ {
+ o_pKey->m_iKeyLength = KMS_MAX_KEY_SIZE;
+
+ if (KMSAgentKeyCallout(o_pKey->m_acKey) != 0)
+ {
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_CREATE_KEY_KEY_CALLOUT_ERROR,
+ NULL,
+ NULL,
+ NULL);
+ bSuccess = false;
+ }
+ }
+ }
+
+ if (bSuccess)
+ {
+ // add Key ID and the creating KMA IP address to the DU cache
+ CDataUnitCache* pDataUnitCache = (CDataUnitCache*) i_pProfile->m_pDataUnitCache;
+
+ if (i_pProfile->m_iClusterDiscoveryFrequency != 0) // load balancing enabled
+ {
+ bSuccess = pDataUnitCache->Insert(
+ NULL,
+ 0,
+ o_pKey->m_acKeyID,
+ KMS_KEY_ID_SIZE,
+ pLoadBalancer->GetApplianceNetworkAddress(iIndex));
+ }
+ }
+ // free allocated memory for output if error condition
+ // Clean up SOAP
+
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+
+ if (bSuccess)
+ {
+ RETURN(KMS_AGENT_STATUS_OK);
+ }
+
+ RETURN(KMSAgent_GetLastStatusCode(i_pProfile,
+ bClientAESKeyWrapSetupError ?
+ CAgentLoadBalancer::AES_KEY_WRAP_SETUP_ERROR : iIndex));
+}
+
+extern "C"
+KMS_AGENT_STATUS 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)
+{
+ bool bSuccess;
+#if defined(METAWARE)
+ ECPT_TRACE_ENTRY *trace = NULL;
+ ECPT_TRACE(trace, KMSAgent_CreateDataUnit);
+#endif
+
+#if defined(DEBUG) && defined(METAWARE)
+#warn "debug Create Data Unit is on"
+ log_printf("KMSAgent_CreateDataUnit entered\n");
+ log_printf("KMSAgent_CreateDataUnit profile=%x\n", i_pProfile);
+#endif
+
+ if (!i_pProfile)
+ {
+ Log(AUDIT_CLIENT_AGENT_CREATE_DATA_UNIT_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Profile arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+ if (!o_pDataUnit)
+ {
+ Log(AUDIT_CLIENT_AGENT_CREATE_DATA_UNIT_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "DataUnit arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (!KMSClient_ProfileLoaded(i_pProfile))
+ {
+ RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
+ }
+
+ CAutoMutex oAutoMutex((K_MUTEX_HANDLE) i_pProfile->m_pLock);
+
+ // validate input parms
+
+ if (i_pExternalUniqueID &&
+ (i_iExternalUniqueIDIDLen <= 0 ||
+ i_iExternalUniqueIDIDLen > KMS_MAX_EXTERNAL_UNIQUE_ID_SIZE))
+ {
+ Log(AUDIT_CLIENT_AGENT_CREATE_DATA_UNIT_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "ExternalUniqueID arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (i_pExternalTag && strlen(i_pExternalTag) > KMS_MAX_EXTERNAL_TAG)
+ {
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (i_pDescription && strlen(i_pDescription) > KMS_MAX_DESCRIPTION)
+ {
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ struct soap *pstSoap = (struct soap *) i_pProfile->m_pvSoap;
+ struct KMS_Agent::KMS_Agent__CreateDataUnitResponse oResponse;
+
+ char * pExternalUniqueID = NULL;
+ if (i_pExternalUniqueID)
+ {
+ pExternalUniqueID = ConvertBinaryDataFromRequest(pstSoap,
+ i_pExternalUniqueID,
+ i_iExternalUniqueIDIDLen);
+ if (pExternalUniqueID == NULL)
+ {
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+ // no memory dont' log
+ RETURN(KMS_AGENT_STATUS_NO_MEMORY);
+ }
+ }
+
+ char * pExternalTag = NULL;
+ if (i_pExternalTag)
+ {
+ pExternalTag = ConvertUTF8StringFromRequest(pstSoap,
+ i_pExternalTag,
+ strlen(i_pExternalTag) + 1);
+ if (pExternalTag == NULL)
+ {
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+ // no memory dont' log
+ RETURN(KMS_AGENT_STATUS_NO_MEMORY);
+ }
+ }
+
+ char * pDescription = NULL;
+ if (i_pDescription)
+ {
+ pDescription = ConvertUTF8StringFromRequest(pstSoap,
+ i_pDescription,
+ strlen(i_pDescription) + 1);
+ if (pDescription == NULL)
+ {
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+ // no memory dont' log
+ RETURN(KMS_AGENT_STATUS_NO_MEMORY);
+ }
+ }
+
+ CAgentLoadBalancer *pLoadBalancer =
+ (CAgentLoadBalancer *) i_pProfile->m_pAgentLoadBalancer;
+ int iIndex = pLoadBalancer->Balance();
+
+ if (iIndex >= 0)
+ {
+ do
+ {
+ const char* sURL = pLoadBalancer->GetHTTPSURL(
+ iIndex,
+ i_pProfile->m_iPortForAgentService);
+
+ strncpy(i_pProfile->m_sURL, sURL, sizeof(i_pProfile->m_sURL));
+
+ i_pProfile->m_sURL[sizeof(i_pProfile->m_sURL)-1] = '\0';
+
+ bSuccess = KMS_Agent::soap_call_KMS_Agent__CreateDataUnit(
+ pstSoap,
+ sURL,
+ NULL,
+ i_pExternalUniqueID ? pExternalUniqueID : (char *) "",
+ i_pExternalTag ? pExternalTag : (char *) "",
+ i_pDescription ? pDescription : (char *) "",
+ oResponse) == SOAP_OK;
+
+ if (!bSuccess)
+ {
+ iIndex = pLoadBalancer->FailOver(iIndex, pstSoap);
+
+ char sKmaAddress[g_iMAX_PEER_NETWORK_ADDRESS_LENGTH];
+ char sSoapFaultMsg[g_iMAX_SOAP_FAULT_MESSAGE_LENGTH];
+
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ GetSoapFault(sSoapFaultMsg, pstSoap);
+
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_CREATE_DATA_UNIT_SOAP_ERROR,
+ NULL,
+ sKmaAddress,
+ sSoapFaultMsg);
+ }
+ else
+ {
+ pLoadBalancer->UpdateResponseStatus(iIndex);
+ }
+
+ }
+ while (iIndex >= 0 && (!bSuccess));
+ }
+ else
+ {
+ bSuccess = false;
+ }
+
+ if (bSuccess)
+ {
+ int iDataUnitIDLength;
+ iDataUnitIDLength = ConvertUTF8HexStringToBinary(
+ oResponse.DataUnit.DataUnitID, o_pDataUnit->m_acDataUnitID);
+
+ if (iDataUnitIDLength != KMS_DATA_UNIT_ID_SIZE)
+ {
+#if defined(DEBUG) && defined(METAWARE)
+ log_printf("iDataUnitIDLength (%x) != KMS_DATA_UNIT_ID_SIZE (%x)",
+ iDataUnitIDLength,
+ KMS_DATA_UNIT_ID_SIZE);
+#endif
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_CREATE_DATA_UNIT_RESPONSE_INVALID_DU_ID_LENGTH,
+ NULL,
+ NULL,
+ NULL);
+ bSuccess = false;
+ }
+ o_pDataUnit->m_iExternalUniqueIDLength = ConvertUTF8HexStringToBinary(
+ oResponse.DataUnit.ExternalUniqueID, o_pDataUnit->m_acExternalUniqueID);
+
+ if (strlen(oResponse.DataUnit.ExternalTag) > KMS_MAX_EXTERNAL_TAG)
+ {
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_CREATE_DATA_UNIT_RESPONSE_INVALID_EXTERNAL_TAG_LENGTH,
+ NULL,
+ NULL,
+ NULL);
+ bSuccess = false;
+ }
+ else
+ {
+ strncpy(o_pDataUnit->m_acExternalTag,
+ oResponse.DataUnit.ExternalTag,
+ sizeof(o_pDataUnit->m_acExternalTag));
+ o_pDataUnit->m_acExternalTag[sizeof(o_pDataUnit->m_acExternalTag)-1] = '\0';
+ }
+
+ if (strlen(oResponse.DataUnit.Description) > KMS_MAX_DESCRIPTION)
+ {
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_CREATE_DATA_UNIT_RESPONSE_INVALID_DESCRIPTION_LENGTH,
+ NULL,
+ NULL,
+ NULL);
+ bSuccess = false;
+ }
+ else
+ {
+ strcpy(o_pDataUnit->m_acDescription,
+ oResponse.DataUnit.Description);
+ }
+
+ o_pDataUnit->m_iDataUnitState =
+ (KMS_AGENT_DATA_UNIT_STATE) oResponse.DataUnit.DataUnitState;
+ }
+
+ if (bSuccess)
+ {
+ // add data unit ID and the creating KMA IP address to the DU cache
+ CDataUnitCache* pDataUnitCache = (CDataUnitCache*) i_pProfile->m_pDataUnitCache;
+
+ if (i_pProfile->m_iClusterDiscoveryFrequency != 0) // load balancing enabled
+ {
+ bSuccess = pDataUnitCache->Insert(
+ o_pDataUnit->m_acDataUnitID,
+ KMS_DATA_UNIT_ID_SIZE,
+ NULL, 0,
+ pLoadBalancer->GetApplianceNetworkAddress(iIndex));
+ }
+ }
+
+ // free allocated memory for output if error condition
+ // Clean up SOAP
+
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+
+ if (bSuccess)
+ {
+ RETURN(KMS_AGENT_STATUS_OK);
+ }
+
+ RETURN(KMSAgent_GetLastStatusCode(i_pProfile, iIndex));
+}
+
+extern "C"
+KMS_AGENT_STATUS KMSAgent_DisassociateDataUnitKeys (
+ KMSClientProfile * const i_pProfile,
+ const KMSAgent_DataUnit * const i_pDataUnit)
+{
+ bool bSuccess;
+#if defined(METAWARE)
+ ECPT_TRACE_ENTRY *trace = NULL;
+ ECPT_TRACE(trace, KMSAgent_DisassociateDataUnitKeys);
+#endif
+
+ if (!i_pProfile)
+ {
+ Log(AUDIT_CLIENT_AGENT_DISASSOCIATE_DATA_UNIT_KEYS_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Profile arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (!i_pDataUnit)
+ {
+ Log(AUDIT_CLIENT_AGENT_DISASSOCIATE_DATA_UNIT_KEYS_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "DataUnit arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+ if (!KMSClient_ProfileLoaded(i_pProfile))
+ {
+ RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
+ }
+
+ CAutoMutex oAutoMutex((K_MUTEX_HANDLE) i_pProfile->m_pLock);
+
+ struct KMS_Agent::KMS_Agent__DataUnit stDataUnit = {"", "", "", "",
+ (KMS_Agent::KMS_Agent__DataUnitState) 0};
+
+ struct soap *pstSoap = (struct soap *) i_pProfile->m_pvSoap;
+ struct KMS_Agent::KMS_Agent__DisassociateDataUnitKeysResponse oResponse;
+
+ if (!CopyDataUnitFromRequest(pstSoap,
+ &stDataUnit,
+ i_pDataUnit))
+ {
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+ // no memory dont' log
+ RETURN(KMS_AGENT_STATUS_NO_MEMORY);
+ }
+
+ CAgentLoadBalancer *pLoadBalancer =
+ (CAgentLoadBalancer *) i_pProfile->m_pAgentLoadBalancer;
+ int iIndex = pLoadBalancer->BalanceByDataUnitID(
+ i_pDataUnit->m_acDataUnitID,
+ KMS_DATA_UNIT_ID_SIZE);
+
+ if (iIndex >= 0)
+ {
+ do
+ {
+ const char* sURL = pLoadBalancer->GetHTTPSURL(
+ iIndex,
+ i_pProfile->m_iPortForAgentService);
+
+ strncpy(i_pProfile->m_sURL, sURL, sizeof(i_pProfile->m_sURL));
+
+ i_pProfile->m_sURL[sizeof(i_pProfile->m_sURL)-1] = '\0';
+
+ bSuccess = KMS_Agent::soap_call_KMS_Agent__DisassociateDataUnitKeys(
+ pstSoap,
+ sURL,
+ NULL,
+ stDataUnit,
+ oResponse) == SOAP_OK;
+
+ if (!bSuccess)
+ {
+ iIndex = pLoadBalancer->FailOver(iIndex, pstSoap);
+
+ char sKmaAddress[g_iMAX_PEER_NETWORK_ADDRESS_LENGTH];
+ char sSoapFaultMsg[g_iMAX_SOAP_FAULT_MESSAGE_LENGTH];
+
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ GetSoapFault(sSoapFaultMsg, pstSoap);
+
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_DISASSOCIATE_DATA_UNIT_KEYS_SOAP_ERROR,
+ NULL,
+ sKmaAddress,
+ sSoapFaultMsg);
+ }
+ else
+ {
+ pLoadBalancer->UpdateResponseStatus(iIndex);
+ }
+ }
+ while (iIndex >= 0 && (!bSuccess));
+ }
+ else
+ {
+ bSuccess = false;
+ }
+
+ // no response data for this transaction
+
+ // free allocated memory for output if error condition
+ // Clean up SOAP
+
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+
+ if (bSuccess)
+ {
+ RETURN(KMS_AGENT_STATUS_OK);
+ }
+
+ RETURN(KMSAgent_GetLastStatusCode(i_pProfile, iIndex));
+}
+
+extern "C"
+KMS_AGENT_STATUS 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)
+{
+ bool bSuccess;
+
+#if defined(METAWARE)
+ ECPT_TRACE_ENTRY *trace = NULL;
+ ECPT_TRACE(trace, KMSAgent_RetrieveKey);
+#endif
+
+ if (!i_pProfile)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_KEY_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Profile arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+ if (!i_pKeyID)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_KEY_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "KeyID arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+ if (!o_pKey)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_KEY_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Key arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (!KMSClient_ProfileLoaded(i_pProfile))
+ {
+ RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
+ }
+
+ CAutoMutex oAutoMutex((K_MUTEX_HANDLE) i_pProfile->m_pLock);
+
+ if (i_pKeyGroupID &&
+ strlen(i_pKeyGroupID) > KMS_MAX_KEY_GROUP_ID_SIZE)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_KEY_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "GroupID arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ struct KMS_Agent::KMS_Agent__DataUnit stDataUnit = {"", "", "", "",
+ (KMS_Agent::KMS_Agent__DataUnitState) 0};
+
+ struct soap *pstSoap = (struct soap *) i_pProfile->m_pvSoap;
+ struct KMS_Agent::KMS_Agent__RetrieveKeyResponse oResponse;
+
+ char * pKeyID = NULL;
+ pKeyID = ConvertBinaryDataFromRequest(pstSoap,
+ i_pKeyID,
+ KMS_KEY_ID_SIZE);
+ if (pKeyID == NULL)
+ {
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+ // no memory dont' log
+ RETURN(KMS_AGENT_STATUS_NO_MEMORY);
+ }
+
+ if (i_pDataUnit != NULL)
+ {
+ if (!CopyDataUnitFromRequest(pstSoap,
+ &stDataUnit,
+ i_pDataUnit))
+ {
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+ // no memory dont' log
+ RETURN(KMS_AGENT_STATUS_NO_MEMORY);
+ }
+ }
+
+ char * pKeyGroupID = NULL;
+ if (i_pKeyGroupID)
+ {
+ pKeyGroupID = ConvertUTF8StringFromRequest(pstSoap,
+ i_pKeyGroupID,
+ KMS_MAX_KEY_GROUP_ID_SIZE + 1);
+ if (pKeyGroupID == NULL)
+ {
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+ // no memory dont' log
+ RETURN(KMS_AGENT_STATUS_NO_MEMORY);
+ }
+ }
+
+ UTF8_KEYID acKWKID;
+
+ char sKmaAddress[g_iMAX_PEER_NETWORK_ADDRESS_LENGTH];
+ char sSoapFaultMsg[g_iMAX_SOAP_FAULT_MESSAGE_LENGTH];
+ bool bClientAESKeyWrapSetupError = false;
+
+ CAgentLoadBalancer *pLoadBalancer =
+ (CAgentLoadBalancer *) i_pProfile->m_pAgentLoadBalancer;
+ int iIndex = pLoadBalancer->BalanceByDataUnitKeyID(i_pKeyID, KMS_KEY_ID_SIZE);
+
+ if (iIndex >= 0)
+ {
+ do
+ {
+ bSuccess = true;
+ const char* sURL = pLoadBalancer->GetHTTPSURL(
+ iIndex,
+ i_pProfile->m_iPortForAgentService);
+
+ strncpy(i_pProfile->m_sURL, sURL, sizeof(i_pProfile->m_sURL));
+
+ i_pProfile->m_sURL[sizeof(i_pProfile->m_sURL)-1] = '\0';
+
+ Long64 lKMAID = pLoadBalancer->GetKMAID(iIndex);
+
+ if (bSuccess && pLoadBalancer->AESKeyWrapSupported(iIndex))
+ {
+ // if this fails we want to utilize normal failover logic, GetKWKID
+ // logs error
+ bSuccess = pLoadBalancer->GetKWKID(iIndex, lKMAID, pstSoap,
+ acKWKID, &bClientAESKeyWrapSetupError) ? true : false;
+ if (bSuccess)
+ {
+ bSuccess = KMS_Agent::soap_call_KMS_Agent__RetrieveKey2(
+ pstSoap,
+ sURL,
+ NULL,
+ pKeyID,
+ stDataUnit,
+ i_pKeyGroupID ? i_pKeyGroupID : (char *) "",
+ acKWKID,
+ //NOTE: this is ugly but the soap response struct's are the same for both flavors of CreateKey
+ *(reinterpret_cast<struct KMS_Agent::KMS_Agent__RetrieveKey2Response *>(&oResponse))) == SOAP_OK;
+ }
+ }
+ else if (bSuccess) // NO AES Key Wrap
+ {
+ bSuccess = KMS_Agent::soap_call_KMS_Agent__RetrieveKey(
+ pstSoap,
+ sURL,
+ NULL,
+ pKeyID,
+ stDataUnit,
+ i_pKeyGroupID ? i_pKeyGroupID : (char *) "",
+ oResponse) == SOAP_OK;
+ }
+
+ // don'f failover for Client side AES Key Wrap setup problems
+ if (!bSuccess && !bClientAESKeyWrapSetupError)
+ {
+ iIndex = pLoadBalancer->FailOver(iIndex, pstSoap);
+
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ GetSoapFault(sSoapFaultMsg, pstSoap);
+
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_KEY_SOAP_ERROR,
+ NULL,
+ sKmaAddress,
+ sSoapFaultMsg);
+ }
+ if (bSuccess)
+ {
+ pLoadBalancer->UpdateResponseStatus(iIndex);
+ }
+ }
+ while (iIndex >= 0 && (!bSuccess) && (!bClientAESKeyWrapSetupError));
+ }
+ else
+ {
+ bSuccess = false;
+ }
+
+ if (bSuccess)
+ {
+ if (KMS_KEY_ID_SIZE != ConvertUTF8HexStringToBinary(
+ oResponse.Key.KeyID, NULL))
+ {
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_KEY_INVALID_KEYID_RESPONSE,
+ NULL,
+ sKmaAddress,
+ NULL);
+ bSuccess = false;
+ }
+ }
+
+ if (bSuccess)
+ {
+ ConvertUTF8HexStringToBinary(
+ oResponse.Key.KeyID, o_pKey->m_acKeyID);
+
+ //if ( oResponse.Key.KeyState < (KMS_Agent__KeyState)KMS_KEY_STATE_ACTIVE_PROTECT_AND_PROCESS ||
+ // oResponse.Key.KeyState > (KMS_Agent__KeyState)KMS_KEY_STATE_COMPROMISED )
+ if ((KMS_AGENT_KEY_STATE) oResponse.Key.KeyState < KMS_KEY_STATE_ACTIVE_PROTECT_AND_PROCESS ||
+ (KMS_AGENT_KEY_STATE) oResponse.Key.KeyState > KMS_KEY_STATE_COMPROMISED)
+ {
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_KEY_INVALID_KEY_STATE_RESPONSE,
+ NULL,
+ sKmaAddress,
+ NULL);
+ bSuccess = false;
+ }
+
+ o_pKey->m_iKeyState = (KMS_AGENT_KEY_STATE) oResponse.Key.KeyState;
+
+ if ((KMS_KEY_TYPE) oResponse.Key.KeyType != KMS_KEY_TYPE_AES_256)
+ {
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_KEY_INVALID_KEY_TYPE_RESPONSE,
+ NULL,
+ sKmaAddress,
+ NULL);
+ bSuccess = false;
+ }
+
+ o_pKey->m_iKeyType = (KMS_KEY_TYPE) oResponse.Key.KeyType;
+
+ if (strlen(oResponse.Key.KeyGroupID) > KMS_MAX_KEY_GROUP_ID_SIZE)
+ {
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_KEY_INVALID_KEY_GROUP_ID_LENGTH_RESPONSE,
+ NULL,
+ sKmaAddress,
+ NULL);
+ bSuccess = false;
+ }
+ else
+ {
+ strncpy(o_pKey->m_acKeyGroupID,
+ oResponse.Key.KeyGroupID,
+ sizeof(o_pKey->m_acKeyGroupID));
+ o_pKey->m_acKeyGroupID[sizeof(o_pKey->m_acKeyGroupID)-1] = '\0';
+ }
+
+ if ( bSuccess && pLoadBalancer->AESKeyWrapSupported(iIndex))
+ {
+ // verify KWK ID matches what was registered
+ if (oResponse.Key.Key.__size != KMS_MAX_WRAPPED_KEY_SIZE)
+ {
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_KEY_INVALID_WRAPPED_KEY_LENGTH_RESPONSE,
+ NULL,
+ sKmaAddress,
+ NULL);
+ bSuccess = false;
+ }
+ else
+ {
+ if (pLoadBalancer->AESKeyUnwrap(&iIndex, oResponse.Key.Key.__ptr,
+ o_pKey->m_acKey) == false)
+ {
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_KEY_AESKEYUNWRAP_ERROR,
+ NULL,
+ sKmaAddress,
+ NULL);
+
+ bSuccess = false;
+ }
+ }
+ }
+ else if (bSuccess) // non-AES key wrap
+ {
+ if (oResponse.Key.Key.__size != KMS_MAX_KEY_SIZE)
+ {
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_KEY_INVALID_KEY_LENGTH_RESPONSE,
+ NULL,
+ sKmaAddress,
+ NULL);
+ bSuccess = false;
+ }
+ else
+ {
+ memcpy(o_pKey->m_acKey,
+ oResponse.Key.Key.__ptr,
+ KMS_MAX_KEY_SIZE);
+ }
+ }
+
+ if (bSuccess)
+ {
+ o_pKey->m_iKeyLength = KMS_MAX_KEY_SIZE;
+
+ if (KMSAgentKeyCallout(o_pKey->m_acKey) != 0)
+ {
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_KEY_KEY_CALLOUT_ERROR,
+ NULL,
+ NULL,
+ NULL);
+ bSuccess = false;
+ }
+ }
+ }
+
+ // free allocated memory for output if error condition
+ // Clean up SOAP
+
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+
+ if (bSuccess)
+ {
+ RETURN(KMS_AGENT_STATUS_OK);
+ }
+
+ RETURN(KMSAgent_GetLastStatusCode(i_pProfile,
+ bClientAESKeyWrapSetupError ?
+ CAgentLoadBalancer::AES_KEY_WRAP_SETUP_ERROR : iIndex));
+}
+
+extern "C"
+KMS_AGENT_STATUS 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)
+{
+ bool bSuccess;
+#if defined(METAWARE)
+ ECPT_TRACE_ENTRY *trace = NULL;
+ ECPT_TRACE(trace, KMSAgent_RetrieveDataUnit);
+#endif
+
+#if defined(DEBUG) && defined(METAWARE)
+ log_printf("KMSAgent_RetrieveDataUnit entered\n");
+#endif
+
+ // required parms
+ if (!i_pProfile)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Profile arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+ if (!i_pDataUnitID)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "DataUnitID arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+ if (!o_pDataUnit)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "DataUnit arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+
+
+ if (!KMSClient_ProfileLoaded(i_pProfile))
+ {
+#if defined(DEBUG) && defined(METAWARE)
+ log_printf("KMSAgent_RetrieveDataUnit profile not loaded\n");
+#endif
+ RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
+ }
+
+ CAutoMutex oAutoMutex((K_MUTEX_HANDLE) i_pProfile->m_pLock);
+
+ // validate input parms
+
+ if (i_pExternalUniqueID &&
+ (i_iExternalUniqueIDLen <= 0 ||
+ i_iExternalUniqueIDLen > KMS_MAX_EXTERNAL_UNIQUE_ID_SIZE))
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "ExternalUniqueID arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (i_pExternalTag && strlen(i_pExternalTag) > KMS_MAX_EXTERNAL_TAG)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "ExternalTag arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (i_pDescription &&
+ strlen(i_pDescription) > KMS_MAX_DESCRIPTION)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Description arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ // prepare args to soap transaction
+
+ struct soap *pstSoap = (struct soap *) i_pProfile->m_pvSoap;
+ struct KMS_Agent::KMS_Agent__RetrieveDataUnitResponse oResponse;
+
+ char * pDataUnitID = NULL;
+ pDataUnitID = ConvertBinaryDataFromRequest(pstSoap,
+ i_pDataUnitID,
+ KMS_DATA_UNIT_ID_SIZE);
+ //sizeof(DATA_UNIT_ID) );
+ if (pDataUnitID == NULL)
+ {
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+ // no memory dont' log
+ RETURN(KMS_AGENT_STATUS_NO_MEMORY);
+ }
+
+ char * pExternalUniqueID = NULL;
+ if (i_pExternalUniqueID)
+ {
+ pExternalUniqueID = ConvertBinaryDataFromRequest(pstSoap,
+ i_pExternalUniqueID,
+ i_iExternalUniqueIDLen);
+ if (pExternalUniqueID == NULL)
+ {
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+ // no memory dont' log
+ RETURN(KMS_AGENT_STATUS_NO_MEMORY);
+ }
+ }
+
+ char * pExternalTag = NULL;
+ if (i_pExternalTag)
+ {
+ pExternalTag = ConvertUTF8StringFromRequest(pstSoap,
+ i_pExternalTag,
+ KMS_MAX_EXTERNAL_TAG + 1);
+ if (pExternalTag == NULL)
+ {
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+ // no memory dont' log
+ RETURN(KMS_AGENT_STATUS_NO_MEMORY);
+ }
+ }
+
+ char * pDescription = NULL;
+ if (i_pDescription)
+ {
+ pDescription = ConvertUTF8StringFromRequest(pstSoap,
+ i_pDescription,
+ KMS_MAX_DESCRIPTION + 1);
+ if (pDescription == NULL)
+ {
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+ // no memory dont' log
+ RETURN(KMS_AGENT_STATUS_NO_MEMORY);
+ }
+ }
+
+ CAgentLoadBalancer *pLoadBalancer =
+ (CAgentLoadBalancer *) i_pProfile->m_pAgentLoadBalancer;
+ int iIndex = pLoadBalancer->BalanceByDataUnitID(i_pDataUnitID,
+ KMS_DATA_UNIT_ID_SIZE);
+
+ if ( iIndex >= 0 )
+ {
+ do
+ {
+ const char* sURL = pLoadBalancer->GetHTTPSURL(
+ iIndex,
+ i_pProfile->m_iPortForAgentService);
+
+ strncpy(i_pProfile->m_sURL, sURL, sizeof(i_pProfile->m_sURL));
+
+ i_pProfile->m_sURL[sizeof(i_pProfile->m_sURL)-1] = '\0';
+
+ bSuccess = KMS_Agent::soap_call_KMS_Agent__RetrieveDataUnit(
+ pstSoap,
+ sURL,
+ NULL,
+ pDataUnitID,
+ i_pExternalUniqueID ? pExternalUniqueID : (char *) "",
+ i_pExternalTag ? pExternalTag : (char *) "",
+ i_pDescription ? pDescription : (char *) "",
+ oResponse) == SOAP_OK;
+
+ if (!bSuccess)
+ {
+ iIndex = pLoadBalancer->FailOver(iIndex, pstSoap);
+
+ char sKmaAddress[g_iMAX_PEER_NETWORK_ADDRESS_LENGTH];
+ char sSoapFaultMsg[g_iMAX_SOAP_FAULT_MESSAGE_LENGTH];
+
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ GetSoapFault(sSoapFaultMsg, pstSoap);
+
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_SOAP_ERROR,
+ NULL,
+ sKmaAddress,
+ sSoapFaultMsg);
+ }
+ else
+ {
+ pLoadBalancer->UpdateResponseStatus(iIndex);
+ }
+ }
+ while (iIndex >= 0 && (!bSuccess));
+ }
+ else
+ {
+ bSuccess = false;
+ }
+
+ if (bSuccess)
+ {
+ ConvertUTF8HexStringToBinary(
+ oResponse.DataUnit.DataUnitID, o_pDataUnit->m_acDataUnitID);
+
+ o_pDataUnit->m_iExternalUniqueIDLength = ConvertUTF8HexStringToBinary(
+ oResponse.DataUnit.ExternalUniqueID, o_pDataUnit->m_acExternalUniqueID);
+
+ if (strlen(oResponse.DataUnit.ExternalTag) > KMS_MAX_EXTERNAL_TAG)
+ {
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_RESPONSE_INVALID_EXTERNAL_TAG_LENGTH,
+ NULL,
+ NULL,
+ NULL);
+ bSuccess = false;
+ }
+ else
+ {
+ strncpy(o_pDataUnit->m_acExternalTag,
+ oResponse.DataUnit.ExternalTag,
+ sizeof(o_pDataUnit->m_acExternalTag));
+ o_pDataUnit->m_acExternalTag[sizeof(o_pDataUnit->m_acExternalTag)-1] = '\0';
+ }
+
+ if (strlen(oResponse.DataUnit.Description) > KMS_MAX_DESCRIPTION)
+ {
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_RESPONSE_INVALID_DESCRIPTION_LENGTH,
+ NULL,
+ NULL,
+ NULL);
+ bSuccess = false;
+ }
+ else
+ {
+ strcpy(o_pDataUnit->m_acDescription,
+ oResponse.DataUnit.Description);
+ }
+
+ o_pDataUnit->m_iDataUnitState =
+ (KMS_AGENT_DATA_UNIT_STATE) oResponse.DataUnit.DataUnitState;
+ }
+
+ // free allocated memory for output if error condition
+ // Clean up SOAP
+
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+
+ if (bSuccess)
+ {
+ RETURN(KMS_AGENT_STATUS_OK);
+ }
+
+ RETURN(KMSAgent_GetLastStatusCode(i_pProfile, iIndex));
+}
+
+extern "C"
+KMS_AGENT_STATUS 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)
+{
+ bool bSuccess;
+#if defined(METAWARE)
+ ECPT_TRACE_ENTRY *trace = NULL;
+ ECPT_TRACE(trace, KMSAgent_RetrieveDataUnitByExternalUniqueID);
+#endif
+
+ // required parms
+ if (!i_pProfile)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_BY_EXTERNAL_UNIQUE_ID_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Profile arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+ if (!i_pExternalUniqueID)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_BY_EXTERNAL_UNIQUE_ID_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "ExternalUniqueID arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+ if (!o_pDataUnit)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_BY_EXTERNAL_UNIQUE_ID_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "DataUnit arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (!KMSClient_ProfileLoaded(i_pProfile))
+ {
+ RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
+ }
+
+ CAutoMutex oAutoMutex((K_MUTEX_HANDLE) i_pProfile->m_pLock);
+
+ // validate input parms
+
+ if (i_iExternalUniqueIDLen <= 0 ||
+ i_iExternalUniqueIDLen > KMS_MAX_EXTERNAL_UNIQUE_ID_SIZE)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_BY_EXTERNAL_UNIQUE_ID_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "ExternalUniqueIDLen arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (i_pExternalTag && strlen(i_pExternalTag) > KMS_MAX_EXTERNAL_TAG)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_BY_EXTERNAL_UNIQUE_ID_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "ExternalTag arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (i_pDescription &&
+ strlen(i_pDescription) > KMS_MAX_DESCRIPTION)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_BY_EXTERNAL_UNIQUE_ID_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Description arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ // prepare args to soap transaction
+
+ struct soap *pstSoap = (struct soap *) i_pProfile->m_pvSoap;
+ struct KMS_Agent::KMS_Agent__RetrieveDataUnitByExternalUniqueIDResponse oResponse;
+
+ char * pExternalUniqueID = NULL;
+ pExternalUniqueID = ConvertBinaryDataFromRequest(pstSoap,
+ i_pExternalUniqueID,
+ i_iExternalUniqueIDLen);
+ if (pExternalUniqueID == NULL)
+ {
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+ // no memory dont' log
+ RETURN(KMS_AGENT_STATUS_NO_MEMORY);
+ }
+
+ char * pExternalTag = NULL;
+ if (i_pExternalTag)
+ {
+ pExternalTag = ConvertUTF8StringFromRequest(pstSoap,
+ i_pExternalTag,
+ KMS_MAX_EXTERNAL_TAG + 1);
+ if (pExternalTag == NULL)
+ {
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+ // no memory dont' log
+ RETURN(KMS_AGENT_STATUS_NO_MEMORY);
+ }
+ }
+
+ char * pDescription = NULL;
+ if (i_pDescription)
+ {
+ pDescription = ConvertUTF8StringFromRequest(pstSoap,
+ i_pDescription,
+ KMS_MAX_DESCRIPTION + 1);
+ if (pDescription == NULL)
+ {
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+ // no memory dont' log
+ RETURN(KMS_AGENT_STATUS_NO_MEMORY);
+ }
+ }
+
+ CAgentLoadBalancer *pLoadBalancer =
+ (CAgentLoadBalancer *) i_pProfile->m_pAgentLoadBalancer;
+ int iIndex = pLoadBalancer->Balance();
+
+ if ( iIndex >= 0 )
+ {
+ do
+ {
+ const char* sURL = pLoadBalancer->GetHTTPSURL(
+ iIndex,
+ i_pProfile->m_iPortForAgentService);
+
+ strncpy(i_pProfile->m_sURL, sURL, sizeof(i_pProfile->m_sURL));
+
+ i_pProfile->m_sURL[sizeof(i_pProfile->m_sURL)-1] = '\0';
+
+ bSuccess = KMS_Agent::
+ soap_call_KMS_Agent__RetrieveDataUnitByExternalUniqueID(
+ pstSoap,
+ sURL,
+ NULL,
+ pExternalUniqueID,
+ i_pExternalTag ? pExternalTag : (char *) "",
+ i_pDescription ? pDescription : (char *) "",
+ oResponse) == SOAP_OK;
+
+ if (!bSuccess)
+ {
+ iIndex = pLoadBalancer->FailOver(iIndex, pstSoap);
+
+ char sKmaAddress[g_iMAX_PEER_NETWORK_ADDRESS_LENGTH];
+ char sSoapFaultMsg[g_iMAX_SOAP_FAULT_MESSAGE_LENGTH];
+
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ GetSoapFault(sSoapFaultMsg, pstSoap);
+
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_BY_EXTERNAL_UNIQUE_ID_SOAP_ERROR,
+ NULL,
+ sKmaAddress,
+ sSoapFaultMsg);
+ }
+ else
+ {
+ pLoadBalancer->UpdateResponseStatus(iIndex);
+ }
+ }
+ while (iIndex >= 0 && (!bSuccess));
+ }
+ else
+ {
+ bSuccess = false;
+ }
+
+ if (bSuccess)
+ {
+ ConvertUTF8HexStringToBinary(
+ oResponse.DataUnit.DataUnitID, o_pDataUnit->m_acDataUnitID);
+
+ o_pDataUnit->m_iExternalUniqueIDLength = ConvertUTF8HexStringToBinary(
+ oResponse.DataUnit.ExternalUniqueID,
+ o_pDataUnit->m_acExternalUniqueID);
+
+ if (strlen(oResponse.DataUnit.ExternalTag) > KMS_MAX_EXTERNAL_TAG)
+ {
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_BY_EXTERNAL_UNIQUE_ID_RESPONSE_INVALID_EXTERNAL_TAG_LENGTH,
+ NULL,
+ NULL,
+ NULL);
+ bSuccess = false;
+ }
+ else
+ {
+ strncpy(o_pDataUnit->m_acExternalTag,
+ oResponse.DataUnit.ExternalTag,
+ sizeof(o_pDataUnit->m_acExternalTag));
+ o_pDataUnit->m_acExternalTag[sizeof(o_pDataUnit->m_acExternalTag)-1] = '\0';
+ }
+
+ if (strlen(oResponse.DataUnit.Description) > KMS_MAX_DESCRIPTION)
+ {
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_BY_EXTERNAL_UNIQUE_ID_RESPONSE_INVALID_DESCRIPTION_LENGTH,
+ NULL,
+ NULL,
+ NULL);
+ bSuccess = false;
+ }
+ else
+ {
+ strcpy(o_pDataUnit->m_acDescription,
+ oResponse.DataUnit.Description);
+ }
+
+ o_pDataUnit->m_iDataUnitState =
+ (KMS_AGENT_DATA_UNIT_STATE) oResponse.DataUnit.DataUnitState;
+
+ if (bSuccess)
+ {
+ // RetrieveDataUnitByExternalUniqueID may create a DU so add data unit ID
+ // and the KMA IP address to the DU cache
+ CDataUnitCache* pDataUnitCache = (CDataUnitCache*) i_pProfile->m_pDataUnitCache;
+
+ if (i_pProfile->m_iClusterDiscoveryFrequency != 0) // load balancing enabled
+ {
+ bSuccess = pDataUnitCache->Insert(
+ o_pDataUnit->m_acDataUnitID,
+ KMS_DATA_UNIT_ID_SIZE,
+ NULL, 0,
+ pLoadBalancer->GetApplianceNetworkAddress(iIndex));
+ }
+ }
+ }
+
+ // free allocated memory for output if error condition
+ // Clean up SOAP
+
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+
+ if (bSuccess)
+ {
+ RETURN(KMS_AGENT_STATUS_OK);
+ }
+
+ RETURN(KMSAgent_GetLastStatusCode(i_pProfile, iIndex));
+}
+
+extern "C"
+KMS_AGENT_STATUS 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)
+{
+ bool bSuccess;
+#if defined(METAWARE)
+ ECPT_TRACE_ENTRY *trace = NULL;
+ ECPT_TRACE(trace, KMSAgent_RetrieveDataUnitKeys);
+#endif
+
+ if (!i_pProfile)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Profile arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+ if (!i_pDataUnit)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "DataUnit arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+ if (!o_piKeysRemaining)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "KeysRemaining arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+ if (!o_ppKeys)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Keys arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+ if (i_pKeyID && i_iPageOffset != 0)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "KeyID and PageOffset are mutually exclusive");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (!KMSClient_ProfileLoaded(i_pProfile))
+ {
+ RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
+ }
+
+ CAutoMutex oAutoMutex((K_MUTEX_HANDLE) i_pProfile->m_pLock);
+
+ // validate input parms
+
+ if (i_iPageSize <= 0 || i_iPageSize > KMS_MAX_PAGE_SIZE)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "PageSize arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (i_iPageOffset < 0)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "PageOffset arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ // prepare args to soap transaction
+
+ struct KMS_Agent::KMS_Agent__DataUnit stDataUnit = {"", "", "", "",
+ (KMS_Agent::KMS_Agent__DataUnitState) 0};
+
+ struct soap *pstSoap = (struct soap *) i_pProfile->m_pvSoap;
+ struct KMS_Agent::KMS_Agent__RetrieveDataUnitKeysResponse oResponse;
+
+ if (!CopyDataUnitFromRequest(pstSoap,
+ &stDataUnit,
+ i_pDataUnit))
+ {
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+ // no memory dont' log
+ RETURN(KMS_AGENT_STATUS_NO_MEMORY);
+ }
+
+ char * pKeyID = NULL;
+ if (i_pKeyID)
+ {
+ pKeyID = ConvertBinaryDataFromRequest(pstSoap,
+ i_pKeyID,
+ KMS_KEY_ID_SIZE);
+ if (pKeyID == NULL)
+ {
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+ // no memory dont' log
+ RETURN(KMS_AGENT_STATUS_NO_MEMORY);
+ }
+ }
+
+ UTF8_KEYID acKWKID;
+ char sKmaAddress[g_iMAX_PEER_NETWORK_ADDRESS_LENGTH];
+ char sSoapFaultMsg[g_iMAX_SOAP_FAULT_MESSAGE_LENGTH];
+ bool bClientAESKeyWrapSetupError = false;
+
+ CAgentLoadBalancer *pLoadBalancer =
+ (CAgentLoadBalancer *) i_pProfile->m_pAgentLoadBalancer;
+
+ int iIndex = pLoadBalancer->BalanceByDataUnitID(i_pDataUnit->m_acDataUnitID,
+ KMS_DATA_UNIT_ID_SIZE);
+
+ if (iIndex >= 0)
+ {
+ do
+ {
+ bSuccess = true;
+
+ const char* sURL = pLoadBalancer->GetHTTPSURL(
+ iIndex,
+ i_pProfile->m_iPortForAgentService);
+
+ strncpy(i_pProfile->m_sURL, sURL, sizeof(i_pProfile->m_sURL));
+
+ i_pProfile->m_sURL[sizeof(i_pProfile->m_sURL)-1] = 0;
+
+ Long64 lKMAID = pLoadBalancer->GetKMAID(iIndex);
+
+ if (bSuccess && pLoadBalancer->AESKeyWrapSupported(iIndex))
+ {
+ // if this fails we want to utilize normal failover logic, GetKWKID
+ // logs error
+ bSuccess = pLoadBalancer->GetKWKID(iIndex, lKMAID, pstSoap,
+ acKWKID, &bClientAESKeyWrapSetupError) ? true : false;
+ if (bSuccess)
+ {
+ bSuccess = KMS_Agent::soap_call_KMS_Agent__RetrieveDataUnitKeys2(
+ pstSoap,
+ sURL,
+ NULL,
+ stDataUnit,
+ i_iPageSize,
+ i_iPageOffset,
+ pKeyID,
+ acKWKID,
+ *(reinterpret_cast<struct KMS_Agent::KMS_Agent__RetrieveDataUnitKeys2Response *>(&oResponse))) == SOAP_OK;
+ }
+ }
+ else if (bSuccess) // No AES Key Wrap
+ {
+ bSuccess = KMS_Agent::soap_call_KMS_Agent__RetrieveDataUnitKeys(
+ pstSoap,
+ sURL,
+ NULL,
+ stDataUnit,
+ i_iPageSize,
+ i_iPageOffset,
+ pKeyID,
+ oResponse) == SOAP_OK;
+ }
+
+ // don'f failover for Client side AES Key Wrap setup problems
+ if (!bSuccess && !bClientAESKeyWrapSetupError)
+ {
+ iIndex = pLoadBalancer->FailOver(iIndex, pstSoap);
+
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ GetSoapFault(sSoapFaultMsg, pstSoap);
+
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_SOAP_ERROR,
+ NULL,
+ sKmaAddress,
+ sSoapFaultMsg);
+ }
+ if (bSuccess)
+ {
+ pLoadBalancer->UpdateResponseStatus(iIndex);
+ }
+ }
+ while (iIndex >= 0 && (!bSuccess) && (!bClientAESKeyWrapSetupError));
+ }
+ else
+ {
+ bSuccess = false;
+ }
+
+ // validate response
+
+ if (bSuccess && oResponse.KeysRemaining < 0)
+ {
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_KEYS_REMAINING_RESPONSE,
+ NULL,
+ NULL,
+ NULL);
+ bSuccess = false;
+ }
+
+ if (bSuccess &&
+ (oResponse.Keys.__size < 0 ||
+ oResponse.Keys.__size > i_iPageSize))
+ {
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_DATA_UNIT_KEYS_INVALID_KEYS_SIZE_RESPONSE,
+ NULL,
+ NULL,
+ NULL);
+ bSuccess = false;
+ }
+
+ if ( bSuccess && pLoadBalancer->AESKeyWrapSupported(iIndex))
+ {
+ // verify KWK ID matches what was registered
+ }
+
+ if (bSuccess)
+ {
+ *o_ppKeys = CopyDataUnitKeysResponse(i_pProfile, &iIndex, &oResponse.Keys);
+
+ if (*o_ppKeys == NULL)
+ {
+ // CopyDataUnitKeysResponse logs errors
+ bSuccess = false;
+ }
+ *o_piKeysRemaining = (int) oResponse.KeysRemaining;
+ }
+
+ // free allocated memory for output if error condition
+ // Clean up SOAP
+
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+
+ if (bSuccess)
+ {
+ RETURN(KMS_AGENT_STATUS_OK);
+ }
+
+ RETURN(KMSAgent_GetLastStatusCode(i_pProfile,
+ bClientAESKeyWrapSetupError ?
+ CAgentLoadBalancer::AES_KEY_WRAP_SETUP_ERROR : iIndex));
+}
+
+extern "C"
+KMS_AGENT_STATUS KMSAgent_RetrieveProtectAndProcessKey (
+ KMSClientProfile * const i_pProfile,
+ const KMSAgent_DataUnit * const i_pDataUnit,
+ utf8cstr const i_pKeyGroupID,
+ KMSAgent_Key * const o_pKey)
+{
+ bool bSuccess;
+#if defined(METAWARE)
+ ECPT_TRACE_ENTRY *trace = NULL;
+ ECPT_TRACE(trace, KMSAgent_RetrieveProtectAndProcessKey);
+#endif
+
+ if (!i_pProfile || !i_pDataUnit || !o_pKey)
+ {
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (!i_pProfile)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Profile arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+ if (!i_pDataUnit)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "DataUnit arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+ if (!o_pKey)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Key arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (i_pKeyGroupID &&
+ strlen(i_pKeyGroupID) > KMS_MAX_KEY_GROUP_ID_SIZE)
+ {
+ Log(AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "GroupID arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (!KMSClient_ProfileLoaded(i_pProfile))
+ {
+ RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
+ }
+
+ CAutoMutex oAutoMutex((K_MUTEX_HANDLE) i_pProfile->m_pLock);
+
+ struct KMS_Agent::KMS_Agent__DataUnit stDataUnit ={"", "", "", "",
+ (KMS_Agent::KMS_Agent__DataUnitState) 0};
+
+ struct soap *pstSoap = (struct soap *) i_pProfile->m_pvSoap;
+ struct KMS_Agent::KMS_Agent__RetrieveProtectAndProcessKeyResponse oResponse;
+
+ if (i_pDataUnit != NULL)
+ {
+ if (!CopyDataUnitFromRequest(pstSoap,
+ &stDataUnit,
+ i_pDataUnit))
+ {
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+ // no memory dont' log
+ RETURN(KMS_AGENT_STATUS_NO_MEMORY);
+ }
+ }
+
+ char * pKeyGroupID = NULL;
+ if (i_pKeyGroupID)
+ {
+ pKeyGroupID = ConvertUTF8StringFromRequest(pstSoap,
+ i_pKeyGroupID,
+ KMS_MAX_KEY_GROUP_ID_SIZE + 1);
+ if (pKeyGroupID == NULL)
+ {
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+ // no memory dont' log
+ RETURN(KMS_AGENT_STATUS_NO_MEMORY);
+ }
+ }
+
+ char sKmaAddress[g_iMAX_PEER_NETWORK_ADDRESS_LENGTH];
+ char sSoapFaultMsg[g_iMAX_SOAP_FAULT_MESSAGE_LENGTH];
+ bool bClientAESKeyWrapSetupError = false;
+ UTF8_KEYID acKWKID;
+
+ CAgentLoadBalancer *pLoadBalancer = (CAgentLoadBalancer *) i_pProfile->m_pAgentLoadBalancer;
+ int iIndex = pLoadBalancer->BalanceByDataUnitID(i_pDataUnit->m_acDataUnitID,
+ KMS_DATA_UNIT_ID_SIZE);
+
+ if (iIndex >= 0)
+ {
+ do
+ {
+ bSuccess = true;
+ const char* sURL = pLoadBalancer->GetHTTPSURL(
+ iIndex,
+ i_pProfile->m_iPortForAgentService);
+
+ strncpy(i_pProfile->m_sURL, sURL, sizeof(i_pProfile->m_sURL));
+
+ i_pProfile->m_sURL[sizeof(i_pProfile->m_sURL)-1] = '\0';
+
+ Long64 lKMAID = pLoadBalancer->GetKMAID(iIndex);
+
+ if (bSuccess && pLoadBalancer->AESKeyWrapSupported(iIndex))
+ {
+ // if this fails we want to utilize normal failover logic, GetKWKID
+ // logs error
+ bSuccess = pLoadBalancer->GetKWKID(iIndex, lKMAID, pstSoap,
+ acKWKID, &bClientAESKeyWrapSetupError)
+ ? true : false;
+ if (bSuccess)
+ {
+ bSuccess = KMS_Agent::soap_call_KMS_Agent__RetrieveProtectAndProcessKey2(
+ pstSoap,
+ sURL,
+ NULL,
+ stDataUnit,
+ i_pKeyGroupID ? i_pKeyGroupID : (char *) "",
+ acKWKID,
+ *(reinterpret_cast<struct KMS_Agent::KMS_Agent__RetrieveProtectAndProcessKey2Response *>(&oResponse))) == SOAP_OK;
+ }
+ }
+ else if (bSuccess) // No AES Key Wrap
+ {
+ bSuccess = KMS_Agent::soap_call_KMS_Agent__RetrieveProtectAndProcessKey(
+ pstSoap,
+ sURL,
+ NULL,
+ stDataUnit,
+ i_pKeyGroupID ? i_pKeyGroupID : (char *) "",
+ oResponse) == SOAP_OK;
+ }
+
+ // don'f failover for Client side AES Key Wrap setup problems
+ if (!bSuccess && !bClientAESKeyWrapSetupError)
+ {
+ iIndex = pLoadBalancer->FailOver(iIndex, pstSoap);
+
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ GetSoapFault(sSoapFaultMsg, pstSoap);
+
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_SOAP_ERROR,
+ NULL,
+ sKmaAddress,
+ sSoapFaultMsg);
+ }
+ else
+ {
+ pLoadBalancer->UpdateResponseStatus(iIndex);
+ }
+ }
+ while (iIndex >= 0 && (!bSuccess) && (!bClientAESKeyWrapSetupError));
+ }
+ else
+ {
+ bSuccess = false;
+ }
+
+ if (bSuccess)
+ {
+ if (KMS_KEY_ID_SIZE != ConvertUTF8HexStringToBinary(
+ oResponse.Key.KeyID, NULL))
+ {
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_INVALID_KEYID_RESPONSE,
+ NULL,
+ sKmaAddress,
+ NULL);
+ bSuccess = false;
+ }
+ }
+
+ if (bSuccess)
+ {
+ ConvertUTF8HexStringToBinary(
+ oResponse.Key.KeyID, o_pKey->m_acKeyID);
+
+ if ((KMS_AGENT_KEY_STATE) oResponse.Key.KeyState < KMS_KEY_STATE_ACTIVE_PROTECT_AND_PROCESS ||
+ (KMS_AGENT_KEY_STATE) oResponse.Key.KeyState > KMS_KEY_STATE_COMPROMISED)
+ {
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_INVALID_KEY_STATE_RESPONSE,
+ NULL,
+ sKmaAddress,
+ NULL);
+ bSuccess = false;
+ }
+
+ o_pKey->m_iKeyState = (KMS_AGENT_KEY_STATE) oResponse.Key.KeyState;
+
+ if ((KMS_KEY_TYPE) oResponse.Key.KeyType != KMS_KEY_TYPE_AES_256)
+ {
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_INVALID_KEY_TYPE_RESPONSE,
+ NULL,
+ sKmaAddress,
+ NULL);
+ bSuccess = false;
+ }
+
+ o_pKey->m_iKeyType = (KMS_KEY_TYPE) oResponse.Key.KeyType;
+
+ if (strlen(oResponse.Key.KeyGroupID) > KMS_MAX_KEY_GROUP_ID_SIZE)
+ {
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_INVALID_KEY_GROUP_ID_LENGTH_RESPONSE,
+ NULL,
+ sKmaAddress,
+ NULL);
+ bSuccess = false;
+ }
+ else
+ {
+ strncpy(o_pKey->m_acKeyGroupID,
+ oResponse.Key.KeyGroupID,
+ sizeof(o_pKey->m_acKeyGroupID));
+ o_pKey->m_acKeyGroupID[sizeof(o_pKey->m_acKeyGroupID)-1] = '\0';
+ }
+
+ if ( bSuccess && pLoadBalancer->AESKeyWrapSupported(iIndex))
+ {
+ // verify KWK ID matches what was registered
+ if (oResponse.Key.Key.__size != KMS_MAX_WRAPPED_KEY_SIZE)
+ {
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_INVALID_WRAPPED_KEY_LENGTH_RESPONSE,
+ NULL,
+ sKmaAddress,
+ NULL);
+ bSuccess = false;
+ }
+ else
+ {
+ if (pLoadBalancer->AESKeyUnwrap(&iIndex, oResponse.Key.Key.__ptr,
+ o_pKey->m_acKey) == false)
+ {
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_AESKEYUNWRAP_ERROR,
+ NULL,
+ sKmaAddress,
+ NULL);
+
+ bSuccess = false;
+ }
+ }
+ }
+ else if (bSuccess) // non-AES key wrap
+ {
+ if (oResponse.Key.Key.__size != KMS_MAX_KEY_SIZE)
+ {
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_INVALID_KEY_LENGTH_RESPONSE,
+ NULL,
+ sKmaAddress,
+ NULL);
+ bSuccess = false;
+ }
+ else
+ {
+ memcpy(o_pKey->m_acKey,
+ oResponse.Key.Key.__ptr,
+ KMS_MAX_KEY_SIZE);
+ }
+ }
+
+ if (bSuccess)
+ {
+ o_pKey->m_iKeyLength = KMS_MAX_KEY_SIZE;
+
+ if (KMSAgentKeyCallout(o_pKey->m_acKey) != 0)
+ {
+ LogError(i_pProfile,
+ AUDIT_CLIENT_AGENT_RETRIEVE_PROTECT_AND_PROCESS_KEY_KEY_CALLOUT_ERROR,
+ NULL,
+ NULL,
+ NULL);
+ bSuccess = false;
+ }
+ }
+ }
+
+ if (bSuccess)
+ {
+ // add Key ID and the creating KMA IP address to the DU cache
+ CDataUnitCache* pDataUnitCache = (CDataUnitCache*) i_pProfile->m_pDataUnitCache;
+
+ if (i_pProfile->m_iClusterDiscoveryFrequency != 0) // load balancing enabled
+ {
+ bSuccess = pDataUnitCache->Insert(
+ NULL,
+ 0,
+ o_pKey->m_acKeyID,
+ KMS_KEY_ID_SIZE,
+ pLoadBalancer->GetApplianceNetworkAddress(iIndex));
+ }
+ }
+
+ // free allocated memory for output if error condition
+ // Clean up SOAP
+
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+
+ if (bSuccess)
+ {
+ RETURN(KMS_AGENT_STATUS_OK);
+ }
+
+ RETURN(KMSAgent_GetLastStatusCode(i_pProfile,
+ bClientAESKeyWrapSetupError ?
+ CAgentLoadBalancer::AES_KEY_WRAP_SETUP_ERROR : iIndex));
+}
+
+extern "C"
+void KMSAgent_FreeArrayOfKeys (
+ KMSAgent_ArrayOfKeys* i_pArrayOfKeys)
+{
+#if defined(METAWARE)
+ ECPT_TRACE_ENTRY *trace = NULL;
+ ECPT_TRACE(trace, KMSAgent_FreeArrayOfKeys);
+#endif
+ if (!i_pArrayOfKeys)
+ {
+ return;
+ }
+
+ // free memory for all information groups
+ if (i_pArrayOfKeys->m_pKeys)
+ {
+ free(i_pArrayOfKeys->m_pKeys);
+ }
+
+ free(i_pArrayOfKeys);
+}
+
+/*---------------------------------------------------------------------------
+ * Function: KMSAgent_CreateAuditLog
+ *
+ *--------------------------------------------------------------------------*/
+extern "C"
+KMS_AGENT_STATUS 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)
+{
+ bool bSuccess = true;
+#ifdef DEBUG_TIMING
+ ECPT_TRACE_ENTRY *trace = NULL;
+ ECPT_TRACE(trace, KMSAgent_CreateAuditLog);
+#endif
+
+ // START_STACK_CHECK;
+
+ if (!i_pProfile)
+ {
+ Log(AUDIT_CLIENT_AGENT_CREATED_AUDIT_LOG_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Profile arg");
+
+ // END_STACK_CHECK;
+
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ // check arguments
+ if (i_iRetention > KMS_AUDIT_LOG_SHORT_TERM_RETENTION)
+ {
+ Log(AUDIT_CLIENT_AGENT_CREATE_AUDIT_LOG_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Retention arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (i_iCondition > KMS_AUDIT_LOG_WARNING_CONDITION)
+ {
+ Log(AUDIT_CLIENT_AGENT_CREATE_AUDIT_LOG_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Condition arg");
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (!i_pMessage || (strlen(i_pMessage) <= 0))
+ {
+ Log(AUDIT_CLIENT_AGENT_CREATE_AUDIT_LOG_INVALID_PARAMETERS,
+ NULL,
+ NULL,
+ "Message arg");
+ // END_STACK_CHECK;
+ RETURN(KMS_AGENT_STATUS_INVALID_PARAMETER);
+ }
+ if (!KMSClient_ProfileLoaded(i_pProfile))
+ {
+ // END_STACK_CHECK;
+ RETURN(KMS_AGENT_STATUS_PROFILE_NOT_LOADED);
+ }
+
+ CAutoMutex oAutoMutex((K_MUTEX_HANDLE) i_pProfile->m_pLock);
+
+ struct soap* pstSoap = (struct soap*) i_pProfile->m_pvSoap;
+
+ // Create Audit Log
+
+ KMS_Agent::KMS_Agent__CreateAuditLogResponse oResponse;
+
+ CAgentLoadBalancer *pLoadBalancer =
+ (CAgentLoadBalancer *) i_pProfile->m_pAgentLoadBalancer;
+
+ int iIndex = pLoadBalancer->Balance();
+ if (iIndex >= 0)
+ {
+ do
+ {
+ const char* sURL = pLoadBalancer->
+ GetHTTPSURL(iIndex, i_pProfile->m_iPortForAgentService);
+ strncpy(i_pProfile->m_sURL, sURL, sizeof(i_pProfile->m_sURL));
+ i_pProfile->m_sURL[sizeof(i_pProfile->m_sURL)-1] = '\0';
+
+ bSuccess = KMS_Agent::soap_call_KMS_Agent__CreateAuditLog(
+ pstSoap,
+ sURL,
+ NULL,
+ (enum KMS_Agent::KMS_Agent__AuditLogRetention)i_iRetention,
+ (enum KMS_Agent::KMS_Agent__AuditLogCondition)i_iCondition,
+ i_bIssueAlert ? true : false,
+ i_pMessage,
+ oResponse) == SOAP_OK;
+
+
+ if (!bSuccess)
+ {
+ char sSoapFaultMsg[g_iMAX_SOAP_FAULT_MESSAGE_LENGTH];
+ char sKmaAddress[g_iMAX_PEER_NETWORK_ADDRESS_LENGTH];
+
+ GetSoapFault(sSoapFaultMsg, pstSoap);
+ GetPeerNetworkAddress(sKmaAddress, pstSoap);
+
+ iIndex = pLoadBalancer->FailOver(iIndex, pstSoap);
+
+ LogError(i_pProfile, AUDIT_CLIENT_AGENT_CREATE_AUDIT_LOG_SOAP_ERROR,
+ NULL,
+ sKmaAddress,
+ sSoapFaultMsg);
+ }
+ else
+ {
+ pLoadBalancer->UpdateResponseStatus(iIndex);
+ }
+ }
+ while (iIndex >= 0 && (!bSuccess));
+ }
+ else
+ {
+ bSuccess = false;
+ }
+
+ // free allocated memory for output if error condition
+ // Clean up SOAP
+
+ soap_destroy(pstSoap);
+ soap_end(pstSoap);
+
+ if (bSuccess)
+ {
+ // END_STACK_CHECK;
+ RETURN(KMS_AGENT_STATUS_OK);
+ }
+
+ // END_STACK_CHECK;
+ RETURN(KMSAgent_GetLastStatusCode(i_pProfile, iIndex));
+}
+
+#ifdef KMSUSERPKCS12
+/*
+ * This function allows the user to change the PIN on the PKCS12
+ * file that holds the clients private key and cert.
+ */
+extern "C"
+KMS_AGENT_STATUS KMSAgent_ChangeLocalPWD(
+ KMSClientProfile* i_pProfile,
+ utf8cstr const i_pOldPassphrase,
+ utf8cstr const i_pNewPassphrase)
+{
+ CCertificate *pCert;
+ CPrivateKey *pKey;
+ bool bSuccess;
+
+ pCert = new CCertificate;
+ pKey = new CPrivateKey;
+
+ bSuccess = GetPKCS12CertAndKey(i_pProfile, i_pOldPassphrase,
+ pCert, pKey);
+ if (!bSuccess)
+ return(KMSAgent_GetLastStatusCode(i_pProfile, 0));
+
+ bSuccess = StoreAgentPKI(i_pProfile, pCert, pKey, i_pNewPassphrase);
+ if (!bSuccess)
+ return(KMSAgent_GetLastStatusCode(i_pProfile, 0));
+
+ return (KMS_AGENT_STATUS_OK);
+}
+#endif /* KMSUSERPKCS12 */