42d1e6e991
Add a main loop, move I/O code into io.go, move configuration into config.go. Use shared.Decode24BitLength instead of manually decoding block lengths. Fix response block decoding and checksum validation. Add constants for commonly used byte values and use these in the signer and the client.
152 lines
3.7 KiB
Go
152 lines
3.7 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"time"
|
|
|
|
"git.cacert.org/cacert-gosigner/datastructures"
|
|
"git.cacert.org/cacert-gosigner/shared"
|
|
|
|
"github.com/goburrow/serial"
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
func main() {
|
|
var configFile string
|
|
|
|
flag.StringVar(&configFile, "c", "client.yaml", "client configuration file in YAML format")
|
|
flag.Parse()
|
|
|
|
var clientConfig *ClientConfig
|
|
var serialConfig *serial.Config
|
|
var err error
|
|
|
|
if clientConfig, err = readConfig(configFile); err != nil {
|
|
log.Panic(err)
|
|
}
|
|
serialConfig = fillSerialConfig(clientConfig)
|
|
if clientConfig.Debug {
|
|
log.SetLevel(log.DebugLevel)
|
|
}
|
|
|
|
log.Infof("connecting to %s", serialConfig.Address)
|
|
log.Tracef("serial parameters %v", serialConfig)
|
|
port, err := serial.Open(serialConfig)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
log.Debug("serial port connected")
|
|
defer func() {
|
|
err := port.Close()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
log.Debug("serial port closed")
|
|
}()
|
|
|
|
errorChannel := make(chan error, 1)
|
|
responseChannel := make(chan datastructures.SignerResponse, 1)
|
|
crlCheck := 0
|
|
|
|
log.Debug("starting main loop")
|
|
|
|
for {
|
|
requestChannel := make(chan datastructures.SignerRequest, 1)
|
|
|
|
go HandleRequests(&port, &responseChannel, &errorChannel, &requestChannel)
|
|
|
|
log.Debug("handling GPG database ...")
|
|
// HandleGPG(&requestChannel)
|
|
log.Debug("issuing certificates ...")
|
|
// HandleCertificates(&requestChannel)
|
|
log.Debug("revoking certificates ...")
|
|
// RevokeCertificates(&requestChannel)
|
|
|
|
crlCheck++
|
|
if crlCheck%100 == 0 {
|
|
log.Debug("refresh CRLs ...")
|
|
// RefreshCRLs(&requestChannel)
|
|
}
|
|
|
|
log.Debug("send NUL request to keep connection open")
|
|
requestChannel <- *datastructures.NewNulRequest()
|
|
|
|
select {
|
|
case response := <-responseChannel:
|
|
if err := Process(response); err != nil {
|
|
log.Error(err)
|
|
}
|
|
case err := <-errorChannel:
|
|
log.Error(err)
|
|
}
|
|
|
|
log.Debug("sleep for 2.7 seconds")
|
|
time.Sleep(2700 * time.Millisecond)
|
|
}
|
|
}
|
|
|
|
func Process(response datastructures.SignerResponse) (err error) {
|
|
log.Infof("process response of type %s", response.Action)
|
|
log.Tracef("process response %v", response)
|
|
|
|
switch response.Action {
|
|
case datastructures.ActionNul:
|
|
log.Trace("received response for NUL request")
|
|
return
|
|
default:
|
|
return fmt.Errorf("unsupported action in response 0x%x", response.Action)
|
|
}
|
|
}
|
|
|
|
func HandleRequests(port *serial.Port, responseChan *chan datastructures.SignerResponse, errorChan *chan error, requestChan *chan datastructures.SignerRequest) {
|
|
for {
|
|
select {
|
|
case request := <-*requestChan:
|
|
SendRequest(port, responseChan, errorChan, &request)
|
|
}
|
|
}
|
|
}
|
|
|
|
func SendRequest(port *serial.Port, responseChan *chan datastructures.SignerResponse, errorChan *chan error, request *datastructures.SignerRequest) {
|
|
log.Tracef("send request %v to serial port %v", *request, *port)
|
|
if err := sendHandShake(*port); err != nil {
|
|
*errorChan <- err
|
|
return
|
|
}
|
|
|
|
requestBytes := request.Serialize()
|
|
if length, err := (*port).Write(requestBytes); err != nil {
|
|
*errorChan <- err
|
|
return
|
|
} else {
|
|
log.Tracef("wrote %d request bytes", length)
|
|
}
|
|
|
|
if length, err := (*port).Write([]byte{datastructures.CalculateXorCheckSum([][]byte{requestBytes})}); err != nil {
|
|
*errorChan <- err
|
|
return
|
|
} else {
|
|
log.Tracef("wrote %d checksum bytes", length)
|
|
}
|
|
|
|
if length, err := (*port).Write([]byte(shared.MagicTrailer)); err != nil {
|
|
*errorChan <- err
|
|
return
|
|
} else {
|
|
log.Tracef("wrote %d trailer bytes", length)
|
|
}
|
|
|
|
header, err := shared.ReceiveBytes(port, 1, 20)
|
|
if err != nil {
|
|
*errorChan <- err
|
|
return
|
|
}
|
|
if header[0] != shared.AckByte {
|
|
*errorChan <- fmt.Errorf("unexpected byte 0x%x expected 0x%x", header, shared.AckByte)
|
|
return
|
|
}
|
|
|
|
receiveResponse(port, responseChan, errorChan)
|
|
}
|