run 'go get -u; make revendor'

Signed-off-by: Stephan Renatus <srenatus@chef.io>
This commit is contained in:
Stephan Renatus
2019-07-31 08:09:38 +02:00
parent 7c1b4b3005
commit 076cd77469
975 changed files with 347835 additions and 77390 deletions

View File

@@ -0,0 +1 @@
*.test

View File

@@ -1,6 +1,9 @@
language: go
go:
- 1.5
- 1.6
- tip
- "1.6.x"
- "1.7.x"
- "1.8.x"
- "1.9.x"
- "1.10.x"
- master

View File

@@ -56,6 +56,40 @@ func (c *c14N11Canonicalizer) Algorithm() AlgorithmID {
return CanonicalXML11AlgorithmId
}
type c14N10RecCanonicalizer struct{}
// MakeC14N10RecCanonicalizer constructs an inclusive canonicalizer.
func MakeC14N10RecCanonicalizer() Canonicalizer {
return &c14N10RecCanonicalizer{}
}
// Canonicalize transforms the input Element into a serialized XML document in canonical form.
func (c *c14N10RecCanonicalizer) Canonicalize(el *etree.Element) ([]byte, error) {
scope := make(map[string]struct{})
return canonicalSerialize(canonicalPrep(el, scope))
}
func (c *c14N10RecCanonicalizer) Algorithm() AlgorithmID {
return CanonicalXML10RecAlgorithmId
}
type c14N10CommentCanonicalizer struct{}
// MakeC14N10CommentCanonicalizer constructs an inclusive canonicalizer.
func MakeC14N10CommentCanonicalizer() Canonicalizer {
return &c14N10CommentCanonicalizer{}
}
// Canonicalize transforms the input Element into a serialized XML document in canonical form.
func (c *c14N10CommentCanonicalizer) Canonicalize(el *etree.Element) ([]byte, error) {
scope := make(map[string]struct{})
return canonicalSerialize(canonicalPrep(el, scope))
}
func (c *c14N10CommentCanonicalizer) Algorithm() AlgorithmID {
return CanonicalXML10CommentAlgorithmId
}
func composeAttr(space, key string) string {
if space != "" {
return space + ":" + key

View File

@@ -16,7 +16,7 @@ func TransformExcC14n(el *etree.Element, inclusiveNamespacesPrefixList string) e
prefixSet[prefix] = struct{}{}
}
err := transformExcC14n(DefaultNSContext, EmptyNSContext, el, prefixSet)
err := transformExcC14n(DefaultNSContext, DefaultNSContext, el, prefixSet)
if err != nil {
return err
}

View File

@@ -266,7 +266,12 @@ func NSFindIterate(el *etree.Element, namespace, tag string, handle NSIterHandle
// returned by NSFindIterate.
func NSFindIterateCtx(ctx NSContext, el *etree.Element, namespace, tag string, handle NSIterHandler) error {
err := NSTraverse(ctx, el, func(ctx NSContext, el *etree.Element) error {
currentNS, err := ctx.LookupPrefix(el.Space)
_ctx, err := ctx.SubContext(el)
if err != nil {
return err
}
currentNS, err := _ctx.LookupPrefix(el.Space)
if err != nil {
return err
}
@@ -309,6 +314,80 @@ func NSFindOneCtx(ctx NSContext, el *etree.Element, namespace, tag string) (*etr
return found, nil
}
// NSIterateChildren iterates the children of an element, invoking the passed
// handler with each direct child of the element, and the context surrounding
// that child.
func NSIterateChildren(ctx NSContext, el *etree.Element, handle NSIterHandler) error {
ctx, err := ctx.SubContext(el)
if err != nil {
return err
}
// Iterate the child elements.
for _, child := range el.ChildElements() {
err = handle(ctx, child)
if err != nil {
return err
}
}
return nil
}
// NSFindIterateChildrenCtx takes an element and its surrounding context, and iterates
// the children of that element searching for an element matching the passed namespace
// and tag. For each such element that is found, handle is invoked with the matched
// element and its own surrounding context.
func NSFindChildrenIterateCtx(ctx NSContext, el *etree.Element, namespace, tag string, handle NSIterHandler) error {
err := NSIterateChildren(ctx, el, func(ctx NSContext, el *etree.Element) error {
_ctx, err := ctx.SubContext(el)
if err != nil {
return err
}
currentNS, err := _ctx.LookupPrefix(el.Space)
if err != nil {
return err
}
// Base case, el is the sought after element.
if currentNS == namespace && el.Tag == tag {
return handle(ctx, el)
}
return nil
})
if err != nil && err != ErrTraversalHalted {
return err
}
return nil
}
// NSFindOneChild behaves identically to NSFindOneChildCtx, but uses
// DefaultNSContext for context.
func NSFindOneChild(el *etree.Element, namespace, tag string) (*etree.Element, error) {
return NSFindOneChildCtx(DefaultNSContext, el, namespace, tag)
}
// NSFindOneCtx conducts a depth-first search for the specified element. If such an
// element is found a reference to it is returned.
func NSFindOneChildCtx(ctx NSContext, el *etree.Element, namespace, tag string) (*etree.Element, error) {
var found *etree.Element
err := NSFindChildrenIterateCtx(ctx, el, namespace, tag, func(ctx NSContext, el *etree.Element) error {
found = el
return ErrTraversalHalted
})
if err != nil && err != ErrTraversalHalted {
return nil, err
}
return found, nil
}
// NSBuildParentContext recurses upward from an element in order to build an NSContext
// for its immediate parent. If the element has no parent DefaultNSContext
// is returned.

View File

@@ -12,6 +12,10 @@ type X509KeyStore interface {
GetKeyPair() (privateKey *rsa.PrivateKey, cert []byte, err error)
}
type X509ChainStore interface {
GetChain() (certs [][]byte, err error)
}
type X509CertificateStore interface {
Certificates() (roots []*x509.Certificate, err error)
}

12
vendor/github.com/russellhaering/goxmldsig/run_test.sh generated vendored Normal file
View File

@@ -0,0 +1,12 @@
#!/bin/bash
cd `dirname $0`
DIRS=`git grep -l 'func Test' | xargs dirname | sort -u`
for DIR in $DIRS
do
echo
echo "dir: $DIR"
echo "======================================"
pushd $DIR >/dev/null
go test -v || exit 1
popd >/dev/null
done

View File

@@ -59,13 +59,13 @@ func (ctx *SigningContext) digest(el *etree.Element) ([]byte, error) {
}
func (ctx *SigningContext) constructSignedInfo(el *etree.Element, enveloped bool) (*etree.Element, error) {
digestAlgorithmIdentifier, ok := digestAlgorithmIdentifiers[ctx.Hash]
if !ok {
digestAlgorithmIdentifier := ctx.GetDigestAlgorithmIdentifier()
if digestAlgorithmIdentifier == "" {
return nil, errors.New("unsupported hash mechanism")
}
signatureMethodIdentifier, ok := signatureMethodIdentifiers[ctx.Hash]
if !ok {
signatureMethodIdentifier := ctx.GetSignatureMethodIdentifier()
if signatureMethodIdentifier == "" {
return nil, errors.New("unsupported signature method")
}
@@ -117,7 +117,7 @@ func (ctx *SigningContext) constructSignedInfo(el *etree.Element, enveloped bool
return signedInfo, nil
}
func (ctx *SigningContext) constructSignature(el *etree.Element, enveloped bool) (*etree.Element, error) {
func (ctx *SigningContext) ConstructSignature(el *etree.Element, enveloped bool) (*etree.Element, error) {
signedInfo, err := ctx.constructSignedInfo(el, enveloped)
if err != nil {
return nil, err
@@ -176,6 +176,14 @@ func (ctx *SigningContext) constructSignature(el *etree.Element, enveloped bool)
return nil, err
}
certs := [][]byte{cert}
if cs, ok := ctx.KeyStore.(X509ChainStore); ok {
certs, err = cs.GetChain()
if err != nil {
return nil, err
}
}
rawSignature, err := rsa.SignPKCS1v15(rand.Reader, key, ctx.Hash, digest)
if err != nil {
return nil, err
@@ -186,8 +194,10 @@ func (ctx *SigningContext) constructSignature(el *etree.Element, enveloped bool)
keyInfo := ctx.createNamespacedElement(sig, KeyInfoTag)
x509Data := ctx.createNamespacedElement(keyInfo, X509DataTag)
x509Certificate := ctx.createNamespacedElement(x509Data, X509CertificateTag)
x509Certificate.SetText(base64.StdEncoding.EncodeToString(cert))
for _, cert := range certs {
x509Certificate := ctx.createNamespacedElement(x509Data, X509CertificateTag)
x509Certificate.SetText(base64.StdEncoding.EncodeToString(cert))
}
return sig, nil
}
@@ -199,7 +209,7 @@ func (ctx *SigningContext) createNamespacedElement(el *etree.Element, tag string
}
func (ctx *SigningContext) SignEnveloped(el *etree.Element) (*etree.Element, error) {
sig, err := ctx.constructSignature(el, true)
sig, err := ctx.ConstructSignature(el, true)
if err != nil {
return nil, err
}
@@ -209,3 +219,38 @@ func (ctx *SigningContext) SignEnveloped(el *etree.Element) (*etree.Element, err
return ret, nil
}
func (ctx *SigningContext) GetSignatureMethodIdentifier() string {
if ident, ok := signatureMethodIdentifiers[ctx.Hash]; ok {
return ident
}
return ""
}
func (ctx *SigningContext) GetDigestAlgorithmIdentifier() string {
if ident, ok := digestAlgorithmIdentifiers[ctx.Hash]; ok {
return ident
}
return ""
}
// Useful for signing query string (including DEFLATED AuthnRequest) when
// using HTTP-Redirect to make a signed request.
// See 3.4.4.1 DEFLATE Encoding of https://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf
func (ctx *SigningContext) SignString(content string) ([]byte, error) {
hash := ctx.Hash.New()
if ln, err := hash.Write([]byte(content)); err != nil {
return nil, fmt.Errorf("error calculating hash: %v", err)
} else if ln < 1 {
return nil, fmt.Errorf("zero length hash")
}
digest := hash.Sum(nil)
var signature []byte
if key, _, err := ctx.KeyStore.GetKeyPair(); err != nil {
return nil, fmt.Errorf("unable to fetch key for signing: %v", err)
} else if signature, err = rsa.SignPKCS1v15(rand.Reader, key, ctx.Hash, digest); err != nil {
return nil, fmt.Errorf("error signing: %v", err)
}
return signature, nil
}

View File

@@ -32,3 +32,8 @@ func (d TLSCertKeyStore) GetKeyPair() (*rsa.PrivateKey, []byte, error) {
return pk, crt, nil
}
//GetChain impliments X509ChainStore using the underlying tls.Certificate
func (d TLSCertKeyStore) GetChain() ([][]byte, error) {
return d.Certificate, nil
}

View File

@@ -63,8 +63,8 @@ type KeyInfo struct {
}
type X509Data struct {
XMLName xml.Name `xml:"http://www.w3.org/2000/09/xmldsig# X509Data"`
X509Certificate X509Certificate `xml:"X509Certificate"`
XMLName xml.Name `xml:"http://www.w3.org/2000/09/xmldsig# X509Data"`
X509Certificates []X509Certificate `xml:"X509Certificate"`
}
type X509Certificate struct {

View File

@@ -15,6 +15,7 @@ import (
)
var uriRegexp = regexp.MustCompile("^#[a-zA-Z_][\\w.-]*$")
var whiteSpace = regexp.MustCompile("\\s+")
var (
// ErrMissingSignature indicates that no enveloped signature was found referencing
@@ -58,31 +59,51 @@ func childPath(space, tag string) string {
}
}
// The RemoveElement method on etree.Element isn't recursive...
func recursivelyRemoveElement(tree, el *etree.Element) bool {
if tree.RemoveChild(el) != nil {
return true
func mapPathToElement(tree, el *etree.Element) []int {
for i, child := range tree.Child {
if child == el {
return []int{i}
}
}
for _, child := range tree.Child {
for i, child := range tree.Child {
if childElement, ok := child.(*etree.Element); ok {
if recursivelyRemoveElement(childElement, el) {
return true
childPath := mapPathToElement(childElement, el)
if childElement != nil {
return append([]int{i}, childPath...)
}
}
}
return false
return nil
}
// transform applies the passed set of transforms to the specified root element.
func removeElementAtPath(el *etree.Element, path []int) bool {
if len(path) == 0 {
return false
}
if len(el.Child) <= path[0] {
return false
}
childElement, ok := el.Child[path[0]].(*etree.Element)
if !ok {
return false
}
if len(path) == 1 {
el.RemoveChild(childElement)
return true
}
return removeElementAtPath(childElement, path[1:])
}
// Transform returns a new element equivalent to the passed root el, but with
// the set of transformations described by the ref applied.
//
// The functionality of transform is currently very limited and purpose-specific.
//
// NOTE(russell_h): Ideally this wouldn't mutate the root passed to it, and would
// instead return a copy. Unfortunately copying the tree makes it difficult to
// correctly locate the signature. I'm opting, for now, to simply mutate the root
// parameter.
func (ctx *ValidationContext) transform(
el *etree.Element,
sig *types.Signature,
@@ -93,6 +114,14 @@ func (ctx *ValidationContext) transform(
return nil, nil, errors.New("Expected Enveloped and C14N transforms")
}
// map the path to the passed signature relative to the passed root, in
// order to enable removal of the signature by an enveloped signature
// transform
signaturePath := mapPathToElement(el, sig.UnderlyingElement())
// make a copy of the passed root
el = el.Copy()
var canonicalizer Canonicalizer
for _, transform := range transforms {
@@ -100,7 +129,7 @@ func (ctx *ValidationContext) transform(
switch AlgorithmID(algo) {
case EnvelopedSignatureAltorithmId:
if !recursivelyRemoveElement(el, sig.UnderlyingElement()) {
if !removeElementAtPath(el, signaturePath) {
return nil, nil, errors.New("Error applying canonicalization transform: Signature not found")
}
@@ -115,6 +144,12 @@ func (ctx *ValidationContext) transform(
case CanonicalXML11AlgorithmId:
canonicalizer = MakeC14N11Canonicalizer()
case CanonicalXML10RecAlgorithmId:
canonicalizer = MakeC14N10RecCanonicalizer()
case CanonicalXML10CommentAlgorithmId:
canonicalizer = MakeC14N10CommentCanonicalizer()
default:
return nil, nil, errors.New("Unknown Transform Algorithm: " + algo)
}
@@ -150,7 +185,16 @@ func (ctx *ValidationContext) digest(el *etree.Element, digestAlgorithmId string
func (ctx *ValidationContext) verifySignedInfo(sig *types.Signature, canonicalizer Canonicalizer, signatureMethodId string, cert *x509.Certificate, decodedSignature []byte) error {
signatureElement := sig.UnderlyingElement()
signedInfo := signatureElement.FindElement(childPath(signatureElement.Space, SignedInfoTag))
nsCtx, err := etreeutils.NSBuildParentContext(signatureElement)
if err != nil {
return err
}
signedInfo, err := etreeutils.NSFindOneChildCtx(nsCtx, signatureElement, Namespace, SignedInfoTag)
if err != nil {
return err
}
if signedInfo == nil {
return errors.New("Missing SignedInfo")
}
@@ -189,7 +233,7 @@ func (ctx *ValidationContext) verifySignedInfo(sig *types.Signature, canonicaliz
}
func (ctx *ValidationContext) validateSignature(el *etree.Element, sig *types.Signature, cert *x509.Certificate) (*etree.Element, error) {
idAttr := el.SelectAttr(DefaultIdAttr)
idAttr := el.SelectAttr(ctx.IdAttribute)
if idAttr == nil || idAttr.Value == "" {
return nil, errors.New("Missing ID attribute")
}
@@ -254,7 +298,7 @@ func contains(roots []*x509.Certificate, cert *x509.Certificate) bool {
// findSignature searches for a Signature element referencing the passed root element.
func (ctx *ValidationContext) findSignature(el *etree.Element) (*types.Signature, error) {
idAttr := el.SelectAttr(DefaultIdAttr)
idAttr := el.SelectAttr(ctx.IdAttribute)
if idAttr == nil || idAttr.Value == "" {
return nil, errors.New("Missing ID attribute")
}
@@ -265,19 +309,18 @@ func (ctx *ValidationContext) findSignature(el *etree.Element) (*types.Signature
err := etreeutils.NSFindIterate(el, Namespace, SignatureTag, func(ctx etreeutils.NSContext, el *etree.Element) error {
found := false
err := etreeutils.NSFindIterateCtx(ctx, el, Namespace, SignedInfoTag,
err := etreeutils.NSFindChildrenIterateCtx(ctx, el, Namespace, SignedInfoTag,
func(ctx etreeutils.NSContext, signedInfo *etree.Element) error {
// Ignore any SignedInfo that isn't an immediate descendent of Signature.
if signedInfo.Parent() != el {
return nil
}
detachedSignedInfo, err := etreeutils.NSDetatch(ctx, signedInfo)
if err != nil {
return err
}
c14NMethod := detachedSignedInfo.FindElement(childPath(detachedSignedInfo.Space, CanonicalizationMethodTag))
c14NMethod, err := etreeutils.NSFindOneChildCtx(ctx, detachedSignedInfo, Namespace, CanonicalizationMethodTag)
if err != nil {
return err
}
if c14NMethod == nil {
return errors.New("missing CanonicalizationMethod on Signature")
}
@@ -302,6 +345,12 @@ func (ctx *ValidationContext) findSignature(el *etree.Element) (*types.Signature
case CanonicalXML11AlgorithmId:
canonicalSignedInfo = canonicalPrep(detachedSignedInfo, map[string]struct{}{})
case CanonicalXML10RecAlgorithmId:
canonicalSignedInfo = canonicalPrep(detachedSignedInfo, map[string]struct{}{})
case CanonicalXML10CommentAlgorithmId:
canonicalSignedInfo = canonicalPrep(detachedSignedInfo, map[string]struct{}{})
default:
return fmt.Errorf("invalid CanonicalizationMethod on Signature: %s", c14NAlgorithm)
}
@@ -363,11 +412,12 @@ func (ctx *ValidationContext) verifyCertificate(sig *types.Signature) (*x509.Cer
if sig.KeyInfo != nil {
// If the Signature includes KeyInfo, extract the certificate from there
if sig.KeyInfo.X509Data.X509Certificate.Data == "" {
if len(sig.KeyInfo.X509Data.X509Certificates) == 0 || sig.KeyInfo.X509Data.X509Certificates[0].Data == "" {
return nil, errors.New("missing X509Certificate within KeyInfo")
}
certData, err := base64.StdEncoding.DecodeString(sig.KeyInfo.X509Data.X509Certificate.Data)
certData, err := base64.StdEncoding.DecodeString(
whiteSpace.ReplaceAllString(sig.KeyInfo.X509Data.X509Certificates[0].Data, ""))
if err != nil {
return nil, errors.New("Failed to parse certificate")
}

View File

@@ -50,6 +50,9 @@ const (
CanonicalXML10ExclusiveAlgorithmId AlgorithmID = "http://www.w3.org/2001/10/xml-exc-c14n#"
CanonicalXML11AlgorithmId AlgorithmID = "http://www.w3.org/2006/12/xml-c14n11"
CanonicalXML10RecAlgorithmId AlgorithmID = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"
CanonicalXML10CommentAlgorithmId AlgorithmID = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"
EnvelopedSignatureAltorithmId AlgorithmID = "http://www.w3.org/2000/09/xmldsig#enveloped-signature"
)