Fix ACME IPv6 HTTP-01 challenges

Fixes #890
This commit is contained in:
Herman Slatman 2022-04-07 12:37:34 +02:00
parent 949c29d7db
commit 479c6d2bf5
No known key found for this signature in database
GPG key ID: F4D8A44EA0A75A4F
2 changed files with 46 additions and 3 deletions

View file

@ -79,7 +79,7 @@ func (ch *Challenge) Validate(ctx context.Context, db DB, jwk *jose.JSONWebKey,
}
func http01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSONWebKey, vo *ValidateChallengeOptions) error {
u := &url.URL{Scheme: "http", Host: ch.Value, Path: fmt.Sprintf("/.well-known/acme-challenge/%s", ch.Token)}
u := &url.URL{Scheme: "http", Host: http01ChallengeHost(ch.Value), Path: fmt.Sprintf("/.well-known/acme-challenge/%s", ch.Token)}
resp, err := vo.HTTPGet(u.String())
if err != nil {
@ -119,6 +119,17 @@ func http01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSONWeb
return nil
}
// http01ChallengeHost checks if a Challenge value is an IPv6 address
// and adds square brackets if that's the case, so that it can be used
// as a hostname. Returns the original Challenge value as the host to
// use in other cases.
func http01ChallengeHost(value string) string {
if ip := net.ParseIP(value); ip != nil && ip.To4() == nil {
value = "[" + value + "]"
}
return value
}
func tlsAlert(err error) uint8 {
var opErr *net.OpError
if errors.As(err, &opErr) {

View file

@ -13,6 +13,7 @@ import (
"encoding/asn1"
"encoding/base64"
"encoding/hex"
"errors"
"fmt"
"io"
"math/big"
@ -23,9 +24,9 @@ import (
"testing"
"time"
"github.com/pkg/errors"
"github.com/smallstep/assert"
"go.step.sm/crypto/jose"
"github.com/smallstep/assert"
)
func Test_storeError(t *testing.T) {
@ -2350,3 +2351,34 @@ func Test_serverName(t *testing.T) {
})
}
}
func Test_http01ChallengeHost(t *testing.T) {
tests := []struct {
name string
value string
want string
}{
{
name: "dns",
value: "www.example.com",
want: "www.example.com",
},
{
name: "ipv4",
value: "127.0.0.1",
want: "127.0.0.1",
},
{
name: "ipv6",
value: "::1",
want: "[::1]",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := http01ChallengeHost(tt.value); got != tt.want {
t.Errorf("http01ChallengeHost() = %v, want %v", got, tt.want)
}
})
}
}