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:
parent
21da2d9b32
commit
edd7a9ddc9
@ -1,9 +1,12 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
@ -18,6 +21,8 @@ import (
|
|||||||
"golang.org/x/crypto/ssh/agent"
|
"golang.org/x/crypto/ssh/agent"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var sigs = []os.Signal{os.Kill, os.Interrupt}
|
||||||
|
|
||||||
var cli struct {
|
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'"`
|
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 {
|
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 {
|
if _, err = os.Stat(c.Agent.Socket); err == nil {
|
||||||
return fmt.Errorf("socket %s already exists", c.Agent.Socket)
|
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
|
// This affects all files created for the process. Since this is a sensitive
|
||||||
// socket, only allow the current user to write to the socket.
|
// socket, only allow the current user to write to the socket.
|
||||||
syscall.Umask(0077)
|
syscall.Umask(0077)
|
||||||
listener, err := net.Listen("unix", c.Agent.Socket)
|
listener, err = net.Listen("unix", c.Agent.Socket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -55,11 +71,11 @@ func launchAgent(c *config.SSHrimp, ctx *kong.Context) error {
|
|||||||
ctx.Printf("listening on %s", c.Agent.Socket)
|
ctx.Printf("listening on %s", c.Agent.Socket)
|
||||||
|
|
||||||
// Generate a new SSH private/public key pair
|
// 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
signer, err := ssh.NewSignerFromKey(privateKey)
|
signer, err = ssh.NewSignerFromKey(privateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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
|
// Listen for signals so that we can close the listener and exit nicely
|
||||||
osSignals := make(chan os.Signal)
|
osSignals := make(chan os.Signal)
|
||||||
signal.Notify(osSignals, os.Interrupt, os.Kill)
|
signal.Notify(osSignals, sigs...)
|
||||||
go func() {
|
go func() {
|
||||||
_ = <-osSignals
|
_ = <-osSignals
|
||||||
listener.Close()
|
listener.Close()
|
||||||
@ -77,7 +93,8 @@ func launchAgent(c *config.SSHrimp, ctx *kong.Context) error {
|
|||||||
|
|
||||||
// Accept connections and serve the agent
|
// Accept connections and serve the agent
|
||||||
for {
|
for {
|
||||||
conn, err := listener.Accept()
|
var conn net.Conn
|
||||||
|
conn, err = listener.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.Contains(err.Error(), "use of closed network connection") {
|
if strings.Contains(err.Error(), "use of closed network connection") {
|
||||||
// Occurs if the user interrupts the agent with a ctrl-c signal
|
// 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
|
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
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
10
cmd/sshrimp-agent/unix.go
Normal file
10
cmd/sshrimp-agent/unix.go
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// +build darwin linux
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
sigs = append(sigs, syscall.SIGTERM, syscall.SIGHUP)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user