forked from TrueCloudLab/lego
Fix nonce starvation bug in SimpleHTTP - fix tests
This commit is contained in:
parent
998a8325aa
commit
3409740d33
3 changed files with 22 additions and 26 deletions
|
@ -67,14 +67,6 @@ func NewClient(caURL string, usr User, keyBits int, optPort string) (*Client, er
|
||||||
return nil, fmt.Errorf("invalid private key: %v", err)
|
return nil, fmt.Errorf("invalid private key: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
jws := &jws{privKey: privKey}
|
|
||||||
|
|
||||||
// REVIEW: best possibility?
|
|
||||||
// Add all available solvers with the right index as per ACME
|
|
||||||
// spec to this map. Otherwise they won`t be found.
|
|
||||||
solvers := make(map[string]solver)
|
|
||||||
solvers["simpleHttp"] = &simpleHTTPChallenge{jws: jws, optPort: optPort}
|
|
||||||
|
|
||||||
if !strings.HasSuffix(caURL, "/directory") {
|
if !strings.HasSuffix(caURL, "/directory") {
|
||||||
caURL = caURL + "/directory"
|
caURL = caURL + "/directory"
|
||||||
}
|
}
|
||||||
|
@ -103,6 +95,14 @@ func NewClient(caURL string, usr User, keyBits int, optPort string) (*Client, er
|
||||||
return nil, errors.New("directory missing revoke certificate URL")
|
return nil, errors.New("directory missing revoke certificate URL")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jws := &jws{privKey: privKey, directoryURL: caURL}
|
||||||
|
|
||||||
|
// REVIEW: best possibility?
|
||||||
|
// Add all available solvers with the right index as per ACME
|
||||||
|
// spec to this map. Otherwise they won`t be found.
|
||||||
|
solvers := make(map[string]solver)
|
||||||
|
solvers["simpleHttp"] = &simpleHTTPChallenge{jws: jws, optPort: optPort}
|
||||||
|
|
||||||
return &Client{directory: dir, user: usr, jws: jws, keyBits: keyBits, solvers: solvers}, nil
|
return &Client{directory: dir, user: usr, jws: jws, keyBits: keyBits, solvers: solvers}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
22
acme/jws.go
22
acme/jws.go
|
@ -4,7 +4,6 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
@ -12,8 +11,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type jws struct {
|
type jws struct {
|
||||||
privKey *rsa.PrivateKey
|
directoryURL string
|
||||||
nonces []string
|
privKey *rsa.PrivateKey
|
||||||
|
nonces []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func keyAsJWK(key interface{}) *jose.JsonWebKey {
|
func keyAsJWK(key interface{}) *jose.JsonWebKey {
|
||||||
|
@ -30,13 +30,6 @@ func keyAsJWK(key interface{}) *jose.JsonWebKey {
|
||||||
|
|
||||||
// Posts a JWS signed message to the specified URL
|
// Posts a JWS signed message to the specified URL
|
||||||
func (j *jws) post(url string, content []byte) (*http.Response, error) {
|
func (j *jws) post(url string, content []byte) (*http.Response, error) {
|
||||||
if len(j.nonces) == 0 {
|
|
||||||
err := j.getNonce(url)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Could not get a nonce for request: %s\n\t\tError: %v", url, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
signedContent, err := j.signContent(content)
|
signedContent, err := j.signContent(content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -77,8 +70,8 @@ func (j *jws) getNonceFromResponse(resp *http.Response) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *jws) getNonce(url string) error {
|
func (j *jws) getNonce() error {
|
||||||
resp, err := http.Head(url)
|
resp, err := http.Head(j.directoryURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -89,7 +82,10 @@ func (j *jws) getNonce(url string) error {
|
||||||
func (j *jws) Nonce() (string, error) {
|
func (j *jws) Nonce() (string, error) {
|
||||||
nonce := ""
|
nonce := ""
|
||||||
if len(j.nonces) == 0 {
|
if len(j.nonces) == 0 {
|
||||||
return nonce, errors.New("No nonce available.")
|
err := j.getNonce()
|
||||||
|
if err != nil {
|
||||||
|
return nonce, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nonce, j.nonces = j.nonces[len(j.nonces)-1], j.nonces[:len(j.nonces)-1]
|
nonce, j.nonces = j.nonces[len(j.nonces)-1], j.nonces[:len(j.nonces)-1]
|
||||||
|
|
|
@ -69,13 +69,13 @@ func TestSimpleHTTPConnectionRefusal(t *testing.T) {
|
||||||
|
|
||||||
func TestSimpleHTTPUnexpectedServerState(t *testing.T) {
|
func TestSimpleHTTPUnexpectedServerState(t *testing.T) {
|
||||||
privKey, _ := generatePrivateKey(rsakey, 512)
|
privKey, _ := generatePrivateKey(rsakey, 512)
|
||||||
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\"}"))
|
w.Write([]byte("{\"type\":\"simpleHttp\",\"status\":\"what\",\"uri\":\"http://some.url\",\"token\":\"4\"}"))
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
jws := &jws{privKey: privKey.(*rsa.PrivateKey), directoryURL: ts.URL}
|
||||||
solver := &simpleHTTPChallenge{jws: jws, optPort: "23456"}
|
solver := &simpleHTTPChallenge{jws: jws, optPort: "23456"}
|
||||||
clientChallenge := challenge{Type: "simpleHttp", Status: "pending", URI: ts.URL, Token: "4"}
|
clientChallenge := challenge{Type: "simpleHttp", Status: "pending", URI: ts.URL, Token: "4"}
|
||||||
|
|
||||||
|
@ -120,7 +120,6 @@ func TestSimpleHTTPChallengeServerUnexpectedDomain(t *testing.T) {
|
||||||
|
|
||||||
func TestSimpleHTTPServerError(t *testing.T) {
|
func TestSimpleHTTPServerError(t *testing.T) {
|
||||||
privKey, _ := generatePrivateKey(rsakey, 512)
|
privKey, _ := generatePrivateKey(rsakey, 512)
|
||||||
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) {
|
||||||
if r.Method == "HEAD" {
|
if r.Method == "HEAD" {
|
||||||
|
@ -132,6 +131,7 @@ func TestSimpleHTTPServerError(t *testing.T) {
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
jws := &jws{privKey: privKey.(*rsa.PrivateKey), directoryURL: ts.URL}
|
||||||
solver := &simpleHTTPChallenge{jws: jws, optPort: "23456"}
|
solver := &simpleHTTPChallenge{jws: jws, optPort: "23456"}
|
||||||
clientChallenge := challenge{Type: "simpleHttp", Status: "pending", URI: ts.URL, Token: "6"}
|
clientChallenge := challenge{Type: "simpleHttp", Status: "pending", URI: ts.URL, Token: "6"}
|
||||||
|
|
||||||
|
@ -147,13 +147,13 @@ func TestSimpleHTTPServerError(t *testing.T) {
|
||||||
|
|
||||||
func TestSimpleHTTPInvalidServerState(t *testing.T) {
|
func TestSimpleHTTPInvalidServerState(t *testing.T) {
|
||||||
privKey, _ := generatePrivateKey(rsakey, 512)
|
privKey, _ := generatePrivateKey(rsakey, 512)
|
||||||
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\":\"invalid\",\"uri\":\"http://some.url\",\"token\":\"7\"}"))
|
w.Write([]byte("{\"type\":\"simpleHttp\",\"status\":\"invalid\",\"uri\":\"http://some.url\",\"token\":\"7\"}"))
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
jws := &jws{privKey: privKey.(*rsa.PrivateKey), directoryURL: ts.URL}
|
||||||
solver := &simpleHTTPChallenge{jws: jws, optPort: "23456"}
|
solver := &simpleHTTPChallenge{jws: jws, optPort: "23456"}
|
||||||
clientChallenge := challenge{Type: "simpleHttp", Status: "pending", URI: ts.URL, Token: "7"}
|
clientChallenge := challenge{Type: "simpleHttp", Status: "pending", URI: ts.URL, Token: "7"}
|
||||||
|
|
||||||
|
@ -169,13 +169,13 @@ func TestSimpleHTTPInvalidServerState(t *testing.T) {
|
||||||
|
|
||||||
func TestSimpleHTTPValidServerResponse(t *testing.T) {
|
func TestSimpleHTTPValidServerResponse(t *testing.T) {
|
||||||
privKey, _ := generatePrivateKey(rsakey, 512)
|
privKey, _ := generatePrivateKey(rsakey, 512)
|
||||||
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\":\"valid\",\"uri\":\"http://some.url\",\"token\":\"8\"}"))
|
w.Write([]byte("{\"type\":\"simpleHttp\",\"status\":\"valid\",\"uri\":\"http://some.url\",\"token\":\"8\"}"))
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
jws := &jws{privKey: privKey.(*rsa.PrivateKey), directoryURL: ts.URL}
|
||||||
solver := &simpleHTTPChallenge{jws: jws, optPort: "23456"}
|
solver := &simpleHTTPChallenge{jws: jws, optPort: "23456"}
|
||||||
clientChallenge := challenge{Type: "simpleHttp", Status: "pending", URI: ts.URL, Token: "8"}
|
clientChallenge := challenge{Type: "simpleHttp", Status: "pending", URI: ts.URL, Token: "8"}
|
||||||
|
|
||||||
|
@ -186,10 +186,10 @@ func TestSimpleHTTPValidServerResponse(t *testing.T) {
|
||||||
|
|
||||||
func TestSimpleHTTPValidFull(t *testing.T) {
|
func TestSimpleHTTPValidFull(t *testing.T) {
|
||||||
privKey, _ := generatePrivateKey(rsakey, 512)
|
privKey, _ := generatePrivateKey(rsakey, 512)
|
||||||
jws := &jws{privKey: privKey.(*rsa.PrivateKey)}
|
|
||||||
|
|
||||||
ts := httptest.NewServer(nil)
|
ts := httptest.NewServer(nil)
|
||||||
|
|
||||||
|
jws := &jws{privKey: privKey.(*rsa.PrivateKey), directoryURL: ts.URL}
|
||||||
solver := &simpleHTTPChallenge{jws: jws, optPort: "23456"}
|
solver := &simpleHTTPChallenge{jws: jws, optPort: "23456"}
|
||||||
clientChallenge := challenge{Type: "simpleHttp", Status: "pending", URI: ts.URL, Token: "9"}
|
clientChallenge := challenge{Type: "simpleHttp", Status: "pending", URI: ts.URL, Token: "9"}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue