Improve the agent signal handling and error handling

There is probably a better way to make the list of signals to catch

I also noticed that the agent kept dying on me when the CA was not setup
correctly with an EOF error from the ssh client
This commit is contained in:
lordwelch 2020-05-04 04:06:11 -07:00
parent 21da2d9b32
commit edd7a9ddc9
2 changed files with 35 additions and 8 deletions

View File

@ -1,9 +1,12 @@
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"errors"
"fmt"
"io"
"net"
"os"
"os/signal"
@ -18,6 +21,8 @@ import (
"golang.org/x/crypto/ssh/agent"
)
var sigs = []os.Signal{os.Kill, os.Interrupt}
var cli struct {
Config string `kong:"arg,type='string',help='sshrimp config file (default: ${config_file} or ${env_var_name} environment variable)',default='${config_file}',env='SSHRIMP_CONFIG'"`
}
@ -38,15 +43,26 @@ func main() {
}
func launchAgent(c *config.SSHrimp, ctx *kong.Context) error {
var (
err error
listener net.Listener
privateKey crypto.Signer
signer ssh.Signer
)
if _, err := os.Stat(c.Agent.Socket); err == nil {
return fmt.Errorf("socket %s already exists", c.Agent.Socket)
if _, err = os.Stat(c.Agent.Socket); err == nil {
conn, sockErr := net.Dial("unix", c.Agent.Socket)
if sockErr == nil { // socket is accepting connections
conn.Close()
return fmt.Errorf("socket %s already exists", c.Agent.Socket)
}
os.Remove(c.Agent.Socket) // socket is not accepting connections, assuming safe to remove
}
// This affects all files created for the process. Since this is a sensitive
// socket, only allow the current user to write to the socket.
syscall.Umask(0077)
listener, err := net.Listen("unix", c.Agent.Socket)
listener, err = net.Listen("unix", c.Agent.Socket)
if err != nil {
return err
}
@ -55,11 +71,11 @@ func launchAgent(c *config.SSHrimp, ctx *kong.Context) error {
ctx.Printf("listening on %s", c.Agent.Socket)
// Generate a new SSH private/public key pair
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
privateKey, err = rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return err
}
signer, err := ssh.NewSignerFromKey(privateKey)
signer, err = ssh.NewSignerFromKey(privateKey)
if err != nil {
return err
}
@ -69,7 +85,7 @@ func launchAgent(c *config.SSHrimp, ctx *kong.Context) error {
// Listen for signals so that we can close the listener and exit nicely
osSignals := make(chan os.Signal)
signal.Notify(osSignals, os.Interrupt, os.Kill)
signal.Notify(osSignals, sigs...)
go func() {
_ = <-osSignals
listener.Close()
@ -77,7 +93,8 @@ func launchAgent(c *config.SSHrimp, ctx *kong.Context) error {
// Accept connections and serve the agent
for {
conn, err := listener.Accept()
var conn net.Conn
conn, err = listener.Accept()
if err != nil {
if strings.Contains(err.Error(), "use of closed network connection") {
// Occurs if the user interrupts the agent with a ctrl-c signal
@ -85,7 +102,7 @@ func launchAgent(c *config.SSHrimp, ctx *kong.Context) error {
}
return err
}
if err := agent.ServeAgent(sshrimpAgent, conn); err != nil {
if err = agent.ServeAgent(sshrimpAgent, conn); err != nil && !errors.Is(err, io.EOF) {
return err
}
}

10
cmd/sshrimp-agent/unix.go Normal file
View File

@ -0,0 +1,10 @@
// +build darwin linux
package main
import (
"syscall"
)
func init() {
sigs = append(sigs, syscall.SIGTERM, syscall.SIGHUP)
}