When an order finalization response is not immediately valid,
Client.CreateOrderCert depends on the ACME server returning a Location
header. The header value is used as the URL for polling the updated
order status. RFC 8555 does not require this header, so CreateOrderCert
does not interoperate with ACME servers that omit it (e.g. Pebble
v2.9.0+).
This commit adds Client.CreateCertFromOrder, which accepts an *Order and
uses its URI for polling instead of relying on the finalization
response's Location header. It also updates existing callers and
documentation to use the new method and updates the integration tests to
Pebble v2.10.1 (the latest available version), which omits the
finalization Location header.
Fixesgolang/go#77704
Change-Id: I0852f19c5d18d6debc9c9686fa2c14a2e39663c2
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/817000
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Previously Manager.createCert() read state.locked without holding any
lock, while the owner goroutine wrote state.locked = false under the
state's write lock. Concurrent goroutines for the same domain raced on
that field.
We fix the issue by removing the certState.locked field and instead
having Manager.certState() return an additional owner bool computed
under the m.stateMu lock. This allows the Manager.createCert() caller to
know whether it must block on the read lock and return the state handled
by another goroutine, or instead do the work itself and release the
write lock.
A regression unit test is included that fails under -race without the
fix, and passes with the fix in-place.
Fixesgolang/go#80119
Change-Id: I0f4c5c98f7e6bcf1ab71a3c0707bb0c7ce73415b
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/793840
Reviewed-by: Roland Shoemaker <roland@golang.org>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
Auto-Submit: Daniel McCarney <daniel@binaryparadox.net>
The Go 1.25.2 release made net/url stricter about parsing bracketed IPv6
hostnames, and is rejecting some test URLs used in the autocert
TestHTTPHandlerDefaultFallback test with an error about the
colon-separated fields requiring at least one hex digit.
This commit replaces the invalid `xxxx` portion of some test URLS with
valid hex digits, fixing the test regression.
Change-Id: I84c192b1cd6daf53ef4199f7987437fd825f7041
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/710155
Reviewed-by: Roland Shoemaker <roland@golang.org>
Auto-Submit: Daniel McCarney <daniel@binaryparadox.net>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
If client.WaitOrder or client.CreateOrderCert return an acme.OrderError
it's helpful to include the order's problem field (if available). This
will often have detailed information about why a particular order
became invalid that's invaluable for debugging (e.g. a challenge
response was incorrect, a name couldn't be resolved, etc).
While it's possible for a consumer to poll the order themselves as part
of handling the order to extract a fresh Order.Error field value, it
would take an extra round-trip network request. Since we have the
underlying error in-hand when we produce the OrderError we might as well
include it directly.
Since this field is a structured object with a number of sub-fields the
OrderError.Error() function isn't updated to include the order problem
error in the String description. Interested callers should instead use
errors.Is to extract the problem information directly.
Resolvesgolang/go#74430
Cq-Include-Trybots: luci.golang.try:x_crypto-gotip-linux-amd64-longtest
Change-Id: I3158f064793bbfdc292dd6b5e1a6bfd7729bd980
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/681037
Auto-Submit: Daniel McCarney <daniel@binaryparadox.net>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Ian Stapleton Cordasco <graffatcolmingov@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
When spawning the pebble and pebble-challtestserv processes redirect
stdout/stderr to bytes.Buffer instances and print their content at test
end as appropriate.
The stdout/stderr content for each process is printed if the test
failed, or if testing is being done in verbose mode. Otherwise the
output is swallowed.
This makes debugging test failures much easier as output from the
subprocesses from independent tests isn't intermingled.
Updates golang/go#74437
Cq-Include-Trybots: luci.golang.try:x_crypto-gotip-linux-amd64-longtest
Change-Id: Ia79a3609ce3522ef6248442de247554c39367162
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/686935
Auto-Submit: Daniel McCarney <daniel@binaryparadox.net>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Reviewed-by: Carlos Amedee <carlos@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
When creating a TLS-ALPN-01 challenge response certificate for an IP
address identifier we need to configure the template IPAddresses field,
not the DNSNames/Subject.CommonName.
Along the way we can do some small tidying:
* Updating the draft TLS-ALPN-01 reference to the finalized RFC
* Adding a reference to the IP address identifier ACME RFC
* Adding a mention of the form the challenge validation request's SNI
will take when verifying an IP address identifier
* Tidying the private tlsChallengeCert() function to take a single
identifier as arg since the only call-sites provide singular values
since the removal of the TLS-SNI-[01|02] challenge helpers.
This allows enabling an IP address identifier in the Pebble integration
tests that otherwise caused a validation failure for TLS-ALPN-01
challenge types because the IP address was used as a DNS SAN.
Updates golang/go#73914
Cq-Include-Trybots: luci.golang.try:x_crypto-gotip-linux-amd64-longtest
Change-Id: Ic671e41b585f424f821db65206c7ffcc6dd386a0
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/677576
Reviewed-by: Ian Stapleton Cordasco <graffatcolmingov@gmail.com>
Auto-Submit: Daniel McCarney <daniel@binaryparadox.net>
Reviewed-by: Roland Shoemaker <roland@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
This commit adds integration test coverage for a complete TLS-ALPN-01
and HTTP-01 based issuance flow.
For each tested challenge type we:
* Spin up a pebble/pebble-challtestsrv environment
* Spin up a small challenge response server
* Create an ACME account
* Create an order for multiple DNS type identifiers
* Provision challenge responses based on the challenge type under test
* Wait for the order to become ready for issuance
* Finalize the order, issuing a certificate
* Check the newly issued certificate chain validates with the Pebble
trust anchor, and that the certificate is valid for each of the names
from our initial order
These tests are skipped in short mode (Pebble has variable delays for
validation requests).
The Pebble source is fetched through the Go module proxy (unless
a local directory is specified to aid development), similar to how the
stdlib crypto packages fetch BoGo tooling.
More test coverage for various other parts of the protocol (key
rollover, account/authz deactivation, revocation, etc) can be added as
follow-up work now that the groundwork for integration testing is laid.
Fixesgolang/go#73914
Cq-Include-Trybots: luci.golang.try:x_crypto-gotip-linux-amd64-longtest
Change-Id: I4e79f4858f31ef290a0c91d345e15fbdc510e9ab
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/677575
Reviewed-by: Roland Shoemaker <roland@golang.org>
Auto-Submit: Daniel McCarney <daniel@binaryparadox.net>
Reviewed-by: Ian Stapleton Cordasco <graffatcolmingov@gmail.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
The TLSSNI01ChallengeCert and TLSSNI02ChallengeCert functions have been
marked deprecated since 2022. The package documentation indicates
pre-RFC 8555 functionality is retained for compilation success, but will
return errors. This commit makes these two deprecated functions match
that description.
No meaningful support for these draft standard challenge types exists
in the ACME ecosystem, and they are insecure for use in shared hosting
environments.
Change-Id: I1c17980a0630092c70eb971b3453a0f115834be0
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/676835
Auto-Submit: Daniel McCarney <daniel@binaryparadox.net>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
acme/autocert currently has ad-hoc logic to find a reasonable default
for a cache directory.
Since that logic was written (in 2017), new functions were added to the
os package to provide that functionality (in Go 1.13, 2019-09):
`os.UserCacheDir` and `os.UserHomeDir`.
This patch replaces the ad-hoc logic with a call to `os.UserCacheDir`.
The fallback to `/` is kept, since it may be relied upon in some
environments.
Change-Id: I3bf692ca670b87bf3d329e5d3684eee15ed374aa
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/440195
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Auto-Submit: Sean Liao <sean@liao.dev>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Sean Liao <sean@liao.dev>
Block when creating the renewal timer, rather than doing it in a
goroutine. This fixes an issue where startRenew and stopRenew are called
very closely together, and due to lock ordering, stopRenew may be called
before startRenew, resulting in the appearance that the renewal timer
has been stopped before it has actually been created.
This is only an issue in tests, as that is the only place stopRenew is
actually used. In particular this issue manifests in TestGetCertiifcate
sub-tests, where a httptest server reuses a port across two of the
sub-tests. In this case, the renewal calls end up creating dirty state
for the subsequent test, which can cause confusing behavior (such as
attempting to register an account twice.)
Another solution to this problem would be introducing a bool, protected
by renewalMu, which indicates if renewal has been halted, and to check
it in startRenew to check if stopRenew has already been called, which
would allow us to continue calling startRenew in a goroutine and relying
on renewalMu locking for ordering. That said I don't see a particularly
strong reason to call startRenew concurrently, so this seems like the
simplest solution for now.
Fixesgolang/go#52494
Change-Id: I95420d3fd877572a0b9e408d2f8cd353f6a4e80e
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/433016
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Roland Shoemaker <roland@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
Don't assume the path passed into the DirCache methods is absolute, and
clean it before further operating on it. Put and Delete are not attacker
controlled, but clean them anyway.
Fixes#53082
Fixes CVE-2022-30636
Change-Id: I755f525a737da60ccba07ebce4d41cc8faebfcca
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/408694
Run-TryBot: Roland Shoemaker <roland@golang.org>
Reviewed-by: Damien Neil <dneil@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Currently discover is not called which results in a panic if just a key
is added to an ACME client and then deactivation is attempted.
This patch adds a discover call as well as missing unit tests for the
API.
Change-Id: I0719e5376eb2fccf62182e5f91e5b5eaa7bdd518
GitHub-Last-Rev: 501d7c6c1b75a3069dcad4254b4d4a0d2ccb02c8
GitHub-Pull-Request: golang/crypto#217
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/406734
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Roland Shoemaker <roland@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Run-TryBot: Roland Shoemaker <roland@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Add support for AccountKeyRollover. API only returns an error since acme.Error
will contain appropriate KID lookup information. Due to the requirements
of double JWS encoding jwsEncodeJSON is also modified to support a
missing Nonce header and raw string embedding in the payload.
Fixesgolang/go#42516
Change-Id: I959660a1a39b2c469b959accd48fda519daf4eb3
GitHub-Last-Rev: 8e8cc5b094743262939c145f56d3a3b57a057d64
GitHub-Pull-Request: golang/crypto#215
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/400274
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Run-TryBot: Roland Shoemaker <roland@golang.org>
In the test server, rather than spawning a goroutine to validate
challenges, block on the validation before responding to the client.
This prevents a test race, where testing.T.Logf is called after the
test is completed.
While this has a slight behavioral difference to some production
ACME server implementations (although is behavior allowed in the spec),
the change has little material impact on what we are testing, since
previously the validation would happen so quickly that it would be
indistinguishable from the new blocking behavior (i.e. we would not be
sending multiple requests during polling previously.)
Fixesgolang/go#52170
Change-Id: I75e3b2da69ddc2302be25a99f1b1151ed0f4af9b
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/405548
Run-TryBot: Roland Shoemaker <roland@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
TestRenewFromCache and TestRenewFromCacheAlreadyRenewed had several
races and API misuses:
1. They called t.Fatalf from a goroutine other than the one invoking
the Test function, which is explicitly disallowed (see
https://pkg.go.dev/testing#T).
2. The test did not stop the renewal timers prior to restoring
test-hook functions, and the process of stopping the renewal timers
itself did not wait for in-flight calls to complete. That could
cause data races if one of the renewals failed and triggered a
retry with a short-enough randomized backoff.
(One such race was observed in
https://build.golang.org/log/1a19e22ad826bedeb5a939c6130f368f9979208a.)
3. The testDidRenewLoop hooks accessed the Manager.renewal field
without locking the Mutex guarding that field.
4. TestGetCertificate_failedAttempt set a testDidRemoveState hook, but
didn't wait for the timers referring to that hook to complete
before restoring it, causing races with other timers. I tried
pulling on that thread a bit, but couldn't untangle the numerous
untracked goroutines in the package. Instead, I have made a smaller
and more local change to copy the value of testDidRemoveState into
a local variable in the timer's closure.
Given the number of untracked goroutines in this package, it is likely
that races and/or deadlocks remain. Notably, so far I have been unable
to spot the actual cause of golang/go#51080.
For golang/go#51080
Change-Id: I7797f6ac34ef3c272f16ca805251dac3aa7f0009
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/384594
Trust: Bryan Mills <bcmills@google.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
At Let's Encrypt, we've found that most autocert users do not provide an email address, which makes it hard to get in touch when things go wrong with their client. Demonstrating how to provide an email will probably encourage more people to provide one.
Change-Id: I0aa1ecea7cfbe55ae155804194fb57a8e695c658
GitHub-Last-Rev: 902b5fe2682a6be5af91e886272fd680fd67a94e
GitHub-Pull-Request: golang/crypto#186
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/323313
Reviewed-by: Roland Shoemaker <roland@golang.org>
Run-TryBot: Roland Shoemaker <roland@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
Trust: Katie Hockman <katie@golang.org>