Beispiel #1
0
func (xmlNode *XmlNode) addChild(node Node) (err error) {
	nodeType := node.NodeType()
	if nodeType == XML_DOCUMENT_NODE || nodeType == XML_HTML_DOCUMENT_NODE {
		err = ERR_CANNOT_MAKE_DUCMENT_AS_CHILD
		return
	}
	nodePtr := node.NodePtr()
	if xmlNode.NodePtr() == nodePtr {
		return
	}
	ret := xmlNode.isAccestor(nodePtr)
	if ret < 0 {
		return
	} else if ret == 0 {
		if !xmlNode.Document.RemoveUnlinkedNode(nodePtr) {
			C.xmlUnlinkNodeWithCheck((*C.xmlNode)(nodePtr))
		}
		C.xmlAddChild(xmlNode.Ptr, (*C.xmlNode)(nodePtr))
	} else if ret > 0 {
		node.Remove()
	}

	/*
		childPtr := C.xmlAddChild(xmlNode.Ptr, (*C.xmlNode)(nodePtr))
		if nodeType == XML_TEXT_NODE && childPtr != (*C.xmlNode)(nodePtr) {
			//check the retured pointer
			//if it is not the text node just added, it means that the text node is freed because it has merged into other nodes
			//then we should invalid this node, because we do not want to have a dangling pointer
			node.Remove()
		}
	*/
	return
}
Beispiel #2
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
}
Beispiel #3
0
func (xmlNode *XmlNode) addChild(node Node) (err error) {
	nodeType := node.NodeType()
	if nodeType == XML_DOCUMENT_NODE || nodeType == XML_HTML_DOCUMENT_NODE {
		err = ERR_CANNOT_MAKE_DUCMENT_AS_CHILD
		return
	}
	nodePtr := node.NodePtr()
	parentPtr := xmlNode.Ptr.parent

	if C.xmlNodePtrCheck(unsafe.Pointer(parentPtr)) == C.int(0) {
		return
	}

	isNodeAccestor := false
	for ; parentPtr != nil; parentPtr = parentPtr.parent {
		if C.xmlNodePtrCheck(unsafe.Pointer(parentPtr)) == C.int(0) {
			return
		}
		p := unsafe.Pointer(parentPtr)
		if p == nodePtr {
			isNodeAccestor = true
		}
	}
	if !isNodeAccestor {
		C.xmlUnlinkNode((*C.xmlNode)(nodePtr))
		C.xmlAddChild(xmlNode.Ptr, (*C.xmlNode)(nodePtr))
	} else {
		node.Remove()
	}

	/*
		childPtr := C.xmlAddChild(xmlNode.Ptr, (*C.xmlNode)(nodePtr))
		if nodeType == XML_TEXT_NODE && childPtr != (*C.xmlNode)(nodePtr) {
			//check the retured pointer
			//if it is not the text node just added, it means that the text node is freed because it has merged into other nodes
			//then we should invalid this node, because we do not want to have a dangling pointer
			node.Remove()
		}
	*/
	return
}
Beispiel #4
0
func (xmlNode *XmlNode) addChild(node Node) (err error) {
	nodeType := node.NodeType()
	if nodeType == XML_DOCUMENT_NODE || nodeType == XML_HTML_DOCUMENT_NODE {
		err = ERR_CANNOT_MAKE_DUCMENT_AS_CHILD
		return
	}
	nodePtr := node.NodePtr()
	if xmlNode.NodePtr() == nodePtr {
		return
	}
	ret := xmlNode.isAccestor(nodePtr)
	if ret < 0 {
		return
	} else if ret == 0 {
		if !xmlNode.Document.RemoveUnlinkedNode(nodePtr) {
			C.xmlUnlinkNodeWithCheck((*C.xmlNode)(nodePtr))
		}
		C.xmlAddChild(xmlNode.Ptr, (*C.xmlNode)(nodePtr))
	} else if ret > 0 {
		node.Remove()
	}

	return
}
Beispiel #5
0
func (n *xmlNode) AddChild(child Node) {
	C.xmlAddChild(n.ptr, (*C.xmlNode)(child.pointer()))
}
Beispiel #6
0
// xmlAddChild
func (parent *Node) AddChild(cur *Node) *Node {
	return makeNode(C.xmlAddChild(parent.Ptr, cur.Ptr))
}
Beispiel #7
0
// NewResponse - create a new response using the supplied metadata and resp. authnrequest and response for filling out the fields
// The response is primarily for the attributes, but other fields is eg. the AuthnContextClassRef is also drawn from it
func NewResponse(params IdAndTiming, idpmd, spmd, authnrequest, sourceResponse *Xp) (response *Xp) {
	template := []byte(`<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
                ID=""
                Version="2.0"
                IssueInstant=""
                InResponseTo=""
                Destination=""
                >
    <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"></saml:Issuer>
    <samlp:Status>
        <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
    </samlp:Status>
    <saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    xmlns:xs="http://www.w3.org/2001/XMLSchema"
                    xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
                    ID=""
                    Version="2.0"
                    IssueInstant=""
                    >
        <saml:Issuer></saml:Issuer>
        <saml:Subject>
            <saml:NameID SPNameQualifier=""
                         Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
                         ></saml:NameID>
            <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
                <saml:SubjectConfirmationData NotOnOrAfter=""
                                              Recipient=""
                                              InResponseTo=""
                                              />
            </saml:SubjectConfirmation>
        </saml:Subject>
        <saml:Conditions NotBefore=""
                         NotOnOrAfter=""
                         >
            <saml:AudienceRestriction>
                <saml:Audience></saml:Audience>
            </saml:AudienceRestriction>
        </saml:Conditions>
        <saml:AuthnStatement AuthnInstant=""
                             SessionNotOnOrAfter=""
                             SessionIndex=""
                             >
            <saml:AuthnContext>
                <saml:AuthnContextClassRef></saml:AuthnContextClassRef>
            </saml:AuthnContext>
        </saml:AuthnStatement>
        <saml:AttributeStatement xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema">
        </saml:AttributeStatement>
    </saml:Assertion>
</samlp:Response>`)

	response = NewXp(template)

	issueInstant := params.Now.Format(xsDateTime)
	assertionIssueInstant := params.Now.Format(xsDateTime)
	assertionNotOnOrAfter := params.Now.Add(params.Slack).Format(xsDateTime)
	sessionNotOnOrAfter := params.Now.Add(params.Sessionduration).Format(xsDateTime)
	msgid := params.Id
	if msgid == "" {
		msgid = Id()
	}
	assertionID := params.Assertionid
	if assertionID == "" {
		assertionID = Id()
	}

	spEntityID := spmd.Query1(nil, `/md:EntityDescriptor/@entityID`)
	idpEntityID := idpmd.Query1(nil, `/md:EntityDescriptor/@entityID`)

	acs := authnrequest.Query1(nil, "@AssertionConsumerServiceURL")
	response.QueryDashP(nil, "./@ID", msgid, nil)
	response.QueryDashP(nil, "./@IssueInstant", issueInstant, nil)
	response.QueryDashP(nil, "./@InResponseTo", authnrequest.Query1(nil, "@ID"), nil)
	response.QueryDashP(nil, "./@Destination", acs, nil)
	response.QueryDashP(nil, "./saml:Issuer", idpEntityID, nil)

	assertion := response.Query(nil, "saml:Assertion")[0]
	response.QueryDashP(assertion, "@ID", assertionID, nil)
	response.QueryDashP(assertion, "@IssueInstant", assertionIssueInstant, nil)
	response.QueryDashP(assertion, "saml:Issuer", idpEntityID, nil)

	nameid := response.Query(assertion, "saml:Subject/saml:NameID")[0]
	response.QueryDashP(nameid, "@SPNameQualifier", spEntityID, nil)
	response.QueryDashP(nameid, "@Format", sourceResponse.Query1(nil, "//saml:NameID/@Format"), nil)
	response.QueryDashP(nameid, ".", sourceResponse.Query1(nil, "//saml:NameID"), nil)

	subjectconfirmationdata := response.Query(assertion, "saml:Subject/saml:SubjectConfirmation/saml:SubjectConfirmationData")[0]
	response.QueryDashP(subjectconfirmationdata, "@NotOnOrAfter", assertionNotOnOrAfter, nil)
	response.QueryDashP(subjectconfirmationdata, "@Recipient", acs, nil)
	response.QueryDashP(subjectconfirmationdata, "@InResponseTo", authnrequest.Query1(nil, "@ID"), nil)

	conditions := response.Query(assertion, "saml:Conditions")[0]
	response.QueryDashP(conditions, "@NotBefore", assertionIssueInstant, nil)
	response.QueryDashP(conditions, "@NotOnOrAfter", assertionNotOnOrAfter, nil)
	response.QueryDashP(conditions, "saml:AudienceRestriction/saml:Audience", spEntityID, nil)

	authstatement := response.Query(assertion, "saml:AuthnStatement")[0]
	response.QueryDashP(authstatement, "@AuthnInstant", assertionIssueInstant, nil)
	response.QueryDashP(authstatement, "@SessionNotOnOrAfter", sessionNotOnOrAfter, nil)
	response.QueryDashP(authstatement, "@SessionIndex", "missing", nil)
	response.QueryDashP(authstatement, "saml:AuthnContext/saml:AuthnContextClassRef", sourceResponse.Query1(nil, "//saml:AuthnContextClassRef"), nil)

	sourceResponse = NewXp([]byte(sourceResponse.Pp()))
	sourceAttributes := sourceResponse.Query(nil, `//saml:AttributeStatement/saml:Attribute`)
	destinationAttributes := response.Query(nil, `//saml:AttributeStatement`)[0]

	attrcache := map[string]*C.xmlNode{}
	for _, attr := range sourceAttributes {
		attrcache[attr.GetAttr("Name")] = attr
		attrcache[attr.GetAttr("FriendlyName")] = attr
	}

	//requestedAttributes := spmd.Query(nil, `./md:SPSSODescriptor/md:AttributeConsumingService[1]/md:RequestedAttribute[@isRequired=true()]`)
	requestedAttributes := spmd.Query(nil, `./md:SPSSODescriptor/md:AttributeConsumingService[1]/md:RequestedAttribute`)

	for _, requestedAttribute := range requestedAttributes {
		// for _, requestedAttribute := range sourceResponse.Query(nil, `//saml:Attribute`) {
		name := requestedAttribute.GetAttr("Name")
		friendlyname := requestedAttribute.GetAttr("FriendlyName")
		//nameFormat := requestedAttribute.GetAttr("NameFormat")
		//log.Println("requestedattribute:", name, nameFormat)
		// look for a requested attribute with the requested nameformat
		// TO-DO - xpath escape name and nameFormat
		// TO-Do - value filtering
		//attributes := sourceResponse.Query(sourceAttributes[0], `saml:Attribute[@Name="`+name+`" or @Name="`+friendlyname+`" or @FriendlyName="`+friendlyname+`"]`)
		//log.Println("src attrs", len(attributes), `saml:Attribute[@Name="`+name+`" or @Name="`+friendlyname+`" or @FriendlyName="`+friendlyname+`"]`)

		//attributes := sourceResponse.Query(sourceAttributes, `saml:Attribute[@Name="`+name+`"]`)
		attribute := attrcache[name]
		if attribute == nil {
			attribute = attrcache[friendlyname]
			if attribute == nil {
				continue
			}
		}
		//		for _, attribute := range sourceAttributes {
		newAttribute := C.xmlAddChild(destinationAttributes, C.xmlDocCopyNode(attribute, response.doc, 2))
		allowedValues := spmd.Query(requestedAttribute, `saml:AttributeValue`)
		allowedValuesMap := make(map[string]bool)
		for _, value := range allowedValues {
			allowedValuesMap[spmd.NodeGetContent(value)] = true
		}
		for _, valueNode := range sourceResponse.Query(attribute, `saml:AttributeValue`) {
			value := sourceResponse.NodeGetContent(valueNode)
			if len(allowedValues) == 0 || allowedValuesMap[value] {
				C.xmlAddChild(newAttribute, C.xmlDocCopyNode(valueNode, response.doc, 1))
			}
		}
		//		}
	}
	return
}
Beispiel #8
0
func (destination *C.xmlNode) AddChild(source *C.xmlNode) (res *C.xmlNode) {
	res = C.xmlAddChild(destination, source)
	return
}
Beispiel #9
0
// NewXpFromNode creates a new *Xp from a node (subtree) from another *Xp
func NewXpFromNode(node *C.xmlNode) *Xp {
	xp := NewXp(nil)
	C.xmlAddChild((*C.xmlNode)(unsafe.Pointer(xp.doc)), C.xmlDocCopyNode(node, xp.doc, 1))
	return xp
}
Beispiel #10
0
func XmlAddChild(node unsafe.Pointer, child unsafe.Pointer) {
	C.xmlAddChild((*C.xmlNode)(node), (*C.xmlNode)(child))
}