示例#1
0
func (document *XmlDocument) Free() {
	//must clear the fragments first
	//because the nodes are put in the unlinked list
	if document.fragments != nil {
		for _, fragment := range document.fragments {
			fragment.Remove()
		}
	}
	document.fragments = nil
	var p *C.xmlNode
	if document.UnlinkedNodes != nil {
		for p, _ = range document.UnlinkedNodes {
			C.xmlFreeNode(p)
		}
	}
	document.UnlinkedNodes = nil
	if document.XPathCtx != nil {
		document.XPathCtx.Free()
		document.XPathCtx = nil
	}
	if document.Ptr != nil {
		C.xmlFreeDoc(document.Ptr)
		document.Ptr = nil
	}
}
示例#2
0
func (document *XmlDocument) Free() {
	//must free the xpath context before freeing the fragments or unlinked nodes
	//otherwise, it causes memory leaks and crashes when dealing with very large documents (a few MB)
	if document.XPathCtx != nil {
		document.XPathCtx.Free()
		document.XPathCtx = nil
	}
	//must clear the fragments first
	//because the nodes are put in the unlinked list
	if document.fragments != nil {
		for _, fragment := range document.fragments {
			fragment.Remove()
		}
	}
	document.fragments = nil
	var p *C.xmlNode
	if document.UnlinkedNodes != nil {
		for p, _ = range document.UnlinkedNodes {
			C.xmlFreeNode(p)
		}
	}
	document.UnlinkedNodes = nil
	if document.Ptr != nil {
		C.xmlFreeDoc(document.Ptr)
		document.Ptr = nil
	}
}
示例#3
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
}
示例#4
0
// xmlFreeNode
func (node *Node) Free() {
	C.xmlFreeNode(node.Ptr)
	node.Ptr = nil
}