mirror of
https://github.com/micromdm/micromdm/
synced 2026-08-04 16:26:23 +08:00
* Refactor MDM service to return a payload from check-ins * Documented public methods, add documentation to main service interface * Remove interface-implementing comments
122 lines
3.5 KiB
Go
122 lines
3.5 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"crypto/rsa"
|
|
"crypto/x509"
|
|
"time"
|
|
|
|
"github.com/go-kit/kit/log"
|
|
"github.com/go-kit/kit/log/level"
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/micromdm/micromdm/mdm"
|
|
)
|
|
|
|
type ScepVerifyDepot interface {
|
|
CA(pass []byte) ([]*x509.Certificate, *rsa.PrivateKey, error)
|
|
HasCN(cn string, allowTime int, cert *x509.Certificate, revokeOldCertificate bool) (bool, error)
|
|
}
|
|
|
|
func VerifyCertificateMiddleware(validateSCEPIssuer bool, validateSCEPExpiration bool, store ScepVerifyDepot, logger log.Logger) mdm.Middleware {
|
|
return func(next mdm.Service) mdm.Service {
|
|
return &verifyCertificateMiddleware{
|
|
store: store,
|
|
next: next,
|
|
logger: logger,
|
|
validateSCEPIssuer: validateSCEPIssuer,
|
|
validateSCEPExpiration: validateSCEPExpiration,
|
|
}
|
|
}
|
|
}
|
|
|
|
type verifyCertificateMiddleware struct {
|
|
store ScepVerifyDepot
|
|
next mdm.Service
|
|
logger log.Logger
|
|
validateSCEPIssuer bool
|
|
validateSCEPExpiration bool
|
|
}
|
|
|
|
func (mw *verifyCertificateMiddleware) verifyIssuer(devcert *x509.Certificate) error {
|
|
if mw.validateSCEPExpiration {
|
|
expiration := devcert.NotAfter
|
|
if time.Now().After(expiration) {
|
|
return errors.New("device certificate is expired")
|
|
}
|
|
}
|
|
ca, _, err := mw.store.CA(nil)
|
|
if err != nil {
|
|
return errors.Wrap(err, "error retrieving CA")
|
|
}
|
|
|
|
roots := x509.NewCertPool()
|
|
for _, cert := range ca {
|
|
roots.AddCert(cert)
|
|
}
|
|
|
|
opts := x509.VerifyOptions{
|
|
Roots: roots,
|
|
KeyUsages: []x509.ExtKeyUsage{
|
|
x509.ExtKeyUsageAny,
|
|
},
|
|
}
|
|
|
|
if _, err := devcert.Verify(opts); err != nil {
|
|
return errors.Wrap(err, "error verifying certificate")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (mw *verifyCertificateMiddleware) Acknowledge(ctx context.Context, req mdm.AcknowledgeEvent) ([]byte, error) {
|
|
devcert, err := mdm.DeviceCertificateFromContext(ctx)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "error retrieving device certificate")
|
|
}
|
|
hasCN, err := mw.store.HasCN(devcert.Subject.CommonName, 0, devcert, false)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "error checking device certificate")
|
|
}
|
|
|
|
unauth_err := errors.New("unauthorized client")
|
|
if !hasCN && !mw.validateSCEPIssuer {
|
|
_ = level.Info(mw.logger).Log("err", unauth_err, "issuer", devcert.Issuer.String(), "expiration", devcert.NotAfter)
|
|
return nil, unauth_err
|
|
}
|
|
|
|
if !hasCN && mw.validateSCEPIssuer {
|
|
err := mw.verifyIssuer(devcert)
|
|
if err != nil {
|
|
_ = level.Info(mw.logger).Log("err", err, "issuer", devcert.Issuer.String(), "expiration", devcert.NotAfter)
|
|
return nil, unauth_err
|
|
}
|
|
}
|
|
|
|
return mw.next.Acknowledge(ctx, req)
|
|
}
|
|
|
|
func (mw *verifyCertificateMiddleware) Checkin(ctx context.Context, req mdm.CheckinEvent) ([]byte, error) {
|
|
devcert, err := mdm.DeviceCertificateFromContext(ctx)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "error retrieving device certificate")
|
|
}
|
|
hasCN, err := mw.store.HasCN(devcert.Subject.CommonName, 0, devcert, false)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "error checking device certificate")
|
|
}
|
|
unauth_err := errors.New("unauthorized client")
|
|
if !hasCN && !mw.validateSCEPIssuer {
|
|
_ = level.Info(mw.logger).Log("err", unauth_err, "issuer", devcert.Issuer.String(), "expiration", devcert.NotAfter)
|
|
return nil, unauth_err
|
|
}
|
|
if !hasCN && mw.validateSCEPIssuer {
|
|
err := mw.verifyIssuer(devcert)
|
|
if err != nil {
|
|
_ = level.Info(mw.logger).Log("err", err, "issuer", devcert.Issuer.String(), "expiration", devcert.NotAfter)
|
|
return nil, unauth_err
|
|
}
|
|
}
|
|
return mw.next.Checkin(ctx, req)
|
|
}
|