summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/xenolf/lego/acme/jws.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/xenolf/lego/acme/jws.go')
-rw-r--r--vendor/github.com/xenolf/lego/acme/jws.go93
1 files changed, 59 insertions, 34 deletions
diff --git a/vendor/github.com/xenolf/lego/acme/jws.go b/vendor/github.com/xenolf/lego/acme/jws.go
index 2a1fc244d..1b4d29d53 100644
--- a/vendor/github.com/xenolf/lego/acme/jws.go
+++ b/vendor/github.com/xenolf/lego/acme/jws.go
@@ -16,8 +16,7 @@ import (
type jws struct {
directoryURL string
privKey crypto.PrivateKey
- nonces []string
- sync.Mutex
+ nonces nonceManager
}
func keyAsJWK(key interface{}) *jose.JsonWebKey {
@@ -38,19 +37,31 @@ func keyAsJWK(key interface{}) *jose.JsonWebKey {
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
+
+ // Even in case of an error, the response should still contain a nonce.
+ nonce, nonceErr := getNonceFromResponse(resp)
+ if nonceErr == nil {
+ j.nonces.Push(nonce)
}
- j.Lock()
- defer j.Unlock()
- j.getNonceFromResponse(resp)
+ if err != nil {
+ switch err.(type) {
+ case NonceError:
+ // In case of a nonce error - retry once
+ resp, err = httpPost(url, "application/jose+json", bytes.NewBuffer([]byte(signedContent.FullSerialize())))
+ if err != nil {
+ return nil, fmt.Errorf("Failed to HTTP POST to %s -> %s", url, err.Error())
+ }
+ default:
+ return nil, fmt.Errorf("Failed to HTTP POST to %s -> %s", url, err.Error())
+ }
+ }
- return resp, err
+ return resp, nil
}
func (j *jws) signContent(content []byte) (*jose.JsonWebSignature, error) {
@@ -69,49 +80,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)
- if err != nil {
- return err
+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
}
- return j.getNonceFromResponse(resp)
+ nonce := n.nonces[len(n.nonces)-1]
+ n.nonces = n.nonces[:len(n.nonces)-1]
+ return nonce, true
}
-func (j *jws) Nonce() (string, error) {
- j.Lock()
- defer j.Unlock()
- nonce := ""
- if len(j.nonces) == 0 {
- err := j.getNonce()
- if err != nil {
- return nonce, err
- }
+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 "", fmt.Errorf("Failed to get nonce from HTTP HEAD -> %s", err.Error())
}
- if len(j.nonces) == 0 {
- return "", fmt.Errorf("Can't get nonce")
+
+ return getNonceFromResponse(resp)
+}
+
+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
}