Skip to content

Commit

Permalink
Get the multiple certificates fix PR (#1)
Browse files Browse the repository at this point in the history
Fix for crewjam#167
  • Loading branch information
bbengfort authored Apr 30, 2019
1 parent ebc5f78 commit cf77aed
Show file tree
Hide file tree
Showing 21 changed files with 70 additions and 54 deletions.
6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
branch = "master"
name = "github.com/russellhaering/goxmldsig"
packages = [".","etreeutils","types"]
revision = "b7efc6231e45b10bfd779852831c8bb59b350ec5"
revision = "92a4e91059a96992cb46191e65fb0933f253bef5"

[[projects]]
name = "github.com/zenazn/goji"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ import (
"net/http"
"net/url"

"github.com/crewjam/saml/samlsp"
"github.com/braineet/saml/samlsp"
)

func hello(w http.ResponseWriter, r *http.Request) {
Expand Down
4 changes: 2 additions & 2 deletions example/idp/idp.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
"flag"
"net/url"

"github.com/crewjam/saml/logger"
"github.com/crewjam/saml/samlidp"
"github.com/braineet/saml/logger"
"github.com/braineet/saml/samlidp"
"github.com/zenazn/goji"
"golang.org/x/crypto/bcrypt"
)
Expand Down
4 changes: 2 additions & 2 deletions example/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import (
"github.com/zenazn/goji"
"github.com/zenazn/goji/web"

"github.com/crewjam/saml/logger"
"github.com/crewjam/saml/samlsp"
"github.com/braineet/saml/logger"
"github.com/braineet/saml/samlsp"
)

var links = map[string]Link{}
Expand Down
2 changes: 1 addition & 1 deletion example/trivial/trivial.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (

"crypto/rsa"

"github.com/crewjam/saml/samlsp"
"github.com/braineet/saml/samlsp"
)

func hello(w http.ResponseWriter, r *http.Request) {
Expand Down
4 changes: 2 additions & 2 deletions identity_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import (
"time"

"github.com/beevik/etree"
"github.com/crewjam/saml/logger"
"github.com/crewjam/saml/xmlenc"
"github.com/braineet/saml/logger"
"github.com/braineet/saml/xmlenc"
dsig "github.com/russellhaering/goxmldsig"
)

Expand Down
6 changes: 3 additions & 3 deletions identity_provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ import (
"os"

"github.com/beevik/etree"
"github.com/crewjam/saml/logger"
"github.com/crewjam/saml/testsaml"
"github.com/crewjam/saml/xmlenc"
"github.com/braineet/saml/logger"
"github.com/braineet/saml/testsaml"
"github.com/braineet/saml/xmlenc"
"github.com/dgrijalva/jwt-go"
. "gopkg.in/check.v1"
)
Expand Down
2 changes: 1 addition & 1 deletion saml.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
// "net/http"
// "net/url"
//
// "github.com/crewjam/saml/samlsp"
// "github.com/braineet/saml/samlsp"
// )
//
// func hello(w http.ResponseWriter, r *http.Request) {
Expand Down
4 changes: 2 additions & 2 deletions samlidp/samlidp.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (
"net/url"
"sync"

"github.com/crewjam/saml"
"github.com/crewjam/saml/logger"
"github.com/braineet/saml"
"github.com/braineet/saml/logger"
"github.com/zenazn/goji/web"
)

Expand Down
4 changes: 2 additions & 2 deletions samlidp/samlidp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import (

"crypto/rsa"

"github.com/crewjam/saml"
"github.com/crewjam/saml/logger"
"github.com/braineet/saml"
"github.com/braineet/saml/logger"
"github.com/dgrijalva/jwt-go"
)

Expand Down
2 changes: 1 addition & 1 deletion samlidp/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"net/http"
"os"

"github.com/crewjam/saml"
"github.com/braineet/saml"
"github.com/zenazn/goji/web"
)

Expand Down
2 changes: 1 addition & 1 deletion samlidp/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

"golang.org/x/crypto/bcrypt"

"github.com/crewjam/saml"
"github.com/braineet/saml"
"github.com/zenazn/goji/web"
)

Expand Down
2 changes: 1 addition & 1 deletion samlidp/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

"io"

"github.com/crewjam/saml"
"github.com/braineet/saml"
)

func randomBytes(n int) []byte {
Expand Down
2 changes: 1 addition & 1 deletion samlsp/cookie.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"strings"
"time"

"github.com/crewjam/saml"
"github.com/braineet/saml"
)

// ClientState implements client side storage for state.
Expand Down
2 changes: 1 addition & 1 deletion samlsp/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"net/http"
"time"

"github.com/crewjam/saml"
"github.com/braineet/saml"
"github.com/dgrijalva/jwt-go"
)

Expand Down
6 changes: 3 additions & 3 deletions samlsp/middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ import (
dsig "github.com/russellhaering/goxmldsig"
. "gopkg.in/check.v1"

"github.com/crewjam/saml"
"github.com/crewjam/saml/logger"
"github.com/crewjam/saml/testsaml"
"github.com/braineet/saml"
"github.com/braineet/saml/logger"
"github.com/braineet/saml/testsaml"
)

// Hook up gocheck into the "go test" runner.
Expand Down
8 changes: 5 additions & 3 deletions samlsp/samlsp.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import (
"net/url"
"time"

"github.com/crewjam/saml"
"github.com/crewjam/saml/logger"
"github.com/braineet/saml"
"github.com/braineet/saml/logger"
)

const defaultTokenMaxAge = time.Hour
Expand All @@ -24,6 +24,7 @@ type Options struct {
Key *rsa.PrivateKey
Logger logger.Interface
Certificate *x509.Certificate
Intermediates []*x509.Certificate
AllowIDPInitiated bool
IDPMetadata *saml.EntityDescriptor
IDPMetadataURL *url.URL
Expand Down Expand Up @@ -56,6 +57,7 @@ func New(opts Options) (*Middleware, error) {
Key: opts.Key,
Logger: logr,
Certificate: opts.Certificate,
Intermediates: opts.Intermediates,
MetadataURL: metadataURL,
AcsURL: acsURL,
IDPMetadata: opts.IDPMetadata,
Expand Down Expand Up @@ -99,7 +101,7 @@ func New(opts Options) (*Middleware, error) {
}
// Some providers (like OneLogin) do not work properly unless the User-Agent header is specified.
// Setting the user agent prevents the 403 Forbidden errors.
req.Header.Set("User-Agent", "Golang; github.com/crewjam/saml")
req.Header.Set("User-Agent", "Golang; github.com/braineet/saml")

for i := 0; true; i++ {
resp, err := c.Do(req)
Expand Down
56 changes: 32 additions & 24 deletions service_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import (
"time"

"github.com/beevik/etree"
"github.com/crewjam/saml/logger"
"github.com/crewjam/saml/xmlenc"
"github.com/braineet/saml/logger"
"github.com/braineet/saml/xmlenc"
dsig "github.com/russellhaering/goxmldsig"
"github.com/russellhaering/goxmldsig/etreeutils"
)
Expand Down Expand Up @@ -55,6 +55,7 @@ type ServiceProvider struct {

// Certificate is the RSA public part of Key.
Certificate *x509.Certificate
Intermediates []*x509.Certificate

// MetadataURL is the full URL to the metadata endpoint on this host,
// i.e. https://example.com/saml/metadata
Expand Down Expand Up @@ -109,6 +110,11 @@ func (sp *ServiceProvider) Metadata() *EntityDescriptor {
authnRequestsSigned := false
wantAssertionsSigned := true
validUntil := TimeNow().Add(validDuration)

certBytes := sp.Certificate.Raw
for _, intermediate := range sp.Intermediates {
certBytes = append(certBytes, intermediate.Raw...)
}
return &EntityDescriptor{
EntityID: sp.MetadataURL.String(),
ValidUntil: validUntil,
Expand All @@ -122,13 +128,13 @@ func (sp *ServiceProvider) Metadata() *EntityDescriptor {
{
Use: "signing",
KeyInfo: KeyInfo{
Certificate: base64.StdEncoding.EncodeToString(sp.Certificate.Raw),
Certificate: base64.StdEncoding.EncodeToString(certBytes),
},
},
{
Use: "encryption",
KeyInfo: KeyInfo{
Certificate: base64.StdEncoding.EncodeToString(sp.Certificate.Raw),
Certificate: base64.StdEncoding.EncodeToString(certBytes),
},
EncryptionMethods: []EncryptionMethod{
{Algorithm: "http://www.w3.org/2001/04/xmlenc#aes128-cbc"},
Expand Down Expand Up @@ -207,46 +213,48 @@ func (sp *ServiceProvider) GetSSOBindingLocation(binding string) string {

// getIDPSigningCert returns the certificate which we can use to verify things
// signed by the IDP in PEM format, or nil if no such certificate is found.
func (sp *ServiceProvider) getIDPSigningCert() (*x509.Certificate, error) {
certStr := ""
func (sp *ServiceProvider) getIDPSigningCert() ([]*x509.Certificate, error) {
var idpCertificates []*x509.Certificate
var certsStr []string
for _, idpSSODescriptor := range sp.IDPMetadata.IDPSSODescriptors {
for _, keyDescriptor := range idpSSODescriptor.KeyDescriptors {
if keyDescriptor.Use == "signing" {
certStr = keyDescriptor.KeyInfo.Certificate
break
certsStr = append(certsStr, keyDescriptor.KeyInfo.Certificate)
}
}
}

// If there are no explicitly signing certs, just return the first
// non-empty cert we find.
if certStr == "" {
if len(certsStr) == 0 {
for _, idpSSODescriptor := range sp.IDPMetadata.IDPSSODescriptors {
for _, keyDescriptor := range idpSSODescriptor.KeyDescriptors {
if keyDescriptor.Use == "" && keyDescriptor.KeyInfo.Certificate != "" {
certStr = keyDescriptor.KeyInfo.Certificate
break
certsStr = append(certsStr, keyDescriptor.KeyInfo.Certificate)
}
}
}
}

if certStr == "" {
if len(certsStr) == 0 {
return nil, errors.New("cannot find any signing certificate in the IDP SSO descriptor")
}


// cleanup whitespace
certStr = regexp.MustCompile(`\s+`).ReplaceAllString(certStr, "")
certBytes, err := base64.StdEncoding.DecodeString(certStr)
if err != nil {
return nil, fmt.Errorf("cannot parse certificate: %s", err)
}
for _, certStr := range certsStr {
certStr = regexp.MustCompile(`\s+`).ReplaceAllString(certStr, "")
certBytes, err := base64.StdEncoding.DecodeString(certStr)
if err != nil {
return nil, fmt.Errorf("cannot parse certificate: %s", err)
}

parsedCert, err := x509.ParseCertificate(certBytes)
if err != nil {
return nil, err
parsedCert, err := x509.ParseCertificate(certBytes)
if err != nil {
return nil, err
}
idpCertificates = append(idpCertificates, parsedCert)
}
return parsedCert, nil
return idpCertificates, nil
}

// MakeAuthenticationRequest produces a new AuthnRequest object for idpURL.
Expand Down Expand Up @@ -627,13 +635,13 @@ func (sp *ServiceProvider) validateSigned(responseEl *etree.Element) error {

// validateSignature returns nill iff the Signature embedded in the element is valid
func (sp *ServiceProvider) validateSignature(el *etree.Element) error {
cert, err := sp.getIDPSigningCert()
certs, err := sp.getIDPSigningCert()
if err != nil {
return err
}

certificateStore := dsig.MemoryX509CertificateStore{
Roots: []*x509.Certificate{cert},
Roots: certs,
}

validationContext := dsig.NewDefaultValidationContext(&certificateStore)
Expand Down
2 changes: 1 addition & 1 deletion service_provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"testing"
"time"

"github.com/crewjam/saml/testsaml"
"github.com/braineet/saml/testsaml"
"github.com/kr/pretty"
dsig "github.com/russellhaering/goxmldsig"

Expand Down

0 comments on commit cf77aed

Please sign in to comment.