From 812e1c72181cdf8d49ff7125a304198897623baa Mon Sep 17 00:00:00 2001 From: Herman Slatman Date: Fri, 26 Feb 2021 12:32:43 +0100 Subject: [PATCH] Add handling of options --- scep/api/api.go | 35 ++++++++++++----------------------- scep/authority.go | 40 +++++++++++++++++++++++----------------- scep/common.go | 22 ++++++++++++++++++++++ 3 files changed, 57 insertions(+), 40 deletions(-) create mode 100644 scep/common.go diff --git a/scep/api/api.go b/scep/api/api.go index ec959519..c73bb53a 100644 --- a/scep/api/api.go +++ b/scep/api/api.go @@ -235,12 +235,12 @@ func (h *Handler) GetCACert(w http.ResponseWriter, r *http.Request, scepResponse func (h *Handler) GetCACaps(w http.ResponseWriter, r *http.Request, scepResponse SCEPResponse) error { - ctx := r.Context() + //ctx := r.Context() - _, err := ProvisionerFromContext(ctx) - if err != nil { - return err - } + // _, err := ProvisionerFromContext(ctx) + // if err != nil { + // return err + // } // TODO: get the actual capabilities from provisioner config scepResponse.Data = formatCapabilities(defaultCapabilities) @@ -250,6 +250,8 @@ func (h *Handler) GetCACaps(w http.ResponseWriter, r *http.Request, scepResponse func (h *Handler) PKIOperation(w http.ResponseWriter, r *http.Request, scepRequest SCEPRequest, scepResponse SCEPResponse) error { + ctx := r.Context() + msg, err := microscep.ParsePKIMessage(scepRequest.Message) if err != nil { return err @@ -262,7 +264,7 @@ func (h *Handler) PKIOperation(w http.ResponseWriter, r *http.Request, scepReque Raw: msg.Raw, } - if err := h.Auth.DecryptPKIEnvelope(pkimsg); err != nil { + if err := h.Auth.DecryptPKIEnvelope(ctx, pkimsg); err != nil { return err } @@ -271,7 +273,7 @@ func (h *Handler) PKIOperation(w http.ResponseWriter, r *http.Request, scepReque } csr := pkimsg.CSRReqMessage.CSR - id, err := createKeyIdentifier(csr.PublicKey) + subjectKeyID, err := createKeyIdentifier(csr.PublicKey) if err != nil { return err } @@ -286,16 +288,17 @@ func (h *Handler) PKIOperation(w http.ResponseWriter, r *http.Request, scepReque Subject: csr.Subject, NotBefore: time.Now().Add(-600).UTC(), NotAfter: time.Now().AddDate(0, 0, days).UTC(), - SubjectKeyId: id, + SubjectKeyId: subjectKeyID, KeyUsage: x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{ x509.ExtKeyUsageClientAuth, }, SignatureAlgorithm: csr.SignatureAlgorithm, EmailAddresses: csr.EmailAddresses, + DNSNames: csr.DNSNames, } - certRep, err := h.Auth.SignCSR(pkimsg, template) + certRep, err := h.Auth.SignCSR(ctx, pkimsg, template) if err != nil { return err } @@ -381,17 +384,3 @@ func contentHeader(operation string, certNum int) string { return "text/plain" } } - -// ProvisionerFromContext searches the context for a provisioner. Returns the -// provisioner or an error. -func ProvisionerFromContext(ctx context.Context) (scep.Provisioner, error) { - val := ctx.Value(acme.ProvisionerContextKey) - if val == nil { - return nil, errors.New("provisioner expected in request context") - } - p, ok := val.(scep.Provisioner) - if !ok || p == nil { - return nil, errors.New("provisioner in context is not a SCEP provisioner") - } - return p, nil -} diff --git a/scep/authority.go b/scep/authority.go index 864ecbba..cb191d34 100644 --- a/scep/authority.go +++ b/scep/authority.go @@ -2,6 +2,7 @@ package scep import ( "bytes" + "context" "crypto/x509" "errors" "fmt" @@ -54,8 +55,8 @@ type Interface interface { GetCACertificates() ([]*x509.Certificate, error) //GetSigningKey() (*rsa.PrivateKey, error) - DecryptPKIEnvelope(*PKIMessage) error - SignCSR(msg *PKIMessage, template *x509.Certificate) (*PKIMessage, error) + DecryptPKIEnvelope(ctx context.Context, msg *PKIMessage) error + SignCSR(ctx context.Context, msg *PKIMessage, template *x509.Certificate) (*PKIMessage, error) } // Authority is the layer that handles all SCEP interactions. @@ -156,7 +157,7 @@ func (a *Authority) GetCACertificates() ([]*x509.Certificate, error) { } // DecryptPKIEnvelope decrypts an enveloped message -func (a *Authority) DecryptPKIEnvelope(msg *PKIMessage) error { +func (a *Authority) DecryptPKIEnvelope(ctx context.Context, msg *PKIMessage) error { data := msg.Raw @@ -221,14 +222,19 @@ func (a *Authority) DecryptPKIEnvelope(msg *PKIMessage) error { return nil } -// SignCSR creates an x509.Certificate based on a template and Cert Authority credentials +// SignCSR creates an x509.Certificate based on a CSR template and Cert Authority credentials // returns a new PKIMessage with CertRep data //func (msg *PKIMessage) SignCSR(crtAuth *x509.Certificate, keyAuth *rsa.PrivateKey, template *x509.Certificate) (*PKIMessage, error) { -func (a *Authority) SignCSR(msg *PKIMessage, template *x509.Certificate) (*PKIMessage, error) { +func (a *Authority) SignCSR(ctx context.Context, msg *PKIMessage, template *x509.Certificate) (*PKIMessage, error) { + + p, err := ProvisionerFromContext(ctx) + if err != nil { + return nil, err + } // check if CSRReqMessage has already been decrypted if msg.CSRReqMessage.CSR == nil { - if err := a.DecryptPKIEnvelope(msg); err != nil { + if err := a.DecryptPKIEnvelope(ctx, msg); err != nil { return nil, err } } @@ -238,13 +244,17 @@ func (a *Authority) SignCSR(msg *PKIMessage, template *x509.Certificate) (*PKIMe // Template data data := x509util.NewTemplateData() data.SetCommonName(csr.Subject.CommonName) - //data.Set(x509util.SANsKey, sans) + data.SetSANs(csr.DNSNames) - // templateOptions, err := provisioner.TemplateOptions(p.GetOptions(), data) - // if err != nil { - // return nil, ServerInternalErr(errors.Wrapf(err, "error creating template options from ACME provisioner")) - // } - // signOps = append(signOps, templateOptions) + // TODO: proper options + opts := provisioner.SignOptions{} + signOps := []provisioner.SignOption{} + + templateOptions, err := provisioner.TemplateOptions(p.GetOptions(), data) + if err != nil { + return nil, fmt.Errorf("error creating template options from SCEP provisioner") + } + signOps = append(signOps, templateOptions) // // Create and store a new certificate. // certChain, err := auth.Sign(csr, provisioner.SignOptions{ @@ -255,11 +265,7 @@ func (a *Authority) SignCSR(msg *PKIMessage, template *x509.Certificate) (*PKIMe // return nil, ServerInternalErr(errors.Wrapf(err, "error generating certificate for order %s", o.ID)) // } - // TODO: proper options - signOps := provisioner.SignOptions{} - signOps2 := []provisioner.SignOption{} - - certs, err := a.signAuth.Sign(csr, signOps, signOps2...) + certs, err := a.signAuth.Sign(csr, opts, signOps...) if err != nil { return nil, err } diff --git a/scep/common.go b/scep/common.go new file mode 100644 index 00000000..123c8d82 --- /dev/null +++ b/scep/common.go @@ -0,0 +1,22 @@ +package scep + +import ( + "context" + "errors" + + "github.com/smallstep/certificates/acme" +) + +// ProvisionerFromContext searches the context for a SCEP provisioner. +// Returns the provisioner or an error. +func ProvisionerFromContext(ctx context.Context) (Provisioner, error) { + val := ctx.Value(acme.ProvisionerContextKey) + if val == nil { + return nil, errors.New("provisioner expected in request context") + } + p, ok := val.(Provisioner) + if !ok || p == nil { + return nil, errors.New("provisioner in context is not a SCEP provisioner") + } + return p, nil +}