Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
D
dex
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
dex
Commits
2a6ae0a6
Commit
2a6ae0a6
authored
Mar 24, 2017
by
Eric Chiang
Committed by
GitHub
Mar 24, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #870 from Calpicow/fix_assertion_fallback
Fix assertion fallback
parents
5d49e184
6f9ef961
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
438 additions
and
151 deletions
+438
-151
saml.go
connector/saml/saml.go
+4
-2
saml_test.go
connector/saml/saml_test.go
+4
-0
oam-ca.pem
connector/saml/testdata/oam-ca.pem
+13
-0
oam-resp.xml
connector/saml/testdata/oam-resp.xml
+1
-0
glide.lock
glide.lock
+4
-3
glide.yaml
glide.yaml
+2
-2
canonicalize.go
vendor/github.com/russellhaering/goxmldsig/canonicalize.go
+9
-101
canonicalize.go
...b.com/russellhaering/goxmldsig/etreeutils/canonicalize.go
+98
-0
namespace.go
...thub.com/russellhaering/goxmldsig/etreeutils/namespace.go
+108
-32
sort.go
...or/github.com/russellhaering/goxmldsig/etreeutils/sort.go
+29
-6
unmarshal.go
...thub.com/russellhaering/goxmldsig/etreeutils/unmarshal.go
+43
-0
sign.go
vendor/github.com/russellhaering/goxmldsig/sign.go
+30
-5
signature.go
...or/github.com/russellhaering/goxmldsig/types/signature.go
+93
-0
validate.go
vendor/github.com/russellhaering/goxmldsig/validate.go
+0
-0
No files found.
connector/saml/saml.go
View file @
2a6ae0a6
...
...
@@ -17,6 +17,7 @@ import (
"github.com/Sirupsen/logrus"
"github.com/beevik/etree"
dsig
"github.com/russellhaering/goxmldsig"
"github.com/russellhaering/goxmldsig/etreeutils"
"github.com/coreos/dex/connector"
)
...
...
@@ -500,8 +501,9 @@ func verify(validator *dsig.ValidationContext, data []byte) (signed []byte, err
verified
=
true
doc
.
SetRoot
(
transformedResponse
)
}
assertion
:=
response
.
SelectElement
(
"Assertion"
)
if
assertion
==
nil
{
// Ensures xmlns are copied down to the assertion element when they are defined in the root
assertion
,
err
:=
etreeutils
.
NSSelectOne
(
response
,
"urn:oasis:names:tc:SAML:2.0:assertion"
,
"Assertion"
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"response does not contain an Assertion element"
)
}
transformedAssertion
,
err
:=
validator
.
Validate
(
assertion
)
...
...
connector/saml/saml_test.go
View file @
2a6ae0a6
...
...
@@ -86,6 +86,10 @@ func TestVerify(t *testing.T) {
runVerify
(
t
,
"testdata/okta-ca.pem"
,
"testdata/okta-resp.xml"
,
true
)
}
func
TestVerifyUnsignedMessageAndSignedAssertionWithRootXmlNs
(
t
*
testing
.
T
)
{
runVerify
(
t
,
"testdata/oam-ca.pem"
,
"testdata/oam-resp.xml"
,
true
)
}
func
TestVerifySignedMessageAndUnsignedAssertion
(
t
*
testing
.
T
)
{
runVerify
(
t
,
"testdata/idp-cert.pem"
,
"testdata/idp-resp-signed-message.xml"
,
true
)
}
...
...
connector/saml/testdata/oam-ca.pem
0 → 100644
View file @
2a6ae0a6
-----BEGIN CERTIFICATE-----
MIIB/jCCAWegAwIBAgIBCjANBgkqhkiG9w0BAQQFADAkMSIwIAYDVQQDExlkZWFv
YW0tZGV2MDIuanBsLm5hc2EuZ292MB4XDTE2MDYzMDA0NTQxNloXDTI2MDYyODA0
NTQxNlowJDEiMCAGA1UEAxMZZGVhb2FtLWRldjAyLmpwbC5uYXNhLmdvdjCBnzAN
BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAht1N4lGdwUbl7YRyHwSCrnep6/e2I3+V
eue0pSA/DGn8OuR/udM8UCja5utqlqJdq200ox4b4Mpz0Jg9kMckALtKe+1DgeES
EIx9FpeuBdHlitYQNSbEr30HIG2nmeTOy4Vi5unBO54um3tNazcUTMA0/LJ6KQL8
LeZSlB/IxwUCAwEAAaNAMD4wDAYDVR0TAQH/BAIwADAPBgNVHQ8BAf8EBQMDB9gA
MB0GA1UdDgQWBBRYo1YjfrNonauLzj6/AsueWFGSszANBgkqhkiG9w0BAQQFAAOB
gQACq7GHK/Zsg0+qC0WWa2ZjmOXE6Dqk/xuooG49QT7ihABs7k9U27Fw3xKF6MkC
7pca1FwT82eZK1N3XKKpZe7Flu1fMKt2o/XSiBkDjWwUcChVnwGsUBe8hJFwFqg7
olNJn1kaVBJUqZIiXF9kS0d+1H55rStOd0CNXAzp9utr2A==
-----END CERTIFICATE-----
connector/saml/testdata/oam-resp.xml
0 → 100644
View file @
2a6ae0a6
<samlp:Response
xmlns:samlp=
"urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:dsig=
"http://www.w3.org/2000/09/xmldsig#"
xmlns:enc=
"http://www.w3.org/2001/04/xmlenc#"
xmlns:saml=
"urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:x500=
"urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
Destination=
"http://127.0.0.1:5556/callback"
ID=
"id-IWlPTptSB-PlR80dwt8ZhVeG70mrz7nPvTVrhduK"
InResponseTo=
"_e66b3a98-831c-4c96-5706-b63fe0549624"
IssueInstant=
"2016-12-12T16:54:35Z"
Version=
"2.0"
><saml:Issuer
Format=
"urn:oasis:names:tc:SAML:2.0:nameid-format:entity"
>
https://deaoam-dev02.jpl.nasa.gov:14101/oam/fed
</saml:Issuer><samlp:Status><samlp:StatusCode
Value=
"urn:oasis:names:tc:SAML:2.0:status:Success"
/></samlp:Status><saml:Assertion
ID=
"id-rT9rTqxdQC9j34YhVeNayUWC9EbIBgym6gp-MZt-"
IssueInstant=
"2016-12-12T16:54:35Z"
Version=
"2.0"
><saml:Issuer
Format=
"urn:oasis:names:tc:SAML:2.0:nameid-format:entity"
>
https://deaoam-dev02.jpl.nasa.gov:14101/oam/fed
</saml:Issuer><dsig:Signature><dsig:SignedInfo><dsig:CanonicalizationMethod
Algorithm=
"http://www.w3.org/2001/10/xml-exc-c14n#"
/><dsig:SignatureMethod
Algorithm=
"http://www.w3.org/2000/09/xmldsig#rsa-sha1"
/><dsig:Reference
URI=
"#id-rT9rTqxdQC9j34YhVeNayUWC9EbIBgym6gp-MZt-"
><dsig:Transforms><dsig:Transform
Algorithm=
"http://www.w3.org/2000/09/xmldsig#enveloped-signature"
/><dsig:Transform
Algorithm=
"http://www.w3.org/2001/10/xml-exc-c14n#"
/></dsig:Transforms><dsig:DigestMethod
Algorithm=
"http://www.w3.org/2000/09/xmldsig#sha1"
/><dsig:DigestValue>
z1HD/59hv6UOd5+jeG+ihaFWLgI=
</dsig:DigestValue></dsig:Reference></dsig:SignedInfo><dsig:SignatureValue>
I99oG5kiOfIgbXYa21z/TOmzftTkFnXe9ObhBNSKit9kAhT93apYROqqXv4Ax96P144Ld7ERX1hgJsytK8LC2874Pk7QrSNm4zvW3x0D4GR4lM06CvJK/EhIur3TrCUJDPigvyP7TJitheCyBejwt0x0lqNP/OzR3tMbAIMRoho=
</dsig:SignatureValue></dsig:Signature><saml:Subject><saml:NameID
Format=
"urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
NameQualifier=
"https://deaoam-dev02.jpl.nasa.gov:14101/oam/fed"
SPNameQualifier=
"JSAuth"
>
pkieu
</saml:NameID><saml:SubjectConfirmation
Method=
"urn:oasis:names:tc:SAML:2.0:cm:bearer"
><saml:SubjectConfirmationData
InResponseTo=
"_e66b3a98-831c-4c96-5706-b63fe0549624"
NotOnOrAfter=
"2016-12-12T16:59:35Z"
Recipient=
"http://127.0.0.1:5556/callback"
/></saml:SubjectConfirmation></saml:Subject><saml:Conditions
NotBefore=
"2016-12-12T16:54:35Z"
NotOnOrAfter=
"2016-12-12T16:59:35Z"
><saml:AudienceRestriction><saml:Audience>
JSAuth
</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement
AuthnInstant=
"2016-12-12T16:54:10Z"
SessionIndex=
"id-l3NCbxKoBfUZcuKhlotMuIF3ydgYJgGGG6BGTTU6"
SessionNotOnOrAfter=
"2016-12-12T17:54:35Z"
><saml:AuthnContext><saml:AuthnContextClassRef>
urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement></saml:Assertion></samlp:Response>
glide.lock
View file @
2a6ae0a6
hash:
4a3ac3a2a2b39357dc5de7ba296dbe20a97dd2fe13bc15a68e904e69afae2adb
updated: 2017-03-2
1T09:24:08.089284929
-07:00
hash:
ba77a77f03b1750479aa4a61de59d7a545dc8bd5c71be10e1c2e9afed37e1925
updated: 2017-03-2
4T11:03:21.332291207
-07:00
imports:
- name: github.com/beevik/etree
version: 4cd0dd976db869f817248477718071a28e978df0
...
...
@@ -46,9 +46,10 @@ imports:
subpackages:
- cacheobject
- name: github.com/russellhaering/goxmldsig
version:
51810e925e5fc495822fbddda8202f70a6e4a3f3
version:
eaac44c63fe007124f8f6255b09febc906784981
subpackages:
- etreeutils
- types
- name: github.com/Sirupsen/logrus
version: d26492970760ca5d33129d2d799e34be5c4782eb
- name: github.com/spf13/cobra
...
...
glide.yaml
View file @
2a6ae0a6
...
...
@@ -73,7 +73,7 @@ import:
-
package
:
golang.org/x/oauth2
version
:
08c8d727d2392d18286f9f88ad775ad98f09ab33
subpackages
:
[]
# The oauth2 package only imports the appengine code when it's given a
# The oauth2 package only imports the appengine code when it's given a
# specific build tags, but glide detects it anyway.
#
# https://github.com/golang/oauth2/blob/d5040cdd/client_appengine.go
...
...
@@ -133,7 +133,7 @@ import:
# XML signature validation for SAML connector
-
package
:
github.com/russellhaering/goxmldsig
version
:
51810e925e5fc495822fbddda8202f70a6e4a3f3
version
:
eaac44c63fe007124f8f6255b09febc906784981
-
package
:
github.com/beevik/etree
version
:
4cd0dd976db869f817248477718071a28e978df0
-
package
:
github.com/jonboulle/clockwork
...
...
vendor/github.com/russellhaering/goxmldsig/canonicalize.go
View file @
2a6ae0a6
...
...
@@ -2,7 +2,6 @@ package dsig
import
(
"sort"
"strings"
"github.com/beevik/etree"
"github.com/russellhaering/goxmldsig/etreeutils"
...
...
@@ -15,28 +14,25 @@ type Canonicalizer interface {
}
type
c14N10ExclusiveCanonicalizer
struct
{
InclusiveNamespaces
map
[
string
]
struct
{}
prefixList
string
}
// MakeC14N10ExclusiveCanonicalizerWithPrefixList constructs an exclusive Canonicalizer
// from a PrefixList in NMTOKENS format (a white space separated list).
func
MakeC14N10ExclusiveCanonicalizerWithPrefixList
(
prefixList
string
)
Canonicalizer
{
prefixes
:=
strings
.
Fields
(
prefixList
)
prefixSet
:=
make
(
map
[
string
]
struct
{},
len
(
prefixes
))
for
_
,
prefix
:=
range
prefixes
{
prefixSet
[
prefix
]
=
struct
{}{}
}
return
&
c14N10ExclusiveCanonicalizer
{
InclusiveNamespaces
:
prefixSe
t
,
prefixList
:
prefixLis
t
,
}
}
// Canonicalize transforms the input Element into a serialized XML document in canonical form.
func
(
c
*
c14N10ExclusiveCanonicalizer
)
Canonicalize
(
el
*
etree
.
Element
)
([]
byte
,
error
)
{
scope
:=
make
(
map
[
string
]
c14nSpace
)
return
canonicalSerialize
(
excCanonicalPrep
(
el
,
scope
,
c
.
InclusiveNamespaces
))
err
:=
etreeutils
.
TransformExcC14n
(
el
,
c
.
prefixList
)
if
err
!=
nil
{
return
nil
,
err
}
return
canonicalSerialize
(
el
)
}
func
(
c
*
c14N10ExclusiveCanonicalizer
)
Algorithm
()
AlgorithmID
{
...
...
@@ -75,94 +71,6 @@ type c14nSpace struct {
const
nsSpace
=
"xmlns"
// excCanonicalPrep accepts an *etree.Element and recursively transforms it into one
// which is ready for serialization to exclusive canonical form. Specifically this
// entails:
//
// 1. Stripping re-declarations of namespaces
// 2. Stripping unused namespaces
// 3. Sorting attributes into canonical order.
//
// NOTE(russell_h): Currently this function modifies the passed element.
func
excCanonicalPrep
(
el
*
etree
.
Element
,
_nsAlreadyDeclared
map
[
string
]
c14nSpace
,
inclusiveNamespaces
map
[
string
]
struct
{})
*
etree
.
Element
{
//Copy alreadyDeclared map (only contains namespaces)
nsAlreadyDeclared
:=
make
(
map
[
string
]
c14nSpace
,
len
(
_nsAlreadyDeclared
))
for
k
:=
range
_nsAlreadyDeclared
{
nsAlreadyDeclared
[
k
]
=
_nsAlreadyDeclared
[
k
]
}
//Track the namespaces used on the current element
nsUsedHere
:=
make
(
map
[
string
]
struct
{})
//Make sure to track the element namespace for the case:
//<foo:bar xmlns:foo="..."/>
if
el
.
Space
!=
""
{
nsUsedHere
[
el
.
Space
]
=
struct
{}{}
}
toRemove
:=
make
([]
string
,
0
,
0
)
for
_
,
a
:=
range
el
.
Attr
{
switch
a
.
Space
{
case
nsSpace
:
//For simplicity, remove all xmlns attribues; to be added in one pass
//later. Otherwise, we need another map/set to track xmlns attributes
//that we left alone.
toRemove
=
append
(
toRemove
,
a
.
Space
+
":"
+
a
.
Key
)
if
_
,
ok
:=
nsAlreadyDeclared
[
a
.
Key
];
!
ok
{
//If we're not tracking ancestor state already for this namespace, add
//it to the map
nsAlreadyDeclared
[
a
.
Key
]
=
c14nSpace
{
a
:
a
,
used
:
false
}
}
// This algorithm accepts a set of namespaces which should be treated
// in an inclusive fashion. Specifically that means we should keep the
// declaration of that namespace closest to the root of the tree. We can
// accomplish that be pretending it was used by this element.
_
,
inclusive
:=
inclusiveNamespaces
[
a
.
Key
]
if
inclusive
{
nsUsedHere
[
a
.
Key
]
=
struct
{}{}
}
default
:
//We only track namespaces, so ignore attributes without one.
if
a
.
Space
!=
""
{
nsUsedHere
[
a
.
Space
]
=
struct
{}{}
}
}
}
//Remove all attributes so that we can add them with much-simpler logic
for
_
,
attrK
:=
range
toRemove
{
el
.
RemoveAttr
(
attrK
)
}
//For all namespaces used on the current element, declare them if they were
//not declared (and used) in an ancestor.
for
k
:=
range
nsUsedHere
{
spc
:=
nsAlreadyDeclared
[
k
]
//If previously unused, mark as used
if
!
spc
.
used
{
el
.
Attr
=
append
(
el
.
Attr
,
spc
.
a
)
spc
.
used
=
true
//Assignment here is only to update the pre-existing `used` tracking value
nsAlreadyDeclared
[
k
]
=
spc
}
}
//Canonicalize all children, passing down the ancestor tracking map
for
_
,
child
:=
range
el
.
ChildElements
()
{
excCanonicalPrep
(
child
,
nsAlreadyDeclared
,
inclusiveNamespaces
)
}
//Sort attributes lexicographically
sort
.
Sort
(
etreeutils
.
SortedAttrs
(
el
.
Attr
))
return
el
.
Copy
()
}
// canonicalPrep accepts an *etree.Element and transforms it into one which is ready
// for serialization into inclusive canonical form. Specifically this
// entails:
...
...
@@ -208,7 +116,7 @@ func canonicalPrep(el *etree.Element, seenSoFar map[string]struct{}) *etree.Elem
func
canonicalSerialize
(
el
*
etree
.
Element
)
([]
byte
,
error
)
{
doc
:=
etree
.
NewDocument
()
doc
.
SetRoot
(
el
)
doc
.
SetRoot
(
el
.
Copy
()
)
doc
.
WriteSettings
=
etree
.
WriteSettings
{
CanonicalAttrVal
:
true
,
...
...
vendor/github.com/russellhaering/goxmldsig/etreeutils/canonicalize.go
0 → 100644
View file @
2a6ae0a6
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
}
vendor/github.com/russellhaering/goxmldsig/etreeutils/namespace.go
View file @
2a6ae0a6
...
...
@@ -47,13 +47,38 @@ type NSContext struct {
prefixes
map
[
string
]
string
}
func
(
ctx
NSContext
)
SubContext
(
el
*
etree
.
Element
)
(
NSContext
,
error
)
{
// The subcontext should inherit existing declared prefixes
func
(
ctx
NSContext
)
Copy
()
NSContext
{
prefixes
:=
make
(
map
[
string
]
string
,
len
(
ctx
.
prefixes
)
+
4
)
for
k
,
v
:=
range
ctx
.
prefixes
{
prefixes
[
k
]
=
v
}
return
NSContext
{
prefixes
:
prefixes
}
}
func
(
ctx
NSContext
)
declare
(
prefix
,
namespace
string
)
etree
.
Attr
{
ctx
.
prefixes
[
prefix
]
=
namespace
switch
prefix
{
case
defaultPrefix
:
return
etree
.
Attr
{
Key
:
xmlnsPrefix
,
Value
:
namespace
,
}
default
:
return
etree
.
Attr
{
Space
:
xmlnsPrefix
,
Key
:
prefix
,
Value
:
namespace
,
}
}
}
func
(
ctx
NSContext
)
SubContext
(
el
*
etree
.
Element
)
(
NSContext
,
error
)
{
// The subcontext should inherit existing declared prefixes
newCtx
:=
ctx
.
Copy
()
// Merge new namespace declarations on top of existing ones.
for
_
,
attr
:=
range
el
.
Attr
{
if
attr
.
Space
==
xmlnsPrefix
{
...
...
@@ -69,7 +94,7 @@ func (ctx NSContext) SubContext(el *etree.Element) (NSContext, error) {
return
ctx
,
ErrReservedNamespace
}
prefixes
[
attr
.
Key
]
=
attr
.
Value
newCtx
.
declare
(
attr
.
Key
,
attr
.
Value
)
}
else
if
attr
.
Space
==
defaultPrefix
&&
attr
.
Key
==
xmlnsPrefix
{
// This attribute is a default namespace declaration
...
...
@@ -78,11 +103,21 @@ func (ctx NSContext) SubContext(el *etree.Element) (NSContext, error) {
return
ctx
,
ErrInvalidDefaultNamespace
}
prefixes
[
defaultPrefix
]
=
attr
.
Value
newCtx
.
declare
(
defaultPrefix
,
attr
.
Value
)
}
}
return
NSContext
{
prefixes
:
prefixes
},
nil
return
newCtx
,
nil
}
// Prefixes returns a copy of this context's prefix map.
func
(
ctx
NSContext
)
Prefixes
()
map
[
string
]
string
{
prefixes
:=
make
(
map
[
string
]
string
,
len
(
ctx
.
prefixes
))
for
k
,
v
:=
range
ctx
.
prefixes
{
prefixes
[
k
]
=
v
}
return
prefixes
}
// LookupPrefix attempts to find a declared namespace for the specified prefix. If the prefix
...
...
@@ -98,7 +133,13 @@ func (ctx NSContext) LookupPrefix(prefix string) (string, error) {
}
}
func
nsTraverse
(
ctx
NSContext
,
el
*
etree
.
Element
,
handle
func
(
NSContext
,
*
etree
.
Element
)
error
)
error
{
// NSIterHandler is a function which is invoked with a element and its surrounding
// NSContext during traversals.
type
NSIterHandler
func
(
NSContext
,
*
etree
.
Element
)
error
// NSTraverse traverses an element tree, invoking the passed handler for each element
// in the tree.
func
NSTraverse
(
ctx
NSContext
,
el
*
etree
.
Element
,
handle
NSIterHandler
)
error
{
ctx
,
err
:=
ctx
.
SubContext
(
el
)
if
err
!=
nil
{
return
err
...
...
@@ -111,7 +152,7 @@ func nsTraverse(ctx NSContext, el *etree.Element, handle func(NSContext, *etree.
// Recursively traverse child elements.
for
_
,
child
:=
range
el
.
ChildElements
()
{
err
:=
ns
Traverse
(
ctx
,
child
,
handle
)
err
:=
NS
Traverse
(
ctx
,
child
,
handle
)
if
err
!=
nil
{
return
err
}
...
...
@@ -120,7 +161,9 @@ func nsTraverse(ctx NSContext, el *etree.Element, handle func(NSContext, *etree.
return
nil
}
func
detachWithNamespaces
(
ctx
NSContext
,
el
*
etree
.
Element
)
(
*
etree
.
Element
,
error
)
{
// NSDetatch makes a copy of the passed element, and declares any namespaces in
// the passed context onto the new element before returning it.
func
NSDetatch
(
ctx
NSContext
,
el
*
etree
.
Element
)
(
*
etree
.
Element
,
error
)
{
ctx
,
err
:=
ctx
.
SubContext
(
el
)
if
err
!=
nil
{
return
nil
,
err
...
...
@@ -177,43 +220,52 @@ func detachWithNamespaces(ctx NSContext, el *etree.Element) (*etree.Element, err
return
el
,
nil
}
// NSSelectOne conducts a depth-first search for an element with the specified namespace
// NSSelectOne behaves identically to NSSelectOneCtx, but uses DefaultNSContext as the
// surrounding context.
func
NSSelectOne
(
el
*
etree
.
Element
,
namespace
,
tag
string
)
(
*
etree
.
Element
,
error
)
{
return
NSSelectOneCtx
(
DefaultNSContext
,
el
,
namespace
,
tag
)
}
// NSSelectOneCtx conducts a depth-first search for an element with the specified namespace
// and tag. If such an element is found, a new *etree.Element is returned which is a
// copy of the found element, but with all in-context namespace declarations attached
// to the element as attributes.
func
NSSelectOne
(
el
*
etree
.
Element
,
namespace
,
tag
string
)
(
*
etree
.
Element
,
error
)
{
func
NSSelectOne
Ctx
(
ctx
NSContext
,
el
*
etree
.
Element
,
namespace
,
tag
string
)
(
*
etree
.
Element
,
error
)
{
var
found
*
etree
.
Element
err
:=
nsTraverse
(
DefaultNSContext
,
el
,
func
(
ctx
NSContext
,
el
*
etree
.
Element
)
error
{
currentNS
,
err
:=
ctx
.
LookupPrefix
(
el
.
Space
)
err
:=
NSFindIterateCtx
(
ctx
,
el
,
namespace
,
tag
,
func
(
ctx
NSContext
,
el
*
etree
.
Element
)
error
{
var
err
error
found
,
err
=
NSDetatch
(
ctx
,
el
)
if
err
!=
nil
{
return
err
}
// Base case, el is the sought after element.
if
currentNS
==
namespace
&&
el
.
Tag
==
tag
{
found
,
err
=
detachWithNamespaces
(
ctx
,
el
)
return
ErrTraversalHalted
}
return
nil
return
ErrTraversalHalted
})
if
err
!=
nil
&&
err
!=
ErrTraversalHalted
{
if
err
!=
nil
{
return
nil
,
err
}
return
found
,
nil
}
// NSFindIterate conducts a depth-first traversal searching for elements with the
// specified tag in the specified namespace. For each such element, the passed
// handler function is invoked. If the handler function returns an error
// traversal is immediately halted. If the error returned by the handler is
// ErrTraversalHalted then nil will be returned by NSFindIterate. If any other
// error is returned by the handler, that error will be returned by NSFindIterate.
func
NSFindIterate
(
el
*
etree
.
Element
,
namespace
,
tag
string
,
handle
func
(
*
etree
.
Element
)
error
)
error
{
err
:=
nsTraverse
(
DefaultNSContext
,
el
,
func
(
ctx
NSContext
,
el
*
etree
.
Element
)
error
{
// NSFindIterate behaves identically to NSFindIterateCtx, but uses DefaultNSContext
// as the surrounding context.
func
NSFindIterate
(
el
*
etree
.
Element
,
namespace
,
tag
string
,
handle
NSIterHandler
)
error
{
return
NSFindIterateCtx
(
DefaultNSContext
,
el
,
namespace
,
tag
,
handle
)
}
// NSFindIterateCtx conducts a depth-first traversal searching for elements with the
// specified tag in the specified namespace. It uses the passed NSContext for prefix
// lookups. For each such element, the passed handler function is invoked. If the
// handler function returns an error traversal is immediately halted. If the error
// returned by the handler is ErrTraversalHalted then nil will be returned by
// NSFindIterate. If any other error is returned by the handler, that error will be
// 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
)
if
err
!=
nil
{
return
err
...
...
@@ -221,7 +273,7 @@ func NSFindIterate(el *etree.Element, namespace, tag string, handle func(*etree.
// Base case, el is the sought after element.
if
currentNS
==
namespace
&&
el
.
Tag
==
tag
{
return
handle
(
el
)
return
handle
(
ctx
,
el
)
}
return
nil
...
...
@@ -234,12 +286,18 @@ func NSFindIterate(el *etree.Element, namespace, tag string, handle func(*etree.
return
nil
}
// NSFindOne
conducts a depth-first search for the specified element. If such an element
//
is found a reference to it is returned
.
// NSFindOne
behaves identically to NSFindOneCtx, but uses DefaultNSContext for
//
context
.
func
NSFindOne
(
el
*
etree
.
Element
,
namespace
,
tag
string
)
(
*
etree
.
Element
,
error
)
{
return
NSFindOneCtx
(
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
NSFindOneCtx
(
ctx
NSContext
,
el
*
etree
.
Element
,
namespace
,
tag
string
)
(
*
etree
.
Element
,
error
)
{
var
found
*
etree
.
Element
err
:=
NSFindIterate
(
el
,
namespace
,
tag
,
func
(
el
*
etree
.
Element
)
error
{
err
:=
NSFindIterate
Ctx
(
ctx
,
el
,
namespace
,
tag
,
func
(
ctx
NSContext
,
el
*
etree
.
Element
)
error
{
found
=
el
return
ErrTraversalHalted
})
...
...
@@ -250,3 +308,21 @@ func NSFindOne(el *etree.Element, namespace, tag string) (*etree.Element, error)
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.
func
NSBuildParentContext
(
el
*
etree
.
Element
)
(
NSContext
,
error
)
{
parent
:=
el
.
Parent
()
if
parent
==
nil
{
return
DefaultNSContext
,
nil
}
ctx
,
err
:=
NSBuildParentContext
(
parent
)
if
err
!=
nil
{
return
ctx
,
err
}
return
ctx
.
SubContext
(
parent
)
}
vendor/github.com/russellhaering/goxmldsig/etreeutils/sort.go
View file @
2a6ae0a6
...
...
@@ -2,6 +2,8 @@ package etreeutils
import
"github.com/beevik/etree"
// SortedAttrs provides sorting capabilities, compatible with XML C14N, on top
// of an []etree.Attr
type
SortedAttrs
[]
etree
.
Attr
func
(
a
SortedAttrs
)
Len
()
int
{
...
...
@@ -13,17 +15,23 @@ func (a SortedAttrs) Swap(i, j int) {
}
func
(
a
SortedAttrs
)
Less
(
i
,
j
int
)
bool
{
// As I understand it: any "xmlns" attribute should come first, followed by any
// any "xmlns:prefix" attributes, presumably ordered by prefix. Lastly any other
// attributes in lexicographical order.
if
a
[
i
]
.
Space
==
defaultPrefix
&&
a
[
i
]
.
Key
==
xmlnsPrefix
{
return
true
}
// This is the best reference I've found on sort order:
// http://dst.lbl.gov/~ksb/Scratch/XMLC14N.html
// If attr j is a default namespace declaration, attr i may
// not be strictly "less" than it.
if
a
[
j
]
.
Space
==
defaultPrefix
&&
a
[
j
]
.
Key
==
xmlnsPrefix
{
return
false
}
// Otherwise, if attr i is a default namespace declaration, it
// must be less than anything else.
if
a
[
i
]
.
Space
==
defaultPrefix
&&
a
[
i
]
.
Key
==
xmlnsPrefix
{
return
true
}
// Next, namespace prefix declarations, sorted by prefix, come before
// anythign else.
if
a
[
i
]
.
Space
==
xmlnsPrefix
{
if
a
[
j
]
.
Space
==
xmlnsPrefix
{
return
a
[
i
]
.
Key
<
a
[
j
]
.
Key
...
...
@@ -35,6 +43,21 @@ func (a SortedAttrs) Less(i, j int) bool {
return
false
}
// Then come unprefixed attributes, sorted by key.
if
a
[
i
]
.
Space
==
defaultPrefix
{
if
a
[
j
]
.
Space
==
defaultPrefix
{
return
a
[
i
]
.
Key
<
a
[
j
]
.
Key
}
return
true
}
if
a
[
j
]
.
Space
==
defaultPrefix
{
return
false
}
// Wow. We're still going. Finally, attributes in the same namespace should be
// sorted by key. Attributes in different namespaces should be sorted by the
// actual namespace (_not_ the prefix). For now just use the prefix.
if
a
[
i
]
.
Space
==
a
[
j
]
.
Space
{
return
a
[
i
]
.
Key
<
a
[
j
]
.
Key
}
...
...
vendor/github.com/russellhaering/goxmldsig/etreeutils/unmarshal.go
0 → 100644
View file @
2a6ae0a6
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
}
vendor/github.com/russellhaering/goxmldsig/sign.go
View file @
2a6ae0a6
...
...
@@ -11,6 +11,7 @@ import (
"fmt"
"github.com/beevik/etree"
"github.com/russellhaering/goxmldsig/etreeutils"
)
type
SigningContext
struct
{
...
...
@@ -133,15 +134,39 @@ func (ctx *SigningContext) constructSignature(el *etree.Element, enveloped bool)
}
sig
.
CreateAttr
(
xmlns
,
Namespace
)
sig
.
AddChild
(
signedInfo
)
sig
.
Child
=
append
(
sig
.
Child
,
signedInfo
)
// When using xml-c14n11 (ie, non-exclusive canonicalization) the canonical form
// of the SignedInfo must declare all namespaces that are in scope at it's final
// enveloped location in the document. In order to do that, we're going to construct
// a series of cascading NSContexts to capture namespace declarations:
// Must propagate down the attributes to the 'SignedInfo' before digesting
for
_
,
attr
:=
range
sig
.
Attr
{
signedInfo
.
CreateAttr
(
attr
.
Space
+
":"
+
attr
.
Key
,
attr
.
Value
)
// First get the context surrounding the element we are signing.
rootNSCtx
,
err
:=
etreeutils
.
NSBuildParentContext
(
el
)
if
err
!=
nil
{
return
nil
,
err
}
// Then capture any declarations on the element itself.
elNSCtx
,
err
:=
rootNSCtx
.
SubContext
(
el
)
if
err
!=
nil
{
return
nil
,
err
}
// Followed by declarations on the Signature (which we just added above)
sigNSCtx
,
err
:=
elNSCtx
.
SubContext
(
sig
)
if
err
!=
nil
{
return
nil
,
err
}
// Finally detatch the SignedInfo in order to capture all of the namespace
// declarations in the scope we've constructed.
detatchedSignedInfo
,
err
:=
etreeutils
.
NSDetatch
(
sigNSCtx
,
signedInfo
)
if
err
!=
nil
{
return
nil
,
err
}
digest
,
err
:=
ctx
.
digest
(
s
ignedInfo
)
digest
,
err
:=
ctx
.
digest
(
detatchedS
ignedInfo
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
vendor/github.com/russellhaering/goxmldsig/types/signature.go
0 → 100644
View file @
2a6ae0a6
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
}
vendor/github.com/russellhaering/goxmldsig/validate.go
View file @
2a6ae0a6
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment