summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorso.yu <so.yu@samsung.com>2013-09-13 13:36:13 +0900
committerso.yu <so.yu@samsung.com>2013-09-13 14:10:09 +0900
commite22e8f773d515aedf79d0ae2fdf7474b4258a1c3 (patch)
treeb75262c048cb8ed100f7c16aa8f474f5b85c3b08
parentd5a874a313396f47c71b822a4eb270c3ea6b337c (diff)
parentf3f1d50d26dcfa4853593bb12a9395919d8d65d1 (diff)
downloadxmlsec1-e22e8f773d515aedf79d0ae2fdf7474b4258a1c3.tar.gz
xmlsec1-e22e8f773d515aedf79d0ae2fdf7474b4258a1c3.tar.bz2
xmlsec1-e22e8f773d515aedf79d0ae2fdf7474b4258a1c3.zip
-rw-r--r--include/xmlsec/keyinfo.h11
-rw-r--r--include/xmlsec/xmldsig.h5
-rw-r--r--src/errors.c22
-rw-r--r--src/io.c6
-rw-r--r--src/openssl/digests.c4
-rw-r--r--src/xmldsig.c711
6 files changed, 750 insertions, 9 deletions
diff --git a/include/xmlsec/keyinfo.h b/include/xmlsec/keyinfo.h
index 5d7cf0e0..0d823b27 100644
--- a/include/xmlsec/keyinfo.h
+++ b/include/xmlsec/keyinfo.h
@@ -155,6 +155,17 @@ typedef enum {
#define XMLSEC_KEYINFO_FLAGS_X509DATA_SKIP_STRICT_CHECKS 0x00004000
/**
+ * XMLSEC_KEYINFO_FLAGS_SKIP_VERIFY_CHAIN:
+ *
+ * If the flag is set then we wont stop document validation
+ * on certificate chain error. Instead of stopping validation
+ * we'll just set flag XMLSEC_KEYINFO_ERROR_FLAGS_BROKEN_CHAIN
+ * as flags2 value.
+ */
+#define XMLSEC_KEYINFO_FLAGS_ALLOW_BROKEN_CHAIN 0x00008000
+#define XMLSEC_KEYINFO_ERROR_FLAGS_BROKEN_CHAIN 0x00000001
+
+/**
* xmlSecKeyInfoCtx:
* @userData: the pointer to user data (xmlsec and xmlsec-crypto
* never touch this).
diff --git a/include/xmlsec/xmldsig.h b/include/xmlsec/xmldsig.h
index 3cd311e6..dabcac64 100644
--- a/include/xmlsec/xmldsig.h
+++ b/include/xmlsec/xmldsig.h
@@ -257,6 +257,11 @@ XMLSEC_EXPORT void xmlSecDSigReferenceCtxDebugDump (xmlSecDSigRefer
XMLSEC_EXPORT void xmlSecDSigReferenceCtxDebugXmlDump(xmlSecDSigReferenceCtxPtr dsigRefCtx,
FILE* output);
+XMLSEC_EXPORT int xmlSecDSigCtxVerifyEx(xmlSecDSigCtxPtr dsigCtx,
+ xmlNodePtr node, int noHash, void* pList);
+
+
+
/**************************************************************************
*
* xmlSecDSigReferenceCtxListKlass
diff --git a/src/errors.c b/src/errors.c
index c9886d36..97fd55c3 100644
--- a/src/errors.c
+++ b/src/errors.c
@@ -10,6 +10,7 @@
*/
#include "globals.h"
+#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
@@ -114,6 +115,7 @@ xmlSecErrorsShutdown(void) {
void
xmlSecErrorsSetCallback(xmlSecErrorsCallback callback) {
xmlSecErrorsClbk = callback;
+ xmlSecErrorsDefaultCallbackEnableOutput(0);
}
/**
@@ -225,13 +227,29 @@ xmlSecError(const char* file, int line, const char* func,
int reason, const char* msg, ...) {
if(xmlSecErrorsClbk != NULL) {
- xmlChar error_msg[XMLSEC_ERRORS_BUFFER_SIZE];
+ xmlChar error_msg[XMLSEC_ERRORS_BUFFER_SIZE] = {'\0',};
+ const char* e_msg = NULL;
+ xmlSecSize i;
+ int len = 0;
+
+ if(xmlSecPrintErrorMessages == 0) {
+ if(reason != XMLSEC_ERRORS_MAX_NUMBER) {
+ for(i = 0; (i < XMLSEC_ERRORS_MAX_NUMBER) && (xmlSecErrorsGetMsg(i) != NULL); ++i) {
+ if(xmlSecErrorsGetCode(i) == reason) {
+ e_msg = xmlSecErrorsGetMsg(i);
+ sprintf(error_msg , "%s] [", e_msg);
+ len = strlen(error_msg);
+ break;
+ }
+ }
+ }
+ }
if(msg != NULL) {
va_list va;
va_start(va, msg);
- xmlSecStrVPrintf(error_msg, sizeof(error_msg), BAD_CAST msg, va);
+ xmlSecStrVPrintf(error_msg + len, sizeof(error_msg) - len, BAD_CAST msg, va);
error_msg[sizeof(error_msg) - 1] = '\0';
va_end(va);
} else {
diff --git a/src/io.c b/src/io.c
index 42e91337..79ee3a63 100644
--- a/src/io.c
+++ b/src/io.c
@@ -424,9 +424,9 @@ xmlSecTransformInputURIOpen(xmlSecTransformPtr transform, const xmlChar *uri) {
xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
"opencallback",
XMLSEC_ERRORS_R_IO_FAILED,
- "uri=%s;errno=%d",
+ "uri=%s;error=%s",
xmlSecErrorsSafeString(uri),
- errno);
+ strerror(errno));
return(-1);
}
@@ -484,7 +484,7 @@ xmlSecTransformInputURIPopBin(xmlSecTransformPtr transform, xmlSecByte* data,
xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
"readcallback",
XMLSEC_ERRORS_R_IO_FAILED,
- "errno=%d", errno);
+ "error=%s", strerror(errno));
return(-1);
}
(*dataSize) = ret;
diff --git a/src/openssl/digests.c b/src/openssl/digests.c
index fa26fa65..2f1adb1c 100644
--- a/src/openssl/digests.c
+++ b/src/openssl/digests.c
@@ -243,7 +243,7 @@ xmlSecOpenSSLEvpDigestVerify(xmlSecTransformPtr transform,
"data_size=%d;dgst_size=%d",
dataSize, ctx->dgstSize);
transform->status = xmlSecTransformStatusFail;
- return(0);
+ return -1;//(0);
}
if(memcmp(ctx->dgst, data, ctx->dgstSize) != 0) {
@@ -253,7 +253,7 @@ xmlSecOpenSSLEvpDigestVerify(xmlSecTransformPtr transform,
XMLSEC_ERRORS_R_INVALID_DATA,
"data and digest do not match");
transform->status = xmlSecTransformStatusFail;
- return(0);
+ return -1;//(0);
}
transform->status = xmlSecTransformStatusOk;
diff --git a/src/xmldsig.c b/src/xmldsig.c
index b08b8b11..2002dc43 100644
--- a/src/xmldsig.c
+++ b/src/xmldsig.c
@@ -46,10 +46,22 @@ static int xmlSecDSigCtxProcessObjectNode (xmlSecDSigCtxPtr dsigCt
xmlNodePtr node);
static int xmlSecDSigCtxProcessManifestNode (xmlSecDSigCtxPtr dsigCtx,
xmlNodePtr node);
+static int xmlSecDSigCtxProcessSignatureNodeEx (xmlSecDSigCtxPtr dsigCtx,
+ xmlNodePtr node, int noHash, void* pList);
+static int xmlSecDSigCtxProcessSignedInfoNodeEx (xmlSecDSigCtxPtr dsigCtx,
+ xmlNodePtr node, int noHash, void* pList);
+static int xmlSecDSigReferenceCtxProcessNodeEx (xmlSecDSigReferenceCtxPtr dsigRefCtx,
+ xmlNodePtr node, int noHash, void* pList);
+
/* The ID attribute in XMLDSig is 'Id' */
static const xmlChar* xmlSecDSigIds[] = { xmlSecAttrId, NULL };
+
+#define _start //xmlSecError(XMLSEC_ERRORS_HERE, NULL, NULL, XMLSEC_ERRORS_MAX_NUMBER," >> start ");
+#define _end //xmlSecError(XMLSEC_ERRORS_HERE, NULL, NULL, XMLSEC_ERRORS_MAX_NUMBER," >> end ");
+static char logMsg[1024];
+
/**
* xmlSecDSigCtxCreate:
* @keysMngr: the pointer to keys manager.
@@ -1568,11 +1580,13 @@ xmlSecDSigReferenceCtxProcessNode(xmlSecDSigReferenceCtxPtr dsigRefCtx, xmlNodeP
/* finally get transforms results */
ret = xmlSecTransformCtxExecute(transformCtx, node->doc);
if(ret < 0) {
+ sprintf(logMsg, "uri:%s", (char*)dsigRefCtx->uri);
+ logMsg[strlen(dsigRefCtx->uri)+5] = '\0';
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlSecTransformCtxExecute",
XMLSEC_ERRORS_R_XMLSEC_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
+ logMsg);
return(-1);
}
dsigRefCtx->result = transformCtx->result;
@@ -1599,11 +1613,13 @@ xmlSecDSigReferenceCtxProcessNode(xmlSecDSigReferenceCtxPtr dsigRefCtx, xmlNodeP
ret = xmlSecTransformVerifyNodeContent(dsigRefCtx->digestMethod,
digestValueNode, transformCtx);
if(ret < 0) {
+ sprintf(logMsg, "uri:%s", (char*)dsigRefCtx->uri);
+ logMsg[strlen(dsigRefCtx->uri)+5] = '\0';
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlSecTransformVerifyNodeContent",
XMLSEC_ERRORS_R_XMLSEC_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
+ logMsg);
return(-1);
}
@@ -1765,6 +1781,697 @@ xmlSecDSigReferenceCtxDebugXmlDump(xmlSecDSigReferenceCtxPtr dsigRefCtx, FILE* o
}
+
+int
+xmlSecDSigCtxVerifyEx(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node, int noHash, void* pList) {
+ int ret;
+ int len = 0;
+
+ if(noHash == 1)
+ _start
+
+ xmlSecAssert2(dsigCtx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(node->doc != NULL, -1);
+
+ /* add ids for Signature nodes */
+ dsigCtx->operation = xmlSecTransformOperationVerify;
+ dsigCtx->status = xmlSecDSigStatusUnknown;
+ xmlSecAddIDs(node->doc, node, xmlSecDSigIds);
+
+ /* read siganture info */
+ ret = xmlSecDSigCtxProcessSignatureNodeEx(dsigCtx, node, noHash, pList);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecDSigCtxProcessSignatureNodeEx",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+
+ return(-1);
+ }
+ xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
+ xmlSecAssert2(dsigCtx->signValueNode != NULL, -1);
+
+ /* references processing might change the status */
+ if(dsigCtx->status != xmlSecDSigStatusUnknown) {
+ return(0);
+ }
+
+ /* verify SignatureValue node content */
+ ret = xmlSecTransformVerifyNodeContent(dsigCtx->signMethod, dsigCtx->signValueNode,
+ &(dsigCtx->transformCtx));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformVerifyNodeContent",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+
+ return(-1);
+ }
+
+ /* set status and we are done */
+ if(dsigCtx->signMethod->status == xmlSecTransformStatusOk) {
+ dsigCtx->status = xmlSecDSigStatusSucceeded;
+ } else {
+ dsigCtx->status = xmlSecDSigStatusInvalid;
+ }
+ _end
+ return(0);
+}
+
+int
+xmlSecDSigCtxProcessSignatureNodeEx (xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node, int noHash, void* pList) {
+ xmlSecTransformDataType firstType;
+ xmlNodePtr signedInfoNode = NULL;
+ xmlNodePtr keyInfoNode = NULL;
+ xmlNodePtr cur;
+ int ret;
+
+ _start
+ xmlSecAssert2(dsigCtx != NULL, -1);
+ xmlSecAssert2((dsigCtx->operation == xmlSecTransformOperationSign) || (dsigCtx->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
+ xmlSecAssert2(dsigCtx->signValueNode == NULL, -1);
+ xmlSecAssert2(dsigCtx->signMethod == NULL, -1);
+ xmlSecAssert2(dsigCtx->c14nMethod == NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ if(!xmlSecCheckNodeName(node, xmlSecNodeSignature, xmlSecDSigNs)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected=%s",
+ xmlSecErrorsSafeString(xmlSecNodeSignature));
+ return(-1);
+ }
+
+ /* read node data */
+ xmlSecAssert2(dsigCtx->id == NULL, -1);
+ dsigCtx->id = xmlGetProp(node, xmlSecAttrId);
+
+ /* first node is required SignedInfo */
+ cur = xmlSecGetNextElementNode(node->children);
+ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeSignedInfo, xmlSecDSigNs))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected=%s",
+ xmlSecErrorsSafeString(xmlSecNodeSignedInfo));
+ return(-1);
+ }
+ signedInfoNode = cur;
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ /* next node is required SignatureValue */
+ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeSignatureValue, xmlSecDSigNs))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected=%s",
+ xmlSecErrorsSafeString(xmlSecNodeSignatureValue));
+ return(-1);
+ }
+ dsigCtx->signValueNode = cur;
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ /* next node is optional KeyInfo */
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeKeyInfo, xmlSecDSigNs))) {
+ keyInfoNode = cur;
+ cur = xmlSecGetNextElementNode(cur->next);
+ } else {
+ keyInfoNode = NULL;
+ }
+
+ /* next nodes are optional Object nodes */
+ while((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeObject, xmlSecDSigNs))) {
+ /* read manifests from objects */
+ if((dsigCtx->flags & XMLSEC_DSIG_FLAGS_IGNORE_MANIFESTS) == 0) {
+ ret = xmlSecDSigCtxProcessObjectNode(dsigCtx, cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecDSigCtxProcessObjectNode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* if there is something left than it's an error */
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* now validated all the references and prepare transform */
+ ret = xmlSecDSigCtxProcessSignedInfoNodeEx(dsigCtx, signedInfoNode, noHash, pList);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecDSigCtxProcessSignedInfoNodeEx",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ /* references processing might change the status */
+ if(dsigCtx->status != xmlSecDSigStatusUnknown) {
+ return(0);
+ }
+
+ /* as the result, we should have sign and c14n methods set */
+ xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
+ xmlSecAssert2(dsigCtx->c14nMethod != NULL, -1);
+
+ ret = xmlSecDSigCtxProcessKeyInfoNode(dsigCtx, keyInfoNode);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecDSigCtxProcessKeyInfoNode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ /* as the result, we should have a key */
+ xmlSecAssert2(dsigCtx->signKey != NULL, -1);
+
+ /* if we need to write result to xml node then we need base64 encode result */
+ if(dsigCtx->operation == xmlSecTransformOperationSign) {
+ xmlSecTransformPtr base64Encode;
+
+ /* we need to add base64 encode transform */
+ base64Encode = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx),
+ xmlSecTransformBase64Id);
+ if(base64Encode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxCreateAndAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ base64Encode->operation = xmlSecTransformOperationEncode;
+ }
+
+ firstType = xmlSecTransformGetDataType(dsigCtx->transformCtx.first,
+ xmlSecTransformModePush, &(dsigCtx->transformCtx));
+ if((firstType & xmlSecTransformDataTypeXml) != 0) {
+ xmlSecNodeSetPtr nodeset = NULL;
+
+ xmlSecAssert2(signedInfoNode != NULL, -1);
+ nodeset = xmlSecNodeSetGetChildren(signedInfoNode->doc, signedInfoNode, 1, 0);
+ if(nodeset == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNodeSetGetChildren",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(signedInfoNode)));
+ return(-1);
+ }
+
+ /* calculate the signature */
+ ret = xmlSecTransformCtxXmlExecute(&(dsigCtx->transformCtx), nodeset);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxXmlExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecNodeSetDestroy(nodeset);
+ return(-1);
+ }
+ xmlSecNodeSetDestroy(nodeset);
+ } else {
+ /* TODO */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "the binary c14n transforms are not supported yet",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ _end
+ return(0);
+}
+
+int
+xmlSecDSigCtxProcessSignedInfoNodeEx(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node, int noHash, void* pList) {
+ xmlSecDSigReferenceCtxPtr dsigRefCtx;
+ xmlNodePtr cur;
+ int ret = -1;
+
+ _start
+ xmlSecAssert2(dsigCtx != NULL, -1);
+ xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
+ xmlSecAssert2(dsigCtx->signMethod == NULL, -1);
+ xmlSecAssert2(dsigCtx->c14nMethod == NULL, -1);
+ xmlSecAssert2((dsigCtx->operation == xmlSecTransformOperationSign) || (dsigCtx->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences)) == 0, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* first node is required CanonicalizationMethod. */
+ cur = xmlSecGetNextElementNode(node->children);
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeCanonicalizationMethod, xmlSecDSigNs))) {
+ dsigCtx->c14nMethod = xmlSecTransformCtxNodeRead(&(dsigCtx->transformCtx),
+ cur, xmlSecTransformUsageC14NMethod);
+ if(dsigCtx->c14nMethod == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ ret = -1;
+ goto error;
+ }
+ } else if(dsigCtx->defC14NMethodId != xmlSecTransformIdUnknown) {
+ /* the dsig spec does require CanonicalizationMethod node
+ * to be present but in some case it application might decide to
+ * minimize traffic */
+ dsigCtx->c14nMethod = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx),
+ dsigCtx->defC14NMethodId);
+ if(dsigCtx->c14nMethod == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ ret = -1;
+ goto error;
+ }
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CanonicalizationMethod",
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected=%s",
+ xmlSecErrorsSafeString(xmlSecNodeCanonicalizationMethod));
+ ret = -1;
+ goto error;
+ }
+
+ /* insert membuf if requested */
+ if((dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNATURE) != 0) {
+ xmlSecAssert2(dsigCtx->preSignMemBufMethod == NULL, -1);
+ dsigCtx->preSignMemBufMethod = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx),
+ xmlSecTransformMemBufId);
+ if(dsigCtx->preSignMemBufMethod == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxCreateAndAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId)));
+ }
+ }
+
+ /* next node is required SignatureMethod. */
+ cur = xmlSecGetNextElementNode( ((cur != NULL) ? cur->next : node->children) );
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeSignatureMethod, xmlSecDSigNs))) {
+ dsigCtx->signMethod = xmlSecTransformCtxNodeRead(&(dsigCtx->transformCtx),
+ cur, xmlSecTransformUsageSignatureMethod);
+ if(dsigCtx->signMethod == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ ret = -1;
+ goto error;
+ }
+ } else if(dsigCtx->defSignMethodId != xmlSecTransformIdUnknown) {
+ /* the dsig spec does require SignatureMethod node
+ * to be present but in some case it application might decide to
+ * minimize traffic */
+ dsigCtx->signMethod = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx),
+ dsigCtx->defSignMethodId);
+ if(dsigCtx->signMethod == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ ret = -1;
+ goto error;
+ }
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected=%s",
+ xmlSecErrorsSafeString(xmlSecNodeSignatureMethod));
+ ret = -1;
+ goto error;
+ }
+ dsigCtx->signMethod->operation = dsigCtx->operation;
+
+ /* calculate references */
+ cur = xmlSecGetNextElementNode(cur->next);
+ while((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeReference, xmlSecDSigNs))) {
+ /* create reference */
+ dsigRefCtx = xmlSecDSigReferenceCtxCreate(dsigCtx, xmlSecDSigReferenceOriginSignedInfo);
+ if(dsigRefCtx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecDSigReferenceCtxCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ ret = -1;
+ goto error;
+ }
+
+ /* add to the list */
+ ret = xmlSecPtrListAdd(&(dsigCtx->signedInfoReferences), dsigRefCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecDSigReferenceCtxDestroy(dsigRefCtx);
+ ret = -1;
+ goto error;
+ }
+
+ /* process */
+ if(noHash != 1){ //if 0, then partial ///if 1, then no_hash
+ ret = xmlSecDSigReferenceCtxProcessNodeEx(dsigRefCtx, cur, noHash, pList);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecDSigReferenceCtxProcessNode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+
+ ret = -1;
+ goto error;
+ }
+ }
+
+ dsigRefCtx->status = xmlSecDSigStatusSucceeded;
+
+ /* bail out if next Reference processing failed */
+ if(dsigRefCtx->status != xmlSecDSigStatusSucceeded) {
+ xmlSecError(XMLSEC_ERRORS_HERE, NULL, NULL, XMLSEC_ERRORS_MAX_NUMBER, "###### false");
+ dsigCtx->status = xmlSecDSigStatusInvalid;
+ ret = -1;
+ goto error;
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* check that we have at least one Reference */
+ if(xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences)) == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_DSIG_NO_REFERENCES,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ ret = -1;
+ goto error;
+ }
+
+ /* if there is something left than it's an error */
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ ret = -1;
+ goto error;
+ }
+ _end
+error:
+ return(ret);
+}
+
+int
+xmlSecDSigReferenceCtxProcessNodeEx(xmlSecDSigReferenceCtxPtr dsigRefCtx, xmlNodePtr node, int noHash, void* pList) {
+ xmlSecTransformCtxPtr transformCtx;
+ xmlNodePtr digestValueNode;
+ xmlNodePtr cur;
+ int ret;
+ int cmpResult = -1;
+ int len = 0;
+ int i = 0;
+
+ char** pNextTmp = (char**)pList;
+
+ xmlSecAssert2(dsigRefCtx != NULL, -1);
+ xmlSecAssert2(dsigRefCtx->dsigCtx != NULL, -1);
+ xmlSecAssert2(dsigRefCtx->digestMethod == NULL, -1);
+ xmlSecAssert2(dsigRefCtx->digestMethod == NULL, -1);
+ xmlSecAssert2(dsigRefCtx->preDigestMemBufMethod == NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(node->doc != NULL, -1);
+
+ _start
+
+ transformCtx = &(dsigRefCtx->transformCtx);
+
+ if(pList == NULL){
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* read attributes first */
+ dsigRefCtx->uri = xmlGetProp(node, xmlSecAttrURI);
+
+ while(pNextTmp[i] != NULL)
+ {
+ len = strlen(pNextTmp[i]);
+ cmpResult = strncmp((const char *)dsigRefCtx->uri, (const char *)pNextTmp[i], len);
+ if( cmpResult == 0 ) {
+ sprintf(logMsg, "uri: %s", (char*)pNextTmp[i]);
+ xmlSecError(XMLSEC_ERRORS_HERE, NULL, NULL, XMLSEC_ERRORS_MAX_NUMBER, logMsg);
+ break;
+ }
+ ++i;
+ }
+
+ if(cmpResult != 0) {
+ cmpResult = -1;
+ goto partial;
+ }
+
+ dsigRefCtx->id = xmlGetProp(node, xmlSecAttrId);
+ dsigRefCtx->type= xmlGetProp(node, xmlSecAttrType);
+
+ /* set start URI (and check that it is enabled!) */
+ ret = xmlSecTransformCtxSetUri(transformCtx, dsigRefCtx->uri, node);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxSetUri",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "uri=%s",
+ xmlSecErrorsSafeString(dsigRefCtx->uri));
+ return(-1);
+ }
+
+ /* first is optional Transforms node */
+ cur = xmlSecGetNextElementNode(node->children);
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeTransforms, xmlSecDSigNs))) {
+ ret = xmlSecTransformCtxNodesListRead(transformCtx,
+ cur, xmlSecTransformUsageDSigTransform);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxNodesListRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ return(-1);
+ }
+
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* insert membuf if requested */
+ if(((dsigRefCtx->origin == xmlSecDSigReferenceOriginSignedInfo) &&
+ ((dsigRefCtx->dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNEDINFO_REFERENCES) != 0)) ||
+ ((dsigRefCtx->origin == xmlSecDSigReferenceOriginManifest) &&
+ ((dsigRefCtx->dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_MANIFEST_REFERENCES) != 0))) {
+ xmlSecAssert2(dsigRefCtx->preDigestMemBufMethod == NULL, -1);
+ dsigRefCtx->preDigestMemBufMethod = xmlSecTransformCtxCreateAndAppend(
+ transformCtx,
+ xmlSecTransformMemBufId);
+ if(dsigRefCtx->preDigestMemBufMethod == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxCreateAndAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId)));
+ return(-1);
+ }
+ }
+
+ /* next node is required DigestMethod. */
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDigestMethod, xmlSecDSigNs))) {
+ dsigRefCtx->digestMethod = xmlSecTransformCtxNodeRead(&(dsigRefCtx->transformCtx),
+ cur, xmlSecTransformUsageDigestMethod);
+ if(dsigRefCtx->digestMethod == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ return(-1);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+ } else if(dsigRefCtx->dsigCtx->defSignMethodId != xmlSecTransformIdUnknown) {
+ /* the dsig spec does require DigestMethod node
+ * to be present but in some case it application might decide to
+ * minimize traffic */
+ dsigRefCtx->digestMethod = xmlSecTransformCtxCreateAndAppend(&(dsigRefCtx->transformCtx),
+ dsigRefCtx->dsigCtx->defSignMethodId);
+ if(dsigRefCtx->digestMethod == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDigestMethod));
+ return(-1);
+ }
+
+ dsigRefCtx->digestMethod->operation = dsigRefCtx->dsigCtx->operation;
+
+ /* last node is required DigestValue */
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDigestValue, xmlSecDSigNs))) {
+ digestValueNode = cur;
+ cur = xmlSecGetNextElementNode(cur->next);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDigestValue));
+ return(-1);
+ }
+
+ /* if we have something else then it's an error */
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* if we need to write result to xml node then we need base64 encode result */
+ if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {
+ xmlSecTransformPtr base64Encode;
+
+ /* we need to add base64 encode transform */
+ base64Encode = xmlSecTransformCtxCreateAndAppend(transformCtx, xmlSecTransformBase64Id);
+ if(base64Encode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxCreateAndAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ base64Encode->operation = xmlSecTransformOperationEncode;
+ }
+
+ /* finally get transforms results */
+ ret = xmlSecTransformCtxExecute(transformCtx, node->doc);
+ if(ret < 0) {
+ sprintf(logMsg, "uri:%s", (char*)dsigRefCtx->uri);
+ logMsg[strlen(dsigRefCtx->uri)+5] = '\0';
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ logMsg);
+ return(-1);
+ }
+
+ dsigRefCtx->result = transformCtx->result;
+
+ if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {
+ if((dsigRefCtx->result == NULL) || (xmlSecBufferGetData(dsigRefCtx->result) == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* write signed data to xml */
+ xmlNodeSetContentLen(digestValueNode,
+ xmlSecBufferGetData(dsigRefCtx->result),
+ xmlSecBufferGetSize(dsigRefCtx->result));
+
+ /* set success status and we are done */
+ dsigRefCtx->status = xmlSecDSigStatusSucceeded;
+ } else {
+ /* verify SignatureValue node content */
+ ret = xmlSecTransformVerifyNodeContent(dsigRefCtx->digestMethod,
+ digestValueNode, transformCtx);
+ if(ret < 0) {
+ sprintf(logMsg, "uri:%s", (char*)dsigRefCtx->uri);
+ logMsg[strlen(dsigRefCtx->uri)+5] = '\0';
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformVerifyNodeContent",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED, logMsg);
+ return(-1);
+ }
+
+ /* set status and we are done */
+ if(dsigRefCtx->digestMethod->status == xmlSecTransformStatusOk) {
+ dsigRefCtx->status = xmlSecDSigStatusSucceeded;
+ } else {
+ dsigRefCtx->status = xmlSecDSigStatusInvalid;
+ }
+ }
+
+ if(dsigRefCtx->digestMethod->status == xmlSecTransformStatusOk) {
+ dsigRefCtx->status = xmlSecDSigStatusSucceeded;
+ }
+
+ _end
+
+partial:
+ return(0);
+}
+
+
/**************************************************************************
*
* xmlSecDSigReferenceCtxListKlass