diff options
Diffstat (limited to 'vendor/github.com/rsc/letsencrypt/vendor/github.com/xenolf/lego/acme/jws.go')
-rw-r--r-- | vendor/github.com/rsc/letsencrypt/vendor/github.com/xenolf/lego/acme/jws.go | 76 |
1 files changed, 50 insertions, 26 deletions
diff --git a/vendor/github.com/rsc/letsencrypt/vendor/github.com/xenolf/lego/acme/jws.go b/vendor/github.com/rsc/letsencrypt/vendor/github.com/xenolf/lego/acme/jws.go index 8435d0cfc..a39434342 100644 --- a/vendor/github.com/rsc/letsencrypt/vendor/github.com/xenolf/lego/acme/jws.go +++ b/vendor/github.com/rsc/letsencrypt/vendor/github.com/xenolf/lego/acme/jws.go @@ -8,6 +8,7 @@ import ( "crypto/rsa" "fmt" "net/http" + "sync" "gopkg.in/square/go-jose.v1" ) @@ -15,7 +16,7 @@ import ( type jws struct { directoryURL string privKey crypto.PrivateKey - nonces []string + nonces nonceManager } func keyAsJWK(key interface{}) *jose.JsonWebKey { @@ -30,21 +31,26 @@ func keyAsJWK(key interface{}) *jose.JsonWebKey { } } -// Posts a JWS signed message to the specified URL +// Posts a JWS signed message to the specified URL. +// It does NOT close the response body, so the caller must +// do that if no error was returned. func (j *jws) post(url string, content []byte) (*http.Response, error) { signedContent, err := j.signContent(content) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to sign content -> %s", err.Error()) } resp, err := httpPost(url, "application/jose+json", bytes.NewBuffer([]byte(signedContent.FullSerialize()))) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to HTTP POST to %s -> %s", url, err.Error()) } - j.getNonceFromResponse(resp) + nonce, nonceErr := getNonceFromResponse(resp) + if nonceErr == nil { + j.nonces.Push(nonce) + } - return resp, err + return resp, nil } func (j *jws) signContent(content []byte) (*jose.JsonWebSignature, error) { @@ -63,45 +69,63 @@ func (j *jws) signContent(content []byte) (*jose.JsonWebSignature, error) { signer, err := jose.NewSigner(alg, j.privKey) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to create jose signer -> %s", err.Error()) } signer.SetNonceSource(j) signed, err := signer.Sign(content) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to sign content -> %s", err.Error()) } return signed, nil } -func (j *jws) getNonceFromResponse(resp *http.Response) error { - nonce := resp.Header.Get("Replay-Nonce") - if nonce == "" { - return fmt.Errorf("Server did not respond with a proper nonce header.") +func (j *jws) Nonce() (string, error) { + if nonce, ok := j.nonces.Pop(); ok { + return nonce, nil } - j.nonces = append(j.nonces, nonce) - return nil + return getNonce(j.directoryURL) } -func (j *jws) getNonce() error { - resp, err := httpHead(j.directoryURL) +type nonceManager struct { + nonces []string + sync.Mutex +} + +func (n *nonceManager) Pop() (string, bool) { + n.Lock() + defer n.Unlock() + + if len(n.nonces) == 0 { + return "", false + } + + nonce := n.nonces[len(n.nonces)-1] + n.nonces = n.nonces[:len(n.nonces)-1] + return nonce, true +} + +func (n *nonceManager) Push(nonce string) { + n.Lock() + defer n.Unlock() + n.nonces = append(n.nonces, nonce) +} + +func getNonce(url string) (string, error) { + resp, err := httpHead(url) if err != nil { - return err + return "", fmt.Errorf("Failed to get nonce from HTTP HEAD -> %s", err.Error()) } - return j.getNonceFromResponse(resp) + return getNonceFromResponse(resp) } -func (j *jws) Nonce() (string, error) { - nonce := "" - if len(j.nonces) == 0 { - err := j.getNonce() - if err != nil { - return nonce, err - } +func getNonceFromResponse(resp *http.Response) (string, error) { + nonce := resp.Header.Get("Replay-Nonce") + if nonce == "" { + return "", fmt.Errorf("Server did not respond with a proper nonce header.") } - nonce, j.nonces = j.nonces[len(j.nonces)-1], j.nonces[:len(j.nonces)-1] return nonce, nil } |