mirror of https://github.com/dexidp/dex.git
9 changed files with 536 additions and 262 deletions
@ -0,0 +1,98 @@
|
||||
package etreeutils |
||||
|
||||
import ( |
||||
"sort" |
||||
"strings" |
||||
|
||||
"github.com/beevik/etree" |
||||
) |
||||
|
||||
// TransformExcC14n transforms the passed element into xml-exc-c14n form.
|
||||
func TransformExcC14n(el *etree.Element, inclusiveNamespacesPrefixList string) error { |
||||
prefixes := strings.Fields(inclusiveNamespacesPrefixList) |
||||
prefixSet := make(map[string]struct{}, len(prefixes)) |
||||
|
||||
for _, prefix := range prefixes { |
||||
prefixSet[prefix] = struct{}{} |
||||
} |
||||
|
||||
err := transformExcC14n(DefaultNSContext, EmptyNSContext, el, prefixSet) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
return nil |
||||
} |
||||
|
||||
func transformExcC14n(ctx, declared NSContext, el *etree.Element, inclusiveNamespaces map[string]struct{}) error { |
||||
scope, err := ctx.SubContext(el) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
visiblyUtilizedPrefixes := map[string]struct{}{ |
||||
el.Space: struct{}{}, |
||||
} |
||||
|
||||
filteredAttrs := []etree.Attr{} |
||||
|
||||
// Filter out all namespace declarations
|
||||
for _, attr := range el.Attr { |
||||
switch { |
||||
case attr.Space == xmlnsPrefix: |
||||
if _, ok := inclusiveNamespaces[attr.Key]; ok { |
||||
visiblyUtilizedPrefixes[attr.Key] = struct{}{} |
||||
} |
||||
|
||||
case attr.Space == defaultPrefix && attr.Key == xmlnsPrefix: |
||||
if _, ok := inclusiveNamespaces[defaultPrefix]; ok { |
||||
visiblyUtilizedPrefixes[defaultPrefix] = struct{}{} |
||||
} |
||||
|
||||
default: |
||||
if attr.Space != defaultPrefix { |
||||
visiblyUtilizedPrefixes[attr.Space] = struct{}{} |
||||
} |
||||
|
||||
filteredAttrs = append(filteredAttrs, attr) |
||||
} |
||||
} |
||||
|
||||
el.Attr = filteredAttrs |
||||
|
||||
declared = declared.Copy() |
||||
|
||||
// Declare all visibly utilized prefixes that are in-scope but haven't
|
||||
// been declared in the canonicalized form yet. These might have been
|
||||
// declared on this element but then filtered out above, or they might
|
||||
// have been declared on an ancestor (before canonicalization) which
|
||||
// didn't visibly utilize and thus had them removed.
|
||||
for prefix := range visiblyUtilizedPrefixes { |
||||
// Skip redundant declarations - they have to already have the same
|
||||
// value.
|
||||
if declaredNamespace, ok := declared.prefixes[prefix]; ok { |
||||
if value, ok := scope.prefixes[prefix]; ok && declaredNamespace == value { |
||||
continue |
||||
} |
||||
} |
||||
|
||||
namespace, err := scope.LookupPrefix(prefix) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
el.Attr = append(el.Attr, declared.declare(prefix, namespace)) |
||||
} |
||||
|
||||
sort.Sort(SortedAttrs(el.Attr)) |
||||
|
||||
// Transform child elements
|
||||
for _, child := range el.ChildElements() { |
||||
err := transformExcC14n(scope, declared, child, inclusiveNamespaces) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
} |
||||
|
||||
return nil |
||||
} |
||||
@ -0,0 +1,43 @@
|
||||
package etreeutils |
||||
|
||||
import ( |
||||
"encoding/xml" |
||||
|
||||
"github.com/beevik/etree" |
||||
) |
||||
|
||||
// NSUnmarshalElement unmarshals the passed etree Element into the value pointed to by
|
||||
// v using encoding/xml in the context of the passed NSContext. If v implements
|
||||
// ElementKeeper, SetUnderlyingElement will be called on v with a reference to el.
|
||||
func NSUnmarshalElement(ctx NSContext, el *etree.Element, v interface{}) error { |
||||
detatched, err := NSDetatch(ctx, el) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
doc := etree.NewDocument() |
||||
doc.AddChild(detatched) |
||||
data, err := doc.WriteToBytes() |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
err = xml.Unmarshal(data, v) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
switch v := v.(type) { |
||||
case ElementKeeper: |
||||
v.SetUnderlyingElement(el) |
||||
} |
||||
|
||||
return nil |
||||
} |
||||
|
||||
// ElementKeeper should be implemented by types which will be passed to
|
||||
// UnmarshalElement, but wish to keep a reference
|
||||
type ElementKeeper interface { |
||||
SetUnderlyingElement(*etree.Element) |
||||
UnderlyingElement() *etree.Element |
||||
} |
||||
@ -0,0 +1,93 @@
|
||||
package types |
||||
|
||||
import ( |
||||
"encoding/xml" |
||||
|
||||
"github.com/beevik/etree" |
||||
) |
||||
|
||||
type InclusiveNamespaces struct { |
||||
XMLName xml.Name `xml:"http://www.w3.org/2001/10/xml-exc-c14n# InclusiveNamespaces"` |
||||
PrefixList string `xml:"PrefixList,attr"` |
||||
} |
||||
|
||||
type Transform struct { |
||||
XMLName xml.Name `xml:"http://www.w3.org/2000/09/xmldsig# Transform"` |
||||
Algorithm string `xml:"Algorithm,attr"` |
||||
InclusiveNamespaces *InclusiveNamespaces `xml:"InclusiveNamespaces"` |
||||
} |
||||
|
||||
type Transforms struct { |
||||
XMLName xml.Name `xml:"http://www.w3.org/2000/09/xmldsig# Transforms"` |
||||
Transforms []Transform `xml:"Transform"` |
||||
} |
||||
|
||||
type DigestMethod struct { |
||||
XMLName xml.Name `xml:"http://www.w3.org/2000/09/xmldsig# DigestMethod"` |
||||
Algorithm string `xml:"Algorithm,attr"` |
||||
} |
||||
|
||||
type Reference struct { |
||||
XMLName xml.Name `xml:"http://www.w3.org/2000/09/xmldsig# Reference"` |
||||
URI string `xml:"URI,attr"` |
||||
DigestValue string `xml:"DigestValue"` |
||||
DigestAlgo DigestMethod `xml:"DigestMethod"` |
||||
Transforms Transforms `xml:"Transforms"` |
||||
} |
||||
|
||||
type CanonicalizationMethod struct { |
||||
XMLName xml.Name `xml:"http://www.w3.org/2000/09/xmldsig# CanonicalizationMethod"` |
||||
Algorithm string `xml:"Algorithm,attr"` |
||||
} |
||||
|
||||
type SignatureMethod struct { |
||||
XMLName xml.Name `xml:"http://www.w3.org/2000/09/xmldsig# SignatureMethod"` |
||||
Algorithm string `xml:"Algorithm,attr"` |
||||
} |
||||
|
||||
type SignedInfo struct { |
||||
XMLName xml.Name `xml:"http://www.w3.org/2000/09/xmldsig# SignedInfo"` |
||||
CanonicalizationMethod CanonicalizationMethod `xml:"CanonicalizationMethod"` |
||||
SignatureMethod SignatureMethod `xml:"SignatureMethod"` |
||||
References []Reference `xml:"Reference"` |
||||
} |
||||
|
||||
type SignatureValue struct { |
||||
XMLName xml.Name `xml:"http://www.w3.org/2000/09/xmldsig# SignatureValue"` |
||||
Data string `xml:",chardata"` |
||||
} |
||||
|
||||
type KeyInfo struct { |
||||
XMLName xml.Name `xml:"http://www.w3.org/2000/09/xmldsig# KeyInfo"` |
||||
X509Data X509Data `xml:"X509Data"` |
||||
} |
||||
|
||||
type X509Data struct { |
||||
XMLName xml.Name `xml:"http://www.w3.org/2000/09/xmldsig# X509Data"` |
||||
X509Certificate X509Certificate `xml:"X509Certificate"` |
||||
} |
||||
|
||||
type X509Certificate struct { |
||||
XMLName xml.Name `xml:"http://www.w3.org/2000/09/xmldsig# X509Certificate"` |
||||
Data string `xml:",chardata"` |
||||
} |
||||
|
||||
type Signature struct { |
||||
XMLName xml.Name `xml:"http://www.w3.org/2000/09/xmldsig# Signature"` |
||||
SignedInfo *SignedInfo `xml:"SignedInfo"` |
||||
SignatureValue *SignatureValue `xml:"SignatureValue"` |
||||
KeyInfo *KeyInfo `xml:"KeyInfo"` |
||||
el *etree.Element |
||||
} |
||||
|
||||
// SetUnderlyingElement will be called with a reference to the Element this Signature
|
||||
// was unmarshaled from.
|
||||
func (s *Signature) SetUnderlyingElement(el *etree.Element) { |
||||
s.el = el |
||||
} |
||||
|
||||
// UnderlyingElement returns a reference to the Element this signature was unmarshaled
|
||||
// from, where applicable.
|
||||
func (s *Signature) UnderlyingElement() *etree.Element { |
||||
return s.el |
||||
} |
||||
Loading…
Reference in new issue