Update github.com/russellhaering/goxmldsig to v1.1.0

See https://github.com/russellhaering/goxmldsig/security/advisories/GHSA-q547-gmf8-8jr7
This commit is contained in:
Andrew Lytvynov
2020-09-29 17:51:50 +00:00
committed by Andrew Lytvynov
parent b2faac1d0d
commit 8aacdc1b0f
34 changed files with 1410 additions and 285 deletions
+3 -3
View File
@@ -11,7 +11,7 @@ require (
github.com/alecthomas/repr v0.0.0-20200325044227-4184120f674c // indirect
github.com/armon/go-radix v1.0.0
github.com/aws/aws-sdk-go v1.32.7
github.com/beevik/etree v0.0.0-20170418002358-cda1c0026246
github.com/beevik/etree v1.1.0
github.com/boombuler/barcode v0.0.0-20161226211916-fe0f26ff6d26 // indirect
github.com/cjbassi/drawille-go v0.1.0 // indirect
github.com/codahale/hdrhistogram v0.0.0-20150708134006-954f16e8b9ef
@@ -44,7 +44,7 @@ require (
github.com/hashicorp/golang-lru v0.5.4
github.com/iovisor/gobpf v0.0.1
github.com/johannesboyne/gofakes3 v0.0.0-20191228161223-9aee1c78a252
github.com/jonboulle/clockwork v0.1.1-0.20190114141812-62fb9bc030d1
github.com/jonboulle/clockwork v0.2.1
github.com/json-iterator/go v1.1.9
github.com/julienschmidt/httprouter v1.2.0
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0
@@ -66,7 +66,7 @@ require (
github.com/prometheus/common v0.6.0
github.com/prometheus/procfs v0.0.4 // indirect
github.com/russellhaering/gosaml2 v0.0.0-20170515204909-8908227c114a
github.com/russellhaering/goxmldsig v0.0.0-20170515183101-605161228693
github.com/russellhaering/goxmldsig v1.1.0
github.com/satori/go.uuid v1.1.1-0.20170321230731-5bf94b69c6b6 // indirect
github.com/sergi/go-diff v1.1.0 // indirect
github.com/shabbyrobe/gocovmerge v0.0.0-20190829150210-3e036491d500 // indirect
+8 -6
View File
@@ -42,8 +42,8 @@ github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgI
github.com/aws/aws-sdk-go v1.17.4/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.32.7 h1:H4VgdCSF1cHw0VD8zGc98T1bGdACoLkh/vK2L6wgOUU=
github.com/aws/aws-sdk-go v1.32.7/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/beevik/etree v0.0.0-20170418002358-cda1c0026246 h1:ug+AeM+Rh5O1beNwuhXlR29jr11nUuB7ZB+X9SzPSJQ=
github.com/beevik/etree v0.0.0-20170418002358-cda1c0026246/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -201,8 +201,10 @@ github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeY
github.com/johannesboyne/gofakes3 v0.0.0-20191228161223-9aee1c78a252 h1:ZABLXRnnFNP5nkVzVBx2kQ/4GvSLUqcD2YUc+9Uc2Mo=
github.com/johannesboyne/gofakes3 v0.0.0-20191228161223-9aee1c78a252/go.mod h1:cPDudDcSR9fls3ZmrXgt0GU2QpQGQRJc4JBNtKyNr1s=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jonboulle/clockwork v0.1.1-0.20190114141812-62fb9bc030d1 h1:qBCV/RLV02TSfQa7tFmxTihnG+u+7JXByOkhlkR5rmQ=
github.com/jonboulle/clockwork v0.1.1-0.20190114141812-62fb9bc030d1/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jonboulle/clockwork v0.2.0 h1:J2SLSdy7HgElq8ekSl2Mxh6vrRNFxqbXGenYH2I02Vs=
github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
github.com/jonboulle/clockwork v0.2.1 h1:S/EaQvW6FpWMYAvYvY+OBDvpaM+izu0oiwo5y0MH7U0=
github.com/jonboulle/clockwork v0.2.1/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@@ -299,8 +301,8 @@ github.com/prometheus/procfs v0.0.4/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDa
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/russellhaering/gosaml2 v0.0.0-20170515204909-8908227c114a h1:t10m/WbIQiAAggqE6J2401FInpp50XPi249G7nE45tc=
github.com/russellhaering/gosaml2 v0.0.0-20170515204909-8908227c114a/go.mod h1:niieRtQaw+opTVp9jzZo1nAAoksI2eNpd+weDcjZ+Mk=
github.com/russellhaering/goxmldsig v0.0.0-20170515183101-605161228693 h1:N6BLFjXGfV1dGbLqHVVqe7u6ii+JHrl7L2lRZK7JzrY=
github.com/russellhaering/goxmldsig v0.0.0-20170515183101-605161228693/go.mod h1:Oz4y6ImuOQZxynhbSXk7btjEfNBtGlj2dcaOvXl2FSM=
github.com/russellhaering/goxmldsig v1.1.0 h1:lK/zeJie2sqG52ZAlPNn1oBBqsIsEKypUUBGpYYF6lk=
github.com/russellhaering/goxmldsig v1.1.0/go.mod h1:QK8GhXPB3+AfuCrfo0oRISa9NfzeCpWmxeGnqEpDF9o=
github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46 h1:GHRpF1pTW19a8tTFrMLUcfWwyC0pnifVo2ClaLq+hP8=
github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46/go.mod h1:uAQ5PCi+MFsC7HjREoAz1BU+Mq60+05gifQSsHSDG/8=
github.com/satori/go.uuid v1.1.1-0.20170321230731-5bf94b69c6b6 h1:oZag5hylqWwZrDdj/laMwWQnXaeWBQf66qm4PGQI6Wc=
+10 -8
View File
@@ -561,15 +561,17 @@ func (o *SAMLConnectorV2) GetServiceProvider(clock clockwork.Clock) (*saml2.SAML
}
for _, kd := range metadata.IDPSSODescriptor.KeyDescriptors {
certData, err := base64.StdEncoding.DecodeString(strings.TrimSpace(kd.KeyInfo.X509Data.X509Certificate.Data))
if err != nil {
return nil, trace.Wrap(err)
for _, samlCert := range kd.KeyInfo.X509Data.X509Certificates {
certData, err := base64.StdEncoding.DecodeString(strings.TrimSpace(samlCert.Data))
if err != nil {
return nil, trace.Wrap(err)
}
cert, err := x509.ParseCertificate(certData)
if err != nil {
return nil, trace.Wrap(err, "failed to parse certificate in metadata")
}
certStore.Roots = append(certStore.Roots, cert)
}
cert, err := x509.ParseCertificate(certData)
if err != nil {
return nil, trace.Wrap(err, "failed to parse certificate in metadata")
}
certStore.Roots = append(certStore.Roots, cert)
}
o.Spec.Issuer = metadata.EntityID
o.Spec.SSO = metadata.IDPSSODescriptor.SingleSignOnService.Location
+1 -3
View File
@@ -2,9 +2,7 @@ language: go
sudo: false
go:
- 1.4.2
- 1.5.1
- 1.6
- 1.11.x
- tip
matrix:
+2
View File
@@ -6,3 +6,5 @@ Matt Smith (ma314smith)
Michal Jemala (michaljemala)
Nicolas Piganeau (npiganeau)
Chris Brown (ccbrown)
Earncef Sequeira (earncef)
Gabriel de Labachelerie (wuzuf)
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright 2015 Brett Vickers. All rights reserved.
Copyright 2015-2019 Brett Vickers. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
+3 -1
View File
@@ -7,7 +7,9 @@ etree
The etree package is a lightweight, pure go package that expresses XML in
the form of an element tree. Its design was inspired by the Python
[ElementTree](http://docs.python.org/2/library/xml.etree.elementtree.html)
module. Some of the package's features include:
module.
Some of the package's capabilities and features:
* Represents XML documents as trees of elements for easy traversal.
* Imports, serializes, modifies or creates XML documents from scratch.
+109
View File
@@ -0,0 +1,109 @@
Release v1.1.0
==============
**New Features**
* New attribute helpers.
* Added the `Element.SortAttrs` method, which lexicographically sorts an
element's attributes by key.
* New `ReadSettings` properties.
* Added `Entity` for the support of custom entity maps.
* New `WriteSettings` properties.
* Added `UseCRLF` to allow the output of CR-LF newlines instead of the
default LF newlines. This is useful on Windows systems.
* Additional support for text and CDATA sections.
* The `Element.Text` method now returns the concatenation of all consecutive
character data tokens immediately following an element's opening tag.
* Added `Element.SetCData` to replace the character data immediately
following an element's opening tag with a CDATA section.
* Added `Element.CreateCData` to create and add a CDATA section child
`CharData` token to an element.
* Added `Element.CreateText` to create and add a child text `CharData` token
to an element.
* Added `NewCData` to create a parentless CDATA section `CharData` token.
* Added `NewText` to create a parentless text `CharData`
token.
* Added `CharData.IsCData` to detect if the token contains a CDATA section.
* Added `CharData.IsWhitespace` to detect if the token contains whitespace
inserted by one of the document Indent functions.
* Modified `Element.SetText` so that it replaces a run of consecutive
character data tokens following the element's opening tag (instead of just
the first one).
* New "tail text" support.
* Added the `Element.Tail` method, which returns the text immediately
following an element's closing tag.
* Added the `Element.SetTail` method, which modifies the text immediately
following an element's closing tag.
* New element child insertion and removal methods.
* Added the `Element.InsertChildAt` method, which inserts a new child token
before the specified child token index.
* Added the `Element.RemoveChildAt` method, which removes the child token at
the specified child token index.
* New element and attribute queries.
* Added the `Element.Index` method, which returns the element's index within
its parent element's child token list.
* Added the `Element.NamespaceURI` method to return the namespace URI
associated with an element.
* Added the `Attr.NamespaceURI` method to return the namespace URI
associated with an element.
* Added the `Attr.Element` method to return the element that an attribute
belongs to.
* New Path filter functions.
* Added `[local-name()='val']` to keep elements whose unprefixed tag matches
the desired value.
* Added `[name()='val']` to keep elements whose full tag matches the desired
value.
* Added `[namespace-prefix()='val']` to keep elements whose namespace prefix
matches the desired value.
* Added `[namespace-uri()='val']` to keep elements whose namespace URI
matches the desired value.
**Bug Fixes**
* A default XML `CharSetReader` is now used to prevent failed parsing of XML
documents using certain encodings.
([Issue](https://github.com/beevik/etree/issues/53)).
* All characters are now properly escaped according to XML parsing rules.
([Issue](https://github.com/beevik/etree/issues/55)).
* The `Document.Indent` and `Document.IndentTabs` functions no longer insert
empty string `CharData` tokens.
**Deprecated**
* `Element`
* The `InsertChild` method is deprecated. Use `InsertChildAt` instead.
* The `CreateCharData` method is deprecated. Use `CreateText` instead.
* `CharData`
* The `NewCharData` method is deprecated. Use `NewText` instead.
Release v1.0.1
==============
**Changes**
* Added support for absolute etree Path queries. An absolute path begins with
`/` or `//` and begins its search from the element's document root.
* Added [`GetPath`](https://godoc.org/github.com/beevik/etree#Element.GetPath)
and [`GetRelativePath`](https://godoc.org/github.com/beevik/etree#Element.GetRelativePath)
functions to the [`Element`](https://godoc.org/github.com/beevik/etree#Element)
type.
**Breaking changes**
* A path starting with `//` is now interpreted as an absolute path.
Previously, it was interpreted as a relative path starting from the element
whose
[`FindElement`](https://godoc.org/github.com/beevik/etree#Element.FindElement)
method was called. To remain compatible with this release, all paths
prefixed with `//` should be prefixed with `.//` when called from any
element other than the document's root.
* [**edit 2/1/2019**]: Minor releases should not contain breaking changes.
Even though this breaking change was very minor, it was a mistake to include
it in this minor release. In the future, all breaking changes will be
limited to major releases (e.g., version 2.0.0).
Release v1.0.0
==============
Initial release.
+656 -146
View File
File diff suppressed because it is too large Load Diff
+99 -11
View File
@@ -1,12 +1,14 @@
// Copyright 2015 Brett Vickers.
// Copyright 2015-2019 Brett Vickers.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package etree
import (
"bufio"
"io"
"strings"
"unicode/utf8"
)
// A simple stack
@@ -147,22 +149,35 @@ func spaceDecompose(str string) (space, key string) {
return str[:colon], str[colon+1:]
}
// Strings used by crIndent
// Strings used by indentCRLF and indentLF
const (
crsp = "\n "
crtab = "\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
indentSpaces = "\r\n "
indentTabs = "\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
)
// crIndent returns a carriage return followed by n copies of the
// first non-CR character in the source string.
func crIndent(n int, source string) string {
// indentCRLF returns a CRLF newline followed by n copies of the first
// non-CRLF character in the source string.
func indentCRLF(n int, source string) string {
switch {
case n < 0:
return source[:1]
case n < len(source):
return source[:n+1]
return source[:2]
case n < len(source)-1:
return source[:n+2]
default:
return source + strings.Repeat(source[1:2], n-len(source)+1)
return source + strings.Repeat(source[2:3], n-len(source)+2)
}
}
// indentLF returns a LF newline followed by n copies of the first non-LF
// character in the source string.
func indentLF(n int, source string) string {
switch {
case n < 0:
return source[1:2]
case n < len(source)-1:
return source[1 : n+2]
default:
return source[1:] + strings.Repeat(source[2:3], n-len(source)+2)
}
}
@@ -186,3 +201,76 @@ func isInteger(s string) bool {
}
return true
}
type escapeMode byte
const (
escapeNormal escapeMode = iota
escapeCanonicalText
escapeCanonicalAttr
)
// escapeString writes an escaped version of a string to the writer.
func escapeString(w *bufio.Writer, s string, m escapeMode) {
var esc []byte
last := 0
for i := 0; i < len(s); {
r, width := utf8.DecodeRuneInString(s[i:])
i += width
switch r {
case '&':
esc = []byte("&amp;")
case '<':
esc = []byte("&lt;")
case '>':
if m == escapeCanonicalAttr {
continue
}
esc = []byte("&gt;")
case '\'':
if m != escapeNormal {
continue
}
esc = []byte("&apos;")
case '"':
if m == escapeCanonicalText {
continue
}
esc = []byte("&quot;")
case '\t':
if m != escapeCanonicalAttr {
continue
}
esc = []byte("&#x9;")
case '\n':
if m != escapeCanonicalAttr {
continue
}
esc = []byte("&#xA;")
case '\r':
if m == escapeNormal {
continue
}
esc = []byte("&#xD;")
default:
if !isInCharacterRange(r) || (r == 0xFFFD && width == 1) {
esc = []byte("\uFFFD")
break
}
continue
}
w.WriteString(s[last : i-width])
w.Write(esc)
last = i
}
w.WriteString(s[last:])
}
func isInCharacterRange(r rune) bool {
return r == 0x09 ||
r == 0x0A ||
r == 0x0D ||
r >= 0x20 && r <= 0xD7FF ||
r >= 0xE000 && r <= 0xFFFD ||
r >= 0x10000 && r <= 0x10FFFF
}
+153 -41
View File
@@ -1,4 +1,4 @@
// Copyright 2015 Brett Vickers.
// Copyright 2015-2019 Brett Vickers.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -10,40 +10,75 @@ import (
)
/*
A Path is an object that represents an optimized version of an
XPath-like search string. Although path strings are XPath-like,
only the following limited syntax is supported:
A Path is a string that represents a search path through an etree starting
from the document root or an arbitrary element. Paths are used with the
Element object's Find* methods to locate and return desired elements.
. Selects the current element
.. Selects the parent of the current element
* Selects all child elements
// Selects all descendants of the current element
tag Selects all child elements with the given tag
[#] Selects the element of the given index (1-based,
negative starts from the end)
[@attrib] Selects all elements with the given attribute
[@attrib='val'] Selects all elements with the given attribute set to val
[tag] Selects all elements with a child element named tag
[tag='val'] Selects all elements with a child element named tag
and text equal to val
A Path consists of a series of slash-separated "selectors", each of which may
be modified by one or more bracket-enclosed "filters". Selectors are used to
traverse the etree from element to element, while filters are used to narrow
the list of candidate elements at each node.
Examples:
Although etree Path strings are similar to XPath strings
(https://www.w3.org/TR/1999/REC-xpath-19991116/), they have a more limited set
of selectors and filtering options.
Select the title elements of all descendant book elements having a
'category' attribute of 'WEB':
The following selectors are supported by etree Path strings:
. Select the current element.
.. Select the parent of the current element.
* Select all child elements of the current element.
/ Select the root element when used at the start of a path.
// Select all descendants of the current element.
tag Select all child elements with a name matching the tag.
The following basic filters are supported by etree Path strings:
[@attrib] Keep elements with an attribute named attrib.
[@attrib='val'] Keep elements with an attribute named attrib and value matching val.
[tag] Keep elements with a child element named tag.
[tag='val'] Keep elements with a child element named tag and text matching val.
[n] Keep the n-th element, where n is a numeric index starting from 1.
The following function filters are also supported:
[text()] Keep elements with non-empty text.
[text()='val'] Keep elements whose text matches val.
[local-name()='val'] Keep elements whose un-prefixed tag matches val.
[name()='val'] Keep elements whose full tag exactly matches val.
[namespace-prefix()='val'] Keep elements whose namespace prefix matches val.
[namespace-uri()='val'] Keep elements whose namespace URI matches val.
Here are some examples of Path strings:
- Select the bookstore child element of the root element:
/bookstore
- Beginning from the root element, select the title elements of all
descendant book elements having a 'category' attribute of 'WEB':
//book[@category='WEB']/title
Select the first book element with a title child containing the text
'Great Expectations':
- Beginning from the current element, select the first descendant
book element with a title child element containing the text 'Great
Expectations':
.//book[title='Great Expectations'][1]
Starting from the current element, select all children of book elements
with an attribute 'language' set to 'english':
- Beginning from the current element, select all child elements of
book elements with an attribute 'language' set to 'english':
./book/*[@language='english']
Select all descendant book elements whose title element has an attribute
'language' set to 'french':
//book/title[@language='french']/..
- Beginning from the current element, select all child elements of
book elements containing the text 'special':
./book/*[text()='special']
- Beginning from the current element, select all descendant book
elements whose title child element has a 'language' attribute of 'french':
.//book/title[@language='french']/..
- Beginning from the current element, select all book elements
belonging to the http://www.w3.org/TR/html4/ namespace:
.//book[namespace-uri()='http://www.w3.org/TR/html4/']
*/
type Path struct {
segments []segment
@@ -173,22 +208,20 @@ type compiler struct {
// through an element tree and returns a slice of segment
// descriptors.
func (c *compiler) parsePath(path string) []segment {
// If path starts or ends with //, fix it
if strings.HasPrefix(path, "//") {
path = "." + path
}
// If path ends with //, fix it
if strings.HasSuffix(path, "//") {
path = path + "*"
}
// Paths cannot be absolute
var segments []segment
// Check for an absolute path
if strings.HasPrefix(path, "/") {
c.err = ErrPath("paths cannot be absolute.")
return nil
segments = append(segments, segment{new(selectRoot), []filter{}})
path = path[1:]
}
// Split path into segment objects
var segments []segment
// Split path into segments
for _, s := range splitPath(path) {
segments = append(segments, c.parseSegment(s))
if c.err != ErrPath("") {
@@ -218,7 +251,7 @@ func (c *compiler) parseSegment(path string) segment {
pieces := strings.Split(path, "[")
seg := segment{
sel: c.parseSelector(pieces[0]),
filters: make([]filter, 0),
filters: []filter{},
}
for i := 1; i < len(pieces); i++ {
fpath := pieces[i]
@@ -247,6 +280,17 @@ func (c *compiler) parseSelector(path string) selector {
}
}
var fnTable = map[string]struct {
hasFn func(e *Element) bool
getValFn func(e *Element) string
}{
"local-name": {nil, (*Element).name},
"name": {nil, (*Element).FullTag},
"namespace-prefix": {nil, (*Element).namespacePrefix},
"namespace-uri": {nil, (*Element).NamespaceURI},
"text": {(*Element).hasText, (*Element).Text},
}
// parseFilter parses a path filter contained within [brackets].
func (c *compiler) parseFilter(path string) filter {
if len(path) == 0 {
@@ -254,7 +298,7 @@ func (c *compiler) parseFilter(path string) filter {
return nil
}
// Filter contains [@attr='val'] or [tag='val']?
// Filter contains [@attr='val'], [fn()='val'], or [tag='val']?
eqindex := strings.Index(path, "='")
if eqindex >= 0 {
rindex := nextIndex(path, "'", eqindex+2)
@@ -262,18 +306,36 @@ func (c *compiler) parseFilter(path string) filter {
c.err = ErrPath("path has mismatched filter quotes.")
return nil
}
key := path[:eqindex]
value := path[eqindex+2 : rindex]
switch {
case path[0] == '@':
return newFilterAttrVal(path[1:eqindex], path[eqindex+2:rindex])
case key[0] == '@':
return newFilterAttrVal(key[1:], value)
case strings.HasSuffix(key, "()"):
fn := key[:len(key)-2]
if t, ok := fnTable[fn]; ok && t.getValFn != nil {
return newFilterFuncVal(t.getValFn, value)
}
c.err = ErrPath("path has unknown function " + fn)
return nil
default:
return newFilterChildText(path[:eqindex], path[eqindex+2:rindex])
return newFilterChildText(key, value)
}
}
// Filter contains [@attr], [N] or [tag]
// Filter contains [@attr], [N], [tag] or [fn()]
switch {
case path[0] == '@':
return newFilterAttr(path[1:])
case strings.HasSuffix(path, "()"):
fn := path[:len(path)-2]
if t, ok := fnTable[fn]; ok && t.hasFn != nil {
return newFilterFunc(t.hasFn)
}
c.err = ErrPath("path has unknown function " + fn)
return nil
case isInteger(path):
pos, _ := strconv.Atoi(path)
switch {
@@ -294,6 +356,17 @@ func (s *selectSelf) apply(e *Element, p *pather) {
p.candidates = append(p.candidates, e)
}
// selectRoot selects the element's root node.
type selectRoot struct{}
func (s *selectRoot) apply(e *Element, p *pather) {
root := e
for root.parent != nil {
root = root.parent
}
p.candidates = append(p.candidates, root)
}
// selectParent selects the element's parent into the candidate list.
type selectParent struct{}
@@ -420,6 +493,45 @@ func (f *filterAttrVal) apply(p *pather) {
p.candidates, p.scratch = p.scratch, p.candidates[0:0]
}
// filterFunc filters the candidate list for elements satisfying a custom
// boolean function.
type filterFunc struct {
fn func(e *Element) bool
}
func newFilterFunc(fn func(e *Element) bool) *filterFunc {
return &filterFunc{fn}
}
func (f *filterFunc) apply(p *pather) {
for _, c := range p.candidates {
if f.fn(c) {
p.scratch = append(p.scratch, c)
}
}
p.candidates, p.scratch = p.scratch, p.candidates[0:0]
}
// filterFuncVal filters the candidate list for elements containing a value
// matching the result of a custom function.
type filterFuncVal struct {
fn func(e *Element) string
val string
}
func newFilterFuncVal(fn func(e *Element) string, value string) *filterFuncVal {
return &filterFuncVal{fn, value}
}
func (f *filterFuncVal) apply(p *pather) {
for _, c := range p.candidates {
if f.fn(c) == f.val {
p.scratch = append(p.scratch, c)
}
}
p.candidates, p.scratch = p.scratch, p.candidates[0:0]
}
// filterChild filters the candidate list for elements having
// a child element with the specified tag.
type filterChild struct {
+12
View File
@@ -0,0 +1,12 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.go]
indent_style = tab
+2
View File
@@ -1,3 +1,5 @@
/.idea/
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
-6
View File
@@ -1,6 +0,0 @@
language: go
go:
- "1.10"
- master
sudo: false
+17 -7
View File
@@ -1,12 +1,16 @@
clockwork
=========
# clockwork
[![Build Status](https://travis-ci.org/jonboulle/clockwork.png?branch=master)](https://travis-ci.org/jonboulle/clockwork)
[![godoc](https://godoc.org/github.com/jonboulle/clockwork?status.svg)](http://godoc.org/github.com/jonboulle/clockwork)
[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge-flat.svg)](https://github.com/avelino/awesome-go#utilities)
a simple fake clock for golang
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/jonboulle/clockwork/CI?style=flat-square)](https://github.com/jonboulle/clockwork/actions?query=workflow%3ACI)
[![Go Report Card](https://goreportcard.com/badge/github.com/jonboulle/clockwork?style=flat-square)](https://goreportcard.com/report/github.com/jonboulle/clockwork)
![Go Version](https://img.shields.io/badge/go%20version-%3E=1.11-61CFDD.svg?style=flat-square)
[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/mod/github.com/jonboulle/clockwork)
# Usage
**A simple fake clock for Go.**
## Usage
Replace uses of the `time` package with the `clockwork.Clock` interface instead.
@@ -19,7 +23,7 @@ func myFunc() {
}
```
inject a clock and use its `Sleep` method instead:
Inject a clock and use its `Sleep` method instead:
```go
func myFunc(clock clockwork.Clock) {
@@ -65,6 +69,12 @@ myFunc(clockwork.NewRealClock())
See [example_test.go](example_test.go) for a full example.
# Credits
clockwork is inspired by @wickman's [threaded fake clock](https://gist.github.com/wickman/3840816), and the [Golang playground](https://blog.golang.org/playground#TOC_3.1.)
## License
Apache License, Version 2.0. Please see [License File](LICENSE) for more information.
+1 -1
View File
@@ -97,7 +97,7 @@ func (fc *fakeClock) After(d time.Duration) <-chan time.Time {
defer fc.l.Unlock()
now := fc.time
done := make(chan time.Time, 1)
if d.Nanoseconds() == 0 {
if d.Nanoseconds() <= 0 {
// special case - trigger immediately
done <- now
} else {
+3
View File
@@ -0,0 +1,3 @@
module github.com/jonboulle/clockwork
go 1.13
+1
View File
@@ -0,0 +1 @@
*.test
+4 -3
View File
@@ -1,6 +1,7 @@
language: go
go:
- 1.5
- 1.6
- tip
- "1.13.x"
- "1.14.x"
- "1.15.x"
- master
+1 -1
View File
@@ -7,7 +7,7 @@ XML Digital Signatures implemented in pure Go.
## Installation
Install `goxmldsig` into your `$GOPATH` using `go get`:
Install `goxmldsig` using `go get`:
```
$ go get github.com/russellhaering/goxmldsig
+34
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
+1 -1
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
}
+80 -1
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.
+9
View File
@@ -0,0 +1,9 @@
module github.com/russellhaering/goxmldsig
go 1.15
require (
github.com/beevik/etree v1.1.0
github.com/jonboulle/clockwork v0.2.0
github.com/stretchr/testify v1.6.1
)
+15
View File
@@ -0,0 +1,15 @@
github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/jonboulle/clockwork v0.2.0 h1:J2SLSdy7HgElq8ekSl2Mxh6vrRNFxqbXGenYH2I02Vs=
github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+4
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
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
+51 -6
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")
}
@@ -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
}
@@ -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
}
+5
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
}
+2 -2
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 {
+105 -32
View File
@@ -15,11 +15,13 @@ import (
)
var uriRegexp = regexp.MustCompile("^#[a-zA-Z_][\\w.-]*$")
var whiteSpace = regexp.MustCompile("\\s+")
var (
// ErrMissingSignature indicates that no enveloped signature was found referencing
// the top level element passed for signature verification.
ErrMissingSignature = errors.New("Missing signature referencing the top-level element")
ErrInvalidSignature = errors.New( "Invalid Signature")
)
type ValidationContext struct {
@@ -58,31 +60,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 +115,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 +130,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 +145,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 +186,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")
}
@@ -252,9 +297,28 @@ func contains(roots []*x509.Certificate, cert *x509.Certificate) bool {
return false
}
// In most places, we use etree Elements, but while deserializing the Signature, we use
// encoding/xml unmarshal directly to convert to a convenient go struct. This presents a problem in some cases because
// when an xml element repeats under the parent, the last element will win and/or be appended. We need to assert that
// the Signature object matches the expected shape of a Signature object.
func validateShape(signatureEl *etree.Element) error {
children := signatureEl.ChildElements()
childCounts := map[string]int{}
for _, child := range children {
childCounts[child.Tag]++
}
validateCount := childCounts[SignedInfoTag] == 1 && childCounts[KeyInfoTag] <= 1 && childCounts[SignatureValueTag] == 1
if !validateCount {
return ErrInvalidSignature
}
return nil
}
// findSignature searches for a Signature element referencing the passed root element.
func (ctx *ValidationContext) findSignature(el *etree.Element) (*types.Signature, error) {
idAttr := el.SelectAttr(ctx.IdAttribute)
func (ctx *ValidationContext) findSignature(root *etree.Element) (*types.Signature, error) {
idAttr := root.SelectAttr(ctx.IdAttribute)
if idAttr == nil || idAttr.Value == "" {
return nil, errors.New("Missing ID attribute")
}
@@ -262,22 +326,24 @@ func (ctx *ValidationContext) findSignature(el *etree.Element) (*types.Signature
var sig *types.Signature
// Traverse the tree looking for a Signature element
err := etreeutils.NSFindIterate(el, Namespace, SignatureTag, func(ctx etreeutils.NSContext, el *etree.Element) error {
err := etreeutils.NSFindIterate(root, Namespace, SignatureTag, func(ctx etreeutils.NSContext, signatureEl *etree.Element) error {
err := validateShape(signatureEl)
if err != nil {
return err
}
found := false
err := etreeutils.NSFindIterateCtx(ctx, el, Namespace, SignedInfoTag,
err = etreeutils.NSFindChildrenIterateCtx(ctx, signatureEl, 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,12 +368,18 @@ 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)
}
el.RemoveChild(signedInfo)
el.AddChild(canonicalSignedInfo)
signatureEl.RemoveChild(signedInfo)
signatureEl.AddChild(canonicalSignedInfo)
found = true
@@ -323,7 +395,7 @@ func (ctx *ValidationContext) findSignature(el *etree.Element) (*types.Signature
// Unmarshal the signature into a structured Signature type
_sig := &types.Signature{}
err = etreeutils.NSUnmarshalElement(ctx, el, _sig)
err = etreeutils.NSUnmarshalElement(ctx, signatureEl, _sig)
if err != nil {
return err
}
@@ -363,11 +435,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")
}
+3
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"
)
-2
View File
@@ -1,7 +1,5 @@
module google.golang.org/grpc
go 1.14
require (
cloud.google.com/go v0.26.0 // indirect
github.com/BurntSushi/toml v0.3.1 // indirect
+3 -3
View File
@@ -96,7 +96,7 @@ github.com/aws/aws-sdk-go/service/s3/s3iface
github.com/aws/aws-sdk-go/service/s3/s3manager
github.com/aws/aws-sdk-go/service/sts
github.com/aws/aws-sdk-go/service/sts/stsiface
# github.com/beevik/etree v0.0.0-20170418002358-cda1c0026246
# github.com/beevik/etree v1.1.0
## explicit
github.com/beevik/etree
# github.com/beorn7/perks v1.0.1
@@ -262,7 +262,7 @@ github.com/johannesboyne/gofakes3
github.com/johannesboyne/gofakes3/backend/s3mem
github.com/johannesboyne/gofakes3/internal/goskipiter
github.com/johannesboyne/gofakes3/internal/s3io
# github.com/jonboulle/clockwork v0.1.1-0.20190114141812-62fb9bc030d1
# github.com/jonboulle/clockwork v0.2.1
## explicit
github.com/jonboulle/clockwork
# github.com/json-iterator/go v1.1.9
@@ -354,7 +354,7 @@ github.com/prometheus/procfs/internal/util
## explicit
github.com/russellhaering/gosaml2
github.com/russellhaering/gosaml2/types
# github.com/russellhaering/goxmldsig v0.0.0-20170515183101-605161228693
# github.com/russellhaering/goxmldsig v1.1.0
## explicit
github.com/russellhaering/goxmldsig
github.com/russellhaering/goxmldsig/etreeutils