diff options
-rw-r--r-- | include/xmlsec/keyinfo.h | 11 | ||||
-rw-r--r-- | include/xmlsec/xmldsig.h | 5 | ||||
-rw-r--r-- | packaging/xmlsec1.changes | 13 | ||||
-rw-r--r-- | packaging/xmlsec1.manifest | 5 | ||||
-rw-r--r-- | packaging/xmlsec1.spec | 126 | ||||
-rw-r--r-- | src/errors.c | 34 | ||||
-rw-r--r-- | src/io.c | 6 | ||||
-rw-r--r-- | src/openssl/digests.c | 4 | ||||
-rw-r--r-- | src/openssl/x509vfy.c | 4 | ||||
-rw-r--r-- | src/xmldsig.c | 745 |
10 files changed, 920 insertions, 33 deletions
diff --git a/include/xmlsec/keyinfo.h b/include/xmlsec/keyinfo.h index fd872852..63b199c5 100644 --- a/include/xmlsec/keyinfo.h +++ b/include/xmlsec/keyinfo.h @@ -154,6 +154,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 diff --git a/include/xmlsec/xmldsig.h b/include/xmlsec/xmldsig.h index ec59f4d4..6c8e12bc 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/packaging/xmlsec1.changes b/packaging/xmlsec1.changes new file mode 100644 index 00000000..f727bd68 --- /dev/null +++ b/packaging/xmlsec1.changes @@ -0,0 +1,13 @@ +* Tue Aug 13 2013 Ryan Ware <ware@linux.intel.com> upstream/1.2.19@3449eaf +- Move to xmlsec1 1.2.19 from 1.2.14 to address CVE-2011-1425 +- resetting manifest requested domain to floor +- Set license using %license +- add Tizen patch to support keys +- move down to 1.2.14 +- remove docs +- add packaging +- add packaging + +* Sat May 11 2013 Anas Nashif <anas.nashif@intel.com> submit/tizen/20130509.185152@99f7699 +- Set license using %license + diff --git a/packaging/xmlsec1.manifest b/packaging/xmlsec1.manifest new file mode 100644 index 00000000..017d22d3 --- /dev/null +++ b/packaging/xmlsec1.manifest @@ -0,0 +1,5 @@ +<manifest> + <request> + <domain name="_"/> + </request> +</manifest> diff --git a/packaging/xmlsec1.spec b/packaging/xmlsec1.spec new file mode 100644 index 00000000..e4a80cfe --- /dev/null +++ b/packaging/xmlsec1.spec @@ -0,0 +1,126 @@ +%define keepstatic 1 +Name: xmlsec1 +Version: 1.2.19 +Release: 0 +License: MIT +Summary: Library providing support for "XML Signature" and "XML Encryption" standards +Url: http://www.aleksey.com/xmlsec/index.html +Group: System/Libraries +Source0: http://www.aleksey.com/xmlsec/download/xmlsec1-%{version}.tar.gz +Source1001: xmlsec1.manifest +BuildRequires: fdupes +BuildRequires: pkgconfig +BuildRequires: pkgconfig(libxml-2.0) >= 2.6.27 +BuildRequires: pkgconfig(libxslt) +BuildRequires: pkgconfig(openssl) + +%description +This C library allows to transform XML files into other XML files +(or HTML, text, ...) using the standard XSLT stylesheet transformation +mechanism. To use it you need to have a version of libxml2 >= 2.6.27 +installed. The xsltproc command is a command line interface to the XSLT engine + +%package gcrypt +Summary: Gcrypt crypto plugin for XML Security Library +Group: System/Libraries +Requires: %{name} = %{version} + +%description gcrypt +Gcrypt plugin for XML Security Library provides gcrypt based crypto services +for the xmlsec library. + +%package openssl +Summary: OpenSSL crypto plugin for XML Security Library +Group: System/Libraries +Requires: %{name} = %{version} + +%description openssl +OpenSSL plugin for XML Security Library provides OpenSSL based crypto services +for the xmlsec library. + +%package devel +Summary: Libraries, includes, etc +Group: Development/Libraries +Requires: %{name} = %{version} + +%description devel +This C library allows to transform XML files into other XML files +(or HTML, text, ...) using the standard XSLT stylesheet transformation +mechanism. To use it you need to have a version of libxml2 >= 2.6.27 +installed. + +%package devel-static +Summary: A library for Perl-compatible regular expressions +Group: System/Libraries +Requires: %{name}-devel = %{version} + +%description devel-static +This C library allows to transform XML files into other XML files +(or HTML, text, ...) using the standard XSLT stylesheet transformation +mechanism. To use it you need to have a version of libxml2 >= 2.6.27 +installed. +This package contains static versions of the libxmlsec1 library. + +%prep +%setup -q +cp %{SOURCE1001} . + + +%build + +%reconfigure \ + --enable-static \ + --enable-dynamic \ + --disable-crypto-dl \ + --disable-apps-crypto-dl \ + --without-gnutls + +%__make %{?_smp_mflags} + +%install +%make_install + +%remove_docs + +%fdupes %{buildroot} + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%post gcrypt -p /sbin/ldconfig + +%postun gcrypt -p /sbin/ldconfig + +%post openssl -p /sbin/ldconfig + +%postun openssl -p /sbin/ldconfig + +%files +%manifest %{name}.manifest +%license COPYING +%doc Copyright +%{_libdir}/libxmlsec1.so.* +%{_bindir}/xmlsec1 + +%files gcrypt +%manifest %{name}.manifest +%{_libdir}/libxmlsec1-gcrypt.so.* + +%files openssl +%manifest %{name}.manifest +%{_libdir}/libxmlsec1-openssl.so.* + +%files devel +%manifest %{name}.manifest +%doc Copyright +%{_includedir}/xmlsec1 +%{_bindir}/xmlsec1-config +%{_libdir}/lib*.so +%{_libdir}/pkgconfig/* +%{_libdir}/xmlsec1Conf.sh +%{_datadir}/aclocal/xmlsec1.m4 + +%files devel-static +%manifest %{name}.manifest +%{_libdir}/*.a diff --git a/src/errors.c b/src/errors.c index 2ff1f42a..0c14da7c 100644 --- a/src/errors.c +++ b/src/errors.c @@ -114,6 +114,7 @@ xmlSecErrorsShutdown(void) { void xmlSecErrorsSetCallback(xmlSecErrorsCallback callback) { xmlSecErrorsClbk = callback; + xmlSecErrorsDefaultCallbackEnableOutput(0); } /** @@ -144,7 +145,7 @@ xmlSecErrorsDefaultCallback(const char* file, int line, const char* func, } } xmlGenericError(xmlGenericErrorContext, - "func=%s:file=%s:line=%d:obj=%s:subj=%s:error=%d:%s:%s\n", + "func=%s:file=%s:line=%d:obj=%s:subj=%s:error=%d:<%s>:<%s>\n", (func != NULL) ? func : "unknown", (file != NULL) ? file : "unknown", line, @@ -220,23 +221,38 @@ xmlSecErrorsGetMsg(xmlSecSize pos) { * function. */ void -xmlSecError(const char* file, int line, const char* func, - const char* errorObject, const char* errorSubject, - int reason, const char* msg, ...) { +xmlSecError(const char* file, int line, const char* func, + const char* errorObject, const char* errorSubject, + 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 { error_msg[0] = '\0'; } - xmlSecErrorsClbk(file, line, func, errorObject, errorSubject, reason, (char*)error_msg); - } + + xmlSecErrorsClbk(file, line, func, errorObject, errorSubject, reason, (char*)error_msg); } } @@ -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); } @@ -523,7 +523,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 1d00a1b7..5ec5299a 100644 --- a/src/openssl/digests.c +++ b/src/openssl/digests.c @@ -298,7 +298,7 @@ xmlSecOpenSSLEvpDigestVerify(xmlSecTransformPtr transform, "data_size=%d;dgst_size=%d", dataSize, ctx->dgstSize); transform->status = xmlSecTransformStatusFail; - return(0); + return -1; } if(memcmp(ctx->dgst, data, ctx->dgstSize) != 0) { @@ -308,7 +308,7 @@ xmlSecOpenSSLEvpDigestVerify(xmlSecTransformPtr transform, XMLSEC_ERRORS_R_INVALID_DATA, "data and digest do not match"); transform->status = xmlSecTransformStatusFail; - return(0); + return -1; } transform->status = xmlSecTransformStatusOk; diff --git a/src/openssl/x509vfy.c b/src/openssl/x509vfy.c index 5560526b..155e1ab5 100644 --- a/src/openssl/x509vfy.c +++ b/src/openssl/x509vfy.c @@ -328,6 +328,10 @@ xmlSecOpenSSLX509StoreVerify(xmlSecKeyDataStorePtr store, XMLSEC_STACK_OF_X509* err = X509_STORE_CTX_get_error(&xsc); X509_STORE_CTX_cleanup (&xsc); + if(ret != 1 && keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_ALLOW_BROKEN_CHAIN){ + ret = 1; + keyInfoCtx->flags2 |= XMLSEC_KEYINFO_ERROR_FLAGS_BROKEN_CHAIN; + } if(ret == 1) { res = cert; diff --git a/src/xmldsig.c b/src/xmldsig.c index faf55459..ff340f77 100644 --- a/src/xmldsig.c +++ b/src/xmldsig.c @@ -47,12 +47,24 @@ static int xmlSecDSigCtxProcessObjectNode (xmlSecDSigCtxPtr dsigCt xmlNodePtr node); static int xmlSecDSigCtxProcessManifestNode (xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node); - static int xmlSecDSigCtxProcessReferences (xmlSecDSigCtxPtr dsigCtx, xmlNodePtr firstReferenceNode); +/* Tizen : Support for various validation mode */ +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 }; +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: @@ -1645,42 +1657,46 @@ 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); + 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); + 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)); + 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); + 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); + NULL, + "xmlSecTransformVerifyNodeContent", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + logMsg); return(-1); } @@ -1842,6 +1858,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 |