forked from TrueCloudLab/lego
Re-organized SimpleHTTPTests and expanded them a bit
This commit is contained in:
parent
fc08101f79
commit
34fe2a5547
3 changed files with 163 additions and 54 deletions
|
@ -1,11 +1 @@
|
||||||
package acme
|
package acme
|
||||||
|
|
||||||
type dvsniChallenge struct{}
|
|
||||||
|
|
||||||
func (s *dvsniChallenge) CanSolve(domain string) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *dvsniChallenge) Solve(challenge challenge, domain string) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package acme
|
package acme
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
|
@ -112,7 +111,7 @@ func (s *simpleHTTPChallenge) startHTTPSServer(domain string, token string) (net
|
||||||
|
|
||||||
tlsListener, err := tls.Listen("tcp", port, tlsConf)
|
tlsListener, err := tls.Listen("tcp", port, tlsConf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Could not start HTTP listener! -> %v", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonBytes, err := json.Marshal(challenge{Type: "simpleHttp", Token: token, TLS: true})
|
jsonBytes, err := json.Marshal(challenge{Type: "simpleHttp", Token: token, TLS: true})
|
||||||
|
@ -121,7 +120,7 @@ func (s *simpleHTTPChallenge) startHTTPSServer(domain string, token string) (net
|
||||||
}
|
}
|
||||||
signed, err := s.jws.signContent(jsonBytes)
|
signed, err := s.jws.signContent(jsonBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("startHTTPSServer: Failed to sign message")
|
return nil, fmt.Errorf("startHTTPSServer: Failed to sign message. %s", err)
|
||||||
}
|
}
|
||||||
signedCompact := signed.FullSerialize()
|
signedCompact := signed.FullSerialize()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -145,13 +144,3 @@ func (s *simpleHTTPChallenge) startHTTPSServer(domain string, token string) (net
|
||||||
|
|
||||||
return tlsListener, nil
|
return tlsListener, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRandomString(length int) string {
|
|
||||||
const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
|
||||||
var bytes = make([]byte, length)
|
|
||||||
rand.Read(bytes)
|
|
||||||
for i, b := range bytes {
|
|
||||||
bytes[i] = alphanum[b%byte(len(alphanum))]
|
|
||||||
}
|
|
||||||
return string(bytes)
|
|
||||||
}
|
|
||||||
|
|
|
@ -12,54 +12,183 @@ import (
|
||||||
"github.com/square/go-jose"
|
"github.com/square/go-jose"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSimpleHTTP(t *testing.T) {
|
func TestSimpleHTTPNonRootBind(t *testing.T) {
|
||||||
privKey, err := generatePrivateKey(rsakey, 512)
|
privKey, _ := generatePrivateKey(rsakey, 128)
|
||||||
if err != nil {
|
jws := &jws{privKey: privKey.(*rsa.PrivateKey)}
|
||||||
t.Errorf("Could not generate public key -> %v", err)
|
|
||||||
|
solver := &simpleHTTPChallenge{jws: jws}
|
||||||
|
clientChallenge := challenge{Type: "simpleHttp", Status: "pending", URI: "localhost:4000", Token: "1"}
|
||||||
|
|
||||||
|
// validate error on non-root bind to 443
|
||||||
|
if err := solver.Solve(clientChallenge, "test.domain"); err == nil {
|
||||||
|
t.Error("BIND: Expected Solve to return an error but the error was nil.")
|
||||||
|
} else {
|
||||||
|
expectedError := "Could not start HTTPS server for challenge -> listen tcp :443: bind: permission denied"
|
||||||
|
if err.Error() != expectedError {
|
||||||
|
t.Errorf("Expected error %s but instead got %s", expectedError, err.Error())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSimpleHTTPShortRSA(t *testing.T) {
|
||||||
|
privKey, _ := generatePrivateKey(rsakey, 128)
|
||||||
|
jws := &jws{privKey: privKey.(*rsa.PrivateKey), nonces: []string{"test1", "test2"}}
|
||||||
|
|
||||||
|
solver := &simpleHTTPChallenge{jws: jws, optPort: "23456"}
|
||||||
|
clientChallenge := challenge{Type: "simpleHttp", Status: "pending", URI: "http://localhost:4000", Token: "2"}
|
||||||
|
|
||||||
|
if err := solver.Solve(clientChallenge, "test.domain"); err == nil {
|
||||||
|
t.Error("UNEXPECTED: Expected Solve to return an error but the error was nil.")
|
||||||
|
} else {
|
||||||
|
expectedError := "Could not start HTTPS server for challenge -> startHTTPSServer: Failed to sign message. crypto/rsa: message too long for RSA public key size"
|
||||||
|
if err.Error() != expectedError {
|
||||||
|
t.Errorf("Expected error %s but instead got %s", expectedError, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSimpleHTTPConnectionRefusal(t *testing.T) {
|
||||||
|
privKey, _ := generatePrivateKey(rsakey, 512)
|
||||||
|
jws := &jws{privKey: privKey.(*rsa.PrivateKey), nonces: []string{"test1", "test2"}}
|
||||||
|
|
||||||
|
solver := &simpleHTTPChallenge{jws: jws, optPort: "23456"}
|
||||||
|
clientChallenge := challenge{Type: "simpleHttp", Status: "pending", URI: "http://localhost:4000", Token: "3"}
|
||||||
|
|
||||||
|
if err := solver.Solve(clientChallenge, "test.domain"); err == nil {
|
||||||
|
t.Error("UNEXPECTED: Expected Solve to return an error but the error was nil.")
|
||||||
|
} else {
|
||||||
|
expectedError := "Failed to post JWS message. -> Post http://localhost:4000: dial tcp 127.0.0.1:4000: getsockopt: connection refused"
|
||||||
|
if err.Error() != expectedError {
|
||||||
|
t.Errorf("Expected error %s but instead got %s", expectedError, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSimpleHTTPUnexpectedServerState(t *testing.T) {
|
||||||
|
privKey, _ := generatePrivateKey(rsakey, 512)
|
||||||
jws := &jws{privKey: privKey.(*rsa.PrivateKey)}
|
jws := &jws{privKey: privKey.(*rsa.PrivateKey)}
|
||||||
|
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Add("Replay-Nonce", "12345")
|
w.Header().Add("Replay-Nonce", "12345")
|
||||||
|
w.Write([]byte("{\"type\":\"simpleHttp\",\"status\":\"what\",\"uri\":\"http://some.url\",\"token\":\"4\"}"))
|
||||||
}))
|
}))
|
||||||
|
|
||||||
solver := &simpleHTTPChallenge{jws: jws}
|
solver := &simpleHTTPChallenge{jws: jws, optPort: "23456"}
|
||||||
clientChallenge := challenge{Type: "simpleHttp", Status: "pending", URI: ts.URL, Token: "123456789"}
|
clientChallenge := challenge{Type: "simpleHttp", Status: "pending", URI: ts.URL, Token: "4"}
|
||||||
|
|
||||||
// validate error on non-root bind to 443
|
if err := solver.Solve(clientChallenge, "test.domain"); err == nil {
|
||||||
if err = solver.Solve(clientChallenge, "test.domain"); err == nil {
|
t.Error("UNEXPECTED: Expected Solve to return an error but the error was nil.")
|
||||||
t.Error("BIND: Expected Solve to return an error but the error was nil.")
|
} else {
|
||||||
|
expectedError := "The server returned an unexpected state."
|
||||||
|
if err.Error() != expectedError {
|
||||||
|
t.Errorf("Expected error %s but instead got %s", expectedError, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate error on unexpected state
|
func TestSimpleHTTPChallengeServerUnexpectedDomain(t *testing.T) {
|
||||||
solver.optPort = "23456"
|
privKey, _ := generatePrivateKey(rsakey, 512)
|
||||||
if err = solver.Solve(clientChallenge, "test.domain"); err == nil {
|
jws := &jws{privKey: privKey.(*rsa.PrivateKey)}
|
||||||
|
|
||||||
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method == "POST" {
|
||||||
|
tr := &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
}
|
||||||
|
client := &http.Client{Transport: tr}
|
||||||
|
req, _ := client.Get("https://localhost:23456/.well-known/acme-challenge/" + "5")
|
||||||
|
reqBytes, _ := ioutil.ReadAll(req.Body)
|
||||||
|
if string(reqBytes) != "TEST" {
|
||||||
|
t.Error("Expected simpleHTTP server to return string TEST on unexpected domain.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Add("Replay-Nonce", "12345")
|
||||||
|
w.Write([]byte("{\"type\":\"simpleHttp\",\"status\":\"invalid\",\"uri\":\"http://some.url\",\"token\":\"5\"}"))
|
||||||
|
}))
|
||||||
|
|
||||||
|
solver := &simpleHTTPChallenge{jws: jws, optPort: "23456"}
|
||||||
|
clientChallenge := challenge{Type: "simpleHttp", Status: "pending", URI: ts.URL, Token: "5"}
|
||||||
|
|
||||||
|
if err := solver.Solve(clientChallenge, "test.domain"); err == nil {
|
||||||
t.Error("UNEXPECTED: Expected Solve to return an error but the error was nil.")
|
t.Error("UNEXPECTED: Expected Solve to return an error but the error was nil.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate error on invalid status
|
|
||||||
ts.Config.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.Header().Add("Replay-Nonce", "12345")
|
|
||||||
failed := challenge{Type: "simpleHttp", Status: "invalid", URI: ts.URL, Token: "1234567810"}
|
|
||||||
jsonBytes, _ := json.Marshal(&failed)
|
|
||||||
w.Write(jsonBytes)
|
|
||||||
})
|
|
||||||
clientChallenge.Token = "1234567810"
|
|
||||||
if err = solver.Solve(clientChallenge, "test.domain"); err == nil {
|
|
||||||
t.Error("FAILED: Expected Solve to return an error but the error was nil.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate no error on valid response
|
func TestSimpleHTTPServerError(t *testing.T) {
|
||||||
ts.Config.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
privKey, _ := generatePrivateKey(rsakey, 512)
|
||||||
|
jws := &jws{privKey: privKey.(*rsa.PrivateKey)}
|
||||||
|
|
||||||
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method == "HEAD" {
|
||||||
w.Header().Add("Replay-Nonce", "12345")
|
w.Header().Add("Replay-Nonce", "12345")
|
||||||
valid := challenge{Type: "simpleHttp", Status: "valid", URI: ts.URL, Token: "1234567811"}
|
} else {
|
||||||
jsonBytes, _ := json.Marshal(&valid)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
w.Write(jsonBytes)
|
w.Header().Add("Replay-Nonce", "12345")
|
||||||
})
|
w.Write([]byte("{\"type\":\"urn:acme:error:unauthorized\",\"detail\":\"Error creating new authz :: Syntax error\"}"))
|
||||||
clientChallenge.Token = "1234567811"
|
}
|
||||||
if err = solver.Solve(clientChallenge, "test.domain"); err != nil {
|
}))
|
||||||
|
|
||||||
|
solver := &simpleHTTPChallenge{jws: jws, optPort: "23456"}
|
||||||
|
clientChallenge := challenge{Type: "simpleHttp", Status: "pending", URI: ts.URL, Token: "6"}
|
||||||
|
|
||||||
|
if err := solver.Solve(clientChallenge, "test.domain"); err == nil {
|
||||||
|
t.Error("UNEXPECTED: Expected Solve to return an error but the error was nil.")
|
||||||
|
} else {
|
||||||
|
expectedError := "[500] Type: urn:acme:error:unauthorized Detail: Error creating new authz :: Syntax error"
|
||||||
|
if err.Error() != expectedError {
|
||||||
|
t.Errorf("Expected error |%s| but instead got |%s|", expectedError, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSimpleHTTPInvalidServerState(t *testing.T) {
|
||||||
|
privKey, _ := generatePrivateKey(rsakey, 512)
|
||||||
|
jws := &jws{privKey: privKey.(*rsa.PrivateKey)}
|
||||||
|
|
||||||
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Add("Replay-Nonce", "12345")
|
||||||
|
w.Write([]byte("{\"type\":\"simpleHttp\",\"status\":\"invalid\",\"uri\":\"http://some.url\",\"token\":\"7\"}"))
|
||||||
|
}))
|
||||||
|
|
||||||
|
solver := &simpleHTTPChallenge{jws: jws, optPort: "23456"}
|
||||||
|
clientChallenge := challenge{Type: "simpleHttp", Status: "pending", URI: ts.URL, Token: "7"}
|
||||||
|
|
||||||
|
if err := solver.Solve(clientChallenge, "test.domain"); err == nil {
|
||||||
|
t.Error("UNEXPECTED: Expected Solve to return an error but the error was nil.")
|
||||||
|
} else {
|
||||||
|
expectedError := "The server could not validate our request."
|
||||||
|
if err.Error() != expectedError {
|
||||||
|
t.Errorf("Expected error |%s| but instead got |%s|", expectedError, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSimpleHTTPValidServerResponse(t *testing.T) {
|
||||||
|
privKey, _ := generatePrivateKey(rsakey, 512)
|
||||||
|
jws := &jws{privKey: privKey.(*rsa.PrivateKey)}
|
||||||
|
|
||||||
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Add("Replay-Nonce", "12345")
|
||||||
|
w.Write([]byte("{\"type\":\"simpleHttp\",\"status\":\"valid\",\"uri\":\"http://some.url\",\"token\":\"8\"}"))
|
||||||
|
}))
|
||||||
|
|
||||||
|
solver := &simpleHTTPChallenge{jws: jws, optPort: "23456"}
|
||||||
|
clientChallenge := challenge{Type: "simpleHttp", Status: "pending", URI: ts.URL, Token: "8"}
|
||||||
|
|
||||||
|
if err := solver.Solve(clientChallenge, "test.domain"); err != nil {
|
||||||
t.Errorf("VALID: Expected Solve to return no error but the error was -> %v", err)
|
t.Errorf("VALID: Expected Solve to return no error but the error was -> %v", err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSimpleHTTPValidFull(t *testing.T) {
|
||||||
|
privKey, _ := generatePrivateKey(rsakey, 512)
|
||||||
|
jws := &jws{privKey: privKey.(*rsa.PrivateKey)}
|
||||||
|
|
||||||
|
ts := httptest.NewServer(nil)
|
||||||
|
|
||||||
|
solver := &simpleHTTPChallenge{jws: jws, optPort: "23456"}
|
||||||
|
clientChallenge := challenge{Type: "simpleHttp", Status: "pending", URI: ts.URL, Token: "9"}
|
||||||
|
|
||||||
// Validate server on port 23456 which responds appropriately
|
// Validate server on port 23456 which responds appropriately
|
||||||
clientChallenge.Token = "1234567812"
|
clientChallenge.Token = "1234567812"
|
||||||
|
@ -112,7 +241,8 @@ func TestSimpleHTTP(t *testing.T) {
|
||||||
jsonBytes, _ := json.Marshal(&valid)
|
jsonBytes, _ := json.Marshal(&valid)
|
||||||
w.Write(jsonBytes)
|
w.Write(jsonBytes)
|
||||||
})
|
})
|
||||||
if err = solver.Solve(clientChallenge, "test.domain"); err != nil {
|
|
||||||
|
if err := solver.Solve(clientChallenge, "test.domain"); err != nil {
|
||||||
t.Errorf("VALID: Expected Solve to return no error but the error was -> %v", err)
|
t.Errorf("VALID: Expected Solve to return no error but the error was -> %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue