-
Notifications
You must be signed in to change notification settings - Fork 17.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
x/crypto/acme/autocert: Registration Update Fails #26251
Comments
I was looking through the ACME RFC to see if the 202 was a deviation by Let's Encrypt. Section 7.3.2 appears to imply that it is indeed a deviation, if my understanding is correct and accounts are analogous to registrations in Let's Encrypt:
It seems that the autocert and ACME libraries make some exceptions for Let's Encrypt deviations in other parts of the code, so perhaps |
It is indeed a Let's Encrypt's implementation divergence from the spec, even though I couldn't find it in https://github.com/letsencrypt/boulder/blob/master/docs/acme-divergences.md. |
I'll fix it. |
Change https://golang.org/cl/125415 mentions this issue: |
How do I release this ? Thanks
[1500953553184_USEPIC.jpg]
[1500953056910_logo2.jpg]
On Jul 6, 2018, at 1:07 PM, Ben Krieger <[email protected]<mailto:[email protected]>> wrote:
What did you do?
I created an HTTP server like log.Fatal(http.Serve(autocert.NewListener("subdomain.example.com<http://subdomain.example.com>"), handler)) where example.com<http://example.com> also has a certificate from Let's Encrypt.
What did you expect to see?
TLS handshakes should succeed.
What did you see instead?
On the first cURL of https://subdomain.example.com<https://urldefense.proofpoint.com/v2/url?u=https-3A__subdomain.example.com&d=DwMCaQ&c=fie8CffxQEyLNW7eyn-hJg&r=o8yBtN2JNRqO6E6PkIZzCYejYlWGO_yL1RH1USJopnk&m=qd8-zBwFVTIlCCa9PxJ9v-xFeV8aj_BD7_6u4NSRydo&s=tbO6n_LMxzkX8XfyPpxP67ZUkiV-ZeLlH1RJNTWkz0Q&e=>, I get curl: (35) error:14077438:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert internal error and see in the server logs:
2018/07/06 16:44:20 http: TLS handshake error from 172.17.0.1:41496: 202 : {
"id": 37902554,
"key": {
"kty": "EC",
"crv": "P-256",
"x": "XXX",
"y": "XXX"
},
"contact": [],
"agreement": "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf<https://urldefense.proofpoint.com/v2/url?u=https-3A__letsencrypt.org_documents_LE-2DSA-2Dv1.2-2DNovember-2D15-2D2017.pdf&d=DwQCaQ&c=fie8CffxQEyLNW7eyn-hJg&r=o8yBtN2JNRqO6E6PkIZzCYejYlWGO_yL1RH1USJopnk&m=qd8-zBwFVTIlCCa9PxJ9v-xFeV8aj_BD7_6u4NSRydo&s=O5hdwkXAR8OZAUgGTugqUQ2IzgAtFt2Ph-eMBe7NqR4&e=>",
"initialIp": "xxx.xxx.xxx.xxx",
"createdAt": "2018-07-06T16:38:46Z",
"status": "valid"
}
On subsequent cURLs, the handshake continues to fail and I see errors like
2018/07/06 16:45:55 http: TLS handshake error from 172.17.0.1:41500: acme/autocert: unable to authorize "subdomain.example.com<http://subdomain.example.com>"
2018/07/06 16:46:55 http: TLS handshake error from 172.17.0.1:41506: acme/autocert: missing certificate
What I Think Is Happening
The error logged is a 202 and takes the form of a registration update response. Autocert initializes the ACME client and in the process calls client.Register here<https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_golang_crypto_blob_master_acme_autocert_autocert.go-23L928&d=DwMCaQ&c=fie8CffxQEyLNW7eyn-hJg&r=o8yBtN2JNRqO6E6PkIZzCYejYlWGO_yL1RH1USJopnk&m=qd8-zBwFVTIlCCa9PxJ9v-xFeV8aj_BD7_6u4NSRydo&s=_Cqn_lvybBmUyRCcOuKNJJwWjxBYDESJOqSYJ-5OOSA&e=>. Then the ACME client creates a new registration and if the Terms of Service need to be accepted, calls UpdateReg here<https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_golang_crypto_blob_master_acme_acme.go-23L276&d=DwMCaQ&c=fie8CffxQEyLNW7eyn-hJg&r=o8yBtN2JNRqO6E6PkIZzCYejYlWGO_yL1RH1USJopnk&m=qd8-zBwFVTIlCCa9PxJ9v-xFeV8aj_BD7_6u4NSRydo&s=sUuA_VLO4GFSTlFoyvXtm92In6pjj2tJjAQbyU_4_S0&e=>. This eventually leads to a call like this
res, err := c.post(ctx, c.Key, url, req, wantStatus(
http.StatusOK, // updates and deletes
http.StatusCreated, // new account creation
))
which errors on any result other than a 200 or 201. This could explain the logged 202 response. Checking Let's Encrypt's Boulder project quickly, I found registration updates are returned with a 202 status here: https://github.com/letsencrypt/boulder/blob/release-2018-07-03/wfe/wfe.go#L1190<https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_letsencrypt_boulder_blob_release-2D2018-2D07-2D03_wfe_wfe.go-23L1190&d=DwMCaQ&c=fie8CffxQEyLNW7eyn-hJg&r=o8yBtN2JNRqO6E6PkIZzCYejYlWGO_yL1RH1USJopnk&m=qd8-zBwFVTIlCCa9PxJ9v-xFeV8aj_BD7_6u4NSRydo&s=a0oP4VCRIZwddo3BMliUxtSFjjYaV0s8shk8nXf63VI&e=>
How I Got It Working Locally
There was no obvious way to pre-accept the terms and conditions, so I decided to test my theory by simply modifying 202 responses for registration update requests to 200s. This worked. The code required to get TLS handshakes working properly looked like this:
func getCertificate(fqdn string) (*tls.Certificate, error) {
m := &autocert.Manager{
Client: &acme.Client{
HTTPClient: &http.Client{
Transport: modRegUpdateRoundTripper{},
},
DirectoryURL: acme.LetsEncryptURL,
},
Prompt: autocert.AcceptTOS,
HostPolicy: autocert.HostWhitelist(fqdn),
}
// Redirect HTTP to HTTPS and fulfill HTTP-01 challenges
go http.ListenAndServe(":80", m.HTTPHandler(nil))
// Listen and serve with TLS
go http.Serve(m.Listener(), nil)
// Get TLS cert
return m.GetCertificate(&tls.ClientHelloInfo{ServerName: fqdn})
}
// Transport that changes registration update 202 responses to 200
type modRegUpdateRoundTripper struct{}
func (modRegUpdateRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
r, err := http.DefaultTransport.RoundTrip(req)
if err != nil {
return nil, err
}
// Intercept registration updates
uri := req.URL.String()
if strings.HasPrefix(uri, "https://acme-v01.api.letsencrypt.org/acme/reg/<https://urldefense.proofpoint.com/v2/url?u=https-3A__acme-2Dv01.api.letsencrypt.org_acme_reg_&d=DwQCaQ&c=fie8CffxQEyLNW7eyn-hJg&r=o8yBtN2JNRqO6E6PkIZzCYejYlWGO_yL1RH1USJopnk&m=qd8-zBwFVTIlCCa9PxJ9v-xFeV8aj_BD7_6u4NSRydo&s=14VJV7BpmPH8JeGMDq7jkI4R16figHDIXbh6t48lviU&e=>") {
// Change 202 to 200
if r.StatusCode == http.StatusAccepted {
r.StatusCode = http.StatusOK
}
}
return r, nil
}
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub<https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_golang_go_issues_26251&d=DwMCaQ&c=fie8CffxQEyLNW7eyn-hJg&r=o8yBtN2JNRqO6E6PkIZzCYejYlWGO_yL1RH1USJopnk&m=qd8-zBwFVTIlCCa9PxJ9v-xFeV8aj_BD7_6u4NSRydo&s=k6BLkPLRNH6uYCMtDMY2e2IVCofNALJmlFpKWfFTigg&e=>, or mute the thread<https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_notifications_unsubscribe-2Dauth_Am13gqYjrlpUjSGWtjEv4Wt-5FWpJHoa-5FCks5uD5k2gaJpZM4VFw5J&d=DwMCaQ&c=fie8CffxQEyLNW7eyn-hJg&r=o8yBtN2JNRqO6E6PkIZzCYejYlWGO_yL1RH1USJopnk&m=qd8-zBwFVTIlCCa9PxJ9v-xFeV8aj_BD7_6u4NSRydo&s=hSlSOdMdPe-eCXvIbQ5wHihK9w9JThNc4qpGPUPO4HA&e=>.
*Wire Fraud is Real*. Before wiring any money, call the intended recipient at a number you know is valid to confirm the instructions. Additionally, please note that the sender does not have authority to bind a party to a real estate contract via written or verbal communication.
|
ACME draft specifies the CA servers should respond with 201 Created status code but Let's Encrypt responds with 202 Accepted when creating a new account. This change adds 202 Accepted as a valid response. Otherwise, the Client hangs while doing retries, discarding 202 responses as invalid. Tests are not updated intentionally due to this being non-conformant with the spec. Fixes golang/go#26251 Change-Id: I2918fce3873592c02e96f4118c4d1ecb42da3c4f Reviewed-on: https://go-review.googlesource.com/125415 Reviewed-by: Brad Fitzpatrick <[email protected]>
ACME draft specifies the CA servers should respond with 201 Created status code but Let's Encrypt responds with 202 Accepted when creating a new account. This change adds 202 Accepted as a valid response. Otherwise, the Client hangs while doing retries, discarding 202 responses as invalid. Tests are not updated intentionally due to this being non-conformant with the spec. Fixes golang/go#26251 Change-Id: I2918fce3873592c02e96f4118c4d1ecb42da3c4f Reviewed-on: https://go-review.googlesource.com/125415 Reviewed-by: Brad Fitzpatrick <[email protected]>
ACME draft specifies the CA servers should respond with 201 Created status code but Let's Encrypt responds with 202 Accepted when creating a new account. This change adds 202 Accepted as a valid response. Otherwise, the Client hangs while doing retries, discarding 202 responses as invalid. Tests are not updated intentionally due to this being non-conformant with the spec. Fixes golang/go#26251 Change-Id: I2918fce3873592c02e96f4118c4d1ecb42da3c4f Reviewed-on: https://go-review.googlesource.com/125415 Reviewed-by: Brad Fitzpatrick <[email protected]>
ACME draft specifies the CA servers should respond with 201 Created status code but Let's Encrypt responds with 202 Accepted when creating a new account. This change adds 202 Accepted as a valid response. Otherwise, the Client hangs while doing retries, discarding 202 responses as invalid. Tests are not updated intentionally due to this being non-conformant with the spec. Fixes golang/go#26251 Change-Id: I2918fce3873592c02e96f4118c4d1ecb42da3c4f Reviewed-on: https://go-review.googlesource.com/125415 Reviewed-by: Brad Fitzpatrick <[email protected]>
ACME draft specifies the CA servers should respond with 201 Created status code but Let's Encrypt responds with 202 Accepted when creating a new account. This change adds 202 Accepted as a valid response. Otherwise, the Client hangs while doing retries, discarding 202 responses as invalid. Tests are not updated intentionally due to this being non-conformant with the spec. Fixes golang/go#26251 Change-Id: I2918fce3873592c02e96f4118c4d1ecb42da3c4f Reviewed-on: https://go-review.googlesource.com/125415 Reviewed-by: Brad Fitzpatrick <[email protected]>
ACME draft specifies the CA servers should respond with 201 Created status code but Let's Encrypt responds with 202 Accepted when creating a new account. This change adds 202 Accepted as a valid response. Otherwise, the Client hangs while doing retries, discarding 202 responses as invalid. Tests are not updated intentionally due to this being non-conformant with the spec. Fixes golang/go#26251 Change-Id: I2918fce3873592c02e96f4118c4d1ecb42da3c4f Reviewed-on: https://go-review.googlesource.com/125415 Reviewed-by: Brad Fitzpatrick <[email protected]>
What did you do?
I created an HTTP server like
log.Fatal(http.Serve(autocert.NewListener("subdomain.example.com"), handler))
whereexample.com
also has a certificate from Let's Encrypt.What did you expect to see?
TLS handshakes should succeed.
What did you see instead?
On the first cURL of https://subdomain.example.com, I get
curl: (35) error:14077438:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert internal error
and see in the server logs:On subsequent cURLs, the handshake continues to fail and I see errors like
What I Think Is Happening
The error logged is a 202 and takes the form of a registration update response. Autocert initializes the ACME client and in the process calls
client.Register
here. Then the ACME client creates a new registration and if the Terms of Service need to be accepted, callsUpdateReg
here. This eventually leads to a call like thiswhich errors on any result other than a
200
or201
. This could explain the logged202
response. Checking Let's Encrypt's Boulder project quickly, I found registration updates are returned with a202
status here: https://github.com/letsencrypt/boulder/blob/release-2018-07-03/wfe/wfe.go#L1190How I Got It Working Locally
There was no obvious way to pre-accept the terms and conditions, so I decided to test my theory by simply modifying 202 responses for registration update requests to 200s. This worked. The code required to get TLS handshakes working properly looked like this:
The text was updated successfully, but these errors were encountered: