From e27124b03741271bf71008f4e01ef28d5180fb0e Mon Sep 17 00:00:00 2001 From: Panagiotis Siatras Date: Thu, 24 Mar 2022 17:08:23 +0200 Subject: [PATCH] scep: remove Interface and the dependency to pkg/errors (#872) * scep: documented the package * scep/api: removed some top level constants * scep: removed dependency to pkg/errors * scep/api: documented the package --- scep/api/api.go | 41 +++++++++++++++++++---------------------- scep/authority.go | 40 +++++++++++++--------------------------- scep/scep.go | 4 +--- 3 files changed, 33 insertions(+), 52 deletions(-) diff --git a/scep/api/api.go b/scep/api/api.go index 91d337fe..31f0f10d 100644 --- a/scep/api/api.go +++ b/scep/api/api.go @@ -1,3 +1,4 @@ +// Package api implements a SCEP HTTP server. package api import ( @@ -31,12 +32,6 @@ const ( const maxPayloadSize = 2 << 20 -const ( - certChainHeader = "application/x-x509-ca-ra-cert" - leafHeader = "application/x-x509-ca-cert" - pkiOperationHeader = "application/x-pki-message" -) - // request is a SCEP server request. type request struct { Operation string @@ -54,17 +49,19 @@ type response struct { // handler is the SCEP request handler. type handler struct { - Auth scep.Interface + auth *scep.Authority } // New returns a new SCEP API router. -func New(scepAuth scep.Interface) api.RouterHandler { - return &handler{scepAuth} +func New(auth *scep.Authority) api.RouterHandler { + return &handler{ + auth: auth, + } } // Route traffic and implement the Router interface. func (h *handler) Route(r api.Router) { - getLink := h.Auth.GetLinkExplicit + getLink := h.auth.GetLinkExplicit r.MethodFunc(http.MethodGet, getLink("{provisionerName}/*", false, nil), h.lookupProvisioner(h.Get)) r.MethodFunc(http.MethodGet, getLink("{provisionerName}", false, nil), h.lookupProvisioner(h.Get)) r.MethodFunc(http.MethodPost, getLink("{provisionerName}/*", false, nil), h.lookupProvisioner(h.Post)) @@ -192,7 +189,7 @@ func (h *handler) lookupProvisioner(next http.HandlerFunc) http.HandlerFunc { return } - p, err := h.Auth.LoadProvisionerByName(provisionerName) + p, err := h.auth.LoadProvisionerByName(provisionerName) if err != nil { fail(w, err) return @@ -213,7 +210,7 @@ func (h *handler) lookupProvisioner(next http.HandlerFunc) http.HandlerFunc { // GetCACert returns the CA certificates in a SCEP response func (h *handler) GetCACert(ctx context.Context) (response, error) { - certs, err := h.Auth.GetCACertificates(ctx) + certs, err := h.auth.GetCACertificates(ctx) if err != nil { return response{}, err } @@ -246,7 +243,7 @@ func (h *handler) GetCACert(ctx context.Context) (response, error) { // GetCACaps returns the CA capabilities in a SCEP response func (h *handler) GetCACaps(ctx context.Context) (response, error) { - caps := h.Auth.GetCACaps(ctx) + caps := h.auth.GetCACaps(ctx) res := response{ Operation: opnGetCACaps, @@ -283,7 +280,7 @@ func (h *handler) PKIOperation(ctx context.Context, req request) (response, erro P7: p7, } - if err := h.Auth.DecryptPKIEnvelope(ctx, msg); err != nil { + if err := h.auth.DecryptPKIEnvelope(ctx, msg); err != nil { return response{}, err } @@ -296,7 +293,7 @@ func (h *handler) PKIOperation(ctx context.Context, req request) (response, erro // a certificate exists; then it will use RenewalReq. Adding the challenge check here may be a small breaking change for clients. // We'll have to see how it works out. if msg.MessageType == microscep.PKCSReq || msg.MessageType == microscep.RenewalReq { - challengeMatches, err := h.Auth.MatchChallengePassword(ctx, msg.CSRReqMessage.ChallengePassword) + challengeMatches, err := h.auth.MatchChallengePassword(ctx, msg.CSRReqMessage.ChallengePassword) if err != nil { return h.createFailureResponse(ctx, csr, msg, microscep.BadRequest, errors.New("error when checking password")) } @@ -314,7 +311,7 @@ func (h *handler) PKIOperation(ctx context.Context, req request) (response, erro // Authentication by the (self-signed) certificate with an optional challenge is required; supporting renewals incl. verification // of the client cert is not. - certRep, err := h.Auth.SignCSR(ctx, csr, msg) + certRep, err := h.auth.SignCSR(ctx, csr, msg) if err != nil { return h.createFailureResponse(ctx, csr, msg, microscep.BadRequest, fmt.Errorf("error when signing new certificate: %w", err)) } @@ -354,7 +351,7 @@ func fail(w http.ResponseWriter, err error) { } func (h *handler) createFailureResponse(ctx context.Context, csr *x509.CertificateRequest, msg *scep.PKIMessage, info microscep.FailInfo, failError error) (response, error) { - certRepMsg, err := h.Auth.CreateFailureResponse(ctx, csr, msg, scep.FailInfoName(info), failError.Error()) + certRepMsg, err := h.auth.CreateFailureResponse(ctx, csr, msg, scep.FailInfoName(info), failError.Error()) if err != nil { return response{}, err } @@ -367,14 +364,14 @@ func (h *handler) createFailureResponse(ctx context.Context, csr *x509.Certifica func contentHeader(r response) string { switch r.Operation { + default: + return "text/plain" case opnGetCACert: if r.CACertNum > 1 { - return certChainHeader + return "application/x-x509-ca-ra-cert" } - return leafHeader + return "application/x-x509-ca-cert" case opnPKIOperation: - return pkiOperationHeader - default: - return "text/plain" + return "application/x-pki-message" } } diff --git a/scep/authority.go b/scep/authority.go index 269e3ae1..71f92152 100644 --- a/scep/authority.go +++ b/scep/authority.go @@ -4,32 +4,18 @@ import ( "context" "crypto/subtle" "crypto/x509" + "errors" + "fmt" "net/url" - "github.com/smallstep/certificates/authority/provisioner" - microx509util "github.com/micromdm/scep/v2/cryptoutil/x509util" microscep "github.com/micromdm/scep/v2/scep" - - "github.com/pkg/errors" - "go.mozilla.org/pkcs7" "go.step.sm/crypto/x509util" -) -// Interface is the SCEP authority interface. -type Interface interface { - LoadProvisionerByName(string) (provisioner.Interface, error) - GetLinkExplicit(provName string, absoluteLink bool, baseURL *url.URL, inputs ...string) string - - GetCACertificates(ctx context.Context) ([]*x509.Certificate, error) - DecryptPKIEnvelope(ctx context.Context, msg *PKIMessage) error - SignCSR(ctx context.Context, csr *x509.CertificateRequest, msg *PKIMessage) (*PKIMessage, error) - CreateFailureResponse(ctx context.Context, csr *x509.CertificateRequest, msg *PKIMessage, info FailInfoName, infoText string) (*PKIMessage, error) - MatchChallengePassword(ctx context.Context, password string) (bool, error) - GetCACaps(ctx context.Context) []string -} + "github.com/smallstep/certificates/authority/provisioner" +) // Authority is the layer that handles all SCEP interactions. type Authority struct { @@ -180,12 +166,12 @@ func (a *Authority) DecryptPKIEnvelope(ctx context.Context, msg *PKIMessage) err p7c, err := pkcs7.Parse(msg.P7.Content) if err != nil { - return errors.Wrap(err, "error parsing pkcs7 content") + return fmt.Errorf("error parsing pkcs7 content: %w", err) } envelope, err := p7c.Decrypt(a.intermediateCertificate, a.service.decrypter) if err != nil { - return errors.Wrap(err, "error decrypting encrypted pkcs7 content") + return fmt.Errorf("error decrypting encrypted pkcs7 content: %w", err) } msg.pkiEnvelope = envelope @@ -194,19 +180,19 @@ func (a *Authority) DecryptPKIEnvelope(ctx context.Context, msg *PKIMessage) err case microscep.CertRep: certs, err := microscep.CACerts(msg.pkiEnvelope) if err != nil { - return errors.Wrap(err, "error extracting CA certs from pkcs7 degenerate data") + return fmt.Errorf("error extracting CA certs from pkcs7 degenerate data: %w", err) } msg.CertRepMessage.Certificate = certs[0] return nil case microscep.PKCSReq, microscep.UpdateReq, microscep.RenewalReq: csr, err := x509.ParseCertificateRequest(msg.pkiEnvelope) if err != nil { - return errors.Wrap(err, "parse CSR from pkiEnvelope") + return fmt.Errorf("parse CSR from pkiEnvelope: %w", err) } // check for challengePassword cp, err := microx509util.ParseChallengePassword(msg.pkiEnvelope) if err != nil { - return errors.Wrap(err, "parse challenge password in pkiEnvelope") + return fmt.Errorf("parse challenge password in pkiEnvelope: %w", err) } msg.CSRReqMessage = µscep.CSRReqMessage{ RawDecrypted: msg.pkiEnvelope, @@ -215,7 +201,7 @@ func (a *Authority) DecryptPKIEnvelope(ctx context.Context, msg *PKIMessage) err } return nil case microscep.GetCRL, microscep.GetCert, microscep.CertPoll: - return errors.Errorf("not implemented") + return errors.New("not implemented") } return nil @@ -274,19 +260,19 @@ func (a *Authority) SignCSR(ctx context.Context, csr *x509.CertificateRequest, m ctx = provisioner.NewContextWithMethod(ctx, provisioner.SignMethod) signOps, err := p.AuthorizeSign(ctx, "") if err != nil { - return nil, errors.Wrap(err, "error retrieving authorization options from SCEP provisioner") + return nil, fmt.Errorf("error retrieving authorization options from SCEP provisioner: %w", err) } opts := provisioner.SignOptions{} templateOptions, err := provisioner.TemplateOptions(p.GetOptions(), data) if err != nil { - return nil, errors.Wrap(err, "error creating template options from SCEP provisioner") + return nil, fmt.Errorf("error creating template options from SCEP provisioner: %w", err) } signOps = append(signOps, templateOptions) certChain, err := a.signAuth.Sign(csr, opts, signOps...) if err != nil { - return nil, errors.Wrap(err, "error generating certificate for order") + return nil, fmt.Errorf("error generating certificate for order: %w", err) } // take the issued certificate (only); https://tools.ietf.org/html/rfc8894#section-3.3.2 diff --git a/scep/scep.go b/scep/scep.go index afabf368..372a5436 100644 --- a/scep/scep.go +++ b/scep/scep.go @@ -1,3 +1,4 @@ +// Package scep implements Simple Certificate Enrollment Protocol related functionality. package scep import ( @@ -5,9 +6,6 @@ import ( "encoding/asn1" microscep "github.com/micromdm/scep/v2/scep" - - //"github.com/smallstep/certificates/scep/pkcs7" - "go.mozilla.org/pkcs7" )