WACS-Kompatibilität
All checks were successful
release-tag / release-image (push) Successful in 1m47s

This commit is contained in:
jbergner
2025-04-29 14:15:37 +02:00
parent 47e89b46bc
commit 1765d55ac6

49
main.go
View File

@@ -420,45 +420,55 @@ type jwsPayload struct {
JWK *jose.JSONWebKey
}
// -----------------------------------------------------------------------------
// JWS verification helper supports both JSON & compact JWS formats
// -----------------------------------------------------------------------------
func (s *server) verifyJWS(ctx context.Context, w http.ResponseWriter, r *http.Request) (*jwsPayload, bool) {
if !jwsVerify {
data, _ := io.ReadAll(r.Body)
return &jwsPayload{Data: data}, true
}
// Decode incoming JWS (JSON serialization expected)
// read full body once
raw, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "read body", http.StatusBadRequest)
return nil, false
}
// try JWS JSON first …
var sig jose.JSONWebSignature
if err := json.NewDecoder(r.Body).Decode(&sig); err != nil {
if err := json.Unmarshal(raw, &sig); err != nil || len(sig.Signatures) == 0 {
// … fallback to compact serialization
cp, err2 := jose.ParseSigned(string(raw))
if err2 != nil {
http.Error(w, "bad JWS", http.StatusBadRequest)
return nil, false
}
if len(sig.Signatures) == 0 {
http.Error(w, "no signature", http.StatusBadRequest)
return nil, false
sig = *cp
}
prot := sig.Signatures[0].Protected // already decoded in gojose v3
prot := sig.Signatures[0].Protected // already base-64 decoded
// Nonce replayprotection
// Nonce replay-protection
if !s.db.takeNonce(ctx, prot.Nonce) {
http.Error(w, "bad nonce", http.StatusForbidden)
return nil, false
}
// Resolve verification key (inline JWK or referenced by kid)
// Resolve verification key
var key *jose.JSONWebKey
if prot.JSONWebKey != nil {
switch {
case prot.JSONWebKey != nil:
key = prot.JSONWebKey
} else if prot.KeyID != "" {
id := path.Base(prot.KeyID) // everything after last '/'
k, err := s.db.accountKey(ctx, id)
if err != nil {
case prot.KeyID != "":
if k, err := s.db.accountKey(ctx, path.Base(prot.KeyID)); err == nil {
key = k
} else {
http.Error(w, "unknown kid", http.StatusUnauthorized)
return nil, false
}
key = k
}
if key == nil {
default:
http.Error(w, "no verification key", http.StatusBadRequest)
return nil, false
}
@@ -468,7 +478,6 @@ func (s *server) verifyJWS(ctx context.Context, w http.ResponseWriter, r *http.R
http.Error(w, "signature invalid", http.StatusUnauthorized)
return nil, false
}
return &jwsPayload{Data: payload, JWK: key}, true
}
@@ -489,6 +498,9 @@ func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Replay-Nonce", n)
w.WriteHeader(http.StatusOK)
case r.Method == http.MethodGet && r.URL.Path == "/directory":
s.handleDirectory(w, r)
case r.Method == http.MethodPost && r.URL.Path == "/acme/new-account":
s.handleNewAccount(ctx, w, r)
@@ -501,9 +513,6 @@ func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
case r.Method == http.MethodPost && r.URL.Path == "/acme/revoke-cert":
s.handleRevoke(ctx, w, r)
case r.Method == http.MethodGet && r.URL.Path == "/acme/directory":
s.handleDirectory(w, r)
case r.Method == http.MethodGet && strings.HasPrefix(r.URL.Path, "/acme/order/"):
s.handleGetOrder(ctx, w, r)