2019-03-11 16:56:48 +00:00
package tlsalpn01
2018-06-13 23:20:56 +00:00
import (
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/subtle"
"crypto/tls"
"encoding/asn1"
2018-12-06 21:50:17 +00:00
"net/http"
2018-06-13 23:20:56 +00:00
"testing"
2018-09-15 17:16:35 +00:00
2019-03-11 16:56:48 +00:00
"github.com/go-acme/lego/acme"
"github.com/go-acme/lego/acme/api"
"github.com/go-acme/lego/challenge"
"github.com/go-acme/lego/platform/tester"
2018-09-15 17:16:35 +00:00
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
2018-06-13 23:20:56 +00:00
)
2018-12-06 21:50:17 +00:00
func TestChallenge ( t * testing . T ) {
_ , apiURL , tearDown := tester . SetupFakeAPI ( )
defer tearDown ( )
2018-06-13 23:20:56 +00:00
domain := "localhost:23457"
2018-09-15 17:16:35 +00:00
2018-12-06 21:50:17 +00:00
mockValidate := func ( _ * api . Core , _ string , chlng acme . Challenge ) error {
2018-06-13 23:20:56 +00:00
conn , err := tls . Dial ( "tcp" , domain , & tls . Config {
InsecureSkipVerify : true ,
} )
2018-10-12 17:29:18 +00:00
require . NoError ( t , err , "Expected to connect to challenge server without an error" )
2018-06-13 23:20:56 +00:00
// Expect the server to only return one certificate
connState := conn . ConnectionState ( )
2018-09-15 17:16:35 +00:00
assert . Len ( t , connState . PeerCertificates , 1 , "Expected the challenge server to return exactly one certificate" )
2018-06-13 23:20:56 +00:00
remoteCert := connState . PeerCertificates [ 0 ]
2018-09-15 17:16:35 +00:00
assert . Len ( t , remoteCert . DNSNames , 1 , "Expected the challenge certificate to have exactly one DNSNames entry" )
assert . Equal ( t , domain , remoteCert . DNSNames [ 0 ] , "challenge certificate DNSName " )
assert . NotEmpty ( t , remoteCert . Extensions , "Expected the challenge certificate to contain extensions" )
2018-06-13 23:20:56 +00:00
idx := - 1
for i , ext := range remoteCert . Extensions {
if idPeAcmeIdentifierV1 . Equal ( ext . Id ) {
idx = i
break
}
}
2018-09-15 17:16:35 +00:00
require . NotEqual ( t , - 1 , idx , "Expected the challenge certificate to contain an extension with the id-pe-acmeIdentifier id," )
2018-06-13 23:20:56 +00:00
ext := remoteCert . Extensions [ idx ]
2018-09-15 17:16:35 +00:00
assert . True ( t , ext . Critical , "Expected the challenge certificate id-pe-acmeIdentifier extension to be marked as critical" )
2018-06-13 23:20:56 +00:00
zBytes := sha256 . Sum256 ( [ ] byte ( chlng . KeyAuthorization ) )
value , err := asn1 . Marshal ( zBytes [ : sha256 . Size ] )
2018-09-15 17:16:35 +00:00
require . NoError ( t , err , "Expected marshaling of the keyAuth to return no error" )
2018-12-06 21:50:17 +00:00
if subtle . ConstantTimeCompare ( value , ext . Value ) != 1 {
2018-06-13 23:20:56 +00:00
t . Errorf ( "Expected the challenge certificate id-pe-acmeIdentifier extension to contain the SHA-256 digest of the keyAuth, %v, but was %v" , zBytes [ : ] , ext . Value )
}
return nil
}
2018-09-15 17:16:35 +00:00
2018-12-06 21:50:17 +00:00
privateKey , err := rsa . GenerateKey ( rand . Reader , 512 )
2018-09-15 17:16:35 +00:00
require . NoError ( t , err , "Could not generate test key" )
2018-12-06 21:50:17 +00:00
core , err := api . New ( http . DefaultClient , "lego-test" , apiURL + "/dir" , "" , privateKey )
require . NoError ( t , err )
2018-09-15 17:16:35 +00:00
2018-12-06 21:50:17 +00:00
solver := NewChallenge (
core ,
mockValidate ,
& ProviderServer { port : "23457" } ,
)
authz := acme . Authorization {
Identifier : acme . Identifier {
Value : domain ,
} ,
Challenges : [ ] acme . Challenge {
{ Type : challenge . TLSALPN01 . String ( ) , Token : "tlsalpn1" } ,
} ,
}
2018-09-15 17:16:35 +00:00
2018-12-06 21:50:17 +00:00
err = solver . Solve ( authz )
2018-10-12 17:29:18 +00:00
require . NoError ( t , err )
2018-06-13 23:20:56 +00:00
}
2018-12-06 21:50:17 +00:00
func TestChallengeInvalidPort ( t * testing . T ) {
_ , apiURL , tearDown := tester . SetupFakeAPI ( )
defer tearDown ( )
privateKey , err := rsa . GenerateKey ( rand . Reader , 128 )
2018-09-15 17:16:35 +00:00
require . NoError ( t , err , "Could not generate test key" )
2018-06-13 23:20:56 +00:00
2018-12-06 21:50:17 +00:00
core , err := api . New ( http . DefaultClient , "lego-test" , apiURL + "/dir" , "" , privateKey )
require . NoError ( t , err )
2018-09-15 17:16:35 +00:00
2018-12-06 21:50:17 +00:00
solver := NewChallenge (
core ,
func ( _ * api . Core , _ string , _ acme . Challenge ) error { return nil } ,
& ProviderServer { port : "123456" } ,
)
authz := acme . Authorization {
Identifier : acme . Identifier {
Value : "localhost:123456" ,
} ,
Challenges : [ ] acme . Challenge {
{ Type : challenge . TLSALPN01 . String ( ) , Token : "tlsalpn1" } ,
} ,
}
2018-09-15 17:16:35 +00:00
2018-12-06 21:50:17 +00:00
err = solver . Solve ( authz )
2018-09-15 17:16:35 +00:00
require . Error ( t , err )
assert . Contains ( t , err . Error ( ) , "invalid port" )
assert . Contains ( t , err . Error ( ) , "123456" )
2018-06-13 23:20:56 +00:00
}