capture errors from libxml2

fixes #4
This commit is contained in:
Ross Kinder
2015-12-23 17:17:48 -05:00
parent c095422255
commit dc37ddb368
6 changed files with 48 additions and 25 deletions

View File

@@ -139,7 +139,7 @@ func (testSuite *DecryptTest) TestInvalid(c *C) {
c.Assert(err, IsNil)
_, err = Decrypt(testSuite.Key, []byte("<invalid xml"))
c.Assert(err, ErrorMatches, "malformed XML")
c.Assert(err, ErrorMatches, ".*Couldn't find end of Start Tag.*")
_, err = Decrypt(testSuite.Key, []byte("<invalid></invalid>"))
c.Assert(err, ErrorMatches, "xmlSecFindNode cannot find EncryptedData node")
@@ -149,7 +149,7 @@ func (testSuite *DecryptTest) TestInvalid(c *C) {
docStr = []byte(`<?xml version="1.0" encoding="UTF-8"?><saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://15661444.ngrok.io/saml2/acs" ID="_59c2431b4916af2018984213940ee675" InResponseTo="id-3d21faf29a101222d740735fa512f161" IssueInstant="2015-11-29T21:29:09.991Z" Version="2.0"><saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://idp.testshib.org/idp/shibboleth</saml2:Issuer><saml2p:Status><saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></saml2p:Status><saml2:EncryptedAssertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"><xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="_62d64ca491a287a346272669fbe93191" Type="http://www.w3.org/2001/04/xmlenc#Element">invalid<`)
_, err = Decrypt(testSuite.Key, docStr)
c.Assert(err, ErrorMatches, "malformed XML")
c.Assert(err, ErrorMatches, ".*Premature end of data in tag.*")
docStr = []byte(`<?xml version="1.0" encoding="UTF-8"?>
<X>

View File

@@ -95,7 +95,7 @@ func (testSuite *XmlencRealWorldTest) TestInvalid(c *C) {
c.Assert(err, IsNil)
_, err = Decrypt(testSuite.Key, []byte("<invalid xml"))
c.Assert(err, ErrorMatches, "malformed XML")
c.Assert(err, ErrorMatches, ".*Couldn't find end of Start Tag.*")
_, err = Decrypt(testSuite.Key, []byte("<invalid></invalid>"))
c.Assert(err, ErrorMatches, "xmlSecFindNode cannot find EncryptedData node")
@@ -105,7 +105,7 @@ func (testSuite *XmlencRealWorldTest) TestInvalid(c *C) {
docStr := []byte(`<?xml version="1.0" encoding="UTF-8"?><saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://15661444.ngrok.io/saml2/acs" ID="_59c2431b4916af2018984213940ee675" InResponseTo="id-3d21faf29a101222d740735fa512f161" IssueInstant="2015-11-29T21:29:09.991Z" Version="2.0"><saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://idp.testshib.org/idp/shibboleth</saml2:Issuer><saml2p:Status><saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></saml2p:Status><saml2:EncryptedAssertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"><xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="_62d64ca491a287a346272669fbe93191" Type="http://www.w3.org/2001/04/xmlenc#Element">invalid<`)
_, err = Decrypt(testSuite.Key, docStr)
c.Assert(err, ErrorMatches, "malformed XML")
c.Assert(err, ErrorMatches, ".*Premature end of data in tag.*")
docStr = []byte(`<?xml version="1.0" encoding="UTF-8"?>
<X>

View File

@@ -4,6 +4,7 @@ import (
"C"
"fmt"
"runtime"
"strings"
"github.com/crewjam/errset"
)
@@ -32,8 +33,8 @@ func (e libraryError) Error() string {
e.Message)
}
//export onError
func onError(file *C.char, line C.int, funcName *C.char, errorObject *C.char, errorSubject *C.char, reason C.int, msg *C.char) {
//export onXmlsecError
func onXmlsecError(file *C.char, line C.int, funcName *C.char, errorObject *C.char, errorSubject *C.char, reason C.int, msg *C.char) {
err := libraryError{
FuncName: C.GoString(funcName),
FileName: C.GoString(file),
@@ -46,6 +47,13 @@ func onError(file *C.char, line C.int, funcName *C.char, errorObject *C.char, er
globalErrors[threadID] = append(globalErrors[threadID], err)
}
//export onXmlError
func onXmlError(msg *C.char) {
threadID := getThreadID()
globalErrors[threadID] = append(globalErrors[threadID],
fmt.Errorf("%s", strings.TrimSuffix(C.GoString(msg), "\n")))
}
// startProcessingXML is called whenever we enter a function exported by this package.
// It locks the current goroutine to the current thread and establishes a thread-local
// error object. If the library later calls onError then the error will be appended

View File

@@ -1,13 +1,31 @@
package xmlsec
// onError_cgo is a C function that can be passed to xmlSecErrorsSetCallback which
// in turn invokes the go function onError which captures errors generated by
// libxmlsec.
// #include <stdio.h>
// #include <stdarg.h>
// #include <libxml/parser.h>
// #include <libxml/parserInternals.h>
// #include <libxml/xmlmemory.h>
// #include <xmlsec/xmlsec.h>
// #include <xmlsec/errors.h>
//
// For reasons I do not completely understand, it must be defined in a different
// file from onError.
// void onError_cgo(char *file, int line, char *funcName, char *errorObject, char *errorSubject, int reason, char *msg) {
// onError(file, line, funcName, errorObject, errorSubject, reason, msg);
// void onXmlError(const char *msg); // implemented in go
// void onXmlsecError(const char *file, int line, const char *funcName, const char *errorObject, const char *errorSubject, int reason, const char *msg); // implemented in go
//
// static void onXmlGenericError_cgo(void *ctx, const char *format, ...) {
// char buffer[256];
// va_list args;
// va_start(args, format);
// vsnprintf(buffer, 256, format, args);
// va_end (args);
// onXmlError(buffer);
// }
//
// static void onXmlsecError_cgo(const char *file, int line, const char *funcName, const char *errorObject, const char *errorSubject, int reason, const char *msg) {
// onXmlsecError(file, line, funcName, errorObject, errorSubject, reason, msg);
// }
//
// void captureXmlErrors() {
// xmlSecErrorsSetCallback(onXmlsecError_cgo);
// xmlSetGenericErrorFunc(NULL, onXmlGenericError_cgo);
// }
import "C"

View File

@@ -218,7 +218,7 @@ func (testSuite *XMLDSigTest) TestVerifyFailsWhenMessageModified(c *C) {
func (testSuite *XMLDSigTest) TestInvalidXML(c *C) {
_, err := Sign(testSuite.Key, []byte("<invalid xml"), SignatureOptions{})
c.Assert(err, ErrorMatches, "malformed XML")
c.Assert(err, ErrorMatches, ".*Couldn't find end of Start Tag.*")
_, err = Sign(testSuite.Key, []byte("<invalid></invalid>"), SignatureOptions{})
c.Assert(err, ErrorMatches, "cannot find start node")
@@ -227,7 +227,7 @@ func (testSuite *XMLDSigTest) TestInvalidXML(c *C) {
c.Assert(err, ErrorMatches, "failed to load pem key")
err = Verify(testSuite.Cert, []byte("<invalid xml"), SignatureOptions{})
c.Assert(err, ErrorMatches, "malformed XML")
c.Assert(err, ErrorMatches, ".*Couldn't find end of Start Tag.*")
err = Verify(testSuite.Cert, []byte("<invalid></invalid>"), SignatureOptions{})
c.Assert(err, ErrorMatches, "cannot find start node")

View File

@@ -1,9 +1,6 @@
package xmlsec
import (
"errors"
"unsafe"
)
import "unsafe"
// Note: on mac you need:
// brew install libxmlsec1 libxml2
@@ -30,7 +27,7 @@ import "C"
// }
import "C"
// void onError_cgo(char *file, int line, char *funcName, char *errorObject, char *errorSubject, int reason, char *msg);
// void captureXmlErrors();
import "C"
func init() {
@@ -46,26 +43,26 @@ func init() {
panic("xmlsec crypto initialization failed.")
}
C.xmlSecErrorsSetCallback((C.xmlSecErrorsCallback)(unsafe.Pointer(C.onError_cgo)))
C.captureXmlErrors()
}
func newDoc(buf []byte, idattrs []XMLIDOption) (*C.xmlDoc, error) {
ctx := C.xmlCreateMemoryParserCtxt((*C.char)(unsafe.Pointer(&buf[0])),
C.int(len(buf)))
if ctx == nil {
return nil, errors.New("error creating parser")
return nil, mustPopError()
}
defer C.xmlFreeParserCtxt(ctx)
C.xmlParseDocument(ctx)
if ctx.wellFormed == C.int(0) {
return nil, errors.New("malformed XML")
return nil, mustPopError()
}
doc := ctx.myDoc
if doc == nil {
return nil, errors.New("parse failed")
return nil, mustPopError()
}
for _, idattr := range idattrs {