/**
* XMLSec library
*
* XMLDsig:KeyInfo node processing
* http://www.w3.org/TR/xmlSec-core/#sec-KeyInfo
*
* The KeyInfo Element
*
* KeyInfo is an optional element that enables the recipient(s) to obtain
* the key needed to validate the signature. KeyInfo may contain keys,
* names, certificates and other public key management information, such as
* in-band key distribution or key agreement data.
*
* Schema Definition:
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
* DTD:
*
*
*
*
*
* See Copyright for the status of this software.
*
* Author: Aleksey Sanin
*/
#include "globals.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef struct _xmlSecKeyInfoNodeStatus {
xmlSecKeysMngrPtr keysMngr;
void *context;
xmlSecKeyId keyId;
xmlSecKeyType keyType;
xmlSecKeyUsage keyUsage;
time_t certsVerificationTime;
int retrievalsLevel;
int encKeysLevel;
} xmlSecKeyInfoNodeStatus, *xmlSecKeyInfoNodeStatusPtr;
#define xmlSecKeyInfoNodeCheckOrigin(status, origin) \
( ( ((status) != NULL) && \
((status)->keysMngr != NULL) && \
((status)->keysMngr->allowedOrigins & origin) ) ? \
1 : 0 )
#define xmlSecKeyInfoNodeCheckRetrievalsLevel(status) \
( ( ((status) != NULL) && \
((status)->keysMngr != NULL) && \
((status)->keysMngr->maxRetrievalsLevel >= 0) ) ? \
((status)->keysMngr->maxRetrievalsLevel > (status)->retrievalsLevel) : \
1 )
#define xmlSecKeyInfoNodeCheckEncKeysLevel(status) \
( ( ((status) != NULL) && \
((status)->keysMngr != NULL) && \
((status)->keysMngr->maxEncKeysLevel >= 0) ) ? \
((status)->keysMngr->maxEncKeysLevel > (status)->encKeysLevel) : \
1 )
#define xmlSecKeyInfoNodeFindKey(status) \
( ( ((status) != NULL) && \
((status)->keysMngr != NULL) ) ? \
(status)->keysMngr->findKey : \
NULL)
static xmlSecKeyPtr xmlSecKeyInfoNodesListRead (xmlNodePtr cur,
xmlSecKeyInfoNodeStatusPtr status);
static xmlSecKeyPtr xmlSecKeyNameNodeRead (xmlNodePtr keyNameNode,
xmlSecKeyInfoNodeStatusPtr status,
xmlChar **name);
static int xmlSecKeyNameNodeWrite (xmlNodePtr keyNameNode,
xmlSecKeyPtr key,
xmlSecKeysMngrPtr keysMngr);
static xmlSecKeyPtr xmlSecKeyValueNodeRead (xmlNodePtr keyValueNode,
xmlSecKeyInfoNodeStatusPtr status);
static int xmlSecKeyValueNodeWrite (xmlNodePtr keyValueNode,
xmlSecKeyPtr key,
xmlSecKeyType type);
static xmlSecKeyPtr xmlSecRetrievalMethodNodeRead (xmlNodePtr retrievalMethodNode,
xmlSecKeyInfoNodeStatusPtr status);
#ifndef XMLSEC_NO_XMLENC
static xmlSecKeyPtr xmlSecEncryptedKeyNodeRead (xmlNodePtr encKeyNode,
xmlSecKeyInfoNodeStatusPtr status);
static int xmlSecEncryptedKeyNodeWrite (xmlNodePtr encKeyNode,
xmlSecKeysMngrPtr keysMngr,
void *context,
xmlSecKeyPtr key,
xmlSecKeyType type);
#endif /* XMLSEC_NO_XMLENC */
/* X509Data node */
#ifndef XMLSEC_NO_X509
static xmlSecKeyPtr xmlSecX509DataNodeRead (xmlNodePtr x509DataNode,
xmlSecKeyInfoNodeStatusPtr status);
static int xmlSecX509DataNodeWrite (xmlNodePtr x509DataNode,
xmlSecKeyPtr key);
static int xmlSecX509IssuerSerialNodeRead (xmlNodePtr serialNode,
xmlSecX509DataPtr x509Data,
xmlSecKeysMngrPtr keysMngr,
void *context);
static int xmlSecX509SKINodeRead (xmlNodePtr skiNode,
xmlSecX509DataPtr x509Data,
xmlSecKeysMngrPtr keysMngr,
void *context);
static int xmlSecX509SubjectNameNodeRead (xmlNodePtr subjectNode,
xmlSecX509DataPtr x509Data,
xmlSecKeysMngrPtr keysMngr,
void *context);
static int xmlSecX509CertificateNodeRead (xmlNodePtr certNode,
xmlSecX509DataPtr x509Data);
static int xmlSecX509CRLNodeRead (xmlNodePtr crlNode,
xmlSecX509DataPtr x509Data);
#endif /* XMLSEC_NO_X509 */
static const xmlChar xmlSecRawX509Cert[] = "http://www.w3.org/2000/09/xmldsig#rawX509Certificate";
/**
* xmlSecKeyInfoAddKeyName:
* @keyInfoNode: the pointer to node.
*
* Adds node to the node @keyInfoNode.
*
* Returns the pointer to the newly created node or
* NULL if an error occurs.
*/
xmlNodePtr
xmlSecKeyInfoAddKeyName(xmlNodePtr keyInfoNode) {
xmlNodePtr cur;
xmlSecAssert2(keyInfoNode != NULL, NULL);
cur = xmlSecFindChild(keyInfoNode, BAD_CAST "KeyName", xmlSecDSigNs);
if(cur != NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,
"KeyName");
return(NULL);
}
cur = xmlSecAddChild(keyInfoNode, BAD_CAST "KeyName", xmlSecDSigNs);
if(cur == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecAddChild(\"KeyName\")");
return(NULL);
}
return(cur);
}
/**
* xmlSecKeyInfoAddKeyValue:
* @keyInfoNode: the pointer to node.
*
* Adds node to the node @keyInfoNode.
*
* Returns the pointer to the newly created node or
* NULL if an error occurs.
*/
xmlNodePtr
xmlSecKeyInfoAddKeyValue(xmlNodePtr keyInfoNode) {
xmlNodePtr cur;
xmlSecAssert2(keyInfoNode != NULL, NULL);
cur = xmlSecFindChild(keyInfoNode, BAD_CAST "KeyValue", xmlSecDSigNs);
if(cur != NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,
"KeyValue");
return(NULL);
}
cur = xmlSecAddChild(keyInfoNode, BAD_CAST "KeyValue", xmlSecDSigNs);
if(cur == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecAddChild(\"KeyValue\")");
return(NULL);
}
return(cur);
}
/**
* xmlSecKeyInfoAddX509Data:
* @keyInfoNode: the pointer to node.
*
* Adds node to the node @keyInfoNode.
*
* Returns the pointer to the newly created node or
* NULL if an error occurs.
*/
xmlNodePtr
xmlSecKeyInfoAddX509Data(xmlNodePtr keyInfoNode) {
xmlNodePtr cur;
xmlSecAssert2(keyInfoNode != NULL, NULL);
cur = xmlSecFindChild(keyInfoNode, BAD_CAST "X509Data", xmlSecDSigNs);
if(cur != NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,
"X509Data");
return(NULL);
}
cur = xmlSecAddChild(keyInfoNode, BAD_CAST "X509Data", xmlSecDSigNs);
if(cur == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecAddChild(\"X509Data\")");
return(NULL);
}
return(cur);
}
/**
* xmlSecKeyInfoAddRetrievalMethod:
* @keyInfoNode: the pointer to node.
* @uri: the URI attribute (optional).
* @type: the Type attribute(optional).
*
* Adds node to the node @keyInfoNode.
*
* Returns the pointer to the newly created node or
* NULL if an error occurs.
*/
xmlNodePtr
xmlSecKeyInfoAddRetrievalMethod(xmlNodePtr keyInfoNode, const xmlChar *uri,
const xmlChar *type) {
xmlNodePtr cur;
xmlSecAssert2(keyInfoNode != NULL, NULL);
cur = xmlSecFindChild(keyInfoNode, BAD_CAST "RetrievalMethod", xmlSecDSigNs);
if(cur != NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,
"RetrievalMethod");
return(NULL);
}
cur = xmlSecAddChild(keyInfoNode, BAD_CAST "RetrievalMethod", xmlSecDSigNs);
if(cur == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecAddChild(\"RetrievalMethod\")");
return(NULL);
}
if(uri != NULL) {
xmlSetProp(cur, BAD_CAST "URI", uri);
}
if(type != NULL) {
xmlSetProp(cur, BAD_CAST "Type", type);
}
return(cur);
}
/**
* xmlSecRetrievalMethodAddTransform:
* @retrMethod: the pointer to node.
* @transform: the transform id.
*
* Adds node (and the parent node
* if required) to the node @retrMethod.
*
* Returns the pointer to the newly created node or
* NULL if an error occurs.
*/
xmlNodePtr
xmlSecRetrievalMethodAddTransform(xmlNodePtr retrMethod,
xmlSecTransformId transform) {
xmlNodePtr transforms;
xmlNodePtr cur;
int ret;
xmlSecAssert2(retrMethod != NULL, NULL);
xmlSecAssert2(transform != NULL, NULL);
transforms = xmlSecFindChild(retrMethod, BAD_CAST "Transforms", xmlSecDSigNs);
if(transforms == NULL) {
transforms = xmlSecAddChild(retrMethod, BAD_CAST "Transforms", xmlSecDSigNs);
if(transforms == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecAddChild(\"Transforms\")");
return(NULL);
}
}
cur = xmlSecAddChild(transforms, BAD_CAST "Transform", xmlSecDSigNs);
if(cur == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecAddChild(\"Transform\")");
return(NULL);
}
ret = xmlSecTransformNodeWrite(cur, transform);
if(ret < 0){
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecTransformNodeWrite - %d", ret);
return(NULL);
}
return(cur);
}
/**
* xmlSecKeyInfoAddEncryptedKey:
* @keyInfoNode: the pointer to node.
* @id: the Id attribute (optional).
* @type: the Type attribute (optional).
* @recipient: the Recipient attribute (optional).
*
* Adds node with given attributes to
* the node @keyInfoNode.
*
* Returns the pointer to the newly created node or
* NULL if an error occurs.
*/
xmlNodePtr
xmlSecKeyInfoAddEncryptedKey(xmlNodePtr keyInfoNode, const xmlChar *id,
const xmlChar *type, const xmlChar *recipient) {
xmlNodePtr encKey;
xmlNodePtr cipherData;
xmlSecAssert2(keyInfoNode != NULL, NULL);
/* we allow multiple encrypted key elements */
encKey = xmlSecAddChild(keyInfoNode, BAD_CAST "EncryptedKey", xmlSecEncNs);
if(encKey == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecAddChild(\"EncryptedKey\")");
return(NULL);
}
if(id != NULL) {
xmlSetProp(encKey, BAD_CAST "Id", id);
}
if(type != NULL) {
xmlSetProp(encKey, BAD_CAST "Type", type);
}
if(recipient != NULL) {
xmlSetProp(encKey, BAD_CAST "Recipient", recipient);
}
cipherData = xmlSecAddChild(encKey, BAD_CAST "CipherData", xmlSecEncNs);
if(cipherData == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecAddChild(\"CipherData\")");
xmlUnlinkNode(encKey);
xmlFreeNode(encKey);
return(NULL);
}
return((xmlNodePtr)encKey);
}
/**
* xmlSecKeyInfoNodeRead:
* @keyInfoNode: the pointer to node.
* @keysMngr: the pointer to #xmlSecKeysMngr struvture.
* @context: the pointer to application specific data that will be
* passed to all callback functions.
* @keyId: the required key id or NULL.
* @keyType: the required key type (may be "any").
* @keyUsage: the desired key usage.
*
* Parses the element and extracts the key (with required
* id, type and usage).
*
* Returns the pointer to extracted key or NULL if an error occurs or
* required key is not found.
*/
xmlSecKeyPtr
xmlSecKeyInfoNodeRead(xmlNodePtr keyInfoNode, xmlSecKeysMngrPtr keysMngr, void *context,
xmlSecKeyId keyId, xmlSecKeyType keyType, xmlSecKeyUsage keyUsage,
time_t certsVerificationTime) {
xmlSecKeyInfoNodeStatus status;
xmlNodePtr cur;
xmlSecAssert2(keyInfoNode != NULL, NULL);
cur = xmlSecGetNextElementNode(keyInfoNode->children);
if(cur == NULL) {
return(NULL);
}
memset(&status, 0, sizeof(status));
status.keysMngr = keysMngr;
status.context = context;
status.keyId = keyId;
status.keyType = keyType;
status.keyUsage = keyUsage;
status.certsVerificationTime = certsVerificationTime;
return(xmlSecKeyInfoNodesListRead(cur, &status));
}
/**
* xmlSecKeyInfoNodeWrite
* @keyInfoNode: the pointer to node.
* @keysMngr: the pointer to #xmlSecKeysMngr struvture.
* @context: the pointer to application specific data that will be
* passed to all callback functions.
* @key: the pointer to the #xmlSecKey structure.
* @type: the key type (public/private).
*
* Writes the key into the template @keyInfoNode.
*
* Returns 0 on success or -1 if an error occurs.
*/
int
xmlSecKeyInfoNodeWrite(xmlNodePtr keyInfoNode, xmlSecKeysMngrPtr keysMngr,
void *context, xmlSecKeyPtr key, xmlSecKeyType type) {
xmlNodePtr cur;
int ret;
xmlSecAssert2(keyInfoNode != NULL, -1);
ret = 0;
cur = xmlSecGetNextElementNode(keyInfoNode->children);
while(cur != NULL) {
if(xmlSecCheckNodeName(cur, BAD_CAST "KeyName", xmlSecDSigNs)) {
ret = xmlSecKeyNameNodeWrite(cur, key, keysMngr);
} else if(xmlSecCheckNodeName(cur, BAD_CAST "KeyValue", xmlSecDSigNs)) {
ret = xmlSecKeyValueNodeWrite(cur, key, type);
} else if(xmlSecCheckNodeName(cur, BAD_CAST "X509Data", xmlSecDSigNs)) {
#ifndef XMLSEC_NO_X509
ret = xmlSecX509DataNodeWrite(cur, key);
#else /* XMLSEC_NO_X509 */
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_DISABLED,
"X509");
#endif /* XMLSEC_NO_X509 */
} else if(xmlSecCheckNodeName(cur, BAD_CAST "EncryptedKey", xmlSecEncNs)) {
#ifndef XMLSEC_NO_XMLENC
ret = xmlSecEncryptedKeyNodeWrite(cur, keysMngr, context, key, type);
#else /* XMLSEC_NO_XMLENC */
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_DISABLED,
"XML Encryption");
#endif /* XMLSEC_NO_XMLENC */
}
/* TODO: add retrieval method, etc. */
if(ret < 0) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"%d", ret);
return(-1);
}
cur = xmlSecGetNextElementNode(cur->next);
}
return(0);
}
/**
* xmlSecKeyNodesListRead:
*/
static xmlSecKeyPtr
xmlSecKeyInfoNodesListRead(xmlNodePtr cur, xmlSecKeyInfoNodeStatusPtr status) {
xmlChar *keyName;
xmlSecKeyPtr key;
xmlSecAssert2(status != NULL, NULL);
key = NULL;
keyName = NULL;
while ((key == NULL) && (cur != NULL)) {
if(xmlSecCheckNodeName(cur, BAD_CAST "KeyName", xmlSecDSigNs)) {
if(keyName != NULL) {
xmlFree(keyName);
keyName = NULL;
}
key = xmlSecKeyNameNodeRead(cur, status, &keyName);
} else if(xmlSecCheckNodeName(cur, BAD_CAST "KeyValue", xmlSecDSigNs)) {
key = xmlSecKeyValueNodeRead(cur, status);
} else if(xmlSecCheckNodeName(cur, BAD_CAST "RetrievalMethod", xmlSecDSigNs)){
key = xmlSecRetrievalMethodNodeRead(cur, status);
} else if(xmlSecCheckNodeName(cur, BAD_CAST "X509Data", xmlSecDSigNs)) {
#ifndef XMLSEC_NO_X509
key = xmlSecX509DataNodeRead(cur, status);
#else /* XMLSEC_NO_X509 */
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_DISABLED,
"X509");
#endif /* XMLSEC_NO_X509 */
} else if(xmlSecCheckNodeName(cur, BAD_CAST "EncryptedKey", xmlSecEncNs)) {
#ifndef XMLSEC_NO_XMLENC
key = xmlSecEncryptedKeyNodeRead(cur, status);
#else /* XMLSEC_NO_XMLENC */
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_DISABLED,
"XML Encryption");
#endif /* XMLSEC_NO_XMLENC */
}
/* TODO: add more nodes (pgp, spki, etc) */
if(key != NULL) {
if(key->name == NULL) {
key->name = keyName;
keyName = NULL;
}
} else {
cur = xmlSecGetNextElementNode(cur->next);
}
}
if(keyName != NULL) {
xmlFree(keyName);
}
return(key);
}
/**
* xmlSecKeyNameNodeRead:
*/
static xmlSecKeyPtr
xmlSecKeyNameNodeRead(xmlNodePtr keyNameNode, xmlSecKeyInfoNodeStatusPtr status,
xmlChar **name) {
xmlSecKeyPtr key = NULL;
xmlSecFindKeyCallback findKey;
xmlChar *content;
xmlSecAssert2(keyNameNode != NULL, NULL);
xmlSecAssert2(status != NULL, NULL);
if(!xmlSecKeyInfoNodeCheckOrigin(status, xmlSecKeyOriginKeyName)) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_INVALID_KEY_ORIGIN,
"xmlSecKeyOriginKeyName");
return(NULL);
}
content = xmlNodeGetContent(keyNameNode);
if(content == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
"KeyName");
return(NULL);
}
/* TODO: decode key name if requested */
findKey = xmlSecKeyInfoNodeFindKey(status);
if(findKey != NULL) {
key = findKey(status->keysMngr, status->context, content,
status->keyId, status->keyType, status->keyUsage);
}
if(name != NULL) {
(*name) = content;
} else {
xmlFree(content);
}
return(key);
}
/**
* xmlSecKeyNameNodeWrite:
*/
static int
xmlSecKeyNameNodeWrite(xmlNodePtr keyNameNode, xmlSecKeyPtr key,
xmlSecKeysMngrPtr keysMngr ATTRIBUTE_UNUSED) {
xmlSecAssert2(keyNameNode != NULL, -1);
xmlSecAssert2(key != NULL, -1);
if(!xmlSecKeyIsValid(key)) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_INVALID_KEY,
" ");
return(-1);
}
if(key->name != NULL) {
/* TODO: encode the key name! */
xmlNodeSetContent(keyNameNode, key->name);
}
return(0);
}
/**
* xmlSecKeyValueNodeRead:
*
* http://www.w3.org/TR/xmldsig-core/#sec-KeyValue
*
* The KeyValue element contains a single public key that may be useful in
* validating the signature. Structured formats for defining DSA (REQUIRED)
* and RSA (RECOMMENDED) public keys are defined in Signature Algorithms
* (section 6.4). The KeyValue element may include externally defined
* public keys values represented as PCDATA or element types from an external
* namespace.
*
* Schema Definition:
*
*
*
*
*
*
*
*
*
*
* DTD:
*
*
*
* =========================================================================
* Support for private keys is added (@type parameter)
*/
static xmlSecKeyPtr
xmlSecKeyValueNodeRead(xmlNodePtr keyValueNode, xmlSecKeyInfoNodeStatusPtr status) {
xmlNodePtr cur;
xmlSecKeyId keyId;
xmlSecKeyPtr key;
size_t i;
xmlSecAssert2(keyValueNode != NULL, NULL);
xmlSecAssert2(status != NULL, NULL);
if(!xmlSecKeyInfoNodeCheckOrigin(status, xmlSecKeyOriginKeyValue)) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_INVALID_KEY_ORIGIN,
"xmlSecKeyOriginKeyValue");
return(NULL);
}
key = NULL;
cur = xmlSecGetNextElementNode(keyValueNode->children);
while(cur != NULL) {
for(i = 0; xmlSecAllKeyIds[i] != xmlSecKeyIdUnknown; ++i) {
keyId = xmlSecAllKeyIds[i];
if((status->keyId != xmlSecTransformUnknown) &&
(status->keyId != keyId)) continue;
if(xmlSecCheckNodeName(cur, keyId->keyValueNodeName,
keyId->keyValueNodeNs)) {
key = xmlSecKeyReadXml(keyId, cur);
break;
}
}
if(key != NULL) {
if((key->type == status->keyType) || (status->keyType == xmlSecKeyTypeAny)) {
return(key);
} else {
xmlSecKeyDestroy(key);
key = NULL;
}
}
cur = xmlSecGetNextElementNode(cur->next);
}
return(key);
}
/**
* xmlSecKeyValueNodeWrite:
*/
static int
xmlSecKeyValueNodeWrite(xmlNodePtr keyValueNode, xmlSecKeyPtr key, xmlSecKeyType type) {
xmlNodePtr cur;
int ret;
xmlSecAssert2(keyValueNode != NULL, -1);
xmlSecAssert2(key != NULL, -1);
if(!xmlSecKeyIsValid(key)) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_INVALID_KEY,
" ");
return(-1);
}
/* remove all existing key value */
xmlNodeSetContent(keyValueNode, NULL);
/* create key node */
cur = xmlSecAddChild(keyValueNode, key->id->keyValueNodeName, key->id->keyValueNodeNs);
if(cur == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecAddChild(\"%s\")", key->id->keyValueNodeName);
return(-1);
}
ret = xmlSecKeyWriteXml(key, type, cur);
if(ret < 0) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecKeyWriteXml - %d", ret);
xmlUnlinkNode(cur);
xmlFreeNode(cur);
}
return(0);
}
static xmlSecKeyPtr
xmlSecRetrievalMethodNodeRead(xmlNodePtr retrievalMethodNode, xmlSecKeyInfoNodeStatusPtr status) {
xmlSecKeyPtr res = NULL;
xmlNodePtr cur;
xmlSecTransformStatePtr state = NULL;
xmlChar *uri = NULL;
xmlChar *retrType = NULL;
int ret;
xmlSecAssert2(retrievalMethodNode != NULL, NULL);
xmlSecAssert2(status != NULL, NULL);
cur = xmlSecGetNextElementNode(retrievalMethodNode->children);
/* read attributes first */
uri = xmlGetProp(retrievalMethodNode, BAD_CAST "URI");
if((uri == NULL) || (xmlStrlen(uri) == 0) || (uri[0] == '#')) {
/* same document uri */
if(!xmlSecKeyInfoNodeCheckOrigin(status, xmlSecKeyOriginRetrievalDocument)) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_INVALID_KEY_ORIGIN,
"xmlSecKeyOriginRetrievalDocument");
xmlFree(uri);
return(NULL);
}
} else {
/* remote document */
if(!xmlSecKeyInfoNodeCheckOrigin(status, xmlSecKeyOriginRetrievalRemote)) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_INVALID_KEY_ORIGIN,
"xmlSecKeyOriginRetrievalRemote");
xmlFree(uri);
return(NULL);
}
}
if(!xmlSecKeyInfoNodeCheckRetrievalsLevel(status)) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_MAX_RETRIEVALS_LEVEL,
"%d", status->retrievalsLevel);
return(NULL);
}
++status->retrievalsLevel;
state = xmlSecTransformStateCreate(retrievalMethodNode->doc, NULL, (char*)uri);
if(state == NULL){
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecTransformStateCreate");
goto done;
}
/* first is optional Transforms node */
if((cur != NULL) && xmlSecCheckNodeName(cur, BAD_CAST "Transforms", xmlSecDSigNs)) {
ret = xmlSecTransformsNodeRead(state, cur);
if(ret < 0){
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecTransformsNodeRead - %d", ret);
goto done;
}
cur = xmlSecGetNextElementNode(cur->next);
}
ret = xmlSecTransformStateFinal(state, xmlSecTransformResultBinary);
if(ret < 0) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecTransformStateFinal - %d", ret);
goto done;
}
if(cur != NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_INVALID_NODE,
(cur->name != NULL) ? (char*)cur->name : "NULL");
goto done;
}
retrType = xmlGetProp(retrievalMethodNode, BAD_CAST "Type");
if(!xmlStrEqual(retrType, xmlSecRawX509Cert)) {
xmlDocPtr keyDoc;
keyDoc = xmlRecoverMemory((char*)xmlBufferContent(state->curBuf),
xmlBufferLength(state->curBuf));
if(keyDoc == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XML_FAILED,
"xmlRecoverMemory");
xmlFreeDoc(keyDoc);
goto done;
}
res = xmlSecKeyInfoNodesListRead(xmlDocGetRootElement(keyDoc), status);
xmlFreeDoc(keyDoc);
} else {
/* special case: raw DER x509 certificate */
#ifndef XMLSEC_NO_X509
xmlSecX509DataPtr x509Data;
x509Data = xmlSecX509DataCreate();
if(x509Data == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecX509DataCreate");
goto done;
}
x509Data->certsVerificationTime = status->certsVerificationTime;
ret = xmlSecX509DataReadDerCert(x509Data, (unsigned char*)xmlBufferContent(state->curBuf),
xmlBufferLength(state->curBuf), 0);
if(ret < 0) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecX509DataReadDerCert - %d", ret);
xmlSecX509DataDestroy(x509Data);
goto done;
}
/* verify data */
if((status->keysMngr != NULL) && (status->keysMngr->verifyX509 != NULL)) {
if((status->keysMngr->verifyX509)(status->keysMngr, status->context, x509Data) != 1) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_CERT_VERIFY_FAILED,
" ");
xmlSecX509DataDestroy(x509Data);
goto done;
}
}
res = xmlSecX509DataCreateKey(x509Data);
if(res == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecX509DataCreateKey");
xmlSecX509DataDestroy(x509Data);
goto done;
}
if(xmlSecVerifyKey(res, NULL, status->keyId, status->keyType) != 1) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_INVALID_KEY,
" ");
xmlSecKeyDestroy(res);
res = NULL;
}
#else /* XMLSEC_NO_X509 */
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_DISABLED,
"X509");
#endif /* XMLSEC_NO_X509 */
}
done:
if(state != NULL) {
xmlSecTransformStateDestroy(state);
}
if(uri != NULL) {
xmlFree(uri);
}
if(retrType != NULL) {
xmlFree(retrType);
}
--status->retrievalsLevel;
return(res);
}
#ifndef XMLSEC_NO_XMLENC
static xmlSecKeyPtr
xmlSecEncryptedKeyNodeRead(xmlNodePtr encKeyNode, xmlSecKeyInfoNodeStatusPtr status) {
xmlSecKeyPtr key = NULL;
xmlSecEncCtxPtr encCtx = NULL;
xmlSecEncResultPtr encResult = NULL;
int ret;
xmlSecAssert2(encKeyNode != NULL, NULL);
xmlSecAssert2(status != NULL, NULL);
if(!xmlSecKeyInfoNodeCheckOrigin(status, xmlSecKeyOriginEncryptedKey) ){
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_INVALID_KEY_ORIGIN,
"xmlSecKeyOriginEncryptedKey");
return(NULL);
}
if(!xmlSecKeyInfoNodeCheckEncKeysLevel(status)) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_MAX_RETRIEVALS_LEVEL,
"%d", status->encKeysLevel);
return(NULL);
}
++status->encKeysLevel;
/**
* Init Enc context
*/
encCtx = xmlSecEncCtxCreate(status->keysMngr);
if(encCtx == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecEncCtxCreate");
goto done;
}
encCtx->ignoreType = 1; /* do not substitute the node! */
ret = xmlSecDecrypt(encCtx, status->context, NULL, encKeyNode, &encResult);
if((ret < 0) || (encResult == NULL) || (encResult->buffer == NULL)){
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecDecrypt - %d", ret);
goto done;
}
key = xmlSecKeyReadBin(status->keyId,
xmlBufferContent(encResult->buffer),
xmlBufferLength(encResult->buffer));
if(key == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecKeyReadBin");
goto done;
}
done:
if(encResult != NULL) {
xmlSecEncResultDestroy(encResult);
}
if(encCtx != NULL) {
xmlSecEncCtxDestroy(encCtx);
}
--status->encKeysLevel;
return(key);
}
static int
xmlSecEncryptedKeyNodeWrite(xmlNodePtr encKeyNode,
xmlSecKeysMngrPtr keysMngr, void *context,
xmlSecKeyPtr key, xmlSecKeyType type) {
xmlSecEncCtxPtr encCtx = NULL;
unsigned char *keyBuf = NULL;
size_t keySize = 0;
int ret;
int res = -1;
xmlSecAssert2(encKeyNode != NULL, -1);
xmlSecAssert2(key != NULL, -1);
if(!xmlSecKeyIsValid(key)) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_INVALID_KEY,
" ");
return(-1);
}
/**
* Init Enc context
*/
encCtx = xmlSecEncCtxCreate(keysMngr);
if(encCtx == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecEncCtxCreate");
goto done;
}
encCtx->ignoreType = 1; /* do not substitute the node! */
ret = xmlSecKeyWriteBin(key, type, &keyBuf, &keySize);
if(ret < 0) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecKeyWriteBin - %d", ret);
goto done;
}
ret = xmlSecEncryptMemory(encCtx, context, NULL, encKeyNode, keyBuf, keySize, NULL);
if(ret < 0) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecEncryptMemory - %d", ret);
goto done;
}
res = 0;
done:
if(keyBuf != NULL) {
memset(keyBuf, 0, keySize);
xmlFree(keyBuf); keyBuf = NULL;
}
if(encCtx != NULL) {
xmlSecEncCtxDestroy(encCtx);
}
return(res);
}
#endif /* XMLSEC_NO_XMLENC */
/* X509Data node */
#ifndef XMLSEC_NO_X509
/**
* The X509Data Element (http://www.w3.org/TR/xmldsig-core/#sec-X509Data)
*
* An X509Data element within KeyInfo contains one or more identifiers of keys
* or X509 certificates (or certificates' identifiers or a revocation list).
* The content of X509Data is:
*
* 1. At least one element, from the following set of element types; any of these may appear together or more than once iff (if and only if) each instance describes or is related to the same certificate:
* 2.
* * The X509IssuerSerial element, which contains an X.509 issuer
* distinguished name/serial number pair that SHOULD be compliant
* with RFC2253 [LDAP-DN],
* * The X509SubjectName element, which contains an X.509 subject
* distinguished name that SHOULD be compliant with RFC2253 [LDAP-DN],
* * The X509SKI element, which contains the base64 encoded plain (i.e.
* non-DER-encoded) value of a X509 V.3 SubjectKeyIdentifier extension.
* * The X509Certificate element, which contains a base64-encoded [X509v3]
* certificate, and
* * Elements from an external namespace which accompanies/complements any
* of the elements above.
* * The X509CRL element, which contains a base64-encoded certificate
* revocation list (CRL) [X509v3].
*
* Any X509IssuerSerial, X509SKI, and X509SubjectName elements that appear
* MUST refer to the certificate or certificates containing the validation key.
* All such elements that refer to a particular individual certificate MUST be
* grouped inside a single X509Data element and if the certificate to which
* they refer appears, it MUST also be in that X509Data element.
*
* Any X509IssuerSerial, X509SKI, and X509SubjectName elements that relate to
* the same key but different certificates MUST be grouped within a single
* KeyInfo but MAY occur in multiple X509Data elements.
*
* All certificates appearing in an X509Data element MUST relate to the
* validation key by either containing it or being part of a certification
* chain that terminates in a certificate containing the validation key.
*
* No ordering is implied by the above constraints.
*
* Note, there is no direct provision for a PKCS#7 encoded "bag" of
* certificates or CRLs. However, a set of certificates and CRLs can occur
* within an X509Data element and multiple X509Data elements can occur in a
* KeyInfo. Whenever multiple certificates occur in an X509Data element, at
* least one such certificate must contain the public key which verifies the
* signature.
*
* Schema Definition
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
* DTD
*
*
*
*
*
*
*
*
*
*/
static xmlSecKeyPtr
xmlSecX509DataNodeRead(xmlNodePtr x509DataNode, xmlSecKeyInfoNodeStatusPtr status) {
xmlNodePtr cur;
xmlSecX509DataPtr x509Data = NULL;
xmlSecKeyPtr key = NULL;
int ret;
xmlSecAssert2(x509DataNode != NULL, NULL);
xmlSecAssert2(status != NULL, NULL);
if(!xmlSecKeyInfoNodeCheckOrigin(status, xmlSecKeyOriginX509)) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_INVALID_KEY_ORIGIN,
"xmlSecKeyOriginX509");
return(NULL);
}
x509Data = xmlSecX509DataCreate();
if(x509Data == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecX509DataCreate");
return(NULL);
}
x509Data->certsVerificationTime = status->certsVerificationTime;
ret = 0;
cur = xmlSecGetNextElementNode(x509DataNode->children);
while(cur != NULL) {
if(xmlSecCheckNodeName(cur, BAD_CAST "X509Certificate", xmlSecDSigNs)) {
ret = xmlSecX509CertificateNodeRead(cur, x509Data);
} else if(xmlSecCheckNodeName(cur, BAD_CAST "X509SubjectName", xmlSecDSigNs)) {
ret = xmlSecX509SubjectNameNodeRead(cur, x509Data, status->keysMngr,
status->context);
} else if(xmlSecCheckNodeName(cur, BAD_CAST "X509IssuerSerial", xmlSecDSigNs)) {
ret = xmlSecX509IssuerSerialNodeRead(cur, x509Data, status->keysMngr,
status->context);
} else if(xmlSecCheckNodeName(cur, BAD_CAST "X509SKI", xmlSecDSigNs)) {
ret = xmlSecX509SKINodeRead(cur, x509Data, status->keysMngr,
status->context);
} else if(xmlSecCheckNodeName(cur, BAD_CAST "X509CRL", xmlSecDSigNs)) {
ret = xmlSecX509CRLNodeRead(cur, x509Data);
} else {
/* laxi schema validation: ignore unknown nodes */
}
if(ret < 0) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"%d", ret);
xmlSecX509DataDestroy(x509Data);
return(NULL);
}
cur = xmlSecGetNextElementNode(cur->next);
}
if(xmlSecX509DataGetCertsNumber(x509Data) <= 0) {
/* no certs found */
goto done;
}
/* verify data */
if((status->keysMngr != NULL) && (status->keysMngr->verifyX509 != NULL)) {
if((status->keysMngr->verifyX509)(status->keysMngr, status->context, x509Data) != 1) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_CERT_VERIFY_FAILED,
" ");
goto done;
}
}
key = xmlSecX509DataCreateKey(x509Data);
if(key == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecX509DataCreateKey");
goto done;
}
x509Data = NULL; /* x509Data assigned to key now */
if(xmlSecVerifyKey(key, NULL, status->keyId, status->keyType) != 1) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_INVALID_KEY,
" ");
xmlSecKeyDestroy(key);
key = NULL;
goto done;
}
/* we are done */
done:
if(x509Data != NULL) {
xmlSecX509DataDestroy(x509Data);
}
return(key);
}
static int
xmlSecX509DataNodeWrite(xmlNodePtr x509DataNode, xmlSecKeyPtr key) {
xmlSecAssert2(x509DataNode != NULL, -1);
xmlSecAssert2(key != NULL, -1);
if(!xmlSecKeyIsValid(key)) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_INVALID_KEY,
" ");
return(-1);
}
/* remove all existing content */
xmlNodeSetContent(x509DataNode, NULL);
if(key->x509Data != NULL) {
xmlNodePtr cur;
xmlChar *buf;
size_t count;
size_t i;
count = xmlSecX509DataGetCertsNumber(key->x509Data);
for(i = 0; i < count; ++i) {
cur = xmlSecAddChild(x509DataNode, BAD_CAST "X509Certificate", xmlSecDSigNs);
if(cur == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecAddChild(\"X509Certificate\")");
return(-1);
}
buf = xmlSecX509DataWriteDerCert(key->x509Data, i);
if(buf == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecX509DataWriteDerCert");
return(-1);
}
xmlNodeSetContent(cur, BAD_CAST "\n");
xmlNodeSetContent(cur, buf);
xmlFree(buf);
}
}
return(0);
}
static int
xmlSecX509IssuerSerialNodeRead(xmlNodePtr serialNode, xmlSecX509DataPtr x509Data,
xmlSecKeysMngrPtr keysMngr, void *context) {
xmlNodePtr cur;
xmlChar *issuerName;
xmlChar *issuerSerial;
xmlSecAssert2(serialNode != NULL, -1);
xmlSecAssert2(x509Data != NULL, -1);
xmlSecAssert2(keysMngr != NULL, -1);
xmlSecAssert2(keysMngr->findX509 != NULL, -1);
cur = xmlSecGetNextElementNode(serialNode->children);
/* the first is required node X509IssuerName */
if((cur == NULL) || !xmlSecCheckNodeName(cur, BAD_CAST "X509IssuerName", xmlSecDSigNs)) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_NODE_NOT_FOUND,
"X509IssuerName");
return(-1);
}
issuerName = xmlNodeGetContent(cur);
if(issuerName == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
"X509IssuerName");
return(-1);
}
cur = xmlSecGetNextElementNode(cur->next);
/* next is required node X509SerialNumber */
if((cur == NULL) || !xmlSecCheckNodeName(cur, BAD_CAST "X509SerialNumber", xmlSecDSigNs)) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_NODE_NOT_FOUND,
"X509SerialNumber");
xmlFree(issuerName);
return(-1);
}
issuerSerial = xmlNodeGetContent(cur);
if(issuerSerial == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
"X509SerialNumber");
xmlFree(issuerName);
return(-1);
}
cur = xmlSecGetNextElementNode(cur->next);
if(cur != NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_INVALID_NODE,
(cur->name != NULL) ? (char*)cur->name : "NULL");
xmlFree(issuerSerial);
xmlFree(issuerName);
return(-1);
}
x509Data = (keysMngr->findX509)(keysMngr, context, NULL, issuerName,
issuerSerial, NULL, x509Data);
if((x509Data == NULL) && (keysMngr->failIfCertNotFound)){
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_CERT_NOT_FOUND,
" ");
xmlFree(issuerSerial);
xmlFree(issuerName);
return(-1);
}
xmlFree(issuerSerial);
xmlFree(issuerName);
return(0);
}
static int
xmlSecX509SKINodeRead(xmlNodePtr skiNode, xmlSecX509DataPtr x509Data,
xmlSecKeysMngrPtr keysMngr, void *context) {
xmlChar *ski;
xmlSecAssert2(x509Data != NULL, -1);
xmlSecAssert2(skiNode != NULL, -1);
xmlSecAssert2(keysMngr != NULL, -1);
xmlSecAssert2(keysMngr->findX509 != NULL, -1);
ski = xmlNodeGetContent(skiNode);
if(ski == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
"X509Ski");
return(-1);
}
x509Data = (keysMngr->findX509)(keysMngr, context, NULL, NULL, NULL, ski, x509Data);
if((x509Data == NULL) && (keysMngr->failIfCertNotFound)){
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_CERT_NOT_FOUND,
" ");
xmlFree(ski);
return(-1);
}
xmlFree(ski);
return(0);
}
static int
xmlSecX509SubjectNameNodeRead(xmlNodePtr subjectNode, xmlSecX509DataPtr x509Data,
xmlSecKeysMngrPtr keysMngr, void *context) {
xmlChar *subjectName;
xmlSecAssert2(x509Data != NULL, -1);
xmlSecAssert2(subjectNode != NULL, -1);
xmlSecAssert2(keysMngr != NULL, -1);
xmlSecAssert2(keysMngr->findX509 != NULL, -1);
subjectName = xmlNodeGetContent(subjectNode);
if(subjectName == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
"X509Subject");
return(-1);
}
x509Data = (keysMngr->findX509)(keysMngr, context, subjectName,
NULL, NULL, NULL, x509Data);
if((x509Data == NULL) && (keysMngr->failIfCertNotFound)){
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_CERT_NOT_FOUND,
" ");
xmlFree(subjectName);
return(-1);
}
xmlFree(subjectName);
return(0);
}
static int
xmlSecX509CertificateNodeRead(xmlNodePtr certNode, xmlSecX509DataPtr x509Data) {
xmlChar *content;
int ret;
xmlSecAssert2(x509Data != NULL, -1);
xmlSecAssert2(certNode != NULL, -1);
content = xmlNodeGetContent(certNode);
if(content == NULL){
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
"X509Certificate");
return(-1);
}
ret = xmlSecX509DataReadDerCert(x509Data, content, 0, 1);
if(ret < 0) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecX509DataReadDerCert - %d", ret);
xmlFree(content);
return(-1);
}
xmlFree(content);
return(0);
}
static int
xmlSecX509CRLNodeRead(xmlNodePtr crlNode, xmlSecX509DataPtr x509Data) {
xmlChar *content;
int ret;
xmlSecAssert2(x509Data != NULL, -1);
xmlSecAssert2(crlNode != NULL, -1);
content = xmlNodeGetContent(crlNode);
if(content == NULL){
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
"X509Crl");
return(-1);
}
ret = xmlSecX509DataReadDerCrl(x509Data, content, 0, 1);
if(ret < 0) {
xmlSecError(XMLSEC_ERRORS_HERE,
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"xmlSecX509DataReadDerCrl - %d", ret);
xmlFree(content);
return(-1);
}
xmlFree(content);
return(0);
}
#endif /* XMLSEC_NO_X509 */