Implement command type handling
This commit changes the wire protocol to split between command announcement and command payload to allow proper typing of sent and received msgpack messages. CRL fetching has been implemented as second command after the existing health check command.
This commit is contained in:
parent
472091b374
commit
2de592d30c
13 changed files with 1258 additions and 214 deletions
9
.gitignore
vendored
9
.gitignore
vendored
|
@ -1,10 +1,11 @@
|
||||||
*.crt
|
*.crt
|
||||||
*.pem
|
*.pem
|
||||||
*.pub
|
*.pub
|
||||||
.idea/
|
/.idea/
|
||||||
|
/ca-hierarchy.json
|
||||||
/clientsim
|
/clientsim
|
||||||
|
/config.yaml
|
||||||
|
/dist/
|
||||||
|
/repos/
|
||||||
/signer
|
/signer
|
||||||
/testPty
|
/testPty
|
||||||
ca-hierarchy.json
|
|
||||||
config.yaml
|
|
||||||
dist/
|
|
|
@ -20,6 +20,7 @@ limitations under the License.
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
@ -30,6 +31,8 @@ import (
|
||||||
"github.com/shamaton/msgpackgen/msgpack"
|
"github.com/shamaton/msgpackgen/msgpack"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"git.cacert.org/cacert-gosigner/pkg/protocol"
|
||||||
|
|
||||||
"git.cacert.org/cacert-gosigner/pkg/messages"
|
"git.cacert.org/cacert-gosigner/pkg/messages"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -39,7 +42,7 @@ var cobsConfig = cobs.Config{SpecialByte: cobsDelimiter, Delimiter: true, Ending
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
logger := logrus.New()
|
logger := logrus.New()
|
||||||
logger.SetOutput(os.Stdout)
|
logger.SetOutput(os.Stderr)
|
||||||
logger.SetLevel(logrus.InfoLevel)
|
logger.SetLevel(logrus.InfoLevel)
|
||||||
|
|
||||||
sim := &clientSimulator{
|
sim := &clientSimulator{
|
||||||
|
@ -48,14 +51,14 @@ func main() {
|
||||||
|
|
||||||
err := sim.Run()
|
err := sim.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("simulator returned an error: %v", err)
|
logger.WithError(err).Error("simulator returned an error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type clientSimulator struct {
|
type clientSimulator struct {
|
||||||
logger *logrus.Logger
|
logger *logrus.Logger
|
||||||
commands chan messages.Command
|
commands chan *protocol.Command
|
||||||
responses chan []byte
|
responses chan [][]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *clientSimulator) writeTestCommands(ctx context.Context) error {
|
func (c *clientSimulator) writeTestCommands(ctx context.Context) error {
|
||||||
|
@ -63,6 +66,13 @@ func (c *clientSimulator) writeTestCommands(ctx context.Context) error {
|
||||||
|
|
||||||
const healthInterval = 10 * time.Second
|
const healthInterval = 10 * time.Second
|
||||||
|
|
||||||
|
time.Sleep(healthInterval)
|
||||||
|
|
||||||
|
c.commands <- &protocol.Command{
|
||||||
|
Announce: messages.BuildCommandAnnounce(messages.CmdFetchCRL),
|
||||||
|
Command: &messages.FetchCRLCommand{IssuerID: "sub-ecc_person_2022"},
|
||||||
|
}
|
||||||
|
|
||||||
timer := time.NewTimer(healthInterval)
|
timer := time.NewTimer(healthInterval)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
@ -70,15 +80,17 @@ func (c *clientSimulator) writeTestCommands(ctx context.Context) error {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
_ = timer.Stop()
|
_ = timer.Stop()
|
||||||
|
|
||||||
|
c.logger.Info("stopping health check loop")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
c.commands <- messages.Command{
|
c.commands <- &protocol.Command{
|
||||||
Code: messages.CmdHealth,
|
Announce: messages.BuildCommandAnnounce(messages.CmdHealth),
|
||||||
TimeStamp: time.Now().UTC(),
|
Command: &messages.HealthCommand{},
|
||||||
}
|
}
|
||||||
|
|
||||||
timer.Reset(healthInterval)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
timer.Reset(healthInterval)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,6 +102,18 @@ func (c *clientSimulator) handleInput(ctx context.Context) error {
|
||||||
|
|
||||||
buf := make([]byte, bufferSize)
|
buf := make([]byte, bufferSize)
|
||||||
|
|
||||||
|
type protocolState int8
|
||||||
|
|
||||||
|
const (
|
||||||
|
stAnn protocolState = iota
|
||||||
|
stResp
|
||||||
|
)
|
||||||
|
|
||||||
|
state := stAnn
|
||||||
|
|
||||||
|
var announce []byte
|
||||||
|
|
||||||
|
reading:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
|
@ -108,12 +132,26 @@ func (c *clientSimulator) handleInput(ctx context.Context) error {
|
||||||
|
|
||||||
data := buf[:count]
|
data := buf[:count]
|
||||||
|
|
||||||
err = cobs.Verify(data, cobsConfig)
|
for _, frame := range bytes.SplitAfter(data, []byte{cobsConfig.SpecialByte}) {
|
||||||
if err != nil {
|
if len(frame) == 0 {
|
||||||
return fmt.Errorf("frame verification failed: %w", err)
|
continue reading
|
||||||
}
|
}
|
||||||
|
|
||||||
c.responses <- cobs.Decode(data, cobsConfig)
|
err = cobs.Verify(frame, cobsConfig)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("frame verification failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if state == stAnn {
|
||||||
|
announce = cobs.Decode(frame, cobsConfig)
|
||||||
|
|
||||||
|
state = stResp
|
||||||
|
} else {
|
||||||
|
c.responses <- [][]byte{announce, cobs.Decode(frame, cobsConfig)}
|
||||||
|
|
||||||
|
state = stAnn
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,75 +160,152 @@ func (c *clientSimulator) handleCommands(ctx context.Context) error {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case command := <-c.commands:
|
case command := <-c.commands:
|
||||||
commandBytes, err := msgpack.Marshal(command)
|
if err := writeCommandAnnouncement(command); err != nil {
|
||||||
if err != nil {
|
return err
|
||||||
return fmt.Errorf("could not marshal command bytes: %w", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = os.Stdout.Write(cobs.Encode(commandBytes, cobsConfig))
|
if err := writeCommand(command); err != nil {
|
||||||
if err != nil {
|
return err
|
||||||
return fmt.Errorf("write failed: %w", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
responseBytes := <-c.responses
|
respData := <-c.responses
|
||||||
|
|
||||||
var response messages.Response
|
c.logger.WithField("respdata", respData).Trace("read response data")
|
||||||
|
|
||||||
err = msgpack.Unmarshal(responseBytes, &response)
|
response := &protocol.Response{}
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not unmarshal msgpack data: %w", err)
|
if err := msgpack.Unmarshal(respData[0], &response.Announce); err != nil {
|
||||||
|
return fmt.Errorf("could not unmarshal response announcement: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.handleResponse(response, respData[1]); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.logger.Errorf("received response: %+v", response)
|
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *clientSimulator) handleResponse(response *protocol.Response, respBytes []byte) error {
|
||||||
|
switch response.Announce.Code {
|
||||||
|
case messages.RespHealth:
|
||||||
|
data := messages.HealthResponse{}
|
||||||
|
|
||||||
|
if err := msgpack.Unmarshal(respBytes, &data); err != nil {
|
||||||
|
return fmt.Errorf("could not unmarshal health data: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.logger.WithField(
|
||||||
|
"announce",
|
||||||
|
response.Announce,
|
||||||
|
).WithField(
|
||||||
|
"data",
|
||||||
|
&data,
|
||||||
|
).Infof("received response")
|
||||||
|
case messages.RespFetchCRL:
|
||||||
|
data := messages.FetchCRLResponse{}
|
||||||
|
|
||||||
|
if err := msgpack.Unmarshal(respBytes, &data); err != nil {
|
||||||
|
return fmt.Errorf("could not unmarshal fetch CRL data: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.logger.WithField(
|
||||||
|
"announce",
|
||||||
|
response.Announce,
|
||||||
|
).WithField(
|
||||||
|
"data",
|
||||||
|
&data,
|
||||||
|
).Infof("received response")
|
||||||
|
case messages.RespError:
|
||||||
|
data := messages.ErrorResponse{}
|
||||||
|
|
||||||
|
if err := msgpack.Unmarshal(respBytes, &data); err != nil {
|
||||||
|
return fmt.Errorf("could not unmarshal error data: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.logger.WithField(
|
||||||
|
"announce",
|
||||||
|
response.Announce,
|
||||||
|
).WithField(
|
||||||
|
"data",
|
||||||
|
&data,
|
||||||
|
).Infof("received response")
|
||||||
|
default:
|
||||||
|
if err := msgpack.Unmarshal(respBytes, &response.Response); err != nil {
|
||||||
|
return fmt.Errorf("could not unmarshal response: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.logger.WithField("response", response).Infof("received response")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeCommandAnnouncement(command *protocol.Command) error {
|
||||||
|
cmdAnnounceBytes, err := msgpack.Marshal(&command.Announce)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not marshal command announcement bytes: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = os.Stdout.Write(cobs.Encode(cmdAnnounceBytes, cobsConfig)); err != nil {
|
||||||
|
return fmt.Errorf("command announcement write failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeCommand(command *protocol.Command) error {
|
||||||
|
cmdBytes, err := msgpack.Marshal(&command.Command)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not marshal command bytes: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = os.Stdout.Write(cobs.Encode(cmdBytes, cobsConfig)); err != nil {
|
||||||
|
return fmt.Errorf("command write failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *clientSimulator) Run() error {
|
func (c *clientSimulator) Run() error {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
|
||||||
c.commands = make(chan messages.Command)
|
c.commands = make(chan *protocol.Command)
|
||||||
c.responses = make(chan []byte)
|
c.responses = make(chan [][]byte)
|
||||||
|
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
wg.Add(2)
|
wg.Add(2)
|
||||||
|
|
||||||
var inputError, commandError error
|
go func() {
|
||||||
|
if err := c.handleInput(ctx); err != nil {
|
||||||
go func(inputErr error) {
|
c.logger.WithError(err).Error("input handling failed")
|
||||||
_ = c.handleInput(ctx)
|
}
|
||||||
|
|
||||||
cancel()
|
cancel()
|
||||||
|
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}(inputError)
|
}()
|
||||||
|
|
||||||
go func(commandErr error) {
|
go func() {
|
||||||
_ = c.handleCommands(ctx)
|
if err := c.handleCommands(ctx); err != nil {
|
||||||
|
c.logger.WithError(err).Error("command handling failed")
|
||||||
|
}
|
||||||
|
|
||||||
cancel()
|
cancel()
|
||||||
|
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}(commandError)
|
}()
|
||||||
|
|
||||||
var result error
|
var result error
|
||||||
|
|
||||||
if err := c.writeTestCommands(ctx); err != nil {
|
if err := c.writeTestCommands(ctx); err != nil {
|
||||||
c.logger.Errorf("test commands failed: %v", err)
|
c.logger.WithError(err).Error("test commands failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
cancel()
|
cancel()
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
if inputError != nil {
|
|
||||||
c.logger.Errorf("reading input failed: %v", inputError)
|
|
||||||
}
|
|
||||||
|
|
||||||
if commandError != nil {
|
|
||||||
c.logger.Errorf("sending commands failed: %v", commandError)
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,13 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"git.cacert.org/cacert-gosigner/pkg/x509/revoking"
|
||||||
|
|
||||||
"git.cacert.org/cacert-gosigner/pkg/config"
|
"git.cacert.org/cacert-gosigner/pkg/config"
|
||||||
"git.cacert.org/cacert-gosigner/pkg/health"
|
"git.cacert.org/cacert-gosigner/pkg/health"
|
||||||
"git.cacert.org/cacert-gosigner/pkg/hsm"
|
"git.cacert.org/cacert-gosigner/pkg/hsm"
|
||||||
|
@ -51,7 +54,7 @@ func main() {
|
||||||
logger.SetOutput(os.Stdout)
|
logger.SetOutput(os.Stdout)
|
||||||
logger.SetLevel(logrus.InfoLevel)
|
logger.SetLevel(logrus.InfoLevel)
|
||||||
|
|
||||||
logger.Infof("cacert-gosigner %s (%s) - built %s\n", version, commit, date)
|
logger.Infof("cacert-gosigner %s (%s) - built %s", version, commit, date)
|
||||||
|
|
||||||
flag.StringVar(&signerConfigFile, "config", defaultSignerConfigFile, "signer configuration file")
|
flag.StringVar(&signerConfigFile, "config", defaultSignerConfigFile, "signer configuration file")
|
||||||
flag.BoolVar(&showVersion, "version", false, "show version")
|
flag.BoolVar(&showVersion, "version", false, "show version")
|
||||||
|
@ -67,12 +70,12 @@ func main() {
|
||||||
|
|
||||||
parsedLevel, err := logrus.ParseLevel(logLevel)
|
parsedLevel, err := logrus.ParseLevel(logLevel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatalf("could not parse log level: %v", err)
|
logger.WithError(err).Fatal("could not parse log level")
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.SetLevel(parsedLevel)
|
logger.SetLevel(parsedLevel)
|
||||||
|
|
||||||
caConfig := LoadConfig(signerConfigFile, logger)
|
caConfig := loadConfig(signerConfigFile, logger)
|
||||||
|
|
||||||
access := initializeHSM(caConfig, setupMode, verbose, logger)
|
access := initializeHSM(caConfig, setupMode, verbose, logger)
|
||||||
|
|
||||||
|
@ -82,23 +85,77 @@ func main() {
|
||||||
|
|
||||||
healthHandler := health.New(version, access)
|
healthHandler := health.New(version, access)
|
||||||
|
|
||||||
proto, err := protocol.New(logger, protocol.RegisterHealthHandler(healthHandler))
|
revokingRepositories, err := configureRepositories(caConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatalf("could not setup protocol handler: %v", err)
|
logger.WithError(err).Fatal("could not setup revoking repositories")
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchCRLHandler := revoking.NewFetchCRLHandler(revokingRepositories)
|
||||||
|
|
||||||
|
proto, err := protocol.New(
|
||||||
|
logger,
|
||||||
|
protocol.RegisterHealthHandler(healthHandler),
|
||||||
|
protocol.RegisterFetchCRLHandler(fetchCRLHandler),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
logger.WithError(err).Fatal("could not setup protocol handler")
|
||||||
}
|
}
|
||||||
|
|
||||||
serialHandler, err := seriallink.New(caConfig.GetSerial(), proto)
|
serialHandler, err := seriallink.New(caConfig.GetSerial(), proto)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatalf("could not setup serial link handler: %v", err)
|
logger.WithError(err).Fatal("could not setup serial link handler")
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() { _ = serialHandler.Close() }()
|
defer func() { _ = serialHandler.Close() }()
|
||||||
|
|
||||||
if err = serialHandler.Run(); err != nil {
|
if err = serialHandler.Run(); err != nil {
|
||||||
logger.Fatalf("error in serial handler: %v", err)
|
logger.WithError(err).Fatal("error in serial handler")
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Infof("setup complete, starting signer operation")
|
logger.Info("setup complete, starting signer operation")
|
||||||
|
}
|
||||||
|
|
||||||
|
func configureRepositories(
|
||||||
|
caConfig *config.SignerConfig,
|
||||||
|
) (map[string]*revoking.X509Revoking, error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
result := make(map[string]*revoking.X509Revoking)
|
||||||
|
|
||||||
|
for _, name := range caConfig.RootCAs() {
|
||||||
|
result[fmt.Sprintf("root-%s", name)], err = buildX509Revoking(caConfig, name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, name := range caConfig.SubordinateCAs() {
|
||||||
|
result[fmt.Sprintf("sub-%s", name)], err = buildX509Revoking(caConfig, name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildX509Revoking(caConfig *config.SignerConfig, name string) (*revoking.X509Revoking, error) {
|
||||||
|
caDef, err := caConfig.GetCADefinition(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not get CA definition for %s: %w", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
repo, err := caConfig.Repository(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not get repository for %s: %w", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return revoking.NewX509Revoking(
|
||||||
|
repo,
|
||||||
|
caDef.KeyInfo.CRLSignatureAlgorithm,
|
||||||
|
caDef.Certificate,
|
||||||
|
caDef.KeyPair,
|
||||||
|
), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func initializeHSM(caConfig *config.SignerConfig, setupMode, verbose bool, logger *logrus.Logger) *hsm.Access {
|
func initializeHSM(caConfig *config.SignerConfig, setupMode, verbose bool, logger *logrus.Logger) *hsm.Access {
|
||||||
|
@ -118,21 +175,21 @@ func initializeHSM(caConfig *config.SignerConfig, setupMode, verbose bool, logge
|
||||||
|
|
||||||
access, err := hsm.NewAccess(logger, opts...)
|
access, err := hsm.NewAccess(logger, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatalf("could not setup HSM access: %v", err)
|
logger.WithError(err).Fatal("could not setup HSM access")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = access.EnsureCAKeysAndCertificates()
|
err = access.EnsureCAKeysAndCertificates()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatalf("could not ensure CA keys and certificates exist: %v", err)
|
logger.WithError(err).Fatal("could not ensure CA keys and certificates exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
return access
|
return access
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadConfig(signerConfigFile string, logger *logrus.Logger) *config.SignerConfig {
|
func loadConfig(signerConfigFile string, logger *logrus.Logger) *config.SignerConfig {
|
||||||
configFile, err := os.Open(signerConfigFile)
|
configFile, err := os.Open(signerConfigFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatalf("could not open signer configuration file %s: %v", signerConfigFile, err)
|
logger.WithError(err).Fatalf("could not open signer configuration file: %s", signerConfigFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
caConfig, err := config.LoadConfiguration(configFile)
|
caConfig, err := config.LoadConfiguration(configFile)
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -6,6 +6,7 @@ require (
|
||||||
github.com/ThalesIgnite/crypto11 v1.2.5
|
github.com/ThalesIgnite/crypto11 v1.2.5
|
||||||
github.com/justincpresley/go-cobs v1.2.0
|
github.com/justincpresley/go-cobs v1.2.0
|
||||||
github.com/shamaton/msgpackgen v0.3.0
|
github.com/shamaton/msgpackgen v0.3.0
|
||||||
|
github.com/sirupsen/logrus v1.9.0
|
||||||
github.com/stretchr/testify v1.8.0
|
github.com/stretchr/testify v1.8.0
|
||||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07
|
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07
|
||||||
golang.org/x/term v0.0.0-20220411215600-e5f449aeb171
|
golang.org/x/term v0.0.0-20220411215600-e5f449aeb171
|
||||||
|
@ -19,7 +20,6 @@ require (
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/shamaton/msgpack/v2 v2.1.0 // indirect
|
github.com/shamaton/msgpack/v2 v2.1.0 // indirect
|
||||||
github.com/sirupsen/logrus v1.9.0 // indirect
|
|
||||||
github.com/thales-e-security/pool v0.0.2 // indirect
|
github.com/thales-e-security/pool v0.0.2 // indirect
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
|
||||||
)
|
)
|
||||||
|
|
1
go.sum
1
go.sum
|
@ -32,7 +32,6 @@ github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07 h1:UyzmZLoiDWMRywV4DUY
|
||||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||||
github.com/thales-e-security/pool v0.0.2 h1:RAPs4q2EbWsTit6tpzuvTFlgFRJ3S8Evf5gtvVDbmPg=
|
github.com/thales-e-security/pool v0.0.2 h1:RAPs4q2EbWsTit6tpzuvTFlgFRJ3S8Evf5gtvVDbmPg=
|
||||||
github.com/thales-e-security/pool v0.0.2/go.mod h1:qtpMm2+thHtqhLzTwgDBj/OuNnMpupY8mv0Phz0gjhU=
|
github.com/thales-e-security/pool v0.0.2/go.mod h1:qtpMm2+thHtqhLzTwgDBj/OuNnMpupY8mv0Phz0gjhU=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
|
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
|
|
@ -25,12 +25,19 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
|
||||||
|
"git.cacert.org/cacert-gosigner/pkg/x509/openssl"
|
||||||
|
"git.cacert.org/cacert-gosigner/pkg/x509/revoking"
|
||||||
|
"git.cacert.org/cacert-gosigner/pkg/x509/signing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const minRSABits = 2048
|
||||||
|
|
||||||
type Serial struct {
|
type Serial struct {
|
||||||
Device string
|
Device string
|
||||||
Baud int
|
Baud int
|
||||||
|
@ -197,10 +204,16 @@ func (k *KeyStorage) UnmarshalYAML(n *yaml.Node) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CARepository interface {
|
||||||
|
revoking.Repository
|
||||||
|
signing.Repository
|
||||||
|
}
|
||||||
|
|
||||||
type SignerConfig struct {
|
type SignerConfig struct {
|
||||||
global *Settings `yaml:"Settings"`
|
global *Settings `yaml:"Settings"`
|
||||||
caMap map[string]*CaCertificateEntry `yaml:"CAs"`
|
caMap map[string]*CaCertificateEntry `yaml:"CAs"`
|
||||||
keyStorage map[string]*KeyStorage `yaml:"KeyStorage"`
|
keyStorage map[string]*KeyStorage `yaml:"KeyStorage"`
|
||||||
|
repositories map[string]CARepository
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *SignerConfig) GetCADefinition(label string) (*CaCertificateEntry, error) {
|
func (c *SignerConfig) GetCADefinition(label string) (*CaCertificateEntry, error) {
|
||||||
|
@ -321,6 +334,26 @@ func (c *SignerConfig) GetSerial() *Serial {
|
||||||
return c.global.Serial
|
return c.global.Serial
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *SignerConfig) Repository(name string) (CARepository, error) {
|
||||||
|
var (
|
||||||
|
repo CARepository
|
||||||
|
ok bool
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
repo, ok = c.repositories[name]
|
||||||
|
if !ok {
|
||||||
|
repo, err = openssl.NewFileRepository(path.Join("repos", name))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not create repository for %s: %w", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.repositories[name] = repo
|
||||||
|
}
|
||||||
|
|
||||||
|
return repo, nil
|
||||||
|
}
|
||||||
|
|
||||||
// LoadConfiguration reads YAML configuration from the given reader as a SignerConfig structure
|
// LoadConfiguration reads YAML configuration from the given reader as a SignerConfig structure
|
||||||
func LoadConfiguration(r io.Reader) (*SignerConfig, error) {
|
func LoadConfiguration(r io.Reader) (*SignerConfig, error) {
|
||||||
config := struct {
|
config := struct {
|
||||||
|
@ -349,23 +382,26 @@ func LoadConfiguration(r io.Reader) (*SignerConfig, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return &SignerConfig{
|
return &SignerConfig{
|
||||||
global: config.Global,
|
global: config.Global,
|
||||||
caMap: config.CAs,
|
caMap: config.CAs,
|
||||||
keyStorage: config.KeyStorage,
|
keyStorage: config.KeyStorage,
|
||||||
|
repositories: make(map[string]CARepository),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type PrivateKeyInfo struct {
|
type PrivateKeyInfo struct {
|
||||||
Algorithm x509.PublicKeyAlgorithm
|
Algorithm x509.PublicKeyAlgorithm
|
||||||
EccCurve elliptic.Curve
|
EccCurve elliptic.Curve
|
||||||
RSABits int
|
RSABits int
|
||||||
|
CRLSignatureAlgorithm x509.SignatureAlgorithm
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PrivateKeyInfo) UnmarshalYAML(value *yaml.Node) error {
|
func (p *PrivateKeyInfo) UnmarshalYAML(value *yaml.Node) error {
|
||||||
internalStructure := struct {
|
internalStructure := struct {
|
||||||
Algorithm string `yaml:"algorithm"`
|
Algorithm string `yaml:"algorithm"`
|
||||||
EccCurve string `yaml:"ecc-curve,omitempty"`
|
EccCurve string `yaml:"ecc-curve,omitempty"`
|
||||||
RSABits *int `yaml:"rsa-bits,omitempty"`
|
RSABits *int `yaml:"rsa-bits,omitempty"`
|
||||||
|
CRLSignatureAlgorithm string `yaml:"crl-signature-algorithm,omitempty"`
|
||||||
}{}
|
}{}
|
||||||
|
|
||||||
err := value.Decode(&internalStructure)
|
err := value.Decode(&internalStructure)
|
||||||
|
@ -382,6 +418,12 @@ func (p *PrivateKeyInfo) UnmarshalYAML(value *yaml.Node) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
p.RSABits = *internalStructure.RSABits
|
p.RSABits = *internalStructure.RSABits
|
||||||
|
|
||||||
|
if p.RSABits < minRSABits {
|
||||||
|
return fmt.Errorf("RSA keys must have a length of at least %d bits", minRSABits)
|
||||||
|
}
|
||||||
|
|
||||||
|
p.CRLSignatureAlgorithm = determineRSASignatureAlgorithm(internalStructure.CRLSignatureAlgorithm)
|
||||||
case "EC":
|
case "EC":
|
||||||
p.Algorithm = x509.ECDSA
|
p.Algorithm = x509.ECDSA
|
||||||
|
|
||||||
|
@ -393,6 +435,8 @@ func (p *PrivateKeyInfo) UnmarshalYAML(value *yaml.Node) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p.CRLSignatureAlgorithm = determineECDSASignatureAlgorithm(internalStructure.CRLSignatureAlgorithm)
|
||||||
case "":
|
case "":
|
||||||
return errors.New("element 'algorithm' must be specified as 'EC' or 'RSA'")
|
return errors.New("element 'algorithm' must be specified as 'EC' or 'RSA'")
|
||||||
default:
|
default:
|
||||||
|
@ -405,6 +449,32 @@ func (p *PrivateKeyInfo) UnmarshalYAML(value *yaml.Node) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func determineRSASignatureAlgorithm(algorithm string) x509.SignatureAlgorithm {
|
||||||
|
switch strings.ToLower(algorithm) {
|
||||||
|
case "sha1withrsa", "sha1":
|
||||||
|
return x509.SHA1WithRSA
|
||||||
|
case "sha384withrsa", "sha384":
|
||||||
|
return x509.SHA384WithRSA
|
||||||
|
case "sha512withrsa", "sha512":
|
||||||
|
return x509.SHA512WithRSA
|
||||||
|
default:
|
||||||
|
return x509.SHA256WithRSA
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func determineECDSASignatureAlgorithm(algorithm string) x509.SignatureAlgorithm {
|
||||||
|
switch strings.ToLower(algorithm) {
|
||||||
|
case "sha1withecdsa", "sha1":
|
||||||
|
return x509.ECDSAWithSHA1
|
||||||
|
case "sha384withecdsa", "sha384":
|
||||||
|
return x509.ECDSAWithSHA384
|
||||||
|
case "sha512withecdsa", "sha512":
|
||||||
|
return x509.ECDSAWithSHA512
|
||||||
|
default:
|
||||||
|
return x509.ECDSAWithSHA256
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (p *PrivateKeyInfo) MarshalYAML() (interface{}, error) {
|
func (p *PrivateKeyInfo) MarshalYAML() (interface{}, error) {
|
||||||
internalStructure := struct {
|
internalStructure := struct {
|
||||||
Algorithm string `yaml:"algorithm"`
|
Algorithm string `yaml:"algorithm"`
|
||||||
|
|
|
@ -79,6 +79,8 @@ func (a *Access) Healthy() (*health.Info, error) {
|
||||||
healthy = false
|
healthy = false
|
||||||
|
|
||||||
moreInfo[infoKey] = checkFailed
|
moreInfo[infoKey] = checkFailed
|
||||||
|
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
moreInfo[infoKey] = fmt.Sprintf("ok, valid until %s", cert.NotAfter.UTC().Format(time.RFC3339))
|
moreInfo[infoKey] = fmt.Sprintf("ok, valid until %s", cert.NotAfter.UTC().Format(time.RFC3339))
|
||||||
|
@ -92,6 +94,8 @@ func (a *Access) Healthy() (*health.Info, error) {
|
||||||
healthy = false
|
healthy = false
|
||||||
|
|
||||||
moreInfo[infoKey] = checkFailed
|
moreInfo[infoKey] = checkFailed
|
||||||
|
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
def, err := a.signerConfig.GetCADefinition(ca)
|
def, err := a.signerConfig.GetCADefinition(ca)
|
||||||
|
@ -99,6 +103,8 @@ func (a *Access) Healthy() (*health.Info, error) {
|
||||||
healthy = false
|
healthy = false
|
||||||
|
|
||||||
moreInfo[infoKey] = checkFailed
|
moreInfo[infoKey] = checkFailed
|
||||||
|
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = a.getKeyPair(ca, def.KeyInfo)
|
_, err = a.getKeyPair(ca, def.KeyInfo)
|
||||||
|
@ -106,6 +112,8 @@ func (a *Access) Healthy() (*health.Info, error) {
|
||||||
healthy = false
|
healthy = false
|
||||||
|
|
||||||
moreInfo[infoKey] = checkFailed
|
moreInfo[infoKey] = checkFailed
|
||||||
|
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
moreInfo[infoKey] = fmt.Sprintf("ok, valid until %s", cert.NotAfter.UTC().Format(time.RFC3339))
|
moreInfo[infoKey] = fmt.Sprintf("ok, valid until %s", cert.NotAfter.UTC().Format(time.RFC3339))
|
||||||
|
@ -307,6 +315,8 @@ func (a *Access) GetSubordinateCACertificate(certLabel string) (*x509.Certificat
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
caCert.Certificate, caCert.KeyPair = certificate, keyPair
|
||||||
|
|
||||||
return certificate, nil
|
return certificate, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,58 +21,82 @@ limitations under the License.
|
||||||
package messages
|
package messages
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/pem"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CommandCode int
|
type CommandCode int8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
CmdHealth CommandCode = iota
|
CmdHealth CommandCode = iota
|
||||||
|
CmdFetchCRL
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var commandNames = map[CommandCode]string{
|
||||||
|
CmdHealth: "HEALTH",
|
||||||
|
CmdFetchCRL: "FETCH URL",
|
||||||
|
}
|
||||||
|
|
||||||
func (c CommandCode) String() string {
|
func (c CommandCode) String() string {
|
||||||
switch c {
|
if name, ok := commandNames[c]; ok {
|
||||||
case CmdHealth:
|
return name
|
||||||
return "HEALTH"
|
|
||||||
default:
|
|
||||||
return fmt.Sprintf("unknown (%d)", int(c))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("unknown %d", c)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Command struct {
|
type ResponseCode int8
|
||||||
Code CommandCode `msgpack:"code"`
|
|
||||||
TimeStamp time.Time `msgpack:"created"`
|
|
||||||
Payload interface{} `msgpack:"payload"` // optional payload
|
|
||||||
}
|
|
||||||
|
|
||||||
type ResponseCode int
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
RspError ResponseCode = -1
|
RespError ResponseCode = -1
|
||||||
RspHealth ResponseCode = iota
|
RespHealth ResponseCode = iota
|
||||||
|
RespFetchCRL
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r ResponseCode) String() string {
|
var responseNames = map[ResponseCode]string{
|
||||||
switch r {
|
RespError: "ERROR",
|
||||||
case RspError:
|
RespHealth: "HEALTH",
|
||||||
return "ERROR"
|
RespFetchCRL: "FETCH CRL",
|
||||||
case RspHealth:
|
}
|
||||||
return "HEALTH"
|
|
||||||
default:
|
func (c ResponseCode) String() string {
|
||||||
return fmt.Sprintf("unknown (%d)", int(r))
|
if name, ok := responseNames[c]; ok {
|
||||||
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("unknown %d", c)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Response struct {
|
type CommandAnnounce struct {
|
||||||
Code ResponseCode `msgpack:"code"`
|
Code CommandCode `msgpack:"code"`
|
||||||
TimeStamp time.Time `msgpack:"created"`
|
Created time.Time `msgpack:"created"`
|
||||||
Payload interface{} `msgpack:"payload"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Response) String() string {
|
func (r *CommandAnnounce) String() string {
|
||||||
return fmt.Sprintf("[%s] at %s: %+v", r.Code, r.TimeStamp, r.Payload)
|
return fmt.Sprintf("CommandAnnounce[code=%s, created=%s]", r.Code, r.Created)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResponseAnnounce struct {
|
||||||
|
Code ResponseCode `msgpack:"code"`
|
||||||
|
Created time.Time `msgpack:"created"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ResponseAnnounce) String() string {
|
||||||
|
return fmt.Sprintf("ResponseAnnounce[code=%s, created=%s]", r.Code, r.Created)
|
||||||
|
}
|
||||||
|
|
||||||
|
type FetchCRLCommand struct {
|
||||||
|
IssuerID string `msgpack:"issuer_id"`
|
||||||
|
LastKnownHash struct {
|
||||||
|
Algorithm string `msgpack:"algorithm"`
|
||||||
|
Value string `msgpack:"value"`
|
||||||
|
} `msgpack:"last_known_hash"` // optional last known hash in format
|
||||||
|
}
|
||||||
|
|
||||||
|
type HealthCommand struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type HealthInfo struct {
|
type HealthInfo struct {
|
||||||
|
@ -97,10 +121,61 @@ func (i *HealthInfo) String() string {
|
||||||
|
|
||||||
type HealthResponse struct {
|
type HealthResponse struct {
|
||||||
Version string `msgpack:"version"`
|
Version string `msgpack:"version"`
|
||||||
Healthy bool
|
Healthy bool `msgpack:"healthy"`
|
||||||
Info []HealthInfo
|
Info []*HealthInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HealthResponse) String() string {
|
||||||
|
builder := &strings.Builder{}
|
||||||
|
|
||||||
|
_, _ = fmt.Fprintf(builder, "signer version=%s, healthy=%v, health data:\n", h.Version, h.Healthy)
|
||||||
|
|
||||||
|
for _, info := range h.Info {
|
||||||
|
_, _ = fmt.Fprintf(builder, " - %s", info)
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
type FetchCRLResponse struct {
|
||||||
|
IssuerID string `msgpack:"issuer_id"`
|
||||||
|
IsDelta bool `msgpack:"is_delta"`
|
||||||
|
CRLData []byte `msgpack:"crl_data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *FetchCRLResponse) String() string {
|
||||||
|
builder := &strings.Builder{}
|
||||||
|
|
||||||
|
_, _ = fmt.Fprintf(builder, "issuer id=%s, delta CRL data=%v", r.IssuerID, r.IsDelta)
|
||||||
|
|
||||||
|
if r.IsDelta {
|
||||||
|
_, _ = fmt.Fprint(builder, ", delta CRL data not shown")
|
||||||
|
} else {
|
||||||
|
revlist, err := x509.ParseRevocationList(r.CRLData)
|
||||||
|
if err != nil {
|
||||||
|
_, _ = fmt.Fprintf(builder, ", could not parse CRL: %s", err.Error())
|
||||||
|
} else {
|
||||||
|
_, _ = fmt.Fprintf(builder, ", CRL info: issuer=%s, number=%s, next update=%s, revoked certificates=%d",
|
||||||
|
revlist.Issuer, revlist.Number, revlist.NextUpdate, len(revlist.RevokedCertificates))
|
||||||
|
_, _ = builder.WriteString(", CRL data:\n")
|
||||||
|
_ = pem.Encode(builder, &pem.Block{
|
||||||
|
Type: "CERTIFICATE REVOCATION LIST",
|
||||||
|
Bytes: r.CRLData,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
type ErrorResponse struct {
|
type ErrorResponse struct {
|
||||||
Message string `msgpack:"message"`
|
Message string `msgpack:"message"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BuildCommandAnnounce(code CommandCode) *CommandAnnounce {
|
||||||
|
return &CommandAnnounce{Code: code, Created: time.Now().UTC()}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BuildResponseAnnounce(code ResponseCode) *ResponseAnnounce {
|
||||||
|
return &ResponseAnnounce{Code: code, Created: time.Now().UTC()}
|
||||||
|
}
|
||||||
|
|
|
@ -26,6 +26,36 @@ func ___encode(i interface{}) ([]byte, error) {
|
||||||
// encodeAsArray
|
// encodeAsArray
|
||||||
func ___encodeAsArray(i interface{}) ([]byte, error) {
|
func ___encodeAsArray(i interface{}) ([]byte, error) {
|
||||||
switch v := i.(type) {
|
switch v := i.(type) {
|
||||||
|
case HealthCommand:
|
||||||
|
encoder := enc.NewEncoder()
|
||||||
|
size, err := ___calcArraySizeHealthCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, encoder)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
encoder.MakeBytes(size)
|
||||||
|
b, offset, err := ___encodeArrayHealthCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, encoder, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if size != offset {
|
||||||
|
return nil, fmt.Errorf("%s size / offset different %d : %d", "HealthCommand", size, offset)
|
||||||
|
}
|
||||||
|
return b, err
|
||||||
|
case *HealthCommand:
|
||||||
|
encoder := enc.NewEncoder()
|
||||||
|
size, err := ___calcArraySizeHealthCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(*v, encoder)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
encoder.MakeBytes(size)
|
||||||
|
b, offset, err := ___encodeArrayHealthCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(*v, encoder, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if size != offset {
|
||||||
|
return nil, fmt.Errorf("%s size / offset different %d : %d", "HealthCommand", size, offset)
|
||||||
|
}
|
||||||
|
return b, err
|
||||||
case HealthInfo:
|
case HealthInfo:
|
||||||
encoder := enc.NewEncoder()
|
encoder := enc.NewEncoder()
|
||||||
size, err := ___calcArraySizeHealthInfo_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, encoder)
|
size, err := ___calcArraySizeHealthInfo_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, encoder)
|
||||||
|
@ -86,6 +116,36 @@ func ___encodeAsArray(i interface{}) ([]byte, error) {
|
||||||
return nil, fmt.Errorf("%s size / offset different %d : %d", "HealthResponse", size, offset)
|
return nil, fmt.Errorf("%s size / offset different %d : %d", "HealthResponse", size, offset)
|
||||||
}
|
}
|
||||||
return b, err
|
return b, err
|
||||||
|
case FetchCRLResponse:
|
||||||
|
encoder := enc.NewEncoder()
|
||||||
|
size, err := ___calcArraySizeFetchCRLResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, encoder)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
encoder.MakeBytes(size)
|
||||||
|
b, offset, err := ___encodeArrayFetchCRLResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, encoder, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if size != offset {
|
||||||
|
return nil, fmt.Errorf("%s size / offset different %d : %d", "FetchCRLResponse", size, offset)
|
||||||
|
}
|
||||||
|
return b, err
|
||||||
|
case *FetchCRLResponse:
|
||||||
|
encoder := enc.NewEncoder()
|
||||||
|
size, err := ___calcArraySizeFetchCRLResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(*v, encoder)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
encoder.MakeBytes(size)
|
||||||
|
b, offset, err := ___encodeArrayFetchCRLResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(*v, encoder, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if size != offset {
|
||||||
|
return nil, fmt.Errorf("%s size / offset different %d : %d", "FetchCRLResponse", size, offset)
|
||||||
|
}
|
||||||
|
return b, err
|
||||||
case ErrorResponse:
|
case ErrorResponse:
|
||||||
encoder := enc.NewEncoder()
|
encoder := enc.NewEncoder()
|
||||||
size, err := ___calcArraySizeErrorResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, encoder)
|
size, err := ___calcArraySizeErrorResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, encoder)
|
||||||
|
@ -123,6 +183,36 @@ func ___encodeAsArray(i interface{}) ([]byte, error) {
|
||||||
// encodeAsMap
|
// encodeAsMap
|
||||||
func ___encodeAsMap(i interface{}) ([]byte, error) {
|
func ___encodeAsMap(i interface{}) ([]byte, error) {
|
||||||
switch v := i.(type) {
|
switch v := i.(type) {
|
||||||
|
case HealthCommand:
|
||||||
|
encoder := enc.NewEncoder()
|
||||||
|
size, err := ___calcMapSizeHealthCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, encoder)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
encoder.MakeBytes(size)
|
||||||
|
b, offset, err := ___encodeMapHealthCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, encoder, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if size != offset {
|
||||||
|
return nil, fmt.Errorf("%s size / offset different %d : %d", "HealthCommand", size, offset)
|
||||||
|
}
|
||||||
|
return b, err
|
||||||
|
case *HealthCommand:
|
||||||
|
encoder := enc.NewEncoder()
|
||||||
|
size, err := ___calcMapSizeHealthCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(*v, encoder)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
encoder.MakeBytes(size)
|
||||||
|
b, offset, err := ___encodeMapHealthCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(*v, encoder, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if size != offset {
|
||||||
|
return nil, fmt.Errorf("%s size / offset different %d : %d", "HealthCommand", size, offset)
|
||||||
|
}
|
||||||
|
return b, err
|
||||||
case HealthInfo:
|
case HealthInfo:
|
||||||
encoder := enc.NewEncoder()
|
encoder := enc.NewEncoder()
|
||||||
size, err := ___calcMapSizeHealthInfo_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, encoder)
|
size, err := ___calcMapSizeHealthInfo_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, encoder)
|
||||||
|
@ -183,6 +273,36 @@ func ___encodeAsMap(i interface{}) ([]byte, error) {
|
||||||
return nil, fmt.Errorf("%s size / offset different %d : %d", "HealthResponse", size, offset)
|
return nil, fmt.Errorf("%s size / offset different %d : %d", "HealthResponse", size, offset)
|
||||||
}
|
}
|
||||||
return b, err
|
return b, err
|
||||||
|
case FetchCRLResponse:
|
||||||
|
encoder := enc.NewEncoder()
|
||||||
|
size, err := ___calcMapSizeFetchCRLResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, encoder)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
encoder.MakeBytes(size)
|
||||||
|
b, offset, err := ___encodeMapFetchCRLResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, encoder, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if size != offset {
|
||||||
|
return nil, fmt.Errorf("%s size / offset different %d : %d", "FetchCRLResponse", size, offset)
|
||||||
|
}
|
||||||
|
return b, err
|
||||||
|
case *FetchCRLResponse:
|
||||||
|
encoder := enc.NewEncoder()
|
||||||
|
size, err := ___calcMapSizeFetchCRLResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(*v, encoder)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
encoder.MakeBytes(size)
|
||||||
|
b, offset, err := ___encodeMapFetchCRLResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(*v, encoder, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if size != offset {
|
||||||
|
return nil, fmt.Errorf("%s size / offset different %d : %d", "FetchCRLResponse", size, offset)
|
||||||
|
}
|
||||||
|
return b, err
|
||||||
case ErrorResponse:
|
case ErrorResponse:
|
||||||
encoder := enc.NewEncoder()
|
encoder := enc.NewEncoder()
|
||||||
size, err := ___calcMapSizeErrorResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, encoder)
|
size, err := ___calcMapSizeErrorResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, encoder)
|
||||||
|
@ -229,6 +349,20 @@ func ___decode(data []byte, i interface{}) (bool, error) {
|
||||||
// decodeAsArray
|
// decodeAsArray
|
||||||
func ___decodeAsArray(data []byte, i interface{}) (bool, error) {
|
func ___decodeAsArray(data []byte, i interface{}) (bool, error) {
|
||||||
switch v := i.(type) {
|
switch v := i.(type) {
|
||||||
|
case *HealthCommand:
|
||||||
|
decoder := dec.NewDecoder(data)
|
||||||
|
offset, err := ___decodeArrayHealthCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, decoder, 0)
|
||||||
|
if err == nil && offset != decoder.Len() {
|
||||||
|
return true, fmt.Errorf("read length is different [%d] [%d] ", offset, decoder.Len())
|
||||||
|
}
|
||||||
|
return true, err
|
||||||
|
case **HealthCommand:
|
||||||
|
decoder := dec.NewDecoder(data)
|
||||||
|
offset, err := ___decodeArrayHealthCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(*v, decoder, 0)
|
||||||
|
if err == nil && offset != decoder.Len() {
|
||||||
|
return true, fmt.Errorf("read length is different [%d] [%d] ", offset, decoder.Len())
|
||||||
|
}
|
||||||
|
return true, err
|
||||||
case *HealthInfo:
|
case *HealthInfo:
|
||||||
decoder := dec.NewDecoder(data)
|
decoder := dec.NewDecoder(data)
|
||||||
offset, err := ___decodeArrayHealthInfo_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, decoder, 0)
|
offset, err := ___decodeArrayHealthInfo_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, decoder, 0)
|
||||||
|
@ -257,6 +391,20 @@ func ___decodeAsArray(data []byte, i interface{}) (bool, error) {
|
||||||
return true, fmt.Errorf("read length is different [%d] [%d] ", offset, decoder.Len())
|
return true, fmt.Errorf("read length is different [%d] [%d] ", offset, decoder.Len())
|
||||||
}
|
}
|
||||||
return true, err
|
return true, err
|
||||||
|
case *FetchCRLResponse:
|
||||||
|
decoder := dec.NewDecoder(data)
|
||||||
|
offset, err := ___decodeArrayFetchCRLResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, decoder, 0)
|
||||||
|
if err == nil && offset != decoder.Len() {
|
||||||
|
return true, fmt.Errorf("read length is different [%d] [%d] ", offset, decoder.Len())
|
||||||
|
}
|
||||||
|
return true, err
|
||||||
|
case **FetchCRLResponse:
|
||||||
|
decoder := dec.NewDecoder(data)
|
||||||
|
offset, err := ___decodeArrayFetchCRLResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(*v, decoder, 0)
|
||||||
|
if err == nil && offset != decoder.Len() {
|
||||||
|
return true, fmt.Errorf("read length is different [%d] [%d] ", offset, decoder.Len())
|
||||||
|
}
|
||||||
|
return true, err
|
||||||
case *ErrorResponse:
|
case *ErrorResponse:
|
||||||
decoder := dec.NewDecoder(data)
|
decoder := dec.NewDecoder(data)
|
||||||
offset, err := ___decodeArrayErrorResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, decoder, 0)
|
offset, err := ___decodeArrayErrorResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, decoder, 0)
|
||||||
|
@ -278,6 +426,20 @@ func ___decodeAsArray(data []byte, i interface{}) (bool, error) {
|
||||||
// decodeAsMap
|
// decodeAsMap
|
||||||
func ___decodeAsMap(data []byte, i interface{}) (bool, error) {
|
func ___decodeAsMap(data []byte, i interface{}) (bool, error) {
|
||||||
switch v := i.(type) {
|
switch v := i.(type) {
|
||||||
|
case *HealthCommand:
|
||||||
|
decoder := dec.NewDecoder(data)
|
||||||
|
offset, err := ___decodeMapHealthCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, decoder, 0)
|
||||||
|
if err == nil && offset != decoder.Len() {
|
||||||
|
return true, fmt.Errorf("read length is different [%d] [%d] ", offset, decoder.Len())
|
||||||
|
}
|
||||||
|
return true, err
|
||||||
|
case **HealthCommand:
|
||||||
|
decoder := dec.NewDecoder(data)
|
||||||
|
offset, err := ___decodeMapHealthCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(*v, decoder, 0)
|
||||||
|
if err == nil && offset != decoder.Len() {
|
||||||
|
return true, fmt.Errorf("read length is different [%d] [%d] ", offset, decoder.Len())
|
||||||
|
}
|
||||||
|
return true, err
|
||||||
case *HealthInfo:
|
case *HealthInfo:
|
||||||
decoder := dec.NewDecoder(data)
|
decoder := dec.NewDecoder(data)
|
||||||
offset, err := ___decodeMapHealthInfo_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, decoder, 0)
|
offset, err := ___decodeMapHealthInfo_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, decoder, 0)
|
||||||
|
@ -306,6 +468,20 @@ func ___decodeAsMap(data []byte, i interface{}) (bool, error) {
|
||||||
return true, fmt.Errorf("read length is different [%d] [%d] ", offset, decoder.Len())
|
return true, fmt.Errorf("read length is different [%d] [%d] ", offset, decoder.Len())
|
||||||
}
|
}
|
||||||
return true, err
|
return true, err
|
||||||
|
case *FetchCRLResponse:
|
||||||
|
decoder := dec.NewDecoder(data)
|
||||||
|
offset, err := ___decodeMapFetchCRLResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, decoder, 0)
|
||||||
|
if err == nil && offset != decoder.Len() {
|
||||||
|
return true, fmt.Errorf("read length is different [%d] [%d] ", offset, decoder.Len())
|
||||||
|
}
|
||||||
|
return true, err
|
||||||
|
case **FetchCRLResponse:
|
||||||
|
decoder := dec.NewDecoder(data)
|
||||||
|
offset, err := ___decodeMapFetchCRLResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(*v, decoder, 0)
|
||||||
|
if err == nil && offset != decoder.Len() {
|
||||||
|
return true, fmt.Errorf("read length is different [%d] [%d] ", offset, decoder.Len())
|
||||||
|
}
|
||||||
|
return true, err
|
||||||
case *ErrorResponse:
|
case *ErrorResponse:
|
||||||
decoder := dec.NewDecoder(data)
|
decoder := dec.NewDecoder(data)
|
||||||
offset, err := ___decodeMapErrorResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, decoder, 0)
|
offset, err := ___decodeMapErrorResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, decoder, 0)
|
||||||
|
@ -324,6 +500,81 @@ func ___decodeAsMap(data []byte, i interface{}) (bool, error) {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// calculate size from git.cacert.org/cacert-gosigner/pkg/messages.HealthCommand
|
||||||
|
func ___calcArraySizeHealthCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v HealthCommand, encoder *enc.Encoder) (int, error) {
|
||||||
|
size := 0
|
||||||
|
size += encoder.CalcStructHeaderFix(0)
|
||||||
|
return size, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate size from git.cacert.org/cacert-gosigner/pkg/messages.HealthCommand
|
||||||
|
func ___calcMapSizeHealthCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v HealthCommand, encoder *enc.Encoder) (int, error) {
|
||||||
|
size := 0
|
||||||
|
size += encoder.CalcStructHeaderFix(0)
|
||||||
|
return size, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// encode from git.cacert.org/cacert-gosigner/pkg/messages.HealthCommand
|
||||||
|
func ___encodeArrayHealthCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v HealthCommand, encoder *enc.Encoder, offset int) ([]byte, int, error) {
|
||||||
|
var err error
|
||||||
|
offset = encoder.WriteStructHeaderFixAsArray(0, offset)
|
||||||
|
return encoder.EncodedBytes(), offset, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// encode from git.cacert.org/cacert-gosigner/pkg/messages.HealthCommand
|
||||||
|
func ___encodeMapHealthCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v HealthCommand, encoder *enc.Encoder, offset int) ([]byte, int, error) {
|
||||||
|
var err error
|
||||||
|
offset = encoder.WriteStructHeaderFixAsMap(0, offset)
|
||||||
|
return encoder.EncodedBytes(), offset, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// decode to git.cacert.org/cacert-gosigner/pkg/messages.HealthCommand
|
||||||
|
func ___decodeArrayHealthCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v *HealthCommand, decoder *dec.Decoder, offset int) (int, error) {
|
||||||
|
offset, err := decoder.CheckStructHeader(0, offset)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return offset, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// decode to git.cacert.org/cacert-gosigner/pkg/messages.HealthCommand
|
||||||
|
func ___decodeMapHealthCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v *HealthCommand, decoder *dec.Decoder, offset int) (int, error) {
|
||||||
|
keys := [][]byte{}
|
||||||
|
offset, err := decoder.CheckStructHeader(0, offset)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
count := 0
|
||||||
|
for count < 0 {
|
||||||
|
var dataKey []byte
|
||||||
|
dataKey, offset, err = decoder.AsStringBytes(offset)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
fieldIndex := -1
|
||||||
|
for i, key := range keys {
|
||||||
|
if len(dataKey) != len(key) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fieldIndex = i
|
||||||
|
for dataKeyIndex := range dataKey {
|
||||||
|
if dataKey[dataKeyIndex] != key[dataKeyIndex] {
|
||||||
|
fieldIndex = -1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if fieldIndex >= 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch fieldIndex {
|
||||||
|
default:
|
||||||
|
return 0, fmt.Errorf("unknown key[%s] found", string(dataKey))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return offset, err
|
||||||
|
}
|
||||||
|
|
||||||
// calculate size from git.cacert.org/cacert-gosigner/pkg/messages.HealthInfo
|
// calculate size from git.cacert.org/cacert-gosigner/pkg/messages.HealthInfo
|
||||||
func ___calcArraySizeHealthInfo_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v HealthInfo, encoder *enc.Encoder) (int, error) {
|
func ___calcArraySizeHealthInfo_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v HealthInfo, encoder *enc.Encoder) (int, error) {
|
||||||
size := 0
|
size := 0
|
||||||
|
@ -562,11 +813,16 @@ func ___calcArraySizeHealthResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81
|
||||||
}
|
}
|
||||||
size += s
|
size += s
|
||||||
for _, vv := range v.Info {
|
for _, vv := range v.Info {
|
||||||
size_vv, err := ___calcArraySizeHealthInfo_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(vv, encoder)
|
if vv != nil {
|
||||||
if err != nil {
|
vvp := *vv
|
||||||
return 0, err
|
size_vvp, err := ___calcArraySizeHealthInfo_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(vvp, encoder)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
size += size_vvp
|
||||||
|
} else {
|
||||||
|
size += encoder.CalcNil()
|
||||||
}
|
}
|
||||||
size += size_vv
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
size += encoder.CalcNil()
|
size += encoder.CalcNil()
|
||||||
|
@ -590,11 +846,16 @@ func ___calcMapSizeHealthResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a8137
|
||||||
}
|
}
|
||||||
size += s
|
size += s
|
||||||
for _, vv := range v.Info {
|
for _, vv := range v.Info {
|
||||||
size_vv, err := ___calcMapSizeHealthInfo_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(vv, encoder)
|
if vv != nil {
|
||||||
if err != nil {
|
vvp := *vv
|
||||||
return 0, err
|
size_vvp, err := ___calcMapSizeHealthInfo_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(vvp, encoder)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
size += size_vvp
|
||||||
|
} else {
|
||||||
|
size += encoder.CalcNil()
|
||||||
}
|
}
|
||||||
size += size_vv
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
size += encoder.CalcNil()
|
size += encoder.CalcNil()
|
||||||
|
@ -611,9 +872,14 @@ func ___encodeArrayHealthResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a8137
|
||||||
if v.Info != nil {
|
if v.Info != nil {
|
||||||
offset = encoder.WriteSliceLength(len(v.Info), offset, false)
|
offset = encoder.WriteSliceLength(len(v.Info), offset, false)
|
||||||
for _, vv := range v.Info {
|
for _, vv := range v.Info {
|
||||||
_, offset, err = ___encodeArrayHealthInfo_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(vv, encoder, offset)
|
if vv != nil {
|
||||||
if err != nil {
|
vvp := *vv
|
||||||
return nil, 0, err
|
_, offset, err = ___encodeArrayHealthInfo_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(vvp, encoder, offset)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
offset = encoder.WriteNil(offset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -628,15 +894,20 @@ func ___encodeMapHealthResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f
|
||||||
offset = encoder.WriteStructHeaderFixAsMap(3, offset)
|
offset = encoder.WriteStructHeaderFixAsMap(3, offset)
|
||||||
offset = encoder.WriteStringFix("version", 7, offset)
|
offset = encoder.WriteStringFix("version", 7, offset)
|
||||||
offset = encoder.WriteString(v.Version, offset)
|
offset = encoder.WriteString(v.Version, offset)
|
||||||
offset = encoder.WriteStringFix("Healthy", 7, offset)
|
offset = encoder.WriteStringFix("healthy", 7, offset)
|
||||||
offset = encoder.WriteBool(v.Healthy, offset)
|
offset = encoder.WriteBool(v.Healthy, offset)
|
||||||
offset = encoder.WriteStringFix("Info", 4, offset)
|
offset = encoder.WriteStringFix("Info", 4, offset)
|
||||||
if v.Info != nil {
|
if v.Info != nil {
|
||||||
offset = encoder.WriteSliceLength(len(v.Info), offset, false)
|
offset = encoder.WriteSliceLength(len(v.Info), offset, false)
|
||||||
for _, vv := range v.Info {
|
for _, vv := range v.Info {
|
||||||
_, offset, err = ___encodeMapHealthInfo_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(vv, encoder, offset)
|
if vv != nil {
|
||||||
if err != nil {
|
vvp := *vv
|
||||||
return nil, 0, err
|
_, offset, err = ___encodeMapHealthInfo_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(vvp, encoder, offset)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
offset = encoder.WriteNil(offset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -668,18 +939,24 @@ func ___decodeArrayHealthResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a8137
|
||||||
v.Healthy = vv
|
v.Healthy = vv
|
||||||
}
|
}
|
||||||
if !decoder.IsCodeNil(offset) {
|
if !decoder.IsCodeNil(offset) {
|
||||||
var vv []HealthInfo
|
var vv []*HealthInfo
|
||||||
var vvl int
|
var vvl int
|
||||||
vvl, offset, err = decoder.SliceLength(offset)
|
vvl, offset, err = decoder.SliceLength(offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
vv = make([]HealthInfo, vvl)
|
vv = make([]*HealthInfo, vvl)
|
||||||
for vvi := range vv {
|
for vvi := range vv {
|
||||||
var vvv HealthInfo
|
var vvv *HealthInfo
|
||||||
offset, err = ___decodeArrayHealthInfo_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(&vvv, decoder, offset)
|
if !decoder.IsCodeNil(offset) {
|
||||||
if err != nil {
|
var vvvp HealthInfo
|
||||||
return 0, err
|
offset, err = ___decodeArrayHealthInfo_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(&vvvp, decoder, offset)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
vvv = &vvvp
|
||||||
|
} else {
|
||||||
|
offset++
|
||||||
}
|
}
|
||||||
vv[vvi] = vvv
|
vv[vvi] = vvv
|
||||||
}
|
}
|
||||||
|
@ -694,7 +971,7 @@ func ___decodeArrayHealthResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a8137
|
||||||
func ___decodeMapHealthResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v *HealthResponse, decoder *dec.Decoder, offset int) (int, error) {
|
func ___decodeMapHealthResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v *HealthResponse, decoder *dec.Decoder, offset int) (int, error) {
|
||||||
keys := [][]byte{
|
keys := [][]byte{
|
||||||
{uint8(0x76), uint8(0x65), uint8(0x72), uint8(0x73), uint8(0x69), uint8(0x6f), uint8(0x6e)}, // version
|
{uint8(0x76), uint8(0x65), uint8(0x72), uint8(0x73), uint8(0x69), uint8(0x6f), uint8(0x6e)}, // version
|
||||||
{uint8(0x48), uint8(0x65), uint8(0x61), uint8(0x6c), uint8(0x74), uint8(0x68), uint8(0x79)}, // Healthy
|
{uint8(0x68), uint8(0x65), uint8(0x61), uint8(0x6c), uint8(0x74), uint8(0x68), uint8(0x79)}, // healthy
|
||||||
{uint8(0x49), uint8(0x6e), uint8(0x66), uint8(0x6f)}, // Info
|
{uint8(0x49), uint8(0x6e), uint8(0x66), uint8(0x6f)}, // Info
|
||||||
}
|
}
|
||||||
offset, err := decoder.CheckStructHeader(3, offset)
|
offset, err := decoder.CheckStructHeader(3, offset)
|
||||||
|
@ -747,22 +1024,239 @@ func ___decodeMapHealthResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f
|
||||||
count++
|
count++
|
||||||
case 2:
|
case 2:
|
||||||
if !decoder.IsCodeNil(offset) {
|
if !decoder.IsCodeNil(offset) {
|
||||||
var vv []HealthInfo
|
var vv []*HealthInfo
|
||||||
var vvl int
|
var vvl int
|
||||||
vvl, offset, err = decoder.SliceLength(offset)
|
vvl, offset, err = decoder.SliceLength(offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
vv = make([]HealthInfo, vvl)
|
vv = make([]*HealthInfo, vvl)
|
||||||
for vvi := range vv {
|
for vvi := range vv {
|
||||||
var vvv HealthInfo
|
var vvv *HealthInfo
|
||||||
offset, err = ___decodeMapHealthInfo_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(&vvv, decoder, offset)
|
if !decoder.IsCodeNil(offset) {
|
||||||
|
var vvvp HealthInfo
|
||||||
|
offset, err = ___decodeMapHealthInfo_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(&vvvp, decoder, offset)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
vvv = &vvvp
|
||||||
|
} else {
|
||||||
|
offset++
|
||||||
|
}
|
||||||
|
vv[vvi] = vvv
|
||||||
|
}
|
||||||
|
v.Info = vv
|
||||||
|
} else {
|
||||||
|
offset++
|
||||||
|
}
|
||||||
|
count++
|
||||||
|
default:
|
||||||
|
return 0, fmt.Errorf("unknown key[%s] found", string(dataKey))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return offset, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate size from git.cacert.org/cacert-gosigner/pkg/messages.FetchCRLResponse
|
||||||
|
func ___calcArraySizeFetchCRLResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v FetchCRLResponse, encoder *enc.Encoder) (int, error) {
|
||||||
|
size := 0
|
||||||
|
size += encoder.CalcStructHeaderFix(3)
|
||||||
|
size += encoder.CalcString(v.IssuerID)
|
||||||
|
size += encoder.CalcBool(v.IsDelta)
|
||||||
|
if v.CRLData != nil {
|
||||||
|
s, err := encoder.CalcSliceLength(len(v.CRLData), true)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
size += s
|
||||||
|
for _, vv := range v.CRLData {
|
||||||
|
size += encoder.CalcByte(vv)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
size += encoder.CalcNil()
|
||||||
|
}
|
||||||
|
return size, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate size from git.cacert.org/cacert-gosigner/pkg/messages.FetchCRLResponse
|
||||||
|
func ___calcMapSizeFetchCRLResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v FetchCRLResponse, encoder *enc.Encoder) (int, error) {
|
||||||
|
size := 0
|
||||||
|
size += encoder.CalcStructHeaderFix(3)
|
||||||
|
size += encoder.CalcStringFix(9)
|
||||||
|
size += encoder.CalcString(v.IssuerID)
|
||||||
|
size += encoder.CalcStringFix(8)
|
||||||
|
size += encoder.CalcBool(v.IsDelta)
|
||||||
|
size += encoder.CalcStringFix(8)
|
||||||
|
if v.CRLData != nil {
|
||||||
|
s, err := encoder.CalcSliceLength(len(v.CRLData), true)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
size += s
|
||||||
|
for _, vv := range v.CRLData {
|
||||||
|
size += encoder.CalcByte(vv)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
size += encoder.CalcNil()
|
||||||
|
}
|
||||||
|
return size, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// encode from git.cacert.org/cacert-gosigner/pkg/messages.FetchCRLResponse
|
||||||
|
func ___encodeArrayFetchCRLResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v FetchCRLResponse, encoder *enc.Encoder, offset int) ([]byte, int, error) {
|
||||||
|
var err error
|
||||||
|
offset = encoder.WriteStructHeaderFixAsArray(3, offset)
|
||||||
|
offset = encoder.WriteString(v.IssuerID, offset)
|
||||||
|
offset = encoder.WriteBool(v.IsDelta, offset)
|
||||||
|
if v.CRLData != nil {
|
||||||
|
offset = encoder.WriteSliceLength(len(v.CRLData), offset, true)
|
||||||
|
for _, vv := range v.CRLData {
|
||||||
|
offset = encoder.WriteByte(vv, offset)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
offset = encoder.WriteNil(offset)
|
||||||
|
}
|
||||||
|
return encoder.EncodedBytes(), offset, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// encode from git.cacert.org/cacert-gosigner/pkg/messages.FetchCRLResponse
|
||||||
|
func ___encodeMapFetchCRLResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v FetchCRLResponse, encoder *enc.Encoder, offset int) ([]byte, int, error) {
|
||||||
|
var err error
|
||||||
|
offset = encoder.WriteStructHeaderFixAsMap(3, offset)
|
||||||
|
offset = encoder.WriteStringFix("issuer_id", 9, offset)
|
||||||
|
offset = encoder.WriteString(v.IssuerID, offset)
|
||||||
|
offset = encoder.WriteStringFix("is_delta", 8, offset)
|
||||||
|
offset = encoder.WriteBool(v.IsDelta, offset)
|
||||||
|
offset = encoder.WriteStringFix("crl_data", 8, offset)
|
||||||
|
if v.CRLData != nil {
|
||||||
|
offset = encoder.WriteSliceLength(len(v.CRLData), offset, true)
|
||||||
|
for _, vv := range v.CRLData {
|
||||||
|
offset = encoder.WriteByte(vv, offset)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
offset = encoder.WriteNil(offset)
|
||||||
|
}
|
||||||
|
return encoder.EncodedBytes(), offset, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// decode to git.cacert.org/cacert-gosigner/pkg/messages.FetchCRLResponse
|
||||||
|
func ___decodeArrayFetchCRLResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v *FetchCRLResponse, decoder *dec.Decoder, offset int) (int, error) {
|
||||||
|
offset, err := decoder.CheckStructHeader(3, offset)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var vv string
|
||||||
|
vv, offset, err = decoder.AsString(offset)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
v.IssuerID = vv
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var vv bool
|
||||||
|
vv, offset, err = decoder.AsBool(offset)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
v.IsDelta = vv
|
||||||
|
}
|
||||||
|
if !decoder.IsCodeNil(offset) {
|
||||||
|
var vv []byte
|
||||||
|
var vvl int
|
||||||
|
vvl, offset, err = decoder.SliceLength(offset)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
vv = make([]byte, vvl)
|
||||||
|
for vvi := range vv {
|
||||||
|
var vvv byte
|
||||||
|
vvv, offset, err = decoder.AsByte(offset)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
vv[vvi] = vvv
|
||||||
|
}
|
||||||
|
v.CRLData = vv
|
||||||
|
} else {
|
||||||
|
offset++
|
||||||
|
}
|
||||||
|
return offset, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// decode to git.cacert.org/cacert-gosigner/pkg/messages.FetchCRLResponse
|
||||||
|
func ___decodeMapFetchCRLResponse_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v *FetchCRLResponse, decoder *dec.Decoder, offset int) (int, error) {
|
||||||
|
keys := [][]byte{
|
||||||
|
{uint8(0x69), uint8(0x73), uint8(0x73), uint8(0x75), uint8(0x65), uint8(0x72), uint8(0x5f), uint8(0x69), uint8(0x64)}, // issuer_id
|
||||||
|
{uint8(0x69), uint8(0x73), uint8(0x5f), uint8(0x64), uint8(0x65), uint8(0x6c), uint8(0x74), uint8(0x61)}, // is_delta
|
||||||
|
{uint8(0x63), uint8(0x72), uint8(0x6c), uint8(0x5f), uint8(0x64), uint8(0x61), uint8(0x74), uint8(0x61)}, // crl_data
|
||||||
|
}
|
||||||
|
offset, err := decoder.CheckStructHeader(3, offset)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
count := 0
|
||||||
|
for count < 3 {
|
||||||
|
var dataKey []byte
|
||||||
|
dataKey, offset, err = decoder.AsStringBytes(offset)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
fieldIndex := -1
|
||||||
|
for i, key := range keys {
|
||||||
|
if len(dataKey) != len(key) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fieldIndex = i
|
||||||
|
for dataKeyIndex := range dataKey {
|
||||||
|
if dataKey[dataKeyIndex] != key[dataKeyIndex] {
|
||||||
|
fieldIndex = -1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if fieldIndex >= 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch fieldIndex {
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
var vv string
|
||||||
|
vv, offset, err = decoder.AsString(offset)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
v.IssuerID = vv
|
||||||
|
}
|
||||||
|
count++
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
var vv bool
|
||||||
|
vv, offset, err = decoder.AsBool(offset)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
v.IsDelta = vv
|
||||||
|
}
|
||||||
|
count++
|
||||||
|
case 2:
|
||||||
|
if !decoder.IsCodeNil(offset) {
|
||||||
|
var vv []byte
|
||||||
|
var vvl int
|
||||||
|
vvl, offset, err = decoder.SliceLength(offset)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
vv = make([]byte, vvl)
|
||||||
|
for vvi := range vv {
|
||||||
|
var vvv byte
|
||||||
|
vvv, offset, err = decoder.AsByte(offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
vv[vvi] = vvv
|
vv[vvi] = vvv
|
||||||
}
|
}
|
||||||
v.Info = vv
|
v.CRLData = vv
|
||||||
} else {
|
} else {
|
||||||
offset++
|
offset++
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,71 +19,116 @@ limitations under the License.
|
||||||
package protocol
|
package protocol
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/shamaton/msgpackgen/msgpack"
|
"github.com/shamaton/msgpackgen/msgpack"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"git.cacert.org/cacert-gosigner/pkg/x509/revoking"
|
||||||
|
|
||||||
"git.cacert.org/cacert-gosigner/pkg/health"
|
"git.cacert.org/cacert-gosigner/pkg/health"
|
||||||
"git.cacert.org/cacert-gosigner/pkg/messages"
|
"git.cacert.org/cacert-gosigner/pkg/messages"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handler is responsible for parsing incoming frames and calling commands
|
// Handler is responsible for parsing incoming frames and calling commands
|
||||||
type Handler interface {
|
type Handler interface {
|
||||||
HandleFrame([]byte) ([]byte, error)
|
HandleCommandAnnounce([]byte) (*messages.CommandAnnounce, error)
|
||||||
|
HandleCommand(*messages.CommandAnnounce, []byte) ([]byte, []byte, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type MsgPackHandler struct {
|
type MsgPackHandler struct {
|
||||||
logger *logrus.Logger
|
logger *logrus.Logger
|
||||||
healthHandler *health.Handler
|
healthHandler *health.Handler
|
||||||
|
fetchCRLHandler *revoking.FetchCRLHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MsgPackHandler) HandleFrame(frame []byte) ([]byte, error) {
|
func (m *MsgPackHandler) HandleCommandAnnounce(frame []byte) (*messages.CommandAnnounce, error) {
|
||||||
var command messages.Command
|
var ann messages.CommandAnnounce
|
||||||
|
|
||||||
err := msgpack.Unmarshal(frame, &command)
|
if err := msgpack.Unmarshal(frame, &ann); err != nil {
|
||||||
if err != nil {
|
return nil, fmt.Errorf("could not unmarshal command announcement: %w", err)
|
||||||
m.logger.Errorf("unmarshal failed: %v", err)
|
|
||||||
|
|
||||||
errorResponse, innerErr := buildErrorResponse("do not understand")
|
|
||||||
if innerErr != nil {
|
|
||||||
return nil, innerErr
|
|
||||||
}
|
|
||||||
|
|
||||||
return errorResponse, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m.logger.Infof("Received %s command sent at %s", command.Code, command.TimeStamp)
|
m.logger.Infof("received command announcement %+v", ann)
|
||||||
|
|
||||||
response, err := m.handleCommand(&command)
|
return &ann, nil
|
||||||
if err != nil {
|
|
||||||
m.logger.Errorf("command failed: %v", err)
|
|
||||||
|
|
||||||
errorResponse, innerErr := buildErrorResponse("command failed")
|
|
||||||
if innerErr != nil {
|
|
||||||
return nil, innerErr
|
|
||||||
}
|
|
||||||
|
|
||||||
return errorResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
responseData, err := msgpack.Marshal(response)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not marshal response: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return responseData, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MsgPackHandler) handleCommand(command *messages.Command) (*messages.Response, error) {
|
func (m *MsgPackHandler) HandleCommand(announce *messages.CommandAnnounce, frame []byte) ([]byte, []byte, error) {
|
||||||
|
var (
|
||||||
|
response *Response
|
||||||
|
clientError, err error
|
||||||
|
)
|
||||||
|
|
||||||
|
switch announce.Code {
|
||||||
|
case messages.CmdHealth:
|
||||||
|
// health has no payload, ignore the frame
|
||||||
|
response, err = m.handleCommand(&Command{Announce: announce, Command: nil})
|
||||||
|
if err != nil {
|
||||||
|
m.logger.WithError(err).Error("health handling failed")
|
||||||
|
|
||||||
|
clientError = errors.New("could not handle request")
|
||||||
|
}
|
||||||
|
case messages.CmdFetchCRL:
|
||||||
|
var command messages.FetchCRLCommand
|
||||||
|
|
||||||
|
err = msgpack.Unmarshal(frame, &command)
|
||||||
|
if err != nil {
|
||||||
|
m.logger.WithError(err).Error("unmarshal failed")
|
||||||
|
|
||||||
|
clientError = errors.New("could not unmarshal fetch crl command")
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err = m.handleCommand(&Command{Announce: announce, Command: command})
|
||||||
|
if err != nil {
|
||||||
|
m.logger.WithError(err).Error("fetch CRL handling failed")
|
||||||
|
|
||||||
|
clientError = errors.New("could not handle request")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if clientError != nil {
|
||||||
|
response = buildErrorResponse(clientError.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
announceData, err := msgpack.Marshal(response.Announce)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("could not marshal response announcement: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
responseData, err := msgpack.Marshal(response.Response)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("could not marshal response: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return announceData, responseData, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Command struct {
|
||||||
|
Announce *messages.CommandAnnounce
|
||||||
|
Command interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Response struct {
|
||||||
|
Announce *messages.ResponseAnnounce
|
||||||
|
Response interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Response) String() string {
|
||||||
|
return fmt.Sprintf("Response[Code=%s] created=%s data=%s", r.Announce.Code, r.Announce.Created, r.Response)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MsgPackHandler) handleCommand(command *Command) (*Response, error) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
payload interface{}
|
responseData interface{}
|
||||||
responseCode messages.ResponseCode
|
responseCode messages.ResponseCode
|
||||||
)
|
)
|
||||||
|
|
||||||
switch command.Code {
|
switch command.Announce.Code {
|
||||||
case messages.CmdHealth:
|
case messages.CmdHealth:
|
||||||
var res *health.Result
|
var res *health.Result
|
||||||
|
|
||||||
|
@ -98,36 +143,52 @@ func (m *MsgPackHandler) handleCommand(command *messages.Command) (*messages.Res
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, info := range res.Info {
|
for _, info := range res.Info {
|
||||||
response.Info = append(response.Info, messages.HealthInfo{
|
response.Info = append(response.Info, &messages.HealthInfo{
|
||||||
Source: info.Source,
|
Source: info.Source,
|
||||||
Healthy: info.Healthy,
|
Healthy: info.Healthy,
|
||||||
MoreInfo: info.MoreInfo,
|
MoreInfo: info.MoreInfo,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
responseCode, payload = messages.RspHealth, response
|
responseCode, responseData = messages.RespHealth, response
|
||||||
|
case messages.CmdFetchCRL:
|
||||||
|
var res *revoking.Result
|
||||||
|
|
||||||
|
fetchCRLPayload, ok := command.Command.(messages.FetchCRLCommand)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("could not use payload as FetchCRLPayload")
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err = m.fetchCRLHandler.FetchCRL(fetchCRLPayload.IssuerID)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
response := messages.FetchCRLResponse{
|
||||||
|
IsDelta: false,
|
||||||
|
CRLData: res.Data,
|
||||||
|
}
|
||||||
|
|
||||||
|
responseCode, responseData = messages.RespFetchCRL, response
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unhandled command %s", command)
|
return nil, fmt.Errorf("unhandled command %v", command)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error from command handler: %w", err)
|
return nil, fmt.Errorf("error from command handler: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &messages.Response{TimeStamp: time.Now().UTC(), Code: responseCode, Payload: payload}, nil
|
return &Response{
|
||||||
|
Announce: messages.BuildResponseAnnounce(responseCode),
|
||||||
|
Response: responseData,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildErrorResponse(errMsg string) ([]byte, error) {
|
func buildErrorResponse(errMsg string) *Response {
|
||||||
marshal, err := msgpack.Marshal(&messages.Response{
|
return &Response{
|
||||||
Code: messages.RspError,
|
Announce: messages.BuildResponseAnnounce(messages.RespError),
|
||||||
TimeStamp: time.Now().UTC(),
|
Response: messages.ErrorResponse{Message: errMsg},
|
||||||
Payload: messages.ErrorResponse{Message: errMsg},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not marshal error response: %w", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return marshal, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(logger *logrus.Logger, handlers ...RegisterHandler) (Handler, error) {
|
func New(logger *logrus.Logger, handlers ...RegisterHandler) (Handler, error) {
|
||||||
|
@ -151,3 +212,9 @@ func RegisterHealthHandler(healthHandler *health.Handler) func(*MsgPackHandler)
|
||||||
h.healthHandler = healthHandler
|
h.healthHandler = healthHandler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RegisterFetchCRLHandler(fetchCRLHandler *revoking.FetchCRLHandler) func(handler *MsgPackHandler) {
|
||||||
|
return func(h *MsgPackHandler) {
|
||||||
|
h.fetchCRLHandler = fetchCRLHandler
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ limitations under the License.
|
||||||
package seriallink
|
package seriallink
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -29,8 +30,17 @@ import (
|
||||||
"git.cacert.org/cacert-gosigner/pkg/protocol"
|
"git.cacert.org/cacert-gosigner/pkg/protocol"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type protocolState int8
|
||||||
|
|
||||||
|
const (
|
||||||
|
stAnnounce protocolState = iota
|
||||||
|
stCommand
|
||||||
|
)
|
||||||
|
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
protocolHandler protocol.Handler
|
protocolHandler protocol.Handler
|
||||||
|
protocolState protocolState
|
||||||
|
currentCommand *protocol.Command
|
||||||
config *serial.Config
|
config *serial.Config
|
||||||
port *serial.Port
|
port *serial.Port
|
||||||
}
|
}
|
||||||
|
@ -57,6 +67,8 @@ func (h *Handler) Close() error {
|
||||||
|
|
||||||
const cobsDelimiter = 0x00
|
const cobsDelimiter = 0x00
|
||||||
|
|
||||||
|
var cobsConfig = cobs.Config{SpecialByte: cobsDelimiter, Delimiter: true, EndingSave: true}
|
||||||
|
|
||||||
func (h *Handler) Run() error {
|
func (h *Handler) Run() error {
|
||||||
const (
|
const (
|
||||||
bufferSize = 1024 * 1024
|
bufferSize = 1024 * 1024
|
||||||
|
@ -65,7 +77,7 @@ func (h *Handler) Run() error {
|
||||||
|
|
||||||
errors := make(chan error)
|
errors := make(chan error)
|
||||||
|
|
||||||
cobsConfig := cobs.Config{SpecialByte: cobsDelimiter, Delimiter: true, EndingSave: true}
|
h.protocolState = stAnnounce
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
buf := make([]byte, bufferSize)
|
buf := make([]byte, bufferSize)
|
||||||
|
@ -84,28 +96,9 @@ func (h *Handler) Run() error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
err = cobs.Verify(buf[:count], cobsConfig)
|
frames := bytes.SplitAfter(buf[:count], []byte{cobsDelimiter})
|
||||||
if err != nil {
|
|
||||||
errors <- err
|
|
||||||
|
|
||||||
return
|
if err := h.handleFrames(frames); err != nil {
|
||||||
}
|
|
||||||
|
|
||||||
// perform COBS decoding
|
|
||||||
decoded := cobs.Decode(buf[:count], cobsConfig)
|
|
||||||
|
|
||||||
msg, err := h.protocolHandler.HandleFrame(decoded)
|
|
||||||
if err != nil {
|
|
||||||
errors <- err
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// perform COBS encoding
|
|
||||||
encoded := cobs.Encode(msg, cobsConfig)
|
|
||||||
|
|
||||||
_, err = h.port.Write(encoded)
|
|
||||||
if err != nil {
|
|
||||||
errors <- err
|
errors <- err
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -121,6 +114,96 @@ func (h *Handler) Run() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Handler) handleFrames(frames [][]byte) error {
|
||||||
|
for _, frame := range frames {
|
||||||
|
if len(frame) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cobs.Verify(frame, cobsConfig); err != nil {
|
||||||
|
return fmt.Errorf("could not verify COBS frame: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// perform COBS decoding
|
||||||
|
decoded := cobs.Decode(frame, cobsConfig)
|
||||||
|
|
||||||
|
if h.protocolState == stAnnounce {
|
||||||
|
if err := h.handleCommandAnnounce(decoded); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if h.protocolState == stCommand {
|
||||||
|
if err := h.handleCommandData(decoded); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := h.nextState(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) handleCommandData(decoded []byte) error {
|
||||||
|
respAnn, msg, err := h.protocolHandler.HandleCommand(h.currentCommand.Announce, decoded)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("command handler for %s failed: %w", h.currentCommand.Announce.Code, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := h.writeResponse(respAnn, msg, cobsConfig); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) handleCommandAnnounce(decoded []byte) error {
|
||||||
|
announce, err := h.protocolHandler.HandleCommandAnnounce(decoded)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("command announce handling failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
h.currentCommand = &protocol.Command{Announce: announce}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) writeResponse(ann, msg []byte, cobsConfig cobs.Config) error {
|
||||||
|
encoded := cobs.Encode(ann, cobsConfig)
|
||||||
|
|
||||||
|
if _, err := h.port.Write(encoded); err != nil {
|
||||||
|
return fmt.Errorf("could not write response announcement: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
encoded = cobs.Encode(msg, cobsConfig)
|
||||||
|
|
||||||
|
if _, err := h.port.Write(encoded); err != nil {
|
||||||
|
return fmt.Errorf("could not write response: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) nextState() error {
|
||||||
|
var next protocolState
|
||||||
|
|
||||||
|
switch h.protocolState {
|
||||||
|
case stAnnounce:
|
||||||
|
next = stCommand
|
||||||
|
case stCommand:
|
||||||
|
next = stAnnounce
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("illegal protocol state %d", int(h.protocolState))
|
||||||
|
}
|
||||||
|
|
||||||
|
h.protocolState = next
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func New(cfg *config.Serial, protocolHandler protocol.Handler) (*Handler, error) {
|
func New(cfg *config.Serial, protocolHandler protocol.Handler) (*Handler, error) {
|
||||||
h := &Handler{protocolHandler: protocolHandler}
|
h := &Handler{protocolHandler: protocolHandler}
|
||||||
h.config = &serial.Config{Name: cfg.Device, Baud: cfg.Baud, ReadTimeout: cfg.Timeout}
|
h.config = &serial.Config{Name: cfg.Device, Baud: cfg.Baud, ReadTimeout: cfg.Timeout}
|
||||||
|
|
|
@ -92,9 +92,45 @@ func (ie *indexEntry) String() string {
|
||||||
// A reference for the file format can be found at
|
// A reference for the file format can be found at
|
||||||
// https://pki-tutorial.readthedocs.io/en/latest/cadb.html.
|
// https://pki-tutorial.readthedocs.io/en/latest/cadb.html.
|
||||||
type Repository struct {
|
type Repository struct {
|
||||||
indexFileName string
|
indexFileName string
|
||||||
lock sync.Locker
|
crlNumberFileName string
|
||||||
entries []indexEntry
|
lock sync.Locker
|
||||||
|
entries []indexEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Repository) NextCRLNumber() (*big.Int, error) {
|
||||||
|
r.lock.Lock()
|
||||||
|
defer r.lock.Unlock()
|
||||||
|
|
||||||
|
number := big.NewInt(0)
|
||||||
|
|
||||||
|
data, err := os.ReadFile(r.crlNumberFileName)
|
||||||
|
if err != nil {
|
||||||
|
if !errors.Is(err, os.ErrNotExist) {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"could not read next CRL number from file %s: %w",
|
||||||
|
r.crlNumberFileName,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if _, ok := number.SetString(string(data), 16); !ok {
|
||||||
|
return nil, fmt.Errorf("could not parse %s as CRL serial number", data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
number.Add(number, big.NewInt(1))
|
||||||
|
|
||||||
|
err = os.WriteFile(r.crlNumberFileName, []byte(number.Text(16)), 0600) //nolint:gomnd
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"could not write next CRL serial number to file %s: %w",
|
||||||
|
r.crlNumberFileName,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return number, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ie *indexEntry) markRevoked(revocationTime time.Time, reason revoking.CRLReason) {
|
func (ie *indexEntry) markRevoked(revocationTime time.Time, reason revoking.CRLReason) {
|
||||||
|
@ -378,13 +414,21 @@ func (r *Repository) newIndexEntryFromLine(text string) (*indexEntry, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFileRepository(baseDirectory string) (*Repository, error) {
|
func NewFileRepository(baseDirectory string) (*Repository, error) {
|
||||||
err := os.Chdir(baseDirectory)
|
_, err := os.ReadDir(baseDirectory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not change to base directory %s: %w", baseDirectory, err)
|
if !errors.Is(err, os.ErrNotExist) {
|
||||||
|
return nil, fmt.Errorf("could not change to base directory %s: %w", baseDirectory, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.MkdirAll(baseDirectory, 0750) //nolint:gomnd
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not create base directory %s: %w", baseDirectory, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Repository{
|
return &Repository{
|
||||||
indexFileName: path.Join(baseDirectory, "index.txt"),
|
indexFileName: path.Join(baseDirectory, "index.txt"),
|
||||||
lock: &sync.Mutex{},
|
crlNumberFileName: path.Join(baseDirectory, "crlnumber"),
|
||||||
|
lock: &sync.Mutex{},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,8 @@ import (
|
||||||
|
|
||||||
var OidCRLReason = asn1.ObjectIdentifier{2, 5, 29, 21}
|
var OidCRLReason = asn1.ObjectIdentifier{2, 5, 29, 21}
|
||||||
|
|
||||||
|
const defaultCRLValidity = 24 * time.Hour
|
||||||
|
|
||||||
type CRLReason int
|
type CRLReason int
|
||||||
|
|
||||||
// CRL reason codes as defined in RFC 5280 section 5.3.1
|
// CRL reason codes as defined in RFC 5280 section 5.3.1
|
||||||
|
@ -138,6 +140,7 @@ func (r *X509Revoking) CreateCRL() (*CRLInformation, error) {
|
||||||
SignatureAlgorithm: r.crlAlgorithm,
|
SignatureAlgorithm: r.crlAlgorithm,
|
||||||
RevokedCertificates: revoked,
|
RevokedCertificates: revoked,
|
||||||
Number: nextNumber,
|
Number: nextNumber,
|
||||||
|
NextUpdate: time.Now().UTC().Add(defaultCRLValidity),
|
||||||
}, r.crlIssuer, r.signer)
|
}, r.crlIssuer, r.signer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not sign revocation list: %w", err)
|
return nil, fmt.Errorf("could not sign revocation list: %w", err)
|
||||||
|
@ -154,3 +157,29 @@ func NewX509Revoking(
|
||||||
) *X509Revoking {
|
) *X509Revoking {
|
||||||
return &X509Revoking{repository: repo, crlAlgorithm: crlAlgorithm, crlIssuer: issuer, signer: signer}
|
return &X509Revoking{repository: repo, crlAlgorithm: crlAlgorithm, crlIssuer: issuer, signer: signer}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Result struct {
|
||||||
|
Data []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type FetchCRLHandler struct {
|
||||||
|
repositories map[string]*X509Revoking
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFetchCRLHandler(repositories map[string]*X509Revoking) *FetchCRLHandler {
|
||||||
|
return &FetchCRLHandler{repositories: repositories}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *FetchCRLHandler) FetchCRL(issuerID string) (*Result, error) {
|
||||||
|
repo, ok := h.repositories[issuerID]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("unknown issuer ID %s", issuerID)
|
||||||
|
}
|
||||||
|
|
||||||
|
currentCRL, err := repo.CreateCRL()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not create CRL for issuer ID %s: %w", issuerID, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Result{Data: currentCRL.CRL}, nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue