Skip to content

Commit

Permalink
Fixed #17 with caddy admin. During reload multiple workdir usage was …
Browse files Browse the repository at this point in the history
…detected
  • Loading branch information
FlorianRoettges committed Oct 17, 2024
1 parent f8aeda7 commit ebce945
Show file tree
Hide file tree
Showing 15 changed files with 457 additions and 274 deletions.
85 changes: 85 additions & 0 deletions RevocationCheckerRepository.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package revocation

import (
"crypto/x509"
"errors"
"github.com/caddyserver/caddy/v2"
"go.uber.org/zap"
"sync"
)

type RevocationCheckerEntry struct {
RevocationChecker *RevocationChecker
usageCount int
ParsedRevocationConfig *ParsedRevocationConfig
}

func (e *RevocationCheckerEntry) IncreaseUsageCount() int {
e.usageCount++
return e.usageCount
}

func (e *RevocationCheckerEntry) DecreaseUsageCount() int {
e.usageCount--
return e.usageCount
}

type RevocationCheckerRepository struct {
crlRevocationCheckerRepository map[string]*RevocationCheckerEntry
repositoryMutex *sync.RWMutex
}

func (c *RevocationCheckerRepository) Provision(ctx caddy.Context, logger *zap.Logger, config *ParsedRevocationConfig) error {
c.repositoryMutex.Lock()
defer c.repositoryMutex.Unlock()
entry := c.crlRevocationCheckerRepository[config.ConfigHash]
if entry == nil {
checker := &RevocationChecker{}
err := checker.Provision(ctx, logger, config)
if err != nil {
return err
}
entry = &RevocationCheckerEntry{checker, 0, config}
c.crlRevocationCheckerRepository[config.ConfigHash] = entry
}
entry.IncreaseUsageCount()
return nil
}

func (c *RevocationCheckerRepository) Cleanup(config *ParsedRevocationConfig) error {
c.repositoryMutex.Lock()
defer c.repositoryMutex.Unlock()
entry := c.crlRevocationCheckerRepository[config.ConfigHash]
if entry != nil {
count := entry.DecreaseUsageCount()
if count == 0 {
err := entry.RevocationChecker.Cleanup()
if err != nil {
return err
}
c.crlRevocationCheckerRepository[config.ConfigHash] = nil
}
//todo cleanup of unneded directories, In case config hash is changed directory stays forever
//but this might be problematic because it might be just a temporary change for example temp disable the checking
//suggestion1: allow option to configure if stores should always be recreated on server start and can therefore be deleted during cleanup
//suggestion2: allow to define an unused store time delay (if the files of the leveldb are older than x days not been updated you can delete it)
}
return nil
}

func (c *RevocationCheckerRepository) VerifyClientCertificate(config *ParsedRevocationConfig, certs [][]byte, chains [][]*x509.Certificate) error {
entry := c.getEntrySynced(config)
if entry == nil {
return errors.New("invalid state no RevocationCheckRepository found")
}
return entry.RevocationChecker.VerifyClientCertificate(certs, chains)
}

func (c *RevocationCheckerRepository) getEntrySynced(config *ParsedRevocationConfig) *RevocationCheckerEntry {
c.repositoryMutex.RLock()
defer c.repositoryMutex.RUnlock()
entry := c.crlRevocationCheckerRepository[config.ConfigHash]
return entry
}

var RevocationCheckerRepositoryInstance *RevocationCheckerRepository = &RevocationCheckerRepository{make(map[string]*RevocationCheckerEntry), &sync.RWMutex{}}
12 changes: 3 additions & 9 deletions caddyfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,7 @@ import (
"strconv"
)

type CertRevocationValidatorConfig struct {
CRLConfig *config.CRLConfig
OCSPConfig *config.OCSPConfig
Mode string
}

func parseConfigFromCaddyfile(d *caddyfile.Dispenser) (*CertRevocationValidatorConfig, error) {
func parseConfigFromCaddyfile(d *caddyfile.Dispenser) (*UnmarshalledRevocationConfig, error) {
// initialize structs
crlConfig := config.CRLConfig{
CDPConfig: &config.CDPConfig{},
Expand All @@ -23,7 +17,7 @@ func parseConfigFromCaddyfile(d *caddyfile.Dispenser) (*CertRevocationValidatorC
ocspConfig := config.OCSPConfig{
TrustedResponderCertsFiles: []string{},
}
certRevocationValidatorConfig := CertRevocationValidatorConfig{
certRevocationValidatorConfig := UnmarshalledRevocationConfig{
OCSPConfig: &ocspConfig,
CRLConfig: &crlConfig,
}
Expand All @@ -40,7 +34,7 @@ func parseConfigFromCaddyfile(d *caddyfile.Dispenser) (*CertRevocationValidatorC
return &certRevocationValidatorConfig, nil
}

func parseConfigEntryFromCaddyfile(d *caddyfile.Dispenser, key string, certRevocationValidatorConfig CertRevocationValidatorConfig) (*CertRevocationValidatorConfig, error, bool) {
func parseConfigEntryFromCaddyfile(d *caddyfile.Dispenser, key string, certRevocationValidatorConfig UnmarshalledRevocationConfig) (*UnmarshalledRevocationConfig, error, bool) {
switch key {
case "mode":
if !d.NextArg() {
Expand Down
27 changes: 20 additions & 7 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@ type CDPConfig struct {
// Configures how and when CRLs are downloaded for the first time
// Supported Values: 'fetch_actively', 'fetch_background'
// See: https://github.com/Gr33nbl00d/caddy-revocation-validator#crl_fetch_mode
CRLFetchModeParsed CRLFetchMode `json:"-"`
}

type CDPConfigParsed struct {
CRLFetchModeParsed CRLFetchMode
CRLCDPStrict bool
}

type CRLConfig struct {
Expand Down Expand Up @@ -81,11 +85,17 @@ type CRLConfig struct {
// If the signature cert is part of the client cert chain there is no need to configure a certificate here.
// PEM and DER encoding are both supported
TrustedSignatureCertsFiles []string `json:"trusted_signature_certs_files,omitempty"`
}

SignatureValidationModeParsed SignatureValidationMode `json:"-"`
StorageTypeParsed StorageType `json:"-"`
TrustedSignatureCerts []*x509.Certificate `json:"-"`
UpdateIntervalParsed time.Duration `json:"-"`
type CRLConfigParsed struct {
SignatureValidationModeParsed SignatureValidationMode
StorageTypeParsed StorageType
TrustedSignatureCerts []*x509.Certificate
UpdateIntervalParsed time.Duration
CDPConfigParsed *CDPConfigParsed
WorkDir string
CRLUrls []string
CRLFiles []string
}

type OCSPConfig struct {
Expand All @@ -103,7 +113,10 @@ type OCSPConfig struct {
// one OCSP server defined can be contacted to check for revocation. Or a valid response of one of the OCSP server is inside the cache
// If no OCSP server can be contacted and no cached response is present or the validation of the OCSP response signature failed connection is denied.
OCSPAIAStrict bool `json:"ocsp_aia_strict,omitempty"`
}

TrustedResponderCerts []*x509.Certificate `json:"-"`
DefaultCacheDurationParsed time.Duration `json:"-"`
type OCSPConfigParsed struct {
TrustedResponderCerts []*x509.Certificate
DefaultCacheDurationParsed time.Duration
OCSPAIAStrict bool
}
Loading

0 comments on commit ebce945

Please sign in to comment.