diff options
Diffstat (limited to 'src/xkms.c')
-rw-r--r-- | src/xkms.c | 4981 |
1 files changed, 4981 insertions, 0 deletions
diff --git a/src/xkms.c b/src/xkms.c new file mode 100644 index 00000000..d10099bb --- /dev/null +++ b/src/xkms.c @@ -0,0 +1,4981 @@ +/** + * XML Security Library (http://www.aleksey.com/xmlsec). + * + * "XML Key Management Specification v 2.0" implementation + * http://www.w3.org/TR/xkms2/ + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + */ +#include "globals.h" + +#ifndef XMLSEC_NO_XKMS + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <libxml/tree.h> +#include <libxml/parser.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/buffer.h> +#include <xmlsec/xmltree.h> +#include <xmlsec/keys.h> +#include <xmlsec/keysmngr.h> +#include <xmlsec/transforms.h> +#include <xmlsec/keyinfo.h> +#include <xmlsec/soap.h> +#include <xmlsec/xkms.h> +#include <xmlsec/private.h> +#include <xmlsec/private/xkms.h> +#include <xmlsec/errors.h> + +#define XMLSEC_XKMS_ID_ATTRIBUTE_LEN 32 + +/* The ID attribute in XKMS is 'Id' */ +static const xmlChar* xmlSecXkmsServerIds[] = { BAD_CAST "Id", NULL }; + +#ifndef XMLSEC_NO_SOAP +static int xmlSecXkmsServerCtxWriteSoap11FatalError (xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr envNode); +static int xmlSecXkmsServerCtxWriteSoap12FatalError (xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr envNode); +#endif /* XMLSEC_NO_SOAP */ + +static int xmlSecXkmsServerCtxRequestAbstractTypeNodeRead (xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr* node); +static int xmlSecXkmsServerCtxSignatureNodeRead (xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node); +static int xmlSecXkmsServerCtxMessageExtensionNodesRead (xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr* node); +static int xmlSecXkmsServerCtxOpaqueClientDataNodeRead (xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node); +static int xmlSecXkmsServerCtxPendingNotificationNodeRead (xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node); +static int xmlSecXkmsServerCtxRespondWithNodesRead (xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr* node); +static int xmlSecXkmsServerCtxPendingRequestNodeRead (xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr* node); +static int xmlSecXkmsServerCtxQueryKeyBindingNodeRead (xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node); +static int xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeRead(xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr* node); +static int xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeWrite(xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node, + xmlSecKeyPtr key); +static int xmlSecXkmsServerCtxKeyInfoNodeWrite (xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node, + xmlSecKeyPtr key); +static int xmlSecXkmsServerCtxUseKeyWithNodesRead (xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr* node); +static int xmlSecXkmsServerCtxUseKeyWithNodesWrite (xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node, + xmlSecKeyPtr key); +static int xmlSecXkmsServerCtxTimeInstantNodeRead (xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node); +static int xmlSecXkmsServerCtxResultTypeNodeWrite (xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node); +static int xmlSecXkmsServerCtxRequestSignatureValueNodeWrite(xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node); +static int xmlSecXkmsServerCtxUnverifiedKeyBindingNodeWrite(xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node, + xmlSecKeyPtr key); +static int xmlSecXkmsServerCtxKeyBindingNodeWrite (xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node, + xmlSecKeyPtr key); +static int xmlSecXkmsServerCtxValidityIntervalNodeWrite (xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node, + xmlSecKeyPtr key); +static int xmlSecXkmsServerCtxKeyBindingStatusNodeWrite (xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node, + xmlSecKeyPtr key); + + +static const xmlSecQName2IntegerInfo gXmlSecXkmsResultMajorInfo[] = +{ + { xmlSecXkmsNs, xmlSecResultMajorCodeSuccess, + xmlSecXkmsResultMajorSuccess }, + { xmlSecXkmsNs, xmlSecResultMajorCodeVersionMismatch, + xmlSecXkmsResultMajorVersionMismatch }, + { xmlSecXkmsNs, xmlSecResultMajorCodeSender, + xmlSecXkmsResultMajorSender }, + { xmlSecXkmsNs, xmlSecResultMajorCodeReceiver, + xmlSecXkmsResultMajorReceiver }, + { xmlSecXkmsNs, xmlSecResultMajorCodeRepresent, + xmlSecXkmsResultMajorRepresent }, + { xmlSecXkmsNs, xmlSecResultMajorCodePending, + xmlSecXkmsResultMajorPending, }, + { NULL , NULL, 0 } /* MUST be last in the list */ +}; + +static const xmlSecQName2IntegerInfo gXmlSecXkmsMinorErrorInfo[] = +{ + { xmlSecXkmsNs, xmlSecResultMinorCodeNoMatch, + xmlSecXkmsResultMinorNoMatch }, + { xmlSecXkmsNs, xmlSecResultMinorCodeTooManyResponses, + xmlSecXkmsResultMinorTooManyResponses }, + { xmlSecXkmsNs, xmlSecResultMinorCodeIncomplete, + xmlSecXkmsResultMinorIncomplete }, + { xmlSecXkmsNs, xmlSecResultMinorCodeFailure, + xmlSecXkmsResultMinorFailure }, + { xmlSecXkmsNs, xmlSecResultMinorCodeRefused, + xmlSecXkmsResultMinorRefused }, + { xmlSecXkmsNs, xmlSecResultMinorCodeNoAuthentication, + xmlSecXkmsResultMinorNoAuthentication }, + { xmlSecXkmsNs, xmlSecResultMinorCodeMessageNotSupported, + xmlSecXkmsResultMinorMessageNotSupported }, + { xmlSecXkmsNs, xmlSecResultMinorCodeUnknownResponseId, + xmlSecXkmsResultMinorUnknownResponseId }, + { xmlSecXkmsNs, xmlSecResultMinorCodeNotSynchronous, + xmlSecXkmsResultMinorSynchronous }, + { NULL, NULL, 0 } /* MUST be last in the list */ +}; + +static const xmlSecQName2IntegerInfo gXmlSecXkmsKeyBindingStatusInfo[] = +{ + { xmlSecXkmsNs, xmlSecKeyBindingStatusValid, + xmlSecXkmsKeyBindingStatusValid }, + { xmlSecXkmsNs, xmlSecKeyBindingStatusInvalid, + xmlSecXkmsKeyBindingStatusInvalid }, + { xmlSecXkmsNs, xmlSecKeyBindingStatusIndeterminate, + xmlSecXkmsKeyBindingStatusIndeterminate }, + { NULL, NULL, 0 } /* MUST be last in the list */ +}; + +static const xmlSecQName2BitMaskInfo gXmlSecXkmsKeyUsageInfo[] = +{ + { xmlSecXkmsNs, xmlSecKeyUsageEncryption, + xmlSecKeyUsageEncrypt | xmlSecKeyUsageDecrypt }, + { xmlSecXkmsNs, xmlSecKeyUsageSignature, + xmlSecKeyUsageSign | xmlSecKeyUsageVerify }, + { xmlSecXkmsNs, xmlSecKeyUsageExchange, + xmlSecKeyUsageKeyExchange}, + { NULL, NULL, 0 } /* MUST be last in the list */ +}; + +static const xmlSecQName2BitMaskInfo gXmlSecXkmsKeyBindingReasonInfo[] = +{ + { xmlSecXkmsNs, xmlSecKeyBindingReasonIssuerTrust, + XMLSEC_XKMS_KEY_BINDING_REASON_MASK_ISSUER_TRAST }, + { xmlSecXkmsNs, xmlSecKeyBindingReasonRevocationStatus, + XMLSEC_XKMS_KEY_BINDING_REASON_MASK_REVOCATION_STATUS }, + { xmlSecXkmsNs, xmlSecKeyBindingReasonValidityInterval, + XMLSEC_XKMS_KEY_BINDING_REASON_MASK_VALIDITY_INTERVAL }, + { xmlSecXkmsNs, xmlSecKeyBindingReasonSignature, + XMLSEC_XKMS_KEY_BINDING_REASON_MASK_SIGNATURE }, + { NULL, NULL, 0 } /* MUST be last in the list */ +}; + +static const xmlSecQName2BitMaskInfo gXmlSecXkmsResponseMechanismInfo[] = +{ + { xmlSecXkmsNs, xmlSecResponseMechanismRepresent, + XMLSEC_XKMS_RESPONSE_MECHANISM_MASK_REPRESENT }, + { xmlSecXkmsNs, xmlSecResponseMechanismPending, + XMLSEC_XKMS_RESPONSE_MECHANISM_MASK_PENDING }, + { xmlSecXkmsNs, xmlSecResponseMechanismRequestSignatureValue, + XMLSEC_XKMS_RESPONSE_MECHANISM_MASK_REQUEST_SIGNATURE_VALUE }, + { NULL, NULL, 0 } /* MUST be last in the list */ +}; + +static const xmlSecQName2IntegerInfo gXmlSecXkmsFormatInfo[] = +{ + { NULL, xmlSecXkmsFormatStrPlain, + xmlSecXkmsServerFormatPlain }, +#ifndef XMLSEC_NO_SOAP + { NULL, xmlSecXkmsFormatStrSoap11, + xmlSecXkmsServerFormatSoap11 }, + { NULL, xmlSecXkmsFormatStrSoap12, + xmlSecXkmsServerFormatSoap12 }, +#endif /* XMLSEC_NO_SOAP */ + { NULL, NULL, 0 } /* MUST be last in the list */ +}; + +/** + * xmlSecXkmsServerFormatFromString: + * @str the string. + * + * Gets xmlSecXkmsServerFormat from string @str. + * + * Returns: corresponding format or xmlSecXkmsServerFormatUnknown + * if format could not be recognized. + */ +xmlSecXkmsServerFormat +xmlSecXkmsServerFormatFromString(const xmlChar* str) { + int res; + int ret; + + xmlSecAssert2(str != NULL, xmlSecXkmsServerFormatUnknown); + + ret = xmlSecQName2IntegerGetInteger(gXmlSecXkmsFormatInfo, NULL, str, &res); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecQName2IntegerGetInteger", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(xmlSecXkmsServerFormatUnknown); + } + + return((xmlSecXkmsServerFormat)res); +} + +/** + * xmlSecXkmsServerFormatToString: + * @format: the format. + * + * Gets string from @format. + * + * Returns: string corresponding to @format or NULL if an error occurs. + */ +const xmlChar* +xmlSecXkmsServerFormatToString (xmlSecXkmsServerFormat format) { + xmlSecQName2IntegerInfoConstPtr info; + + xmlSecAssert2(format != xmlSecXkmsServerFormatUnknown, NULL); + + info = xmlSecQName2IntegerGetInfo(gXmlSecXkmsFormatInfo, format); + if(info == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecQName2IntegerGetInfo", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + return(info->qnameLocalPart); +} + +/** + * xmlSecXkmsServerCtxCreate: + * @keysMngr: the pointer to keys manager. + * + * Creates XKMS request server side processing context. + * The caller is responsible for destroying returned object by calling + * #xmlSecXkmsServerCtxDestroy function. + * + * Returns: pointer to newly allocated context object or NULL if an error + * occurs. + */ +xmlSecXkmsServerCtxPtr +xmlSecXkmsServerCtxCreate(xmlSecKeysMngrPtr keysMngr) { + xmlSecXkmsServerCtxPtr ctx; + int ret; + + ctx = (xmlSecXkmsServerCtxPtr) xmlMalloc(sizeof(xmlSecXkmsServerCtx)); + if(ctx == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_MALLOC_FAILED, + "sizeof(xmlSecXkmsServerCtx)=%d", + sizeof(xmlSecXkmsServerCtx)); + return(NULL); + } + + ret = xmlSecXkmsServerCtxInitialize(ctx, keysMngr); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxInitialize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxDestroy(ctx); + return(NULL); + } + return(ctx); +} + +/** + * xmlSecXkmsServerCtxDestroy: + * @ctx: the pointer to XKMS processing context. + * + * Destroy context object created with #xmlSecXkmsServerCtxCreate function. + */ +void +xmlSecXkmsServerCtxDestroy(xmlSecXkmsServerCtxPtr ctx) { + xmlSecAssert(ctx != NULL); + + xmlSecXkmsServerCtxFinalize(ctx); + xmlFree(ctx); +} + +/** + * xmlSecXkmsServerCtxInitialize: + * @ctx: the pointer to XKMS processing context. + * @keysMngr: the pointer to keys manager. + * + * Initializes XKMS element processing context. + * The caller is responsible for cleaning up returned object by calling + * #xmlSecXkmsServerCtxFinalize function. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecXkmsServerCtxInitialize(xmlSecXkmsServerCtxPtr ctx, xmlSecKeysMngrPtr keysMngr) { + int ret; + + xmlSecAssert2(ctx != NULL, -1); + + memset(ctx, 0, sizeof(xmlSecXkmsServerCtx)); + + ctx->resultMajor = xmlSecXkmsResultMajorSuccess; + ctx->resultMinor = xmlSecXkmsResultMinorNone; + ctx->responseLimit = XMLSEC_XKMS_NO_RESPONSE_LIMIT; + ctx->idLen = XMLSEC_XKMS_ID_ATTRIBUTE_LEN; + + /* initialize key info */ + ret = xmlSecKeyInfoCtxInitialize(&(ctx->keyInfoReadCtx), keysMngr); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyInfoCtxInitialize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + ctx->keyInfoReadCtx.mode = xmlSecKeyInfoModeRead; + + ret = xmlSecKeyInfoCtxInitialize(&(ctx->keyInfoWriteCtx), keysMngr); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyInfoCtxInitialize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + ctx->keyInfoWriteCtx.mode = xmlSecKeyInfoModeWrite; + + /* enabled RespondWith */ + ret = xmlSecPtrListInitialize(&(ctx->enabledRespondWithIds), xmlSecXkmsRespondWithIdListId); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecPtrListInitialize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* enabled ServerRequest */ + ret = xmlSecPtrListInitialize(&(ctx->enabledServerRequestIds), xmlSecXkmsServerRequestIdListId); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecPtrListInitialize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + + + /* initialize keys list */ + ret = xmlSecPtrListInitialize(&(ctx->keys), xmlSecKeyPtrListId); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecPtrListInitialize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* initialize RespondWith list */ + ret = xmlSecPtrListInitialize(&(ctx->respWithList), xmlSecXkmsRespondWithIdListId); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecPtrListInitialize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +/** + * xmlSecXkmsServerCtxFinalize: + * @ctx: the pointer to XKMS processing context. + * + * Cleans up @ctx object. + */ +void +xmlSecXkmsServerCtxFinalize(xmlSecXkmsServerCtxPtr ctx) { + xmlSecAssert(ctx != NULL); + + xmlSecXkmsServerCtxReset(ctx); + + if(ctx->expectedService != NULL) { + xmlFree(ctx->expectedService); + } + if(ctx->idPrefix != NULL) { + xmlFree(ctx->idPrefix); + } + + xmlSecKeyInfoCtxFinalize(&(ctx->keyInfoReadCtx)); + xmlSecKeyInfoCtxFinalize(&(ctx->keyInfoWriteCtx)); + xmlSecPtrListFinalize(&(ctx->enabledRespondWithIds)); + xmlSecPtrListFinalize(&(ctx->enabledServerRequestIds)); + xmlSecPtrListFinalize(&(ctx->keys)); + xmlSecPtrListFinalize(&(ctx->respWithList)); + memset(ctx, 0, sizeof(xmlSecXkmsServerCtx)); +} + +/** + * xmlSecXkmsServerCtxReset: + * @ctx: the pointer to XKMS processing context. + * + * Resets @ctx object, user settings are not touched. + */ +void +xmlSecXkmsServerCtxReset(xmlSecXkmsServerCtxPtr ctx) { + xmlSecAssert(ctx != NULL); + + ctx->resultMajor = xmlSecXkmsResultMajorSuccess; + ctx->resultMinor = xmlSecXkmsResultMinorNone; + xmlSecKeyInfoCtxReset(&(ctx->keyInfoReadCtx)); + xmlSecKeyInfoCtxReset(&(ctx->keyInfoWriteCtx)); + xmlSecPtrListEmpty(&(ctx->keys)); + xmlSecPtrListEmpty(&(ctx->respWithList)); + + ctx->requestNode = NULL; + ctx->opaqueClientDataNode = NULL; + ctx->firtsMsgExtNode = NULL; + ctx->keyInfoNode = NULL; + ctx->requestId = xmlSecXkmsServerRequestIdUnknown; + + if(ctx->id != NULL) { + xmlFree(ctx->id); ctx->id = NULL; + } + if(ctx->service != NULL) { + xmlFree(ctx->service); ctx->service = NULL; + } + if(ctx->nonce != NULL) { + xmlFree(ctx->nonce); ctx->nonce = NULL; + } + if(ctx->originalRequestId != NULL) { + xmlFree(ctx->originalRequestId); ctx->originalRequestId = NULL; + } + if(ctx->pendingNotificationMechanism != NULL) { + xmlFree(ctx->pendingNotificationMechanism); + ctx->pendingNotificationMechanism = NULL; + } + if(ctx->pendingNotificationIdentifier != NULL) { + xmlFree(ctx->pendingNotificationIdentifier); + ctx->pendingNotificationIdentifier = NULL; + } + if(ctx->compoundRequestContexts != NULL) { + xmlSecPtrListDestroy(ctx->compoundRequestContexts); + ctx->compoundRequestContexts = NULL; + } + + ctx->responseLimit = XMLSEC_XKMS_NO_RESPONSE_LIMIT; + ctx->responseMechanismMask = 0; +} + +/** + * xmlSecXkmsServerCtxCopyUserPref: + * @dst: the pointer to destination context. + * @src: the pointer to source context. + * + * Copies user preference from @src context to @dst. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecXkmsServerCtxCopyUserPref(xmlSecXkmsServerCtxPtr dst, xmlSecXkmsServerCtxPtr src) { + int ret; + + xmlSecAssert2(dst != NULL, -1); + xmlSecAssert2(src != NULL, -1); + + dst->userData = src->userData; + dst->flags = src->flags; + dst->flags2 = src->flags2; + + ret = xmlSecKeyInfoCtxCopyUserPref(&(dst->keyInfoReadCtx), &(src->keyInfoReadCtx)); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyInfoCtxCopyUserPref", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecKeyInfoCtxCopyUserPref(&(dst->keyInfoWriteCtx), &(src->keyInfoWriteCtx)); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyInfoCtxCopyUserPref", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + if(src->expectedService != NULL) { + dst->expectedService = xmlStrdup(src->expectedService); + if(dst->expectedService == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlStrdup", + XMLSEC_ERRORS_R_MALLOC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + + if(src->idPrefix != NULL) { + dst->idPrefix = xmlStrdup(src->idPrefix); + if(dst->idPrefix == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlStrdup", + XMLSEC_ERRORS_R_MALLOC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + src->idLen = dst->idLen; + + + ret = xmlSecPtrListCopy(&(dst->enabledRespondWithIds), &(src->enabledRespondWithIds)); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecPtrListCopy", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecPtrListCopy(&(dst->enabledServerRequestIds), &(src->enabledServerRequestIds)); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecPtrListCopy", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +/** + * xmlSecXkmsServerCtxProcess: + * @ctx: the pointer to XKMS processing context. + * @node: the pointer to request node. + * @format: the request/response format. + * @doc: the pointer to response parent XML document (might be NULL). + * + * Reads XKMS request from @node and creates response to a newly created node. + * Caller is responsible for adding the returned node to the XML document. + * + * Returns: pointer to newly created XKMS response node or NULL + * if an error occurs. + */ +xmlNodePtr +xmlSecXkmsServerCtxProcess(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, + xmlSecXkmsServerFormat format, xmlDocPtr doc) { + int ret; + + xmlSecAssert2(ctx != NULL, NULL); + xmlSecAssert2(ctx->requestId == NULL, NULL); + xmlSecAssert2(ctx->requestNode == NULL, NULL); + xmlSecAssert2(node != NULL, NULL); + + ctx->requestNode = xmlSecXkmsServerCtxRequestUnwrap(ctx, node, format); + if(ctx->requestNode == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxRequestUnwrap", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(node->name)); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + goto done; + } + + ret = xmlSecXkmsServerCtxRequestRead(ctx, ctx->requestNode); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerRequestIdListFindByNode", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "ctx->requestNode=%s", + xmlSecErrorsSafeString(ctx->requestNode->name)); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + goto done; + } + + ret = xmlSecXkmsServerRequestExecute(ctx->requestId, ctx); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerRequestExecute", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "ctx->requestNode=%s", + xmlSecErrorsSafeString(ctx->requestNode->name)); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + goto done; + } + +done: + /* always try to write response back */ + if(ctx->requestId != NULL) { + xmlNodePtr respNode; + xmlNodePtr wrappedRespNode; + + respNode = xmlSecXkmsServerCtxResponseWrite(ctx, doc); + if(respNode == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxResponseWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "ctx->requestNode=%s", + xmlSecErrorsSafeString(ctx->requestNode->name)); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + goto error; + } + + + wrappedRespNode = xmlSecXkmsServerCtxResponseWrap(ctx, respNode, format, doc); + if(wrappedRespNode == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxResponseWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "ctx->requestNode=%s", + xmlSecErrorsSafeString(ctx->requestNode->name)); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + xmlFreeNode(respNode); + goto error; + } + + return(wrappedRespNode); + } + +error: + /* last attempt: create fatatl error response */ + return(xmlSecXkmsServerCtxFatalErrorResponseCreate(ctx, format, doc)); +} + +/** + * xmlSecXkmsServerCtxRequestRead: + * @ctx: the pointer to XKMS processing context. + * @node: the pointer to request node. + * + * Reads XKMS request from @node and stores data in @ctx. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecXkmsServerCtxRequestRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) { + int ret; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->requestId == NULL, -1); + xmlSecAssert2(node != NULL, -1); + + /* find out what the request is */ + if(xmlSecPtrListGetSize(&(ctx->enabledServerRequestIds)) > 0) { + ctx->requestId = xmlSecXkmsServerRequestIdListFindByNode(&(ctx->enabledServerRequestIds), node); + } else { + ctx->requestId = xmlSecXkmsServerRequestIdListFindByNode(xmlSecXkmsServerRequestIdsGet(), node); + } + if(ctx->requestId == xmlSecXkmsServerRequestIdUnknown) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerRequestIdListFindByNode", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(node->name)); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorMessageNotSupported); + return(-1); + } + + xmlSecAddIDs(node->doc, node, xmlSecXkmsServerIds); + ret = xmlSecXkmsServerRequestNodeRead(ctx->requestId, ctx, node); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerRequestNodeRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "request=%s", + xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(ctx->requestId))); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure); + return(-1); + } + + return(0); +} + +/** + * xmlSecXkmsServerCtxResponseWrite: + * @ctx: the pointer to XKMS processing context. + * @doc: the pointer to response parent XML document (might be NULL). + * + * Writes XKMS response from context to a newly created node. Caller is + * responsible for adding the returned node to the XML document. + * + * Returns: pointer to newly created XKMS response node or NULL + * if an error occurs. + */ +xmlNodePtr +xmlSecXkmsServerCtxResponseWrite(xmlSecXkmsServerCtxPtr ctx, xmlDocPtr doc) { + xmlNodePtr respNode; + + xmlSecAssert2(ctx != NULL, NULL); + xmlSecAssert2(ctx->requestId != NULL, NULL); + + /* now write results */ + respNode = xmlSecXkmsServerRequestNodeWrite(ctx->requestId, ctx, doc, NULL); + if(respNode == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerRequestNodeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "request=%s", + xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(ctx->requestId))); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + return(NULL); + } + + return(respNode); +} + +/** + * xmlSecXkmsServerCtxRequestUnwrap: + * @ctx: the pointer to XKMS processing context. + * @node: the pointer to request node. + * @format: the request/response format. + * + * Removes SOAP or other envelope from XKMS request. + * + * Returns: pointer to "real" XKMS request node or NULL if an error occurs. + */ +xmlNodePtr +xmlSecXkmsServerCtxRequestUnwrap(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecXkmsServerFormat format) { + xmlNodePtr result = NULL; + + xmlSecAssert2(ctx != NULL, NULL); + xmlSecAssert2(node != NULL, NULL); + + switch(format) { + case xmlSecXkmsServerFormatPlain: + result = node; + break; +#ifndef XMLSEC_NO_SOAP + case xmlSecXkmsServerFormatSoap11: + /* verify that it is actually soap Envelope node */ + if(xmlSecSoap11CheckEnvelope(node) != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecSoap11CheckEnvelope", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure); + return(NULL); + } + + /* check that Body has exactly one entry */ + if(xmlSecSoap11GetBodyEntriesNumber(node) != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecSoap11GetBodyEntriesNumber", + XMLSEC_ERRORS_R_INVALID_DATA, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure); + return(NULL); + } + + /* this one enntry is our xkms request */ + result = xmlSecSoap11GetBodyEntry(node, 0); + if(result == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecSoap11GetBodyEntry", + XMLSEC_ERRORS_R_INVALID_DATA, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure); + return(NULL); + } + + break; + case xmlSecXkmsServerFormatSoap12: + /* verify that it is actually soap Envelope node */ + if(xmlSecSoap12CheckEnvelope(node) != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecSoap12CheckEnvelope", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure); + return(NULL); + } + + /* check that Body has exactly one entry */ + if(xmlSecSoap12GetBodyEntriesNumber(node) != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecSoap12GetBodyEntriesNumber", + XMLSEC_ERRORS_R_INVALID_DATA, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure); + return(NULL); + } + + /* this one enntry is our xkms request */ + result = xmlSecSoap12GetBodyEntry(node, 0); + if(result == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecSoap12GetBodyEntry", + XMLSEC_ERRORS_R_INVALID_DATA, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure); + return(NULL); + } + + break; +#endif /* XMLSEC_NO_SOAP */ + default: + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_NOT_IMPLEMENTED, + "format=%d", + format); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure); + return(NULL); + } + + return(result); +} + +/** + * xmlSecXkmsServerCtxResponseWrap: + * @ctx: the pointer to XKMS processing context. + * @node: the pointer to response node. + * @format: the request/response format. + * @doc: the pointer to response parent XML document (might be NULL). + * + * Creates SOAP or other envelope around XKMS response. + * Caller is responsible for adding the returned node to the XML document. + * + * Returns: pointer to newly created response envelope node or NULL + * if an error occurs. + */ +xmlNodePtr +xmlSecXkmsServerCtxResponseWrap(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecXkmsServerFormat format, xmlDocPtr doc) { + xmlNodePtr result = NULL; + + xmlSecAssert2(ctx != NULL, NULL); + xmlSecAssert2(node != NULL, NULL); + + switch(format) { + case xmlSecXkmsServerFormatPlain: + result = node; /* do nothing */ + break; +#ifndef XMLSEC_NO_SOAP + case xmlSecXkmsServerFormatSoap11: + result = xmlSecSoap11CreateEnvelope(doc); + if(result == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecSoap11CreateEnvelope", + XMLSEC_ERRORS_R_INVALID_DATA, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + return(NULL); + } + + if(xmlSecSoap11AddBodyEntry(result, node) == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecSoap11AddBodyEntry", + XMLSEC_ERRORS_R_INVALID_DATA, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + return(NULL); + } + break; + case xmlSecXkmsServerFormatSoap12: + result = xmlSecSoap12CreateEnvelope(doc); + if(result == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecSoap12CreateEnvelope", + XMLSEC_ERRORS_R_INVALID_DATA, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + return(NULL); + } + + if(xmlSecSoap12AddBodyEntry(result, node) == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecSoap12AddBodyEntry", + XMLSEC_ERRORS_R_INVALID_DATA, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + return(NULL); + } + break; +#endif /* XMLSEC_NO_SOAP */ + default: + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_NOT_IMPLEMENTED, + "format=%d", + format); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure); + return(NULL); + } + + return(result); +} + +/** + * xmlSecXkmsServerCtxFatalErrorResponseCreate: + * @ctx: the pointer to XKMS processing context. + * @format: the request/response format. + * @doc: the pointer to response parent XML document (might be NULL). + * + * Creates a "fatal error" SOAP or other envelope respons. Caller is + * responsible for adding the returned node to the XML document. + * + * Returns: pointer to newly created fatal error response (it might be NULL). + */ +xmlNodePtr +xmlSecXkmsServerCtxFatalErrorResponseCreate(xmlSecXkmsServerCtxPtr ctx, xmlSecXkmsServerFormat format, xmlDocPtr doc) { + xmlNodePtr result = NULL; + int ret; + + xmlSecAssert2(ctx != NULL, NULL); + + /* make sure that we have an error */ + if(ctx->resultMajor == xmlSecXkmsResultMajorSuccess) { + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + } + + switch(format) { + case xmlSecXkmsServerFormatPlain: + /* try to create fatal error response with XKMS Status request */ + result = xmlSecXkmsServerRequestNodeWrite(xmlSecXkmsServerRequestResultId, ctx, doc, NULL); + if(result == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerRequestNodeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + break; +#ifndef XMLSEC_NO_SOAP + case xmlSecXkmsServerFormatSoap11: + result = xmlSecSoap11CreateEnvelope(doc); + if(result == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecSoap11CreateEnvelope", + XMLSEC_ERRORS_R_INVALID_DATA, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + return(NULL); + } + + ret = xmlSecXkmsServerCtxWriteSoap11FatalError(ctx, result); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxWriteSoap11FatalError", + XMLSEC_ERRORS_R_INVALID_DATA, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + xmlFreeNode(result); + return(NULL); + } + + break; + case xmlSecXkmsServerFormatSoap12: + result = xmlSecSoap12CreateEnvelope(doc); + if(result == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecSoap12CreateEnvelope", + XMLSEC_ERRORS_R_INVALID_DATA, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + return(NULL); + } + + ret = xmlSecXkmsServerCtxWriteSoap12FatalError(ctx, result); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxWriteSoap12FatalError", + XMLSEC_ERRORS_R_INVALID_DATA, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + xmlFreeNode(result); + return(NULL); + } + + break; +#endif /* XMLSEC_NO_SOAP */ + default: + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_NOT_IMPLEMENTED, + "format=%d", + format); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure); + return(NULL); + } + + return(result); +} + +#ifndef XMLSEC_NO_SOAP +static int +xmlSecXkmsServerCtxWriteSoap11FatalError(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr envNode) { + const xmlChar* faultCodeHref = NULL; + const xmlChar* faultCodeLocalPart = NULL; + xmlChar* faultString = NULL; + int len; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(envNode != NULL, -1); + + if((ctx->resultMajor == xmlSecXkmsResultMajorVersionMismatch) || + (ctx->requestNode == NULL)) { + /* we were not able to parse the envelope or its general version mismatch error */ + faultCodeHref = xmlSecSoap11Ns; + faultCodeLocalPart = xmlSecSoapFaultCodeVersionMismatch; + faultString = xmlStrdup(xmlSecXkmsSoapFaultReasonUnsupportedVersion); + if(faultString == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlStrdup", + XMLSEC_ERRORS_R_XML_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + return(-1); + } + } else if((ctx->resultMajor == xmlSecXkmsResultMajorSender) && + (ctx->requestId == NULL)) { + /* we understood the request but were not able to parse input message */ + faultCodeHref = xmlSecSoap11Ns; + faultCodeLocalPart = xmlSecSoapFaultCodeClient; + + len = xmlStrlen(BAD_CAST xmlSecErrorsSafeString(ctx->requestNode->name)) + + xmlStrlen(xmlSecXkmsSoapFaultReasonMessageInvalid) + 1; + faultString = xmlMalloc(len + 1); + if(faultString == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlMalloc", + XMLSEC_ERRORS_R_XML_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + return(-1); + } + xmlSecStrPrintf(faultString, len , xmlSecXkmsSoapFaultReasonMessageInvalid, + xmlSecErrorsSafeString(ctx->requestNode->name)); + } else if((ctx->resultMajor == xmlSecXkmsResultMajorReceiver) && + (ctx->requestId == NULL)) { + /* we understood the request but were not able to process it */ + faultCodeHref = xmlSecSoap11Ns; + faultCodeLocalPart = xmlSecSoapFaultCodeServer; + faultString = xmlStrdup(xmlSecXkmsSoapFaultReasonServiceUnavailable); + if(faultString == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlStrdup", + XMLSEC_ERRORS_R_XML_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + return(-1); + } + } else if((ctx->requestId == NULL) && (ctx->requestNode != NULL)) { + /* we parsed the envelope but were not able to understand this request */ + faultCodeHref = xmlSecSoap11Ns; + faultCodeLocalPart = xmlSecSoapFaultCodeClient; + + len = xmlStrlen(BAD_CAST xmlSecErrorsSafeString(ctx->requestNode->name)) + + xmlStrlen(xmlSecXkmsSoapFaultReasonMessageNotSupported) + 1; + faultString = xmlMalloc(len + 1); + if(faultString == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlMalloc", + XMLSEC_ERRORS_R_XML_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + return(-1); + } + xmlSecStrPrintf(faultString, len , xmlSecXkmsSoapFaultReasonMessageNotSupported, + xmlSecErrorsSafeString(ctx->requestNode->name)); + } else { + /* just some error */ + faultCodeHref = xmlSecSoap11Ns; + faultCodeLocalPart = xmlSecSoapFaultCodeServer; + faultString = xmlStrdup(xmlSecXkmsSoapFaultReasonServiceUnavailable); + if(faultString == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlStrdup", + XMLSEC_ERRORS_R_XML_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + return(-1); + } + } + + if(xmlSecSoap11AddFaultEntry(envNode, faultCodeHref, faultCodeLocalPart, faultString, NULL) == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecSoap11AddFaultEntry", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + xmlFree(faultString); + return(-1); + } + + xmlFree(faultString); + return(0); +} + +static int +xmlSecXkmsServerCtxWriteSoap12FatalError(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr envNode) { + xmlSecSoap12FaultCode faultCode = xmlSecSoap12FaultCodeUnknown; + const xmlChar* faultSubCodeHref = NULL; + const xmlChar* faultSubCodeLocalPart = NULL; + xmlChar* faultReason = NULL; + int len; + xmlNodePtr faultNode; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(envNode != NULL, -1); + + if((ctx->resultMajor == xmlSecXkmsResultMajorVersionMismatch) || + (ctx->requestNode == NULL)) { + /* we were not able to parse the envelope or its general version mismatch error */ + faultCode = xmlSecSoap12FaultCodeVersionMismatch; + faultReason = xmlStrdup(xmlSecXkmsSoapFaultReasonUnsupportedVersion); + if(faultReason == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlStrdup", + XMLSEC_ERRORS_R_XML_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + return(-1); + } + } else if((ctx->resultMajor == xmlSecXkmsResultMajorSender) && + (ctx->requestId == NULL)) { + /* we understood the request but were not able to parse input message */ + faultCode = xmlSecSoap12FaultCodeSender; + faultSubCodeHref = xmlSecXkmsNs; + faultSubCodeLocalPart = xmlSecXkmsSoapSubcodeValueMessageNotSupported; + + len = xmlStrlen(BAD_CAST xmlSecErrorsSafeString(ctx->requestNode->name)) + + xmlStrlen(xmlSecXkmsSoapFaultReasonMessageInvalid) + 1; + faultReason = xmlMalloc(len + 1); + if(faultReason == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlMalloc", + XMLSEC_ERRORS_R_XML_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + return(-1); + } + xmlSecStrPrintf(faultReason, len , xmlSecXkmsSoapFaultReasonMessageInvalid, + xmlSecErrorsSafeString(ctx->requestNode->name)); + } else if((ctx->resultMajor == xmlSecXkmsResultMajorReceiver) && + (ctx->requestId == NULL)) { + /* we understood the request but were not able to process it */ + faultCode = xmlSecSoap12FaultCodeReceiver; + faultReason = xmlStrdup(xmlSecXkmsSoapFaultReasonServiceUnavailable); + if(faultReason == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlStrdup", + XMLSEC_ERRORS_R_XML_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + return(-1); + } + } else if((ctx->requestId == NULL) && (ctx->requestNode != NULL)) { + /* we parsed the envelope but were not able to understand this request */ + faultCode = xmlSecSoap12FaultCodeSender; + faultSubCodeHref = xmlSecXkmsNs; + faultSubCodeLocalPart = xmlSecXkmsSoapSubcodeValueBadMessage; + + len = xmlStrlen(BAD_CAST xmlSecErrorsSafeString(ctx->requestNode->name)) + + xmlStrlen(xmlSecXkmsSoapFaultReasonMessageNotSupported) + 1; + faultReason = xmlMalloc(len + 1); + if(faultReason == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlMalloc", + XMLSEC_ERRORS_R_XML_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + return(-1); + } + xmlSecStrPrintf(faultReason, len , xmlSecXkmsSoapFaultReasonMessageNotSupported, + xmlSecErrorsSafeString(ctx->requestNode->name)); + } else { + /* just some error */ + faultCode = xmlSecSoap12FaultCodeReceiver; + faultReason = xmlStrdup(xmlSecXkmsSoapFaultReasonServiceUnavailable); + if(faultReason == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlStrdup", + XMLSEC_ERRORS_R_XML_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + return(-1); + } + } + xmlSecAssert2(faultCode != xmlSecSoap12FaultCodeUnknown, -1); + xmlSecAssert2(faultReason != NULL, -1); + + faultNode = xmlSecSoap12AddFaultEntry(envNode, faultCode, faultReason, + xmlSecXkmsSoapFaultReasonLang, NULL, NULL); + if(faultNode == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecSoap12AddFaultEntry", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + xmlFree(faultReason); + return(-1); + } + xmlFree(faultReason); + + if((faultSubCodeHref != NULL) && (faultSubCodeLocalPart != NULL)) { + /* make sure that we have subcode (xkms) namespace declared */ + if(xmlNewNs(faultNode, faultSubCodeHref, BAD_CAST "xkms") == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlNewNs", + XMLSEC_ERRORS_R_XML_FAILED, + "ns=%s", + xmlSecErrorsSafeString(faultSubCodeHref)); + return(-1); + } + if(xmlSecSoap12AddFaultSubcode(faultNode, faultSubCodeHref, faultSubCodeLocalPart) == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecSoap12AddFaultSubcode", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "href=%s,value=%s", + xmlSecErrorsSafeString(faultSubCodeHref), + xmlSecErrorsSafeString(faultSubCodeLocalPart)); + return(-1); + } + } + + return(0); +} + +#endif /* XMLSEC_NO_SOAP */ + + +/** + * xmlSecXkmsServerCtxSetResult: + * @ctx: the pointer to XKMS processing context. + * @resultMajor: the major result code. + * @resultMinor: the minor result code. + * + * Sets the major/minor result code in the context if no other result is already + * reported. + */ +void +xmlSecXkmsServerCtxSetResult(xmlSecXkmsServerCtxPtr ctx, xmlSecXkmsResultMajor resultMajor, + xmlSecXkmsResultMinor resultMinor) { + xmlSecAssert(ctx != NULL); + + if((ctx->resultMajor == xmlSecXkmsResultMajorSuccess) && + (resultMinor != xmlSecXkmsResultMajorSuccess)) { + ctx->resultMajor = resultMajor; + ctx->resultMinor = resultMinor; + } else if((ctx->resultMajor == xmlSecXkmsResultMajorSuccess) && + (ctx->resultMinor == xmlSecXkmsResultMinorNone)) { + xmlSecAssert(resultMajor == xmlSecXkmsResultMajorSuccess); + + ctx->resultMinor = resultMinor; + } +} + + +/** + * xmlSecXkmsServerCtxDebugDump: + * @ctx: the pointer to XKMS processing context. + * @output: the pointer to output FILE. + * + * Prints the debug information about @ctx to @output. + */ +void +xmlSecXkmsServerCtxDebugDump(xmlSecXkmsServerCtxPtr ctx, FILE* output) { + xmlSecAssert(ctx != NULL); + xmlSecAssert(output != NULL); + + fprintf(output, "= XKMS SERVER CONTEXT: %s\n", + (ctx->requestId != xmlSecXkmsServerRequestIdUnknown && + xmlSecXkmsServerRequestKlassGetName(ctx->requestId)) ? + xmlSecXkmsServerRequestKlassGetName(ctx->requestId) : + BAD_CAST "NULL"); + + xmlSecQName2IntegerDebugDump(gXmlSecXkmsResultMajorInfo, + ctx->resultMajor, BAD_CAST "resultMajor", output); + xmlSecQName2IntegerDebugDump(gXmlSecXkmsMinorErrorInfo, + ctx->resultMinor, BAD_CAST "resultMinor", output); + + fprintf(output, "== id: %s\n", + (ctx->id) ? ctx->id : BAD_CAST ""); + fprintf(output, "== service: %s\n", + (ctx->service) ? ctx->service : BAD_CAST ""); + fprintf(output, "== nonce: %s\n", + (ctx->nonce) ? ctx->nonce : BAD_CAST ""); + fprintf(output, "== originalRequestId: %s\n", + (ctx->originalRequestId) ? ctx->originalRequestId : BAD_CAST ""); + fprintf(output, "== pendingNotificationMechanism: %s\n", + (ctx->pendingNotificationMechanism) ? + ctx->pendingNotificationMechanism : + BAD_CAST ""); + fprintf(output, "== pendingNotificationIdentifier: %s\n", + (ctx->pendingNotificationIdentifier) ? + ctx->pendingNotificationIdentifier : + BAD_CAST ""); + if(ctx->responseLimit != XMLSEC_XKMS_NO_RESPONSE_LIMIT) { + fprintf(output, "== ResponseLimit: %d\n", ctx->responseLimit); + } + xmlSecQName2BitMaskDebugDump(gXmlSecXkmsResponseMechanismInfo, + ctx->responseMechanismMask, BAD_CAST "responseMechanism", output); + + if(ctx->expectedService != NULL) { + fprintf(output, "== expected service: %s\n", ctx->expectedService); + } + fprintf(output, "== flags: 0x%08x\n", ctx->flags); + fprintf(output, "== flags2: 0x%08x\n", ctx->flags2); + + fprintf(output, "== Key Info Read Ctx:\n"); + xmlSecKeyInfoCtxDebugDump(&(ctx->keyInfoReadCtx), output); + + fprintf(output, "== Key Info Write Ctx:\n"); + xmlSecKeyInfoCtxDebugDump(&(ctx->keyInfoWriteCtx), output); + + if(xmlSecPtrListGetSize(&(ctx->enabledRespondWithIds)) > 0) { + fprintf(output, "== Enabled RespondWith: "); + xmlSecTransformIdListDebugDump(&(ctx->enabledRespondWithIds), output); + } else { + fprintf(output, "== Enabled RespondWith: all\n"); + } + + if(xmlSecPtrListGetSize(&(ctx->enabledServerRequestIds)) > 0) { + fprintf(output, "== Enabled ServerRequest: "); + xmlSecTransformIdListDebugDump(&(ctx->enabledServerRequestIds), output); + } else { + fprintf(output, "== Enabled ServerRequest: all\n"); + } + + fprintf(output, "== RespondWith List:\n"); + xmlSecPtrListDebugDump(&(ctx->respWithList), output); + + fprintf(output, "== Keys:\n"); + xmlSecPtrListDebugDump(&(ctx->keys), output); + + if(ctx->compoundRequestContexts != NULL) { + fprintf(output, "== Compound Request:\n"); + xmlSecPtrListDebugDump(ctx->compoundRequestContexts, output); + } +} + +/** + * xmlSecXkmsServerCtxDebugXmlDump: + * @ctx: the pointer to XKMS processing context. + * @output: the pointer to output FILE. + * + * Prints the debug information about @ctx to @output in XML format. + */ +void +xmlSecXkmsServerCtxDebugXmlDump(xmlSecXkmsServerCtxPtr ctx, FILE* output) { + xmlSecAssert(ctx != NULL); + xmlSecAssert(output != NULL); + + fprintf(output, "<XkmsServerRequestContext name=\""); + xmlSecPrintXmlString(output, + (ctx->requestId != xmlSecXkmsServerRequestIdUnknown) ? + xmlSecXkmsServerRequestKlassGetName(ctx->requestId) : + BAD_CAST "NULL" + ); + fprintf(output, "\">\n"); + + xmlSecQName2IntegerDebugXmlDump(gXmlSecXkmsResultMajorInfo, + ctx->resultMajor, BAD_CAST "MajorError", output); + xmlSecQName2IntegerDebugXmlDump(gXmlSecXkmsMinorErrorInfo, + ctx->resultMinor, BAD_CAST "MinorError", output); + + fprintf(output, "<Id>"); + xmlSecPrintXmlString(output, ctx->id); + fprintf(output, "</Id>\n"); + + fprintf(output, "<Service>"); + xmlSecPrintXmlString(output, ctx->service); + fprintf(output, "</Service>\n"); + + fprintf(output, "<Nonce>"); + xmlSecPrintXmlString(output, ctx->nonce); + fprintf(output, "</Nonce>\n"); + + fprintf(output, "<OriginalRequestId>"); + xmlSecPrintXmlString(output, ctx->originalRequestId); + fprintf(output, "</OriginalRequestId>\n"); + + fprintf(output, "<PendingNotificationMechanism>"); + xmlSecPrintXmlString(output, ctx->pendingNotificationMechanism); + fprintf(output, "</PendingNotificationMechanism>\n"); + + fprintf(output, "<PendingNotificationIdentifier>"); + xmlSecPrintXmlString(output, ctx->pendingNotificationIdentifier); + fprintf(output, "</PendingNotificationIdentifier>\n"); + + if(ctx->responseLimit != XMLSEC_XKMS_NO_RESPONSE_LIMIT) { + fprintf(output, "<ResponseLimit>%d</ResponseLimit>\n", ctx->responseLimit); + } + xmlSecQName2BitMaskDebugXmlDump(gXmlSecXkmsResponseMechanismInfo, + ctx->responseMechanismMask, BAD_CAST "ResponseMechanism", output); + + + fprintf(output, "<ExpectedService>"); + xmlSecPrintXmlString(output, ctx->expectedService); + fprintf(output, "</ExpectedService>\n"); + + fprintf(output, "<Flags>%08x</Flags>\n", ctx->flags); + fprintf(output, "<Flags2>%08x</Flags2>\n", ctx->flags2); + + fprintf(output, "<KeyInfoReadCtx>\n"); + xmlSecKeyInfoCtxDebugXmlDump(&(ctx->keyInfoReadCtx), output); + fprintf(output, "</KeyInfoReadCtx>\n"); + + fprintf(output, "<KeyInfoWriteCtx>\n"); + xmlSecKeyInfoCtxDebugXmlDump(&(ctx->keyInfoWriteCtx), output); + fprintf(output, "</KeyInfoWriteCtx>\n"); + + if(xmlSecPtrListGetSize(&(ctx->enabledRespondWithIds)) > 0) { + fprintf(output, "<EnabledRespondWith>\n"); + xmlSecTransformIdListDebugXmlDump(&(ctx->enabledRespondWithIds), output); + fprintf(output, "</EnabledRespondWith>\n"); + } else { + fprintf(output, "<EnabledRespondWith>all</EnabledRespondWith>\n"); + } + + if(xmlSecPtrListGetSize(&(ctx->enabledServerRequestIds)) > 0) { + fprintf(output, "<EnabledServerRequest>\n"); + xmlSecTransformIdListDebugXmlDump(&(ctx->enabledServerRequestIds), output); + fprintf(output, "</EnabledServerRequest>\n"); + } else { + fprintf(output, "<EnabledServerRequest>all</EnabledServerRequest>\n"); + } + + + fprintf(output, "<RespondWithList>\n"); + xmlSecPtrListDebugXmlDump(&(ctx->respWithList), output); + fprintf(output, "</RespondWithList>\n"); + + fprintf(output, "<Keys>\n"); + xmlSecPtrListDebugXmlDump(&(ctx->keys), output); + fprintf(output, "</Keys>\n"); + + if(ctx->compoundRequestContexts != NULL) { + fprintf(output, "<CompoundRequest>\n"); + xmlSecPtrListDebugXmlDump(ctx->compoundRequestContexts, output); + fprintf(output, "</CompoundRequest>\n"); + } + + fprintf(output, "</XkmsServerRequestContext>\n"); +} + +/** + * <xkms:MessageAbstractType Id Service Nonce?> + * <ds:Signature>? + * <xkms:MessageExtension>* + * (<xkms:OpaqueClientData> + * <xkms:OpaqueData>? + * )? + * + * <xkms:RequestAbstractType Id Service Nonce? OriginalRequestId? ResponseLimit?> + * <ds:Signature>? + * <xkms:MessageExtension>* + * (<xkms:OpaqueClientData> + * <xkms:OpaqueData>? + * )? + * <xkms:ResponseMechanism>* + * <xkms:RespondWith>* + * <xkms:PendingNotification Mechanism Identifier>? + * + * XML Schema: + * + * <!-- RequestAbstractType --> + * <complexType name="RequestAbstractType" abstract="true"> + * <complexContent> + * <extension base="xkms:MessageAbstractType"> + * <sequence> + * <element ref="xkms:ResponseMechanism" minOccurs="0" + * maxOccurs="unbounded"/> + * <element ref="xkms:RespondWith" minOccurs="0" + * maxOccurs="unbounded"/> + * <element ref="xkms:PendingNotification" minOccurs="0"/> + * </sequence> + * <attribute name="OriginalRequestId" type="anyURI" + * use="optional"/> + * <attribute name="ResponseLimit" type="integer" use="optional"/> + * </extension> + * </complexContent> + * </complexType> + * <!-- /RequestAbstractType --> + * + * <!-- MessageAbstractType --> + * <complexType name="MessageAbstractType" abstract="true"> + * <sequence> + * <element ref="ds:Signature" minOccurs="0"/> + * <element ref="xkms:MessageExtension" minOccurs="0" + * maxOccurs="unbounded"/> + * <element ref="xkms:OpaqueClientData" minOccurs="0"/> + * </sequence> + * <attribute name="Id" type="ID" use="required"/> + * <attribute name="Service" type="anyURI" use="required"/> + * <attribute name="Nonce" type="base64Binary" use="optional"/> + * </complexType> + * <!-- /MessageAbstractType --> + */ +static int +xmlSecXkmsServerCtxRequestAbstractTypeNodeRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr* node) { + xmlNodePtr cur; + xmlChar* tmp; + int ret; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2((*node) != NULL, -1); + + cur = (*node); + xmlSecAssert2(cur != NULL, -1); + + /* required Id attribute */ + xmlSecAssert2(ctx->id == NULL, -1); + ctx->id = xmlGetProp(cur, xmlSecAttrId); + if(ctx->id == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlGetProp", + XMLSEC_ERRORS_R_XML_FAILED, + "name=%s;node=%s", + xmlSecErrorsSafeString(xmlSecAttrId), + xmlSecErrorsSafeString(cur->name)); + return(-1); + } + + /* required Service attribute */ + xmlSecAssert2(ctx->service == NULL, -1); + ctx->service = xmlGetProp(cur, xmlSecAttrService); + if(ctx->service == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlGetProp", + XMLSEC_ERRORS_R_XML_FAILED, + "name=%s;node=%s", + xmlSecErrorsSafeString(xmlSecAttrService), + xmlSecErrorsSafeString(cur->name)); + return(-1); + } + + /* check service */ + if((ctx->expectedService != NULL) && (!xmlStrEqual(ctx->expectedService, ctx->service))) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_INVALID_DATA, + "expectedService=%s;actualService=%s", + xmlSecErrorsSafeString(ctx->expectedService), + xmlSecErrorsSafeString(ctx->service)); + return(-1); + } + + /* optional Nonce attribute */ + xmlSecAssert2(ctx->nonce == NULL, -1); + ctx->nonce = xmlGetProp(cur, xmlSecAttrNonce); + + /* optional OriginalRequestId attribute */ + xmlSecAssert2(ctx->originalRequestId == NULL, -1); + ctx->originalRequestId = xmlGetProp(cur, xmlSecAttrOriginalRequestId); + + /* optional ResponseLimit attribute */ + xmlSecAssert2(ctx->responseLimit == XMLSEC_XKMS_NO_RESPONSE_LIMIT, -1); + tmp = xmlGetProp(cur, xmlSecAttrResponseLimit); + if(tmp != NULL) { + ctx->responseLimit = atoi((char*)tmp); + xmlFree(tmp); + } + + /* now read children */ + cur = xmlSecGetNextElementNode(cur->children); + + /* first node is optional <dsig:Signature/> node */ + if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeSignature, xmlSecDSigNs)) { + ret = xmlSecXkmsServerCtxSignatureNodeRead(ctx, cur); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxSignatureNodeRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + cur = xmlSecGetNextElementNode(cur->next); + } + + /* next is zero or more <xkms:MessageExtension/> nodes */ + ret = xmlSecXkmsServerCtxMessageExtensionNodesRead(ctx, &cur); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxMessageExtensionNodesRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* next is optional <xkms:OpaqueClientData/> node */ + if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeOpaqueClientData, xmlSecXkmsNs)) { + ret = xmlSecXkmsServerCtxOpaqueClientDataNodeRead(ctx, cur); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxOpaqueClientDataNodeRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + cur = xmlSecGetNextElementNode(cur->next); + } + + /* next is zero or more <xkms:ResponseMechanism/> nodes */ + ret = xmlSecQName2BitMaskNodesRead(gXmlSecXkmsResponseMechanismInfo, &cur, + xmlSecNodeResponseMechanism, xmlSecXkmsNs, + ((ctx->flags & XMLSEC_XKMS_SERVER_FLAGS_STOP_ON_UNKNOWN_RESPONSE_MECHANISM) != 0) ? 1 : 0, + &ctx->responseMechanismMask); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecQName2BitMaskNodesRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "name=%s", + xmlSecErrorsSafeString(xmlSecNodeResponseMechanism)); + return(-1); + } + + /* next is zero or more <xkms:RespondWith/> nodes */ + ret = xmlSecXkmsServerCtxRespondWithNodesRead(ctx, &cur); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxRespondWithNodesRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* next is optional <xkms:PendingNotification/> node */ + if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodePendingNotification, xmlSecXkmsNs)) { + ret = xmlSecXkmsServerCtxPendingNotificationNodeRead(ctx, cur); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxPendingNotificationNodeRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + cur = xmlSecGetNextElementNode(cur->next); + } + + (*node) = cur; + return(0); +} + +static int +xmlSecXkmsServerCtxSignatureNodeRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) { + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + /* todo: verify signature and make sure that correct data was signed */ + return(0); +} + +/** + * <!-- MessageExtension --> + * <element name="MessageExtension" type="xkms:MessageExtensionAbstractType" + * abstract="true"/> + * <complexType name="MessageExtensionAbstractType" abstract="true"/> + * <!-- /MessageExtension --> + */ +static int +xmlSecXkmsServerCtxMessageExtensionNodesRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr* node) { + xmlNodePtr cur; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->firtsMsgExtNode == NULL, -1); + xmlSecAssert2(node != NULL, -1); + + cur = (*node); + while((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeMessageExtension, xmlSecXkmsNs)) { + if(ctx->firtsMsgExtNode == NULL) { + ctx->firtsMsgExtNode = cur; + } + cur = xmlSecGetNextElementNode(cur->next); + } + + (*node) = cur; + return(0); +} + +static int +xmlSecXkmsServerCtxOpaqueClientDataNodeRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) { + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->opaqueClientDataNode == NULL, -1); + xmlSecAssert2(node != NULL, -1); + + /* remember that node, will copy it in the response later */ + ctx->opaqueClientDataNode = node; + return(0); +} + +static int +xmlSecXkmsServerCtxRespondWithNodesRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr* node) { + xmlNodePtr cur; + int ret; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + cur = (*node); + while((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeRespondWith, xmlSecXkmsNs)) { + xmlSecXkmsRespondWithId id = xmlSecXkmsRespondWithIdUnknown; + + if(xmlSecPtrListGetSize(&(ctx->enabledRespondWithIds)) > 0) { + id = xmlSecXkmsRespondWithIdListFindByNodeValue(&(ctx->enabledRespondWithIds), cur); + } else { + id = xmlSecXkmsRespondWithIdListFindByNodeValue(xmlSecXkmsRespondWithIdsGet(), cur); + } + + if(id != xmlSecXkmsRespondWithIdUnknown) { + ret = xmlSecXkmsRespondWithNodeRead(id, ctx, cur); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecCreateTree", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } else if((ctx->flags & XMLSEC_XKMS_SERVER_FLAGS_STOP_ON_UNKNOWN_RESPOND_WITH) != 0) { + xmlChar* content ; + + content = xmlNodeGetContent(cur); + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "name=%s,value=%s", + xmlSecErrorsSafeString(cur->name), + xmlSecErrorsSafeString(content)); + if(content != NULL) { + xmlFree(content); + } + return(-1); + } + cur = xmlSecGetNextElementNode(cur->next); + } + + (*node) = cur; + return(0); +} + +/** + * XML Schema: + * <!-- PendingNotification --> + * <element name="PendingNotification" type="xkms:PendingNotificationType"/> + * <complexType name="PendingNotificationType"> + * <attribute name="Mechanism" type="anyURI" use="required"/> + * <attribute name="Identifier" type="anyURI" use="required"/> + * </complexType> + * <!-- /PendingNotification --> + */ +static int +xmlSecXkmsServerCtxPendingNotificationNodeRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) { + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + xmlSecAssert2(ctx->pendingNotificationMechanism == NULL, -1); + ctx->pendingNotificationMechanism = xmlGetProp(node, xmlSecAttrMechanism); + if(ctx->pendingNotificationMechanism == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlGetProp", + XMLSEC_ERRORS_R_XML_FAILED, + "name=%s;node=%s", + xmlSecErrorsSafeString(xmlSecAttrMechanism), + xmlSecErrorsSafeString(node->name)); + return(-1); + } + + xmlSecAssert2(ctx->pendingNotificationIdentifier == NULL, -1); + ctx->pendingNotificationIdentifier = xmlGetProp(node, xmlSecAttrIdentifier); + if(ctx->pendingNotificationIdentifier == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlGetProp", + XMLSEC_ERRORS_R_XML_FAILED, + "name=%s;node=%s", + xmlSecErrorsSafeString(xmlSecAttrIdentifier), + xmlSecErrorsSafeString(node->name)); + return(-1); + } + + return(0); +} + +/** + * <xkms:PendingRequestType Id Service Nonce? OriginalRequestId? ResponseLimit? ResponseId?> + * <ds:Signature>? + * <xkms:MessageExtension>* + * (<xkms:OpaqueClientData> + * <xkms:OpaqueData>? + * )? + * <xkms:ResponseMechanism>* + * <xkms:RespondWith>* + * <xkms:PendingNotification Mechanism Identifier>? + * + * XML Schema: + * + * <!-- PendingRequest --> + * <element name="PendingRequest" type="xkms:PendingRequestType"/> + * <complexType name="PendingRequestType"> + * <complexContent> + * <extension base="xkms:RequestAbstractType"> + * <attribute name="ResponseId" type="anyURI" use="optional"/> + * </extension> + * </complexContent> + * </complexType> + * <!-- /PendingRequest --> * + */ +static int +xmlSecXkmsServerCtxPendingRequestNodeRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr* node) { + int ret; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + /* first read "parent" type */ + ret = xmlSecXkmsServerCtxRequestAbstractTypeNodeRead(ctx, node); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxRequestAbstractTypeNodeRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* todo: read responseId */ + return(0); +} + +/** + * <xkms:QueryKeyBinding Id? + * <ds:KeyInfo>? + * <xkms:KeyUsage>? + * <xkms:KeyUsage>? + * <xkms:KeyUsage>? + * <xkms:UseKeyWith Application Identifier>* + * <xkms:TimeInstant Time>? + * + * XML Schema: + * <!-- QueryKeyBinding --> + * <element name="QueryKeyBinding" type="xkms:QueryKeyBindingType"/> + * <complexType name="QueryKeyBindingType"> + * <complexContent> + * <extension base="xkms:KeyBindingAbstractType"> + * <sequence> + * <element ref="xkms:TimeInstant" minOccurs="0"/> + * </sequence> + * </extension> + * </complexContent> + * </complexType> + * <!-- /QueryKeyBinding --> + */ +static int +xmlSecXkmsServerCtxQueryKeyBindingNodeRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) { + xmlNodePtr cur; + int ret; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + /* first read "parent" type */ + cur = node; + ret = xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeRead(ctx, &cur); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* next is optional <xkms:TimeInstant/> node */ + if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeTimeInstant, xmlSecXkmsNs)) { + ret = xmlSecXkmsServerCtxTimeInstantNodeRead(ctx, cur); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxTimeInstantNodeRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + cur = xmlSecGetNextElementNode(cur->next); + } + + /* check that there is nothing after the last node */ + if(cur != NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_UNEXPECTED_NODE, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +/** + * <xkms:KeyBindingAbstractType Id?> + * <ds:KeyInfo>? + * <xkms:KeyUsage>? + * <xkms:KeyUsage>? + * <xkms:KeyUsage>? + * <xkms:UseKeyWith Application Identifier>* + * + * XML Schema: + * <!-- KeyBindingAbstractType--> + * <complexType name="KeyBindingAbstractType" abstract="true"> + * <sequence> + * <element ref="ds:KeyInfo" minOccurs="0"/> + * <element ref="xkms:KeyUsage" minOccurs="0" maxOccurs="3"/> + * <element ref="xkms:UseKeyWith" minOccurs="0" + * maxOccurs="unbounded"/> + * </sequence> + * <attribute name="Id" type="ID" use="optional"/> + * </complexType> + * <!-- /KeyBindingAbstractType--> + */ +static int +xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr* node) { + xmlNodePtr cur; + int ret; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2((*node) != NULL, -1); + + cur = (*node); + xmlSecAssert2(cur != NULL, -1); + + /* we don't care about Id attribute in this node */ + cur = xmlSecGetNextElementNode(cur->children); + + /* first node is optional <dsig:KeyInfo/> node. for now we only remember pointer */ + xmlSecAssert2(ctx->keyInfoNode == NULL, -1); + if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeKeyInfo, xmlSecDSigNs)) { + ctx->keyInfoNode = cur; + cur = xmlSecGetNextElementNode(cur->next); + } + + /* next is zero or more <xkms:KeyUsage/> nodes */ + ret = xmlSecQName2BitMaskNodesRead(gXmlSecXkmsKeyUsageInfo, &cur, + xmlSecNodeKeyUsage, xmlSecXkmsNs, + ((ctx->flags & XMLSEC_XKMS_SERVER_FLAGS_STOP_ON_UNKNOWN_KEY_USAGE) != 0) ? 1 : 0, + &(ctx->keyInfoReadCtx.keyReq.keyUsage)); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecQName2BitMaskNodesRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "name=%s", + xmlSecErrorsSafeString(xmlSecNodeKeyUsage)); + return(-1); + } + + /* next is zero or more <xkms:UseKeyWith/> nodes */ + ret = xmlSecXkmsServerCtxUseKeyWithNodesRead(ctx, &cur); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxUseKeyWithNodesRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + (*node) = cur; + return(0); +} + +static int +xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecKeyPtr key) { + xmlNodePtr cur; + int ret; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(key != NULL, -1); + + /* generate and add Id attribute */ + ret = xmlSecGenerateAndAddID(node, xmlSecAttrId, ctx->idPrefix, ctx->idLen); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGenerateAndAddID", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* <dsig:KeyInfo/> node */ + cur = xmlSecAddChild(node, xmlSecNodeKeyInfo, xmlSecDSigNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeKeyInfo)); + return(-1); + } + + ret = xmlSecXkmsServerCtxKeyInfoNodeWrite(ctx, cur, key); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxKeyInfoNodeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* next is <xkms:KeyUsage/> node */ + ret = xmlSecQName2BitMaskNodesWrite(gXmlSecXkmsKeyUsageInfo, node, + xmlSecNodeKeyUsage, xmlSecXkmsNs, + key->usage); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecQName2BitMaskNodesWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "name=%s", + xmlSecErrorsSafeString(xmlSecNodeKeyUsage)); + return(-1); + } + + /* and the last node is <xkms:UseKeyWith/> */ + ret = xmlSecXkmsServerCtxUseKeyWithNodesWrite(ctx, node, key); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxUseKeyWithNodesWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +static int +xmlSecXkmsServerCtxKeyInfoNodeWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecKeyPtr key) { + int ret; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + /* add child nodes as requested in <xkms:RespondWith/> nodes */ + ret = xmlSecXkmsRespondWithIdListWrite(&(ctx->respWithList), ctx, node); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsRespondWithIdListWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecKeyInfoNodeWrite(node, key, &(ctx->keyInfoWriteCtx)); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyInfoNodeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + + +/** + * XML Schema: + * <!-- UseKeyWith --> + * <element name="UseKeyWith" type="xkms:UseKeyWithType"/> + * <complexType name="UseKeyWithType"> + * <attribute name="Application" type="anyURI" use="required"/> + * <attribute name="Identifier" type="string" use="required"/> + * </complexType> + * <!-- /UseKeyWith --> + */ +static int +xmlSecXkmsServerCtxUseKeyWithNodesRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr* node) { + xmlSecPtrListPtr list; + xmlNodePtr cur; + xmlSecKeyUseWithPtr keyUseWith; + xmlChar* application; + xmlChar* identifier; + int ret; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + list = &(ctx->keyInfoReadCtx.keyReq.keyUseWithList); + xmlSecAssert2(xmlSecPtrListGetSize(list) == 0, -1); + + cur = (*node); + while((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeUseKeyWith, xmlSecXkmsNs)) { + application = xmlGetProp(cur, xmlSecAttrApplication); + if(application == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlGetProp", + XMLSEC_ERRORS_R_XML_FAILED, + "name=%s;node=%s", + xmlSecErrorsSafeString(xmlSecAttrApplication), + xmlSecErrorsSafeString(cur->name)); + return(-1); + } + + identifier = xmlGetProp(cur, xmlSecAttrIdentifier); + if(identifier == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlGetProp", + XMLSEC_ERRORS_R_XML_FAILED, + "name=%s;node=%s", + xmlSecErrorsSafeString(xmlSecAttrIdentifier), + xmlSecErrorsSafeString(cur->name)); + xmlFree(application); + return(-1); + } + + keyUseWith = xmlSecKeyUseWithCreate(application, identifier); + if(keyUseWith == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyUseWithCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlFree(application); + xmlFree(identifier); + return(-1); + } + xmlFree(application); + xmlFree(identifier); + + ret = xmlSecPtrListAdd(list, keyUseWith); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecPtrListAdd", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecKeyUseWithDestroy(keyUseWith); + return(-1); + } + + cur = xmlSecGetNextElementNode(cur->next); + } + + (*node) = cur; + return(0); +} + +static int +xmlSecXkmsServerCtxUseKeyWithNodesWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecKeyPtr key) { + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(key != NULL, -1); + + /* todo: write UseKeyWith */ + return(0); +} + + +static int +xmlSecXkmsServerCtxTimeInstantNodeRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) { + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + /* todo: parse xml schema dataTime or use libxml? */ + return(0); +} + +/** + * <xkms:ResultType Id Service Nonce? ResultMajor ResultMinor? RequestId?> + * <ds:Signature>? + * <xkms:MessageExtension>* + * (<xkms:OpaqueClientData> + * <xkms:OpaqueData>? + * )? + * <xkms:RequestSignatureValue>* + * + * XML Schema: + * <!-- ResultType --> + * <element name="Result" type="xkms:ResultType"/> + * <complexType name="ResultType"> + * <complexContent> + * <extension base="xkms:MessageAbstractType"> + * <sequence> + * <element ref="xkms:RequestSignatureValue" minOccurs="0"/> + * </sequence> + * <attribute name="ResultMajor" type="QName" use="required"/> + * <attribute name="ResultMinor" type="QName" use="optional"/> + * <attribute name="RequestId" type="anyURI" use="optional"/> + * </extension> + * </complexContent> + * </complexType> + * <!-- /ResultType --> + */ +static int +xmlSecXkmsServerCtxResultTypeNodeWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) { + int ret; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + /* generate and add Id attribute */ + ret = xmlSecGenerateAndAddID(node, xmlSecAttrId, ctx->idPrefix, ctx->idLen); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGenerateAndAddID", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* todo: generate nonce? */ + + /* set Service atribute (required) */ + if((ctx->service == NULL) || (xmlSetProp(node, xmlSecAttrService, ctx->service) == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSetProp", + XMLSEC_ERRORS_R_XML_FAILED, + "name=%s,value=%s", + xmlSecErrorsSafeString(xmlSecAttrService), + xmlSecErrorsSafeString(ctx->service)); + return(-1); + } + + + /* set RequestId atribute (optional) */ + if((ctx->id != NULL) && (xmlSetProp(node, xmlSecAttrRequestId, ctx->id) == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSetProp", + XMLSEC_ERRORS_R_XML_FAILED, + "name=%s,value=%s", + xmlSecErrorsSafeString(xmlSecAttrRequestId), + xmlSecErrorsSafeString(ctx->id)); + return(-1); + } + + + /* set major code (required) */ + ret = xmlSecQName2IntegerAttributeWrite(gXmlSecXkmsResultMajorInfo, node, + xmlSecAttrResultMajor, ctx->resultMajor); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecQName2IntegerAttributeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "name=%s,value=%d", + xmlSecErrorsSafeString(xmlSecAttrResultMajor), + ctx->resultMajor); + return(-1); + } + + /* set minor code (optional) */ + if(ctx->resultMinor != xmlSecXkmsResultMinorNone) { + ret = xmlSecQName2IntegerAttributeWrite(gXmlSecXkmsMinorErrorInfo, node, + xmlSecAttrResultMinor, ctx->resultMinor); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecQName2IntegerAttributeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "name=%s,value=%d", + xmlSecErrorsSafeString(xmlSecAttrResultMinor), + ctx->resultMinor); + return(-1); + } + } + + /* todo: create signature template */ + + /* todo: create message extension nodes? */ + + /* <xkms:OpaqueClientData/>: An XKMS service SHOULD return the value of + * the <OpaqueClientData> element unmodified in a request in a response + * with status code Succes */ + if((ctx->resultMajor == xmlSecXkmsResultMajorSuccess) && (ctx->opaqueClientDataNode != NULL)) { + xmlNodePtr copyNode; + + copyNode = xmlDocCopyNode(ctx->opaqueClientDataNode, node->doc, 1); + if(copyNode == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSetProp", + XMLSEC_ERRORS_R_XML_FAILED, + "name=%s", + xmlSecErrorsSafeString(ctx->opaqueClientDataNode->name)); + return(-1); + } + + if(xmlSecAddChildNode(node, copyNode) == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecAddChildNode", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "name=%s", + xmlSecErrorsSafeString(copyNode->name)); + return(-1); + } + } + + ret = xmlSecXkmsServerCtxRequestSignatureValueNodeWrite(ctx, node); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxRequestSignatureValueNodeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +/** + * A service SHOULD include the <RequestSignatureValue> element in a response + * if the following conditions are satisfied and MUST NOT include the value + * otherwise: + * + * + * - The <ds:Signature> element was present in the corresponding request + * - The service successfully verified the <ds:Signature> element in the + * corresponding request, and + * - The ResponseMechanism RequestSignatureValue was specified. + * + */ +static int +xmlSecXkmsServerCtxRequestSignatureValueNodeWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) { + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + /* todo: check all conditions for RequestSignatureValue */ + if((ctx->responseMechanismMask & XMLSEC_XKMS_RESPONSE_MECHANISM_MASK_REQUEST_SIGNATURE_VALUE) == 0) { + /* The ResponseMechanism RequestSignatureValue was not specified. */ + return(0); + } + + /* todo: write RequestSignatureValue */ + return(0); +} + + +/** + * + * <xkms:UnverifiedKeyBindingType Id?> + * <ds:KeyInfo>? + * <xkms:KeyUsage>? + * <xkms:KeyUsage>? + * <xkms:KeyUsage>? + * <xkms:UseKeyWith Application Identifier>* + * <xkms:ValidityInterval NotBefore NotOnOrAfter>? + * + * XML Schema: + * + * <!-- UnverifiedKeyBinding --> + * <element name="UnverifiedKeyBinding" type="xkms:UnverifiedKeyBindingType"/> + * <complexType name="UnverifiedKeyBindingType"> + * <complexContent> + * <extension base="xkms:KeyBindingAbstractType"> + * <sequence> + * <element ref="xkms:ValidityInterval" minOccurs="0"/> + * </sequence> + * </extension> + * </complexContent> + * </complexType> + * <!-- /UnverifiedKeyBinding --> + */ +static int +xmlSecXkmsServerCtxUnverifiedKeyBindingNodeWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecKeyPtr key) { + int ret; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + /* first write "parent" type */ + ret = xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeWrite(ctx, node, key); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* <xkms:ValidityInterval/> node */ + ret = xmlSecXkmsServerCtxValidityIntervalNodeWrite(ctx, node, key); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxValidityIntervalNodeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +static int +xmlSecXkmsServerCtxValidityIntervalNodeWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecKeyPtr key) { + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + /* todo: write key validity interval */ + return(0); +} + +/** + * <xkms:KeyBinding Id?> + * <ds:KeyInfo>? + * <xkms:KeyUsage>? + * <xkms:KeyUsage>? + * <xkms:KeyUsage>? + * <xkms:UseKeyWith Application Identifier>* + * <xkms:ValidityInterval NotBefore NotOnOrAfter>? + * <xkms:Status StatusValue> + * (<xkms:ValidReason>? + * <xkms:IndeterminateReason>? + * <xkms:InvalidReason>? + * )* + * + * XML Schema: + * + * <!-- KeyBinding --> + * <element name="KeyBinding" type="xkms:KeyBindingType"/> + * <complexType name="KeyBindingType"> + * <complexContent> + * <extension base="xkms:UnverifiedKeyBindingType"> + * <sequence> + * <element ref="xkms:Status"/> + * </sequence> + * </extension> + * </complexContent> + * </complexType> + * <!-- /KeyBinding --> + */ +static int +xmlSecXkmsServerCtxKeyBindingNodeWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecKeyPtr key) { + int ret; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + /* first write "parent" type */ + ret = xmlSecXkmsServerCtxUnverifiedKeyBindingNodeWrite(ctx, node, key); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* <xkms:Status/> node */ + ret = xmlSecXkmsServerCtxKeyBindingStatusNodeWrite(ctx, node, key); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxKeyBindingStatusNodeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +/** + * <xkms:Status StatusValue> + * (<xkms:ValidReason>? + * <xkms:IndeterminateReason>? + * <xkms:InvalidReason>? + * )* + * + * XML Schema: + * + * <!-- Status --> + * <element name="Status" type="xkms:StatusType"/> + * <complexType name="StatusType"> + * <sequence> + * <element ref="xkms:ValidReason" minOccurs="0" + * maxOccurs="unbounded"/> + * <element ref="xkms:IndeterminateReason" minOccurs="0" + * maxOccurs="unbounded"/> + * <element ref="xkms:InvalidReason" minOccurs="0" + * maxOccurs="unbounded"/> + * </sequence> + * <attribute name="StatusValue" type="xkms:KeyBindingStatus" + * use="required"/> + * </complexType> + * <simpleType name="KeyBindingStatus"> + * <restriction base="QName"> + * <enumeration value="xkms:Valid"/> + * <enumeration value="xkms:Invalid"/> + * <enumeration value="xkms:Indeterminate"/> + * </restriction> + * </simpleType> + * <!-- /Status --> + */ +static int +xmlSecXkmsServerCtxKeyBindingStatusNodeWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecKeyPtr key) { + xmlNodePtr cur; + int ret; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + cur = xmlSecAddChild(node, xmlSecNodeStatus, xmlSecXkmsNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeStatus)); + return(-1); + } + + /* if we are here then the key was validated */ + ret = xmlSecQName2IntegerAttributeWrite(gXmlSecXkmsKeyBindingStatusInfo, cur, + xmlSecAttrStatusValue, xmlSecXkmsKeyBindingStatusValid); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecQName2IntegerAttributeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "name=%s", + xmlSecErrorsSafeString(xmlSecAttrStatusValue)); + return(-1); + } + + /* todo: write the reasons */ + return(0); +} + +/************************************************************************ + * + * xmlSecXkmsServerCtx list + * + ************************************************************************/ +static xmlSecPtrListKlass xmlSecXkmsServerCtxPtrListKlass = { + BAD_CAST "xkms-server-ctx-list", + NULL, /* xmlSecPtrDuplicateItemMethod duplicateItem; */ + (xmlSecPtrDestroyItemMethod)xmlSecXkmsServerCtxDestroy, /* xmlSecPtrDestroyItemMethod destroyItem; */ + (xmlSecPtrDebugDumpItemMethod)xmlSecXkmsServerCtxDebugDump, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */ + (xmlSecPtrDebugDumpItemMethod)xmlSecXkmsServerCtxDebugXmlDump, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */ +}; + +xmlSecPtrListId +xmlSecXkmsServerCtxPtrListGetKlass(void) { + return(&xmlSecXkmsServerCtxPtrListKlass); +} + + +/************************************************************************** + * + * Global xmlSecXkmsRespondWithIds list functions + * + *************************************************************************/ +static xmlSecPtrList xmlSecAllXkmsRespondWithIds; + + +/** + * xmlSecXkmsRespondWithIdsGet: + * + * Gets global registered RespondWith klasses list. + * + * Returns: the pointer to list of all registered RespondWith klasses. + */ +xmlSecPtrListPtr +xmlSecXkmsRespondWithIdsGet(void) { + return(&xmlSecAllXkmsRespondWithIds); +} + +/** + * xmlSecXkmsRespondWithIdsInit: + * + * Initializes the RespondWith klasses. This function is called from the + * #xmlSecInit function and the application should not call it directly. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecXkmsRespondWithIdsInit(void) { + int ret; + + ret = xmlSecPtrListInitialize(xmlSecXkmsRespondWithIdsGet(), xmlSecXkmsRespondWithIdListId); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecPtrListPtrInitialize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "xmlSecXkmsRespondWithIdListId"); + return(-1); + } + + ret = xmlSecXkmsRespondWithIdsRegisterDefault(); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsRespondWithIdsRegisterDefault", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +/** + * xmlSecXkmsRespondWithIdsShutdown: + * + * Shuts down the keys data klasses. This function is called from the + * #xmlSecShutdown function and the application should not call it directly. + */ +void +xmlSecXkmsRespondWithIdsShutdown(void) { + xmlSecPtrListFinalize(xmlSecXkmsRespondWithIdsGet()); +} + +/** + * xmlSecXkmsRespondWithIdsRegister: + * @id: the RespondWith klass. + * + * Registers @id in the global list of RespondWith klasses. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithId id) { + int ret; + + xmlSecAssert2(id != xmlSecXkmsRespondWithIdUnknown, -1); + + ret = xmlSecPtrListAdd(xmlSecXkmsRespondWithIdsGet(), (xmlSecPtr)id); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecPtrListAdd", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "RespondWith=%s", + xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id))); + return(-1); + } + + return(0); +} + +/** + * xmlSecXkmsRespondWithIdsRegisterDefault: + * + * Registers default (implemented by XML Security Library) + * RespondWith klasses: KeyName, KeyValue,... + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecXkmsRespondWithIdsRegisterDefault(void) { + if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithKeyNameId) < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsRespondWithIdsRegister", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "name=%s", + xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithKeyNameId))); + return(-1); + } + + if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithKeyValueId) < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsRespondWithIdsRegister", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "name=%s", + xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithKeyValueId))); + return(-1); + } + + if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithPrivateKeyId) < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsRespondWithIdsRegister", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "name=%s", + xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithPrivateKeyId))); + return(-1); + } + + if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithRetrievalMethodId) < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsRespondWithIdsRegister", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "name=%s", + xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithRetrievalMethodId))); + return(-1); + } + + if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithX509CertId) < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsRespondWithIdsRegister", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "name=%s", + xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithX509CertId))); + return(-1); + } + + if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithX509ChainId) < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsRespondWithIdsRegister", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "name=%s", + xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithX509ChainId))); + return(-1); + } + + if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithX509CRLId) < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsRespondWithIdsRegister", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "name=%s", + xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithX509CRLId))); + return(-1); + } + + /* TODO: OCSP, PGP, PGPWeb, SPKI */ + /* + if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithPGPId) < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsRespondWithIdsRegister", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "name=%s", + xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithPGPId))); + return(-1); + } + + if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithSPKIId) < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsRespondWithIdsRegister", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "name=%s", + xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithSPKIId))); + return(-1); + } + */ + return(0); +} + + +/************************************************************************ + * + * XKMS RespondWith Klass + * + ************************************************************************/ +/** + * xmlSecXkmsRespondWithNodeRead: + * @id: the RespondWith class. + * @ctx: the XKMS request processing context. + * @node: the pointer to <xkms:RespondWith/> node. + * + * Reads the content of the <xkms:RespondWith/> @node. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecXkmsRespondWithNodeRead(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node) { + xmlSecAssert2(id != xmlSecXkmsRespondWithIdUnknown, -1); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + if(id->readNode != NULL) { + return((id->readNode)(id, ctx, node)); + } + return(0); +} + +/** + * xmlSecXkmsRespondWithNodeWrite: + * @id: the RespondWith class. + * @ctx: the XKMS request processing context. + * @node: the pointer to <xkms:RespondWith/> node. + * + * Writes the content of the <xkms:RespondWith/> @node. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecXkmsRespondWithNodeWrite(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node) { + xmlSecAssert2(id != xmlSecXkmsRespondWithIdUnknown, -1); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + if(id->writeNode != NULL) { + return((id->writeNode)(id, ctx, node)); + } + return(0); +} + +/** + * xmlSecXkmsRespondWithDebugDump: + * @id: the RespondWith class. + * @output: the output file. + * + * Writes debug information about @id into the @output. + */ +void +xmlSecXkmsRespondWithDebugDump(xmlSecXkmsRespondWithId id, FILE* output) { + xmlSecAssert(id != xmlSecXkmsRespondWithIdUnknown); + xmlSecAssert(output != NULL); + + fprintf(output, "=== RespondWith: \"%s\" (href=\"%s\")\n", + xmlSecErrorsSafeString(id->valueName), + xmlSecErrorsSafeString(id->valueNs)); +} + +/** + * xmlSecXkmsRespondWithDebugXmlDump: + * @id: the RespondWith class. + * @output: the output file. + * + * Writes debug information about @id into the @output in XML format. + */ +void +xmlSecXkmsRespondWithDebugXmlDump(xmlSecXkmsRespondWithId id, FILE* output) { + xmlSecAssert(id != xmlSecXkmsRespondWithIdUnknown); + xmlSecAssert(output != NULL); + + fprintf(output, "<RespondWith href=\""); + xmlSecPrintXmlString(output, id->valueNs); + fprintf(output, "\">"); + xmlSecPrintXmlString(output, id->valueName); + fprintf(output, "</RespondWith>\n"); +} + +int +xmlSecXkmsRespondWithDefaultNodeRead(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node) { + int ret; + + xmlSecAssert2(id != xmlSecXkmsRespondWithIdUnknown, -1); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + ret = xmlSecXkmsRespondWithIdListFind(&(ctx->respWithList), id); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)), + "xmlSecXkmsRespondWithIdListFind", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } else if(ret > 0) { + /* do nothing, we already have it in the list */ + return(0); + } + + ret = xmlSecPtrListAdd(&(ctx->respWithList), id); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)), + "xmlSecPtrListAdd", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +int +xmlSecXkmsRespondWithDefaultNodeWrite(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node) { + xmlNodePtr cur; + + xmlSecAssert2(id != xmlSecXkmsRespondWithIdUnknown, -1); + xmlSecAssert2(id->nodeName != NULL, -1); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + cur = xmlSecAddChild(node, id->nodeName, id->nodeNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)), + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(id->nodeName)); + return(-1); + } + + return(0); +} + +/************************************************************************ + * + * XKMS RespondWith Klass List + * + ************************************************************************/ +static xmlSecPtrListKlass xmlSecXkmsRespondWithIdListKlass = { + BAD_CAST "respond-with-ids-list", + NULL, /* xmlSecPtrDuplicateItemMethod duplicateItem; */ + NULL, /* xmlSecPtrDestroyItemMethod destroyItem; */ + (xmlSecPtrDebugDumpItemMethod)xmlSecXkmsRespondWithDebugDump, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */ + (xmlSecPtrDebugDumpItemMethod)xmlSecXkmsRespondWithDebugXmlDump, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */ +}; + +xmlSecPtrListId +xmlSecXkmsRespondWithIdListGetKlass(void) { + return(&xmlSecXkmsRespondWithIdListKlass); +} + +int +xmlSecXkmsRespondWithIdListFind(xmlSecPtrListPtr list, xmlSecXkmsRespondWithId id) { + xmlSecSize i, size; + + xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecXkmsRespondWithIdListId), -1); + xmlSecAssert2(id != xmlSecXkmsRespondWithIdUnknown, -1); + + size = xmlSecPtrListGetSize(list); + for(i = 0; i < size; ++i) { + if((xmlSecXkmsRespondWithId)xmlSecPtrListGetItem(list, i) == id) { + return(1); + } + } + return(0); +} + +xmlSecXkmsRespondWithId +xmlSecXkmsRespondWithIdListFindByNodeValue(xmlSecPtrListPtr list, xmlNodePtr node) { + xmlSecXkmsRespondWithId result = xmlSecXkmsRespondWithIdUnknown; + xmlSecXkmsRespondWithId id; + xmlChar* content; + xmlChar* qnameLocalPart = NULL; + xmlChar* qnamePrefix = NULL; + const xmlChar* qnameHref; + xmlNsPtr ns; + xmlSecSize i, size; + + xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecXkmsRespondWithIdListId), xmlSecXkmsRespondWithIdUnknown); + xmlSecAssert2(node != NULL, xmlSecXkmsRespondWithIdUnknown); + + content = xmlNodeGetContent(node); + if(content == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlNodeGetContent", + XMLSEC_ERRORS_R_XML_FAILED, + "node=%s", + xmlSecErrorsSafeString(node->name)); + return(xmlSecXkmsRespondWithIdUnknown); + } + + qnameLocalPart = (xmlChar*)xmlStrchr(content, ':'); + if(qnameLocalPart != NULL) { + qnamePrefix = content; + *(qnameLocalPart++) = '\0'; + } else { + qnamePrefix = NULL; + qnameLocalPart = content; + } + + /* search namespace href */ + ns = xmlSearchNs(node->doc, node, qnamePrefix); + if((ns == NULL) && (qnamePrefix != NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSearchNs", + XMLSEC_ERRORS_R_XML_FAILED, + "node=%s,qnamePrefix=%s", + xmlSecErrorsSafeString(node->name), + xmlSecErrorsSafeString(qnamePrefix)); + xmlFree(content); + return(xmlSecXkmsRespondWithIdUnknown); + } + qnameHref = (ns != NULL) ? ns->href : BAD_CAST NULL; + + size = xmlSecPtrListGetSize(list); + for(i = 0; i < size; ++i) { + id = (xmlSecXkmsRespondWithId)xmlSecPtrListGetItem(list, i); + if((id != xmlSecXkmsRespondWithIdUnknown) && + xmlStrEqual(id->valueName, qnameLocalPart) && + xmlStrEqual(id->valueNs, qnameHref)) { + result = id; + break; + } + } + + xmlFree(content); + return(result); +} + +int +xmlSecXkmsRespondWithIdListWrite(xmlSecPtrListPtr list, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) { + xmlSecXkmsRespondWithId id; + xmlSecSize i, size; + int ret; + + xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecXkmsRespondWithIdListId), -1); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + size = xmlSecPtrListGetSize(list); + for(i = 0; i < size; ++i) { + id = (xmlSecXkmsRespondWithId)xmlSecPtrListGetItem(list, i); + if(id != xmlSecXkmsRespondWithIdUnknown) { + ret = xmlSecXkmsRespondWithNodeWrite(id, ctx, node); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)), + "xmlSecXkmsRespondWithNodeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + } + + return(0); +} + +/******************************************************************** + * + * XML Sec Library RespondWith Ids + * + *******************************************************************/ +static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithKeyNameKlass = { + xmlSecRespondWithKeyName, /* const xmlChar* valueName; */ + xmlSecXkmsNs, /* const xmlChar* valueNs; */ + xmlSecNodeKeyName, /* const xmlChar* nodeName; */ + xmlSecDSigNs, /* const xmlChar* nodeNs; */ + xmlSecXkmsRespondWithDefaultNodeRead, /* xmlSecXkmsRespondWithNodeReadMethod readNode; */ + xmlSecXkmsRespondWithDefaultNodeWrite, /* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */ + NULL, /* void* reserved1; */ + NULL /* void* reserved2; */ +}; + +/** + * xmlSecXkmsRespondWithKeyNameGetKlass: + * + * The respond with KeyName klass. + * + * Returns: respond with KeyName klass. + */ +xmlSecXkmsRespondWithId +xmlSecXkmsRespondWithKeyNameGetKlass(void) { + return(&xmlSecXkmsRespondWithKeyNameKlass); +} + + + +static int xmlSecXkmsRespondWithKeyValueNodeRead (xmlSecXkmsRespondWithId id, + xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node); +static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithKeyValueKlass = { + xmlSecRespondWithKeyValue, /* const xmlChar* valueName; */ + xmlSecXkmsNs, /* const xmlChar* valueNs; */ + xmlSecNodeKeyValue, /* const xmlChar* nodeName; */ + xmlSecDSigNs, /* const xmlChar* nodeNs; */ + xmlSecXkmsRespondWithKeyValueNodeRead, /* xmlSecXkmsRespondWithNodeReadMethod readNode; */ + xmlSecXkmsRespondWithDefaultNodeWrite, /* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */ + NULL, /* void* reserved1; */ + NULL /* void* reserved2; */ +}; + +/** + * xmlSecXkmsRespondWithKeyValueGetKlass: + * + * The respond with KeyValue klass. + * + * Returns: respond with KeyValue klass. + */ +xmlSecXkmsRespondWithId +xmlSecXkmsRespondWithKeyValueGetKlass(void) { + return(&xmlSecXkmsRespondWithKeyValueKlass); +} + +static int +xmlSecXkmsRespondWithKeyValueNodeRead(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node) { + int ret; + + xmlSecAssert2(id == xmlSecXkmsRespondWithKeyValueId, -1); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + /* do usual stuff */ + ret = xmlSecXkmsRespondWithDefaultNodeRead(id, ctx, node); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)), + "xmlSecXkmsRespondWithDefaultNodeRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* and now set some parameters in the ctx to look for a public or private + * key and to write a public key + */ + ctx->keyInfoReadCtx.keyReq.keyType |= (xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate); + ctx->keyInfoWriteCtx.keyReq.keyType |= xmlSecKeyDataTypePublic; + + return(0); +} + +static int xmlSecXkmsRespondWithPrivateKeyNodeRead (xmlSecXkmsRespondWithId id, + xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node); +static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithPrivateKeyKlass = { + xmlSecRespondWithPrivateKey, /* const xmlChar* valueName; */ + xmlSecXkmsNs, /* const xmlChar* valueNs; */ + xmlSecNodeKeyValue, /* const xmlChar* nodeName; */ + xmlSecDSigNs, /* const xmlChar* nodeNs; */ + xmlSecXkmsRespondWithPrivateKeyNodeRead, /* xmlSecXkmsRespondWithNodeReadMethod readNode; */ + xmlSecXkmsRespondWithDefaultNodeWrite, /* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */ + NULL, /* void* reserved1; */ + NULL /* void* reserved2; */ +}; + +/** + * xmlSecXkmsRespondWithPrivateKeyGetKlass: + * + * The respond with PrivateKey klass. + * + * Returns: respond with PrivateKey klass. + */ +xmlSecXkmsRespondWithId +xmlSecXkmsRespondWithPrivateKeyGetKlass(void) { + return(&xmlSecXkmsRespondWithPrivateKeyKlass); +} + +static int +xmlSecXkmsRespondWithPrivateKeyNodeRead(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node) { + int ret; + + xmlSecAssert2(id == xmlSecXkmsRespondWithPrivateKeyId, -1); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + /* do usual stuff */ + ret = xmlSecXkmsRespondWithDefaultNodeRead(id, ctx, node); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)), + "xmlSecXkmsRespondWithDefaultNodeRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* and now set some parameters in the ctx to look for a private + * key and to write a private key + */ + ctx->keyInfoReadCtx.keyReq.keyType |= xmlSecKeyDataTypePrivate; + ctx->keyInfoWriteCtx.keyReq.keyType |= xmlSecKeyDataTypePrivate; + + return(0); +} + +static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithRetrievalMethodKlass = { + xmlSecRespondWithRetrievalMethod, /* const xmlChar* valueName; */ + xmlSecXkmsNs, /* const xmlChar* valueNs; */ + xmlSecNodeRetrievalMethod, /* const xmlChar* nodeName; */ + xmlSecDSigNs, /* const xmlChar* nodeNs; */ + xmlSecXkmsRespondWithDefaultNodeRead, /* xmlSecXkmsRespondWithNodeReadMethod readNode; */ + xmlSecXkmsRespondWithDefaultNodeWrite, /* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */ + NULL, /* void* reserved1; */ + NULL /* void* reserved2; */ +}; + +/** + * xmlSecXkmsRespondWithRetrievalMethodGetKlass: + * + * The respond with RetrievalMethod klass. + * + * Returns: respond with RetrievalMethod klass. + */ +xmlSecXkmsRespondWithId +xmlSecXkmsRespondWithRetrievalMethodGetKlass(void) { + return(&xmlSecXkmsRespondWithRetrievalMethodKlass); +} + + + +static int xmlSecXkmsRespondWithX509CertNodeRead (xmlSecXkmsRespondWithId id, + xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node); +static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithX509CertKlass = { + xmlSecRespondWithX509Cert, /* const xmlChar* valueName; */ + xmlSecXkmsNs, /* const xmlChar* valueNs; */ + xmlSecNodeX509Data, /* const xmlChar* nodeName; */ + xmlSecDSigNs, /* const xmlChar* nodeNs; */ + xmlSecXkmsRespondWithX509CertNodeRead, /* xmlSecXkmsRespondWithNodeReadMethod readNode; */ + xmlSecXkmsRespondWithDefaultNodeWrite, /* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */ + NULL, /* void* reserved1; */ + NULL /* void* reserved2; */ +}; + +/** + * xmlSecXkmsRespondWithX509CertGetKlass: + * + * The respond with X509Cert klass. + * + * Returns: respond with X509Cert klass. + */ +xmlSecXkmsRespondWithId +xmlSecXkmsRespondWithX509CertGetKlass(void) { + return(&xmlSecXkmsRespondWithX509CertKlass); +} + +static int +xmlSecXkmsRespondWithX509CertNodeRead(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node) { + int ret; + + xmlSecAssert2(id == xmlSecXkmsRespondWithX509CertId, -1); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + /* do usual stuff */ + ret = xmlSecXkmsRespondWithDefaultNodeRead(id, ctx, node); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)), + "xmlSecXkmsRespondWithDefaultNodeRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +static int xmlSecXkmsRespondWithX509ChainNodeRead (xmlSecXkmsRespondWithId id, + xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node); +static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithX509ChainKlass = { + xmlSecRespondWithX509Chain, /* const xmlChar* valueName; */ + xmlSecXkmsNs, /* const xmlChar* valueNs; */ + xmlSecNodeX509Data, /* const xmlChar* nodeName; */ + xmlSecDSigNs, /* const xmlChar* nodeNs; */ + xmlSecXkmsRespondWithX509ChainNodeRead, /* xmlSecXkmsRespondWithNodeReadMethod readNode; */ + xmlSecXkmsRespondWithDefaultNodeWrite, /* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */ + NULL, /* void* reserved1; */ + NULL /* void* reserved2; */ +}; + +/** + * xmlSecXkmsRespondWithX509ChainGetKlass: + * + * The respond with X509Chain klass. + * + * Returns: respond with X509Chain klass. + */ +xmlSecXkmsRespondWithId +xmlSecXkmsRespondWithX509ChainGetKlass(void) { + return(&xmlSecXkmsRespondWithX509ChainKlass); +} + +static int +xmlSecXkmsRespondWithX509ChainNodeRead(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node) { + int ret; + + xmlSecAssert2(id == xmlSecXkmsRespondWithX509ChainId, -1); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + /* do usual stuff */ + ret = xmlSecXkmsRespondWithDefaultNodeRead(id, ctx, node); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)), + "xmlSecXkmsRespondWithDefaultNodeRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +static int xmlSecXkmsRespondWithX509CRLNodeRead (xmlSecXkmsRespondWithId id, + xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node); +static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithX509CRLKlass = { + xmlSecRespondWithX509CRL, /* const xmlChar* valueName; */ + xmlSecXkmsNs, /* const xmlChar* valueNs; */ + xmlSecNodeX509Data, /* const xmlChar* nodeName; */ + xmlSecDSigNs, /* const xmlChar* nodeNs; */ + xmlSecXkmsRespondWithX509CRLNodeRead, /* xmlSecXkmsRespondWithNodeReadMethod readNode; */ + xmlSecXkmsRespondWithDefaultNodeWrite, /* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */ + NULL, /* void* reserved1; */ + NULL /* void* reserved2; */ +}; + +/** + * xmlSecXkmsRespondWithX509CRLGetKlass: + * + * The respond with X509CRL klass. + * + * Returns: respond with X509CRL klass. + */ +xmlSecXkmsRespondWithId +xmlSecXkmsRespondWithX509CRLGetKlass(void) { + return(&xmlSecXkmsRespondWithX509CRLKlass); +} + +static int +xmlSecXkmsRespondWithX509CRLNodeRead(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node) { + int ret; + + xmlSecAssert2(id == xmlSecXkmsRespondWithX509CRLId, -1); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + /* do usual stuff */ + ret = xmlSecXkmsRespondWithDefaultNodeRead(id, ctx, node); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)), + "xmlSecXkmsRespondWithDefaultNodeRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithPGPKlass = { + xmlSecRespondWithPGP, /* const xmlChar* valueName; */ + xmlSecXkmsNs, /* const xmlChar* valueNs; */ + xmlSecNodePGPData, /* const xmlChar* nodeName; */ + xmlSecDSigNs, /* const xmlChar* nodeNs; */ + xmlSecXkmsRespondWithDefaultNodeRead, /* xmlSecXkmsRespondWithNodeReadMethod readNode; */ + xmlSecXkmsRespondWithDefaultNodeWrite, /* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */ + NULL, /* void* reserved1; */ + NULL /* void* reserved2; */ +}; + +/** + * xmlSecXkmsRespondWithPGPGetKlass: + * + * The respond with PGP klass. + * + * Returns: respond with PGP klass. + */ +xmlSecXkmsRespondWithId +xmlSecXkmsRespondWithPGPGetKlass(void) { + return(&xmlSecXkmsRespondWithPGPKlass); +} + +static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithSPKIKlass = { + xmlSecRespondWithSPKI, /* const xmlChar* valueName; */ + xmlSecXkmsNs, /* const xmlChar* valueNs; */ + xmlSecNodeSPKIData, /* const xmlChar* nodeName; */ + xmlSecDSigNs, /* const xmlChar* nodeNs; */ + xmlSecXkmsRespondWithDefaultNodeRead, /* xmlSecXkmsRespondWithNodeReadMethod readNode; */ + xmlSecXkmsRespondWithDefaultNodeWrite, /* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */ + NULL, /* void* reserved1; */ + NULL /* void* reserved2; */ +}; + +/** + * xmlSecXkmsRespondWithSPKIGetKlass: + * + * The respond with SPKI klass. + * + * Returns: respond with SPKI klass. + */ +xmlSecXkmsRespondWithId +xmlSecXkmsRespondWithSPKIGetKlass(void) { + return(&xmlSecXkmsRespondWithSPKIKlass); +} + +/************************************************************************** + * + * Global xmlSecXkmsServerRequestIds list functions + * + *************************************************************************/ +static xmlSecPtrList xmlSecAllXkmsServerRequestIds; + + +/** + * xmlSecXkmsServerRequestIdsGet: + * + * Gets global registered ServerRequest klasses list. + * + * Returns: the pointer to list of all registered ServerRequest klasses. + */ +xmlSecPtrListPtr +xmlSecXkmsServerRequestIdsGet(void) { + return(&xmlSecAllXkmsServerRequestIds); +} + +/** + * xmlSecXkmsServerRequestIdsInit: + * + * Initializes the ServerRequest klasses. This function is called from the + * #xmlSecInit function and the application should not call it directly. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecXkmsServerRequestIdsInit(void) { + int ret; + + ret = xmlSecPtrListInitialize(xmlSecXkmsServerRequestIdsGet(), xmlSecXkmsServerRequestIdListId); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecPtrListPtrInitialize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "xmlSecXkmsServerRequestIdListId"); + return(-1); + } + + ret = xmlSecXkmsServerRequestIdsRegisterDefault(); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerRequestIdsRegisterDefault", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +/** + * xmlSecXkmsServerRequestIdsShutdown: + * + * Shuts down the keys data klasses. This function is called from the + * #xmlSecShutdown function and the application should not call it directly. + */ +void +xmlSecXkmsServerRequestIdsShutdown(void) { + xmlSecPtrListFinalize(xmlSecXkmsServerRequestIdsGet()); +} + +/** + * xmlSecXkmsServerRequestIdsRegister: + * @id: the ServerRequest klass. + * + * Registers @id in the global list of ServerRequest klasses. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecXkmsServerRequestIdsRegister(xmlSecXkmsServerRequestId id) { + int ret; + + xmlSecAssert2(id != xmlSecXkmsServerRequestIdUnknown, -1); + + ret = xmlSecPtrListAdd(xmlSecXkmsServerRequestIdsGet(), (xmlSecPtr)id); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecPtrListAdd", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "ServerRequest=%s", + xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(id))); + return(-1); + } + + return(0); +} + +/** + * xmlSecXkmsServerRequestIdsRegisterDefault: + * + * Registers default (implemented by XML Security Library) + * ServerRequest klasses: KeyName, KeyValue,... + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecXkmsServerRequestIdsRegisterDefault(void) { + if(xmlSecXkmsServerRequestIdsRegister(xmlSecXkmsServerRequestResultId) < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerRequestIdsRegister", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "name=%s", + xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(xmlSecXkmsServerRequestResultId))); + return(-1); + } + + if(xmlSecXkmsServerRequestIdsRegister(xmlSecXkmsServerRequestStatusId) < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerRequestIdsRegister", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "name=%s", + xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(xmlSecXkmsServerRequestStatusId))); + return(-1); + } + + if(xmlSecXkmsServerRequestIdsRegister(xmlSecXkmsServerRequestCompoundId) < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerRequestIdsRegister", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "name=%s", + xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(xmlSecXkmsServerRequestCompoundId))); + return(-1); + } + + if(xmlSecXkmsServerRequestIdsRegister(xmlSecXkmsServerRequestLocateId) < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerRequestIdsRegister", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "name=%s", + xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(xmlSecXkmsServerRequestLocateId))); + return(-1); + } + + if(xmlSecXkmsServerRequestIdsRegister(xmlSecXkmsServerRequestValidateId) < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerRequestIdsRegister", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "name=%s", + xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(xmlSecXkmsServerRequestValidateId))); + return(-1); + } + + return(0); +} + + +/************************************************************************ + * + * XKMS ServerRequest Klass + * + ************************************************************************/ +/** + * xmlSecXkmsServerRequestNodeRead: + * @id: the ServerRequest class. + * @ctx: the XKMS request processing context. + * @node: the pointer to <xkms:ServerRequest/> node. + * + * Reads the content of the <xkms:ServerRequest/> @node. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecXkmsServerRequestNodeRead(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node) { + xmlSecAssert2(id != xmlSecXkmsServerRequestIdUnknown, -1); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + if(id->readNode != NULL) { + return((id->readNode)(id, ctx, node)); + } + return(0); +} + +/** + * xmlSecXkmsServerExecute: + * @id: the ServerRequest class. + * @ctx: the XKMS request processing context. + * + * Executes XKMS server request. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecXkmsServerRequestExecute(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx) { + xmlSecAssert2(id != xmlSecXkmsServerRequestIdUnknown, -1); + xmlSecAssert2(ctx != NULL, -1); + + if(id->execute != NULL) { + return((id->execute)(id, ctx)); + } + return(0); +} + + +/** + * xmlSecXkmsServerResponseNodeWrite: + * @id: the ServerRequest class. + * @ctx: the XKMS request processing context. + * @doc: the pointer to response parent XML document (might be NULL). + * @node: the pointer to response parent XML node (might be NULL). + * + * Writes XKMS response from context to a newly created node. Caller is + * responsible for adding the returned node to the XML document. + * + * Returns: pointer to newly created XKMS response node or NULL + * if an error occurs. + */ +xmlNodePtr +xmlSecXkmsServerRequestNodeWrite(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, + xmlDocPtr doc, xmlNodePtr node) { + xmlNodePtr respNode; + int ret; + + xmlSecAssert2(id != xmlSecXkmsServerRequestIdUnknown, NULL); + xmlSecAssert2(ctx != NULL, NULL); + + /* create the response root node */ + if(node == NULL) { + xmlNsPtr ns; + + respNode = xmlNewDocNode(doc, NULL, id->resultNodeName, NULL); + if(respNode == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlNewDocNode", + XMLSEC_ERRORS_R_XML_FAILED, + "node=%s", + xmlSecErrorsSafeString(id->resultNodeName)); + return(NULL); + } + ns = xmlNewNs(respNode, id->resultNodeNs, NULL); + if(ns == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlNewNs", + XMLSEC_ERRORS_R_XML_FAILED, + "ns=%s", + xmlSecErrorsSafeString(id->resultNodeNs)); + xmlFreeNode(respNode); + return(NULL); + } + xmlSetNs(respNode, ns); + } else { + respNode = xmlSecAddChild(node, id->resultNodeName, id->resultNodeNs); + if(respNode == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(id->resultNodeName)); + return(NULL); + } + } + + if(id->writeNode != NULL) { + ret = (id->writeNode)(id, ctx, respNode); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "writeNode", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(id->resultNodeName)); + xmlFreeNode(respNode); + return(NULL); + } + } + + return(respNode); +} + +/** + * xmlSecXkmsServerRequestDebugDump: + * @id: the ServerRequest class. + * @output: the output file. + * + * Writes debug information about @id into the @output. + */ +void +xmlSecXkmsServerRequestDebugDump(xmlSecXkmsServerRequestId id, FILE* output) { + xmlSecAssert(id != xmlSecXkmsServerRequestIdUnknown); + xmlSecAssert(output != NULL); + + fprintf(output, "=== ServerRequest: %s\n", xmlSecErrorsSafeString(id->name)); +} + +/** + * xmlSecXkmsServerRequestDebugXmlDump: + * @id: the ServerRequest class. + * @output: the output file. + * + * Writes debug information about @id into the @output in XML format. + */ +void +xmlSecXkmsServerRequestDebugXmlDump(xmlSecXkmsServerRequestId id, FILE* output) { + xmlSecAssert(id != xmlSecXkmsServerRequestIdUnknown); + xmlSecAssert(output != NULL); + + fprintf(output, "<ServerRequest>"); + xmlSecPrintXmlString(output, id->name); + fprintf(output, "</ServerRequest>\n"); +} + +/************************************************************************ + * + * XKMS ServerRequest Klass List + * + ************************************************************************/ +static xmlSecPtrListKlass xmlSecXkmsServerRequestIdListKlass = { + BAD_CAST "xkms-server-request-ids-list", + NULL, /* xmlSecPtrDuplicateItemMethod duplicateItem; */ + NULL, /* xmlSecPtrDestroyItemMethod destroyItem; */ + (xmlSecPtrDebugDumpItemMethod)xmlSecXkmsServerRequestDebugDump, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */ + (xmlSecPtrDebugDumpItemMethod)xmlSecXkmsServerRequestDebugXmlDump, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */ +}; + +xmlSecPtrListId +xmlSecXkmsServerRequestIdListGetKlass(void) { + return(&xmlSecXkmsServerRequestIdListKlass); +} + +int +xmlSecXkmsServerRequestIdListFind(xmlSecPtrListPtr list, xmlSecXkmsServerRequestId id) { + xmlSecSize i, size; + + xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecXkmsServerRequestIdListId), -1); + xmlSecAssert2(id != xmlSecXkmsServerRequestIdUnknown, -1); + + size = xmlSecPtrListGetSize(list); + for(i = 0; i < size; ++i) { + if((xmlSecXkmsServerRequestId)xmlSecPtrListGetItem(list, i) == id) { + return(1); + } + } + return(0); +} + +xmlSecXkmsServerRequestId +xmlSecXkmsServerRequestIdListFindByName(xmlSecPtrListPtr list, const xmlChar* name) { + xmlSecXkmsServerRequestId id; + xmlSecSize i, size; + + xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecXkmsServerRequestIdListId), xmlSecXkmsServerRequestIdUnknown); + xmlSecAssert2(name != NULL, xmlSecXkmsServerRequestIdUnknown); + + size = xmlSecPtrListGetSize(list); + for(i = 0; i < size; ++i) { + id = (xmlSecXkmsServerRequestId)xmlSecPtrListGetItem(list, i); + if((id != xmlSecXkmsServerRequestIdUnknown) && xmlStrEqual(id->name, name)) { + return(id); + } + } + return(xmlSecXkmsServerRequestIdUnknown); +} + +xmlSecXkmsServerRequestId +xmlSecXkmsServerRequestIdListFindByNode(xmlSecPtrListPtr list, xmlNodePtr node) { + xmlSecXkmsServerRequestId id; + xmlSecSize i, size; + + xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecXkmsServerRequestIdListId), xmlSecXkmsServerRequestIdUnknown); + xmlSecAssert2(node != NULL, xmlSecXkmsServerRequestIdUnknown); + + size = xmlSecPtrListGetSize(list); + for(i = 0; i < size; ++i) { + id = (xmlSecXkmsServerRequestId)xmlSecPtrListGetItem(list, i); + if((id != xmlSecXkmsServerRequestIdUnknown) && + xmlSecCheckNodeName(node, id->requestNodeName, id->requestNodeNs)) { + + return(id); + } + } + return(xmlSecXkmsServerRequestIdUnknown); +} + +/******************************************************************** + * + * XML Sec Library ServerRequest Ids + * + *******************************************************************/ + + +/******************************************************************** + * + * Result response + * + *******************************************************************/ +static int xmlSecXkmsServerRequestResultNodeWrite (xmlSecXkmsServerRequestId id, + xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node); + +static xmlSecXkmsServerRequestKlass xmlSecXkmsServerRequestResultKlass = { + xmlSecXkmsServerRequestResultName, /* const xmlChar* name; */ + NULL, /* const xmlChar* requestNodeName; */ + NULL, /* const xmlChar* requestNodeNs; */ + xmlSecNodeResult, /* const xmlChar* responseNodeName; */ + xmlSecXkmsNs, /* const xmlChar* responseNodeNs; */ + 0, /* xmlSecBitMask flags; */ + NULL, /* xmlSecXkmsServerRequestNodeReadMethod readNode; */ + xmlSecXkmsServerRequestResultNodeWrite, /* xmlSecXkmsServerRequestNodeWriteMethod writeNode; */ + NULL, /* xmlSecXkmsServerRequestExecuteMethod execute; */ + NULL, /* void* reserved1; */ + NULL /* void* reserved2; */ +}; + +/** + * xmlSecXkmsServerRequestResultGetKlass: + * + * The Result response klass. + * + * Returns: Result response klass. + */ +xmlSecXkmsServerRequestId +xmlSecXkmsServerRequestResultGetKlass(void) { + return(&xmlSecXkmsServerRequestResultKlass); +} + +static int +xmlSecXkmsServerRequestResultNodeWrite(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) { + int ret; + + xmlSecAssert2(id == xmlSecXkmsServerRequestResultId, -1); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + /* set missing parameters (if any) */ + if(ctx->service == NULL) { + ctx->service = xmlStrdup((ctx->expectedService != NULL) ? ctx->expectedService : BAD_CAST ""); + if(ctx->service == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlStrdup", + XMLSEC_ERRORS_R_MALLOC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + + /* first write the "parent" type */ + ret = xmlSecXkmsServerCtxResultTypeNodeWrite(ctx, node); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxResultTypeNodeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +/******************************************************************** + * + * StatusRequest/StatusResponse + * + *******************************************************************/ +static int xmlSecXkmsServerRequestStatusNodeRead (xmlSecXkmsServerRequestId id, + xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node); +static int xmlSecXkmsServerRequestStatusNodeWrite (xmlSecXkmsServerRequestId id, + xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node); + +static xmlSecXkmsServerRequestKlass xmlSecXkmsServerRequestStatusKlass = { + xmlSecXkmsServerRequestStatusName, /* const xmlChar* name; */ + xmlSecNodeStatusRequest, /* const xmlChar* requestNodeName; */ + xmlSecXkmsNs, /* const xmlChar* requestNodeNs; */ + xmlSecNodeStatusResult, /* const xmlChar* responseNodeName; */ + xmlSecXkmsNs, /* const xmlChar* responseNodeNs; */ + 0, /* xmlSecBitMask flags; */ + xmlSecXkmsServerRequestStatusNodeRead, /* xmlSecXkmsServerRequestNodeReadMethod readNode; */ + xmlSecXkmsServerRequestStatusNodeWrite, /* xmlSecXkmsServerRequestNodeWriteMethod writeNode; */ + NULL, /* xmlSecXkmsServerRequestExecuteMethod execute; */ + NULL, /* void* reserved1; */ + NULL /* void* reserved2; */ +}; + +/** + * xmlSecXkmsServerRequestStatusGetKlass: + * + * The StatusRequest klass. + * + * Returns: StatusRequest klass. + */ +xmlSecXkmsServerRequestId +xmlSecXkmsServerRequestStatusGetKlass(void) { + return(&xmlSecXkmsServerRequestStatusKlass); +} + +/** + * + * <xkms:StatusRequest Id Service Nonce? OriginalRequestId? ResponseLimit? ResponseId?> + * <ds:Signature>? + * <xkms:MessageExtension>* + * (<xkms:OpaqueClientData> + * <xkms:OpaqueData>? + * )? + * <xkms:ResponseMechanism>* + * <xkms:RespondWith>* + * <xkms:PendingNotification Mechanism Identifier>? + * + * XML Schema: + * <!-- StatusRequest --> + * <element name="StatusRequest" type="xkms:StatusRequestType"/> + * <complexType name="StatusRequestType"> + * <complexContent> + * <extension base="xkms:PendingRequestType"/> + * </complexContent> + * </complexType> + * <!-- /StatusRequest --> + */ +static int +xmlSecXkmsServerRequestStatusNodeRead(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) { + xmlNodePtr cur; + int ret; + + xmlSecAssert2(id == xmlSecXkmsServerRequestStatusId, -1); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + cur = node; + + /* first read "parent" type */ + ret = xmlSecXkmsServerCtxPendingRequestNodeRead(ctx, &cur); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxPendingRequestNodeRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* check that there is nothing after the last node */ + if(cur != NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_UNEXPECTED_NODE, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +/** + * + * <xkms:StatusResult Id Service Nonce? ResultMajor ResultMinor? RequestId? Success? Failure? Pending?> + * <ds:Signature>? + * <xkms:MessageExtension>* + * (<xkms:OpaqueClientData> + * <xkms:OpaqueData>? + * )? + * <xkms:RequestSignatureValue>* + * + * XML Schema: + * + * <!-- StatusResult --> + * <element name="StatusResult" type="xkms:StatusResultType"/> + * <complexType name="StatusResultType"> + * <complexContent> + * <extension base="xkms:ResultType"> + * <attribute name="Success" type="integer" use="optional"/> + * <attribute name="Failure" type="integer" use="optional"/> + * <attribute name="Pending" type="integer" use="optional"/> + * </extension> + * </complexContent> + * </complexType> + * <!-- /StatusResult --> * + */ +static int +xmlSecXkmsServerRequestStatusNodeWrite(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) { + int ret; + + xmlSecAssert2(id == xmlSecXkmsServerRequestStatusId, -1); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + /* first write the "parent" type */ + ret = xmlSecXkmsServerCtxResultTypeNodeWrite(ctx, node); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxResultTypeNodeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* todo: add optional StatusResult attributes */ + return(0); +} + +/******************************************************************** + * + * CompoundRequest/CompoundResponse + * + *******************************************************************/ +static int xmlSecXkmsServerRequestCompoundNodeRead (xmlSecXkmsServerRequestId id, + xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node); +static int xmlSecXkmsServerRequestCompoundNodeWrite(xmlSecXkmsServerRequestId id, + xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node); +static int xmlSecXkmsServerRequestCompoundExecute (xmlSecXkmsServerRequestId id, + xmlSecXkmsServerCtxPtr ctx); + +static xmlSecXkmsServerRequestKlass xmlSecXkmsServerRequestCompoundKlass = { + xmlSecXkmsServerRequestCompoundName, /* const xmlChar* name; */ + xmlSecNodeCompoundRequest, /* const xmlChar* requestNodeName; */ + xmlSecXkmsNs, /* const xmlChar* requestNodeNs; */ + xmlSecNodeCompoundResult, /* const xmlChar* responseNodeName; */ + xmlSecXkmsNs, /* const xmlChar* responseNodeNs; */ + 0, /* xmlSecBitMask flags; */ + xmlSecXkmsServerRequestCompoundNodeRead, /* xmlSecXkmsServerRequestNodeReadMethod readNode; */ + xmlSecXkmsServerRequestCompoundNodeWrite, /* xmlSecXkmsServerRequestNodeWriteMethod writeNode; */ + xmlSecXkmsServerRequestCompoundExecute, /* xmlSecXkmsServerRequestExecuteMethod execute; */ + NULL, /* void* reserved1; */ + NULL /* void* reserved2; */ +}; + +/** + * xmlSecXkmsServerRequestCompoundGetKlass: + * + * The CompoundRequest klass. + * + * Returns: CompoundRequest klass. + */ +xmlSecXkmsServerRequestId +xmlSecXkmsServerRequestCompoundGetKlass(void) { + return(&xmlSecXkmsServerRequestCompoundKlass); +} + +/** + * <xkms:CompoundRequest Id Service Nonce? OriginalRequestId? ResponseLimit?> + * <ds:Signature>? + * <xkms:MessageExtension>* + * (<xkms:OpaqueClientData> + * <xkms:OpaqueData>? + * )? + * <xkms:ResponseMechanism>* + * <xkms:RespondWith>* + * <xkms:PendingNotification Mechanism Identifier>? + * ( + * <xkms:LocateRequest>? + * <xkms:ValidateRequest>? + * <xkms:RegisterRequest>? + * <xkms:ReissueRequest>? + * <xkms:RecoverRequest>? + * <xkms:RevokeRequest>? + * )* + * + * XML Schema: + * + * <!-- CompoundRequest --> + * <element name="CompoundRequest" type="xkms:CompoundRequestType"/> + * <complexType name="CompoundRequestType"> + * <complexContent> + * <extension base="xkms:RequestAbstractType"> + * <choice maxOccurs="unbounded"> + * <element ref="xkms:LocateRequest"/> + * <element ref="xkms:ValidateRequest"/> + * <element ref="xkms:RegisterRequest"/> + * <element ref="xkms:ReissueRequest"/> + * <element ref="xkms:RecoverRequest"/> + * <element ref="xkms:RevokeRequest"/> + * </choice> + * </extension> + * </complexContent> + * </complexType> + * <!-- /CompoundRequest --> + */ +static int +xmlSecXkmsServerRequestCompoundNodeRead(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) { + xmlSecPtrListPtr serverRequestIdsList; + xmlNodePtr cur; + int ret; + + xmlSecAssert2(id == xmlSecXkmsServerRequestCompoundId, -1); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + cur = node; + + /* first read "parent" type */ + ret = xmlSecXkmsServerCtxRequestAbstractTypeNodeRead(ctx, &cur); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxRequestAbstractTypeNodeRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* create list for compound requests */ + xmlSecAssert2(ctx->compoundRequestContexts == NULL, -1); + ctx->compoundRequestContexts = xmlSecPtrListCreate(xmlSecXkmsServerCtxPtrListId); + if(ctx->compoundRequestContexts == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecPtrListCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* get the list of enabled or all request klasses */ + if(xmlSecPtrListGetSize(&(ctx->enabledServerRequestIds)) > 0) { + serverRequestIdsList = &(ctx->enabledServerRequestIds); + } else { + serverRequestIdsList = xmlSecXkmsServerRequestIdsGet(); + } + xmlSecAssert2(serverRequestIdsList != NULL, -1); + + while(cur != NULL) { + xmlSecXkmsServerCtxPtr ctxChild; + + /* create a new context */ + ctxChild = xmlSecXkmsServerCtxCreate(ctx->keyInfoReadCtx.keysMngr); + if(ctxChild == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* copy all settings from us */ + ret = xmlSecXkmsServerCtxCopyUserPref(ctxChild, ctx); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxCopyUserPref", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxDestroy(ctxChild); + return(-1); + } + + /* add it to the list */ + ret = xmlSecPtrListAdd(ctx->compoundRequestContexts, ctxChild); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecPtrListAdd", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxDestroy(ctxChild); + return(-1); + } + + /* and now process request from current node */ + ctxChild->requestId = xmlSecXkmsServerRequestIdListFindByNode(serverRequestIdsList, cur); + if((ctxChild->requestId == xmlSecXkmsServerRequestIdUnknown) || + ((ctxChild->requestId->flags & XMLSEC_XKMS_SERVER_REQUEST_KLASS_ALLOWED_IN_COUMPOUND) == 0)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerRequestIdListFindByNode", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(node->name)); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorMessageNotSupported); + return(-1); + } + + ret = xmlSecXkmsServerRequestNodeRead(ctxChild->requestId, ctxChild, cur); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerRequestNodeRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "request=%s", + xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(ctxChild->requestId))); + xmlSecXkmsServerCtxSetResult(ctxChild, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure); + return(-1); + } + cur = xmlSecGetNextElementNode(cur->next); + } + + /* check that there is nothing after the last node */ + if(cur != NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_UNEXPECTED_NODE, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +/** + * <xkms:CompoundResult Id Service Nonce? ResultMajor ResultMinor? RequestId?> + * <ds:Signature>? + * <xkms:MessageExtension>* + * (<xkms:OpaqueClientData> + * <xkms:OpaqueData>? + * )? + * <xkms:RequestSignatureValue>* + * ( + * <xkms:LocateResult>? + * <xkms:ValidateResult>? + * <xkms:RegisterResult>? + * <xkms:ReissueResult>? + * <xkms:RecoverResult>? + * <xkms:RevokeResult>? + * )* + * + * + * XML Schema: + * + * <!-- CompoundResponse --> + * <element name="CompoundResult" type="xkms:CompoundResultType"/> + * <complexType name="CompoundResultType"> + * <complexContent> + * <extension base="xkms:ResultType"> + * <choice maxOccurs="unbounded"> + * <element ref="xkms:LocateResult"/> + * <element ref="xkms:ValidateResult"/> + * <element ref="xkms:RegisterResult"/> + * <element ref="xkms:ReissueResult"/> + * <element ref="xkms:RecoverResult"/> + * <element ref="xkms:RevokeResult"/> + * </choice> + * </extension> + * </complexContent> + * </complexType> + * <!-- /CompoundResponse --> + */ +static int +xmlSecXkmsServerRequestCompoundNodeWrite(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) { + int ret; + + xmlSecAssert2(id == xmlSecXkmsServerRequestCompoundId, -1); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + /* walk thru the list of chilren and pickup first error */ + if(ctx->compoundRequestContexts != NULL) { + xmlSecSize pos; + + for(pos = 0; pos < xmlSecPtrListGetSize(ctx->compoundRequestContexts); pos++) { + xmlSecXkmsServerCtxPtr ctxChild; + + ctxChild = (xmlSecXkmsServerCtxPtr)xmlSecPtrListGetItem(ctx->compoundRequestContexts, pos); + if(ctxChild == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecPtrListGetItem", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + if(ctxChild->resultMajor != xmlSecXkmsResultMajorSuccess) { + xmlSecXkmsServerCtxSetResult(ctx, ctxChild->resultMajor, ctxChild->resultMinor); + break; + } + } + } + + /* first write the "parent" type */ + ret = xmlSecXkmsServerCtxResultTypeNodeWrite(ctx, node); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxResultTypeNodeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* write compound result */ + if(ctx->compoundRequestContexts != NULL) { + xmlSecSize pos; + + for(pos = 0; pos < xmlSecPtrListGetSize(ctx->compoundRequestContexts); pos++) { + xmlSecXkmsServerCtxPtr ctxChild; + xmlNodePtr cur; + + ctxChild = (xmlSecXkmsServerCtxPtr)xmlSecPtrListGetItem(ctx->compoundRequestContexts, pos); + if(ctxChild == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecPtrListGetItem", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + cur = xmlSecXkmsServerRequestNodeWrite(ctxChild->requestId, ctxChild, node->doc, node); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerRequestNodeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "request=%s", + xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(ctxChild->requestId))); + return(-1); + } + + if(xmlSecAddChildNode(node, cur) == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecAddChildNode", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlFreeNode(cur); + return(-1); + } + } + } + + return(0); +} + +static int +xmlSecXkmsServerRequestCompoundExecute(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx) { + int ret; + + xmlSecAssert2(id == xmlSecXkmsServerRequestCompoundId, -1); + xmlSecAssert2(ctx != NULL, -1); + + if(ctx->compoundRequestContexts != NULL) { + xmlSecSize pos; + + for(pos = 0; pos < xmlSecPtrListGetSize(ctx->compoundRequestContexts); pos++) { + xmlSecXkmsServerCtxPtr ctxChild; + + ctxChild = (xmlSecXkmsServerCtxPtr)xmlSecPtrListGetItem(ctx->compoundRequestContexts, pos); + if(ctxChild == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecPtrListGetItem", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure); + continue; + } + + ret = xmlSecXkmsServerRequestExecute(ctxChild->requestId, ctxChild); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerRequestExecute", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "request=%s", + xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(ctxChild->requestId))); + xmlSecXkmsServerCtxSetResult(ctxChild, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure); + continue; + } + } + } + + return(0); +} + + +/******************************************************************** + * + * LocateRequest/LocateResponse + * + *******************************************************************/ +static int xmlSecXkmsServerRequestLocateNodeRead (xmlSecXkmsServerRequestId id, + xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node); +static int xmlSecXkmsServerRequestLocateNodeWrite (xmlSecXkmsServerRequestId id, + xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node); +static int xmlSecXkmsServerRequestLocateExecute (xmlSecXkmsServerRequestId id, + xmlSecXkmsServerCtxPtr ctx); + +static xmlSecXkmsServerRequestKlass xmlSecXkmsServerRequestLocateKlass = { + xmlSecXkmsServerRequestLocateName, /* const xmlChar* name; */ + xmlSecNodeLocateRequest, /* const xmlChar* requestNodeName; */ + xmlSecXkmsNs, /* const xmlChar* requestNodeNs; */ + xmlSecNodeLocateResult, /* const xmlChar* responseNodeName; */ + xmlSecXkmsNs, /* const xmlChar* responseNodeNs; */ + XMLSEC_XKMS_SERVER_REQUEST_KLASS_ALLOWED_IN_COUMPOUND, /* xmlSecBitMask flags; */ + xmlSecXkmsServerRequestLocateNodeRead, /* xmlSecXkmsServerRequestNodeReadMethod readNode; */ + xmlSecXkmsServerRequestLocateNodeWrite, /* xmlSecXkmsServerRequestNodeWriteMethod writeNode; */ + xmlSecXkmsServerRequestLocateExecute, /* xmlSecXkmsServerRequestExecuteMethod execute; */ + NULL, /* void* reserved1; */ + NULL /* void* reserved2; */ +}; + +/** + * xmlSecXkmsServerRequestLocateGetKlass: + * + * The LocateRequest klass. + * + * Returns: LocateRequest klass. + */ +xmlSecXkmsServerRequestId +xmlSecXkmsServerRequestLocateGetKlass(void) { + return(&xmlSecXkmsServerRequestLocateKlass); +} + +/** + * <xkms:LocateRequest Id Service Nonce? OriginalRequestId? ResponseLimit?> + * <ds:Signature>? + * <xkms:MessageExtension>* + * (<xkms:OpaqueClientData> + * <xkms:OpaqueData>? + * )? + * <xkms:ResponseMechanism>* + * <xkms:RespondWith>* + * <xkms:PendingNotification Mechanism Identifier>? + * <xkms:QueryKeyBinding Id?> + * <ds:KeyInfo>? + * <xkms:KeyUsage>? + * <xkms:KeyUsage>? + * <xkms:KeyUsage>? + * <xkms:UseKeyWith Application Identifier>* + * <xkms:TimeInstant Time>? + * + * XML Schema: + * + * <!-- LocateRequest --> + * <element name="LocateRequest" type="xkms:LocateRequestType"/> + * <complexType name="LocateRequestType"> + * <complexContent> + * <extension base="xkms:RequestAbstractType"> + * <sequence> + * <element ref="xkms:QueryKeyBinding"/> + * </sequence> + * </extension> + * </complexContent> + * </complexType> + * <!-- /LocateRequest --> + */ +static int +xmlSecXkmsServerRequestLocateNodeRead(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) { + xmlNodePtr cur; + int ret; + + xmlSecAssert2(id == xmlSecXkmsServerRequestLocateId, -1); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + cur = node; + + /* first read "parent" type */ + ret = xmlSecXkmsServerCtxRequestAbstractTypeNodeRead(ctx, &cur); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxRequestAbstractTypeNodeRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* now read required <xkms:QueryKeyBinding/> node */ + if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeQueryKeyBinding, xmlSecXkmsNs))) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_INVALID_NODE, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeQueryKeyBinding)); + return(-1); + } + + /* read <xkms:QueryKeyBinding/> node */ + ret = xmlSecXkmsServerCtxQueryKeyBindingNodeRead(ctx, cur); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxQueryKeyBindingNodeRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + cur = xmlSecGetNextElementNode(cur->next); + + /* check that there is nothing after the last node */ + if(cur != NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_UNEXPECTED_NODE, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +/** + * <xkms:LocateResult Id Service Nonce? ResultMajor ResultMinor? RequestId?> + * <ds:Signature>? + * <xkms:MessageExtension>* + * (<xkms:OpaqueClientData> + * <xkms:OpaqueData>? + * )? + * <xkms:RequestSignatureValue>* + * (<xkms:UnverifiedKeyBinding Id?> + * <ds:KeyInfo>? + * <xkms:KeyUsage>? + * <xkms:KeyUsage>? + * <xkms:KeyUsage>? + * <xkms:UseKeyWith Application Identifier>* + * <xkms:ValidityInterval NotBefore NotOnOrAfter>? + * )* + * + * XML Schema: + * <!-- LocateResult --> + * <element name="LocateResult" type="xkms:LocateResultType"/> + * <complexType name="LocateResultType"> + * <complexContent> + * <extension base="xkms:ResultType"> + * <sequence> + * <element ref="xkms:UnverifiedKeyBinding" minOccurs="0" + * maxOccurs="unbounded"/> + * </sequence> + * </extension> + * </complexContent> + * </complexType> + * <!-- /LocateResult --> + */ +static int +xmlSecXkmsServerRequestLocateNodeWrite(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) { + xmlSecSize pos, size; + xmlSecKeyPtr key; + xmlNodePtr cur; + int ret; + + xmlSecAssert2(id == xmlSecXkmsServerRequestLocateId, -1); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + /* first write the "parent" type */ + ret = xmlSecXkmsServerCtxResultTypeNodeWrite(ctx, node); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxResultTypeNodeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* write keys in <xkms:UnverifiedKeyBinding> nodes */ + size = xmlSecPtrListGetSize(&(ctx->keys)); + for(pos = 0; pos < size; ++pos) { + key = (xmlSecKeyPtr)xmlSecPtrListGetItem(&(ctx->keys), pos); + if(key == NULL) { + continue; + } + + cur = xmlSecAddChild(node, xmlSecNodeUnverifiedKeyBinding, xmlSecXkmsNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeUnverifiedKeyBinding)); + return(-1); + } + + ret = xmlSecXkmsServerCtxUnverifiedKeyBindingNodeWrite(ctx, cur, key); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxUnverifiedKeyBindingNodeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + + return(0); +} + +static int +xmlSecXkmsServerRequestLocateExecute(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx) { + xmlSecKeyPtr key = NULL; + int ret; + + xmlSecAssert2(id == xmlSecXkmsServerRequestLocateId, -1); + xmlSecAssert2(ctx != NULL, -1); + + /* now we are ready to search for key */ + if((ctx->keyInfoReadCtx.keysMngr != NULL) && (ctx->keyInfoReadCtx.keysMngr->getKey != NULL)) { + /* todo: set parameters to locate but not validate the key */ + key = (ctx->keyInfoReadCtx.keysMngr->getKey)(ctx->keyInfoNode, &(ctx->keyInfoReadCtx)); + } + + /* check that we got what we needed */ + if((key == NULL) || (!xmlSecKeyMatch(key, NULL, &(ctx->keyInfoReadCtx.keyReq)))) { + if(key != NULL) { + xmlSecKeyDestroy(key); + } + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorNoMatch); + return(-1); + } + + xmlSecAssert2(key != NULL, -1); + ret = xmlSecPtrListAdd(&(ctx->keys), key); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecPtrListAdd", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecKeyDestroy(key); + return(-1); + } + + return(0); +} + + +/******************************************************************** + * + * ValidateRequest/ValidateResponse + * + *******************************************************************/ +static int xmlSecXkmsServerRequestValidateNodeRead (xmlSecXkmsServerRequestId id, + xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node); +static int xmlSecXkmsServerRequestValidateNodeWrite(xmlSecXkmsServerRequestId id, + xmlSecXkmsServerCtxPtr ctx, + xmlNodePtr node); +static int xmlSecXkmsServerRequestValidateExecute (xmlSecXkmsServerRequestId id, + xmlSecXkmsServerCtxPtr ctx); + +static xmlSecXkmsServerRequestKlass xmlSecXkmsServerRequestValidateKlass = { + xmlSecXkmsServerRequestValidateName, /* const xmlChar* name; */ + xmlSecNodeValidateRequest, /* const xmlChar* requestNodeName; */ + xmlSecXkmsNs, /* const xmlChar* requestNodeNs; */ + xmlSecNodeValidateResult, /* const xmlChar* responseNodeName; */ + xmlSecXkmsNs, /* const xmlChar* responseNodeNs; */ + XMLSEC_XKMS_SERVER_REQUEST_KLASS_ALLOWED_IN_COUMPOUND, /* xmlSecBitMask flags; */ + xmlSecXkmsServerRequestValidateNodeRead, /* xmlSecXkmsServerRequestNodeReadMethod readNode; */ + xmlSecXkmsServerRequestValidateNodeWrite, /* xmlSecXkmsServerRequestNodeWriteMethod writeNode; */ + xmlSecXkmsServerRequestValidateExecute, /* xmlSecXkmsServerRequestExecuteMethod execute; */ + NULL, /* void* reserved1; */ + NULL /* void* reserved2; */ +}; + +/** + * xmlSecXkmsServerRequestValidateGetKlass: + * + * The ValidateRequest klass. + * + * Returns: ValidateRequest klass. + */ +xmlSecXkmsServerRequestId +xmlSecXkmsServerRequestValidateGetKlass(void) { + return(&xmlSecXkmsServerRequestValidateKlass); +} + +/** + * <xkms:ValidateRequest Id Service Nonce? OriginalRequestId? ResponseLimit?> + * <ds:Signature>? + * <xkms:MessageExtension>* + * (<xkms:OpaqueClientData> + * <xkms:OpaqueData>? + * )? + * <xkms:ResponseMechanism>* + * <xkms:RespondWith>* + * <xkms:PendingNotification Mechanism Identifier>? + * <xkms:QueryKeyBinding Id?> + * <ds:KeyInfo>? + * <xkms:KeyUsage>? + * <xkms:KeyUsage>? + * <xkms:KeyUsage>? + * <xkms:UseKeyWith Application Identifier>* + * <xkms:TimeInstant Time>? + * + * XML Schema: + * + * <!-- ValidateRequest --> + * <element name="ValidateRequest" type="xkms:ValidateRequestType"/> + * <complexType name="ValidateRequestType"> + * <complexContent> + * <extension base="xkms:RequestAbstractType"> + * <sequence> + * <element ref="xkms:QueryKeyBinding"/> + * </sequence> + * </extension> + * </complexContent> + * </complexType> + * <!-- /ValidateRequest --> + */ +static int +xmlSecXkmsServerRequestValidateNodeRead(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) { + xmlNodePtr cur; + int ret; + + xmlSecAssert2(id == xmlSecXkmsServerRequestValidateId, -1); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + cur = node; + + /* first read "parent" type */ + ret = xmlSecXkmsServerCtxRequestAbstractTypeNodeRead(ctx, &cur); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxRequestAbstractTypeNodeRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* now read required <xkms:QueryKeyBinding/> node */ + if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeQueryKeyBinding, xmlSecXkmsNs))) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_INVALID_NODE, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeQueryKeyBinding)); + return(-1); + } + + /* read <xkms:QueryKeyBinding/> node */ + ret = xmlSecXkmsServerCtxQueryKeyBindingNodeRead(ctx, cur); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxQueryKeyBindingNodeRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + cur = xmlSecGetNextElementNode(cur->next); + + /* check that there is nothing after the last node */ + if(cur != NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_UNEXPECTED_NODE, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +/** + * <xkms:ValidateResult Id Service Nonce? ResultMajor ResultMinor? RequestId?> + * <ds:Signature>? + * <xkms:MessageExtension>* + * (<xkms:OpaqueClientData> + * <xkms:OpaqueData>? + * )? + * <xkms:RequestSignatureValue>* + * (<xkms:KeyBinding Id?> + * <ds:KeyInfo>? + * <xkms:KeyUsage>? + * <xkms:KeyUsage>? + * <xkms:KeyUsage>? + * <xkms:UseKeyWith Application Identifier>* + * <xkms:ValidityInterval NotBefore NotOnOrAfter>? + * <xkms:Status StatusValue> + * (<xkms:ValidReason>? + * <xkms:IndeterminateReason>? + * <xkms:InvalidReason>? + * )* + * )* + * + * XML Schema: + * + * <!-- ValidateResult --> + * <element name="ValidateResult" type="xkms:ValidateResultType"/> + * <complexType name="ValidateResultType"> + * <complexContent> + * <extension base="xkms:ResultType"> + * <sequence> + * <element ref="xkms:KeyBinding" minOccurs="0" + * maxOccurs="unbounded"/> + * </sequence> + * </extension> + * </complexContent> + * </complexType> + * <!-- /ValidateResult --> + */ +static int +xmlSecXkmsServerRequestValidateNodeWrite(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) { + xmlSecSize pos, size; + xmlSecKeyPtr key; + xmlNodePtr cur; + int ret; + + xmlSecAssert2(id == xmlSecXkmsServerRequestValidateId, -1); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + /* first write the "parent" type */ + ret = xmlSecXkmsServerCtxResultTypeNodeWrite(ctx, node); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxResultTypeNodeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* write keys in <xkms:UnverifiedKeyBinding> nodes */ + size = xmlSecPtrListGetSize(&(ctx->keys)); + for(pos = 0; pos < size; ++pos) { + key = (xmlSecKeyPtr)xmlSecPtrListGetItem(&(ctx->keys), pos); + if(key == NULL) { + continue; + } + + cur = xmlSecAddChild(node, xmlSecNodeUnverifiedKeyBinding, xmlSecXkmsNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeUnverifiedKeyBinding)); + return(-1); + } + + ret = xmlSecXkmsServerCtxKeyBindingNodeWrite(ctx, cur, key); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecXkmsServerCtxKeyBindingNodeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + + return(0); +} + +static int +xmlSecXkmsServerRequestValidateExecute(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx) { + xmlSecKeyPtr key = NULL; + int ret; + + xmlSecAssert2(id == xmlSecXkmsServerRequestValidateId, -1); + xmlSecAssert2(ctx != NULL, -1); + + /* now we are ready to search for key */ + if((ctx->keyInfoReadCtx.keysMngr != NULL) && (ctx->keyInfoReadCtx.keysMngr->getKey != NULL)) { + key = (ctx->keyInfoReadCtx.keysMngr->getKey)(ctx->keyInfoNode, &(ctx->keyInfoReadCtx)); + } + + /* check that we got what we needed */ + if((key == NULL) || (!xmlSecKeyMatch(key, NULL, &(ctx->keyInfoReadCtx.keyReq)))) { + if(key != NULL) { + xmlSecKeyDestroy(key); + } + xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorNoMatch); + return(-1); + } + + xmlSecAssert2(key != NULL, -1); + ret = xmlSecPtrListAdd(&(ctx->keys), key); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecPtrListAdd", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecKeyDestroy(key); + return(-1); + } + + return(0); +} + +#endif /* XMLSEC_NO_XKMS */ + |