Exemple #1
0
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, mustPopError()
	}
	defer C.xmlFreeParserCtxt(ctx)

	C.xmlParseDocument(ctx)

	if ctx.wellFormed == C.int(0) {
		return nil, mustPopError()
	}

	doc := ctx.myDoc
	if doc == nil {
		return nil, mustPopError()
	}

	for _, idattr := range idattrs {
		addIDAttr(C.xmlDocGetRootElement(doc),
			idattr.AttributeName, idattr.ElementName, idattr.ElementNamespace)
	}
	return doc, nil
}
Exemple #2
0
func (document *XmlDocument) Root() (element *ElementNode) {
	nodePtr := C.xmlDocGetRootElement(document.Ptr)
	if nodePtr != nil {
		element = NewNode(unsafe.Pointer(nodePtr), document).(*ElementNode)
	}
	return
}
Exemple #3
0
func ParseHTMLString(content string) (*Document, error) {
	d := htmlReadDoc(content, "", "", DefaultHtmlParseFlags)
	root, err := C.xmlDocGetRootElement(d)
	if err != nil || root == nil {
		C.xmlFreeDoc(d)
		return nil, err
	}

	return &Document{ptr: d, root: root}, nil
}
Exemple #4
0
// Decrypt finds the first encrypted part of doc, decrypts it using
// privateKey and returns the plaintext of the embedded document.
func Decrypt(privateKey []byte, doc []byte) ([]byte, error) {
	startProcessingXML()
	defer stopProcessingXML()

	keysMngr := C.xmlSecKeysMngrCreate()
	if keysMngr == nil {
		return nil, popError()
	}
	defer C.xmlSecKeysMngrDestroy(keysMngr)

	if rv := C.xmlSecCryptoAppDefaultKeysMngrInit(keysMngr); rv < 0 {
		return nil, popError()
	}

	key := C.xmlSecCryptoAppKeyLoadMemory(
		(*C.xmlSecByte)(unsafe.Pointer(&privateKey[0])),
		C.xmlSecSize(len(privateKey)),
		C.xmlSecKeyDataFormatPem,
		nil, nil, nil)
	if key == nil {
		return nil, popError()
	}

	if rv := C.xmlSecCryptoAppDefaultKeysMngrAdoptKey(keysMngr, key); rv < 0 {
		return nil, popError()
	}

	parsedDoc, err := newDoc(doc, nil)
	if err != nil {
		return nil, err
	}
	defer closeDoc(parsedDoc)

	// create encryption context
	encCtx := C.xmlSecEncCtxCreate(keysMngr)
	if encCtx == nil {
		return nil, popError()
	}
	defer C.xmlSecEncCtxDestroy(encCtx)

	encDataNode := C.xmlSecFindNode(C.xmlDocGetRootElement(parsedDoc),
		(*C.xmlChar)(unsafe.Pointer(&C.xmlSecNodeEncryptedData)),
		(*C.xmlChar)(unsafe.Pointer(&C.xmlSecEncNs)))
	if encDataNode == nil {
		return nil, fmt.Errorf("xmlSecFindNode cannot find EncryptedData node")
	}

	// decrypt the data
	if rv := C.xmlSecEncCtxDecrypt(encCtx, encDataNode); rv < 0 {
		return nil, popError()
	}
	encDataNode = nil // the template is inserted in the doc, so we don't own it

	return dumpDoc(parsedDoc), nil
}
Exemple #5
0
// xmlXPathEvalExpression shim around the libxml2 function of the same name
func (xp *Xp) xmlXPathEvalExpression(context *C.xmlNode, path string) (xmlXPathObject *C.xmlXPathObject) {
	if context == nil {
		context = C.xmlDocGetRootElement(xp.doc)
	}
	C.xmlXPathSetContextNode(context, xp.xpathCtx)

	Cpath := unsafe.Pointer(C.CString(path))
	defer C.free(Cpath)
	xmlXPathObject = C.xmlXPathEvalExpression((*C.xmlChar)(Cpath), xp.xpathCtx)
	return
}
Exemple #6
0
func (d *Document) DocumentElement() Node {
	if d.ptr == nil {
		return nil
	}

	if d.root == nil {
		n := C.xmlDocGetRootElement(d.ptr)
		if n == nil {
			return nil
		}
		d.root = n
	}

	return wrapToNode(d.root)
}
Exemple #7
0
// CreateElementNS Create an element with the given namespace
func (xp *Xp) createElementNS(prefix, element string, context *C.xmlNode, before *C.xmlNode) (newcontext *C.xmlNode) {

	ns := C.xmlNewNs(nil, namespaces[prefix].ns_uri, namespaces[prefix].prefix) // candidate for cache ...
	if ns == nil {
		panic("ns is nil")
	}
	celement := unsafe.Pointer(C.CString(element))
	newelement := C.xmlNewDocNode(xp.doc, ns, (*C.xmlChar)(celement), nil)
	C.free(celement)

	if before != nil {
		newcontext = C.xmlAddPrevSibling(before, newelement)
	} else {
		if context == nil {
			context = C.xmlDocGetRootElement(xp.doc)
		}
		newcontext = C.xmlAddChild(context, newelement)
	}
	return
}
Exemple #8
0
// Sign returns a version of doc signed with key according to
// the XMLDSIG standard. doc is a template document meaning
// that it contains an `http://www.w3.org/2000/09/xmldsig#Signature`
// element whose properties define how and what to sign.
func Sign(key []byte, doc []byte, opts SignatureOptions) ([]byte, error) {
	startProcessingXML()
	defer stopProcessingXML()

	ctx := C.xmlSecDSigCtxCreate(nil)
	if ctx == nil {
		return nil, errors.New("failed to create signature context")
	}
	defer C.xmlSecDSigCtxDestroy(ctx)

	ctx.signKey = C.xmlSecCryptoAppKeyLoadMemory(
		(*C.xmlSecByte)(unsafe.Pointer(&key[0])),
		C.xmlSecSize(len(key)),
		C.xmlSecKeyDataFormatPem,
		nil, nil, nil)
	if ctx.signKey == nil {
		return nil, errors.New("failed to load pem key")
	}

	parsedDoc, err := newDoc(doc, opts.XMLID)
	if err != nil {
		return nil, err
	}
	defer closeDoc(parsedDoc)

	node := C.xmlSecFindNode(C.xmlDocGetRootElement(parsedDoc),
		(*C.xmlChar)(unsafe.Pointer(&C.xmlSecNodeSignature)),
		(*C.xmlChar)(unsafe.Pointer(&C.xmlSecDSigNs)))
	if node == nil {
		return nil, errors.New("cannot find start node")
	}

	if rv := C.xmlSecDSigCtxSign(ctx, node); rv < 0 {
		return nil, errors.New("failed to sign")
	}

	return dumpDoc(parsedDoc), nil

}
Exemple #9
0
func wrapDocument(n *C.xmlDoc) *Document {
	r := C.xmlDocGetRootElement(n) // XXX Should check for n == nil
	return &Document{ptr: n, root: r}
}
Exemple #10
0
// Encrypt encrypts the XML document to publicKey and returns the encrypted
// document.
func Encrypt(publicKey, doc []byte, opts EncryptOptions) ([]byte, error) {
	startProcessingXML()
	defer stopProcessingXML()

	keysMngr := C.xmlSecKeysMngrCreate()
	if keysMngr == nil {
		return nil, mustPopError()
	}
	defer C.xmlSecKeysMngrDestroy(keysMngr)

	if rv := C.xmlSecCryptoAppDefaultKeysMngrInit(keysMngr); rv < 0 {
		return nil, mustPopError()
	}

	key := C.xmlSecCryptoAppKeyLoadMemory(
		(*C.xmlSecByte)(unsafe.Pointer(&publicKey[0])),
		C.xmlSecSize(len(publicKey)),
		C.xmlSecKeyDataFormatCertPem,
		nil, nil, nil)
	if key == nil {
		return nil, mustPopError()
	}

	if rv := C.xmlSecCryptoAppKeyCertLoadMemory(key,
		(*C.xmlSecByte)(unsafe.Pointer(&publicKey[0])),
		C.xmlSecSize(len(publicKey)),
		C.xmlSecKeyDataFormatCertPem); rv < 0 {
		C.xmlSecKeyDestroy(key)
		return nil, mustPopError()
	}

	if rv := C.xmlSecCryptoAppDefaultKeysMngrAdoptKey(keysMngr, key); rv < 0 {
		return nil, mustPopError()
	}

	parsedDoc, err := newDoc(doc, nil)
	if err != nil {
		return nil, err
	}
	defer closeDoc(parsedDoc)

	var sessionCipherTransform C.xmlSecTransformId
	switch opts.SessionCipher {
	case DefaultSessionCipher:
		sessionCipherTransform = C.MY_xmlSecTransformAes256CbcId()
	case Aes256Cbc:
		sessionCipherTransform = C.MY_xmlSecTransformAes256CbcId()
	case Aes192Cbc:
		sessionCipherTransform = C.MY_xmlSecTransformAes192CbcId()
	case Aes128Cbc:
		sessionCipherTransform = C.MY_xmlSecTransformAes128CbcId()
	case Des3Cbc:
		sessionCipherTransform = C.MY_xmlSecTransformDes3CbcId()
	default:
		return nil, errInvalidAlgorithm
	}

	// create encryption template to encrypt XML file and replace
	// its content with encryption result
	encDataNode := C.xmlSecTmplEncDataCreate(parsedDoc, sessionCipherTransform,
		nil, (*C.xmlChar)(unsafe.Pointer(&C.xmlSecTypeEncElement)), nil, nil)
	if encDataNode == nil {
		return nil, mustPopError()
	}
	defer func() {
		if encDataNode != nil {
			C.xmlFreeNode(encDataNode)
			encDataNode = nil
		}
	}()

	// we want to put encrypted data in the <enc:CipherValue/> node
	if C.xmlSecTmplEncDataEnsureCipherValue(encDataNode) == nil {
		return nil, mustPopError()
	}

	// add <dsig:KeyInfo/>
	keyInfoNode := C.xmlSecTmplEncDataEnsureKeyInfo(encDataNode, nil)
	if keyInfoNode == nil {
		return nil, mustPopError()
	}

	// add <enc:EncryptedKey/> to store the encrypted session key
	var cipherTransform C.xmlSecTransformId
	switch opts.Cipher {
	case DefaultCipher:
		cipherTransform = C.MY_xmlSecTransformRsaOaepId()
	case RsaOaep:
		cipherTransform = C.MY_xmlSecTransformRsaOaepId()
	case RsaPkcs1:
		cipherTransform = C.MY_xmlSecTransformRsaPkcs1Id()
	}
	encKeyNode := C.xmlSecTmplKeyInfoAddEncryptedKey(keyInfoNode, cipherTransform, nil, nil, nil)
	if encKeyNode == nil {
		return nil, mustPopError()
	}

	// we want to put encrypted key in the <enc:CipherValue/> node
	if C.xmlSecTmplEncDataEnsureCipherValue(encKeyNode) == nil {
		return nil, mustPopError()
	}

	// add <dsig:KeyInfo/> and <dsig:KeyName/> nodes to <enc:EncryptedKey/>
	keyInfoNode2 := C.xmlSecTmplEncDataEnsureKeyInfo(encKeyNode, nil)
	if keyInfoNode2 == nil {
		return nil, mustPopError()
	}

	// Add a DigestMethod element to the encryption method node
	{
		encKeyMethod := C.xmlSecTmplEncDataGetEncMethodNode(encKeyNode)
		var algorithm *C.xmlChar
		switch opts.DigestAlgorithm {
		case Sha512:
			algorithm = constSha512
		case Sha384:
			algorithm = constSha384
		case Sha256:
			algorithm = constSha256
		case Sha1:
			algorithm = constSha1
		case DefaultDigestAlgorithm:
			algorithm = constSha1
		default:
			return nil, errInvalidAlgorithm
		}
		node := C.xmlSecAddChild(encKeyMethod, constDigestMethod, constDsigNamespace)
		C.xmlSetProp(node, constAlgorithm, algorithm)
	}

	// add our certificate to KeyInfoNode
	x509dataNode := C.xmlSecTmplKeyInfoAddX509Data(keyInfoNode2)
	if x509dataNode == nil {
		return nil, mustPopError()
	}
	if dataNode := C.xmlSecTmplX509DataAddCertificate(x509dataNode); dataNode == nil {
		return nil, mustPopError()
	}

	// create encryption context
	var encCtx = C.xmlSecEncCtxCreate(keysMngr)
	if encCtx == nil {
		return nil, mustPopError()
	}
	defer C.xmlSecEncCtxDestroy(encCtx)

	// generate a key of the appropriate type
	switch opts.SessionCipher {
	case DefaultSessionCipher:
		encCtx.encKey = C.xmlSecKeyGenerate(C.MY_xmlSecKeyDataAesId(), 256,
			C.xmlSecKeyDataTypeSession)
	case Aes128Cbc:
		encCtx.encKey = C.xmlSecKeyGenerate(C.MY_xmlSecKeyDataAesId(), 128,
			C.xmlSecKeyDataTypeSession)
	case Aes192Cbc:
		encCtx.encKey = C.xmlSecKeyGenerate(C.MY_xmlSecKeyDataAesId(), 192,
			C.xmlSecKeyDataTypeSession)
	case Aes256Cbc:
		encCtx.encKey = C.xmlSecKeyGenerate(C.MY_xmlSecKeyDataAesId(), 256,
			C.xmlSecKeyDataTypeSession)
	case Des3Cbc:
		encCtx.encKey = C.xmlSecKeyGenerate(C.MY_xmlSecKeyDataDesId(), 192,
			C.xmlSecKeyDataTypeSession)
	default:
		return nil, errInvalidAlgorithm
	}
	if encCtx.encKey == nil {
		return nil, mustPopError()
	}

	// encrypt the data
	if rv := C.xmlSecEncCtxXmlEncrypt(encCtx, encDataNode, C.xmlDocGetRootElement(parsedDoc)); rv < 0 {
		return nil, mustPopError()
	}
	encDataNode = nil // the template is inserted in the doc, so we don't own it

	return dumpDoc(parsedDoc), nil
}
Exemple #11
0
// Verify checks that the signature in doc is valid according
// to the XMLDSIG specification. publicKey is the public part of
// the key used to sign doc. If the signature is not correct,
// this function returns ErrVerificationFailed.
func Verify(publicKey []byte, doc []byte, opts SignatureOptions) error {
	startProcessingXML()
	defer stopProcessingXML()

	keysMngr := C.xmlSecKeysMngrCreate()
	if keysMngr == nil {
		return mustPopError()
	}
	defer C.xmlSecKeysMngrDestroy(keysMngr)

	if rv := C.xmlSecCryptoAppDefaultKeysMngrInit(keysMngr); rv < 0 {
		return mustPopError()
	}

	key := C.xmlSecCryptoAppKeyLoadMemory(
		(*C.xmlSecByte)(unsafe.Pointer(&publicKey[0])),
		C.xmlSecSize(len(publicKey)),
		C.xmlSecKeyDataFormatCertPem,
		nil, nil, nil)
	if key == nil {
		return mustPopError()
	}

	if rv := C.xmlSecCryptoAppKeyCertLoadMemory(key,
		(*C.xmlSecByte)(unsafe.Pointer(&publicKey[0])),
		C.xmlSecSize(len(publicKey)),
		C.xmlSecKeyDataFormatCertPem); rv < 0 {
		C.xmlSecKeyDestroy(key)
		return mustPopError()
	}

	if rv := C.xmlSecCryptoAppDefaultKeysMngrAdoptKey(keysMngr, key); rv < 0 {
		return mustPopError()
	}

	dsigCtx := C.xmlSecDSigCtxCreate(keysMngr)
	if dsigCtx == nil {
		return mustPopError()
	}
	defer C.xmlSecDSigCtxDestroy(dsigCtx)

	parsedDoc, err := newDoc(doc, opts.XMLID)
	if err != nil {
		return err
	}
	defer closeDoc(parsedDoc)

	node := C.xmlSecFindNode(C.xmlDocGetRootElement(parsedDoc),
		(*C.xmlChar)(unsafe.Pointer(&C.xmlSecNodeSignature)),
		(*C.xmlChar)(unsafe.Pointer(&C.xmlSecDSigNs)))
	if node == nil {
		return errors.New("cannot find start node")
	}

	if rv := C.xmlSecDSigCtxVerify(dsigCtx, node); rv < 0 {
		return ErrVerificationFailed
	}

	if dsigCtx.status != xmlSecDSigStatusSucceeded {
		return ErrVerificationFailed
	}
	return nil
}
Exemple #12
0
func XmlDocGetRootElement(d *C.xmlDoc) *C.xmlNode {
	return C.xmlDocGetRootElement(d)
}
Exemple #13
0
// xmlDocGetRootElement
func (doc *Document) Root() *Node {
	cnode := C.xmlDocGetRootElement(doc.Ptr)
	return makeNode(cnode)
}
Exemple #14
0
func (xp *Xp) DocGetRootElement() (res *C.xmlNode) {
	return C.xmlDocGetRootElement(xp.doc)
}
Exemple #15
0
func XmlDocGetRootElement(doc unsafe.Pointer) unsafe.Pointer {
	cnode := C.xmlDocGetRootElement(C.xmlDocPtr(doc))
	return unsafe.Pointer(cnode)
}