This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

superconfig / 5pkgs / ssh-tpm-agent / client-pid.patch
13 kB 312 lines
1diff --git a/agent/agent.go b/agent/agent.go 2index 76a2610..e643575 100644 3--- a/agent/agent.go 4+++ b/agent/agent.go 5@@ -25,6 +25,7 @@ import ( 6 "github.com/google/go-tpm/tpm2/transport" 7 "golang.org/x/crypto/ssh" 8 "golang.org/x/crypto/ssh/agent" 9+ "golang.org/x/sys/unix" 10 "golang.org/x/text/cases" 11 "golang.org/x/text/language" 12 ) 13@@ -37,17 +38,18 @@ var ( 14 var SSH_TPM_AGENT_ADD = "tpm-add-key" 15 16 type Agent struct { 17- mu sync.Mutex 18- tpm func() transport.TPMCloser 19- op func() ([]byte, error) 20- pin func(key.SSHTPMKeys) ([]byte, error) 21- listener *net.UnixListener 22- quit chan interface{} 23- wg sync.WaitGroup 24- keyring func() *keyring.ThreadKeyring 25- keys []key.SSHTPMKeys 26- hierkeys []*key.HierSSHTPMKey 27- agents []agent.ExtendedAgent 28+ mu sync.Mutex 29+ tpm func() transport.TPMCloser 30+ op func() ([]byte, error) 31+ pin func(key.SSHTPMKeys, int) ([]byte, error) 32+ listener *net.UnixListener 33+ quit chan interface{} 34+ wg sync.WaitGroup 35+ keyring func() *keyring.ThreadKeyring 36+ keys []key.SSHTPMKeys 37+ hierkeys []*key.HierSSHTPMKey 38+ agents []agent.ExtendedAgent 39+ clientPID int 40 } 41 42 var _ agent.ExtendedAgent = &Agent{} 43@@ -118,8 +120,8 @@ func (a *Agent) signers() ([]ssh.Signer, error) { 44 s, err := ssh.NewSignerFromSigner(k.Signer( 45 a.keyring(), a.op, a.tpm, 46 func(_ *keyfile.TPMKey) ([]byte, error) { 47- // Shimming the function to get the correct type 48- return a.pin(k) 49+ // Shimming the function to get the correct type, pass client PID 50+ return a.pin(k, a.clientPID) 51 }), 52 ) 53 if err != nil { 54@@ -225,6 +227,21 @@ func (a *Agent) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) { 55 } 56 57 func (a *Agent) serveConn(c net.Conn) { 58+ // Extract peer credentials to get the client PID 59+ if uc, ok := c.(*net.UnixConn); ok { 60+ rawConn, err := uc.SyscallConn() 61+ if err == nil { 62+ rawConn.Control(func(fd uintptr) { 63+ if cred, err := unix.GetsockoptUcred(int(fd), unix.SOL_SOCKET, unix.SO_PEERCRED); err == nil { 64+ a.mu.Lock() 65+ a.clientPID = int(cred.Pid) 66+ a.mu.Unlock() 67+ slog.Debug("client connected", slog.Int("pid", int(cred.Pid))) 68+ } 69+ }) 70+ } 71+ } 72+ 73 if err := agent.ServeAgent(a, c); err != io.EOF { 74 slog.Info("Agent client connection ended unsuccessfully", slog.String("error", err.Error())) 75 } 76@@ -461,7 +478,7 @@ func LoadKeys(keyDir string) ([]key.SSHTPMKeys, error) { 77 return keys, err 78 } 79 80-func NewAgent(listener *net.UnixListener, agents []agent.ExtendedAgent, keyring func() *keyring.ThreadKeyring, tpmFetch func() transport.TPMCloser, ownerPassword func() ([]byte, error), pin func(key.SSHTPMKeys) ([]byte, error)) *Agent { 81+func NewAgent(listener *net.UnixListener, agents []agent.ExtendedAgent, keyring func() *keyring.ThreadKeyring, tpmFetch func() transport.TPMCloser, ownerPassword func() ([]byte, error), pin func(key.SSHTPMKeys, int) ([]byte, error)) *Agent { 82 a := &Agent{ 83 agents: agents, 84 tpm: tpmFetch, 85diff --git a/agent/agent_test.go b/agent/agent_test.go 86index acaec3d..189b607 100644 87--- a/agent/agent_test.go 88+++ b/agent/agent_test.go 89@@ -45,7 +45,7 @@ func TestAddKey(t *testing.T) { 90 // Owner password 91 func() ([]byte, error) { return []byte(""), nil }, 92 // PIN Callback 93- func(_ key.SSHTPMKeys) ([]byte, error) { return []byte(""), nil }, 94+ func(_ key.SSHTPMKeys, _ int) ([]byte, error) { return []byte(""), nil }, 95 ) 96 defer ag.Stop() 97 98diff --git a/askpass/askpass.go b/askpass/askpass.go 99index 8ef6370..0653165 100644 100--- a/askpass/askpass.go 101+++ b/askpass/askpass.go 102@@ -8,6 +8,7 @@ import ( 103 "log/slog" 104 "os" 105 "os/exec" 106+ "strconv" 107 "strings" 108 "syscall" 109 110@@ -66,7 +67,7 @@ func isTerminal(fd uintptr) bool { 111 return err == nil 112 } 113 114-func ReadPassphrase(prompt string, flags ReadPassFlags) ([]byte, error) { 115+func ReadPassphrase(prompt string, flags ReadPassFlags, clientPID int) ([]byte, error) { 116 var allow_askpass bool 117 var use_askpass bool 118 var askpass_hint string 119@@ -104,7 +105,7 @@ func ReadPassphrase(prompt string, flags ReadPassFlags) ([]byte, error) { 120 if (flags & RP_ASK_PERMISSION) != 0 { 121 askpass_hint = "confirm" 122 } 123- return SshAskPass(prompt, askpass_hint) 124+ return SshAskPass(prompt, askpass_hint, clientPID) 125 } 126 127 // If we want to echo stuff, we read directly from stdin 128@@ -130,7 +131,7 @@ func ReadPassphrase(prompt string, flags ReadPassFlags) ([]byte, error) { 129 return pin, nil 130 } 131 132-func SshAskPass(prompt, hint string) ([]byte, error) { 133+func SshAskPass(prompt, hint string, clientPID int) ([]byte, error) { 134 var askpass string 135 var err error 136 if s, ok := os.LookupEnv("SSH_ASKPASS"); ok { 137@@ -147,6 +148,11 @@ func SshAskPass(prompt, hint string) ([]byte, error) { 138 if hint != "" { 139 os.Setenv("SSH_ASKPASS_PROMPT", hint) 140 } 141+ 142+ if clientPID > 0 { 143+ os.Setenv("SSH_CLIENT_PID", strconv.Itoa(clientPID)) 144+ } 145+ 146 out, err := exec.Command(askpass, prompt).Output() 147 switch hint { 148 case "confirm": 149@@ -169,8 +175,8 @@ func SshAskPass(prompt, hint string) ([]byte, error) { 150 151 // AskPremission runs SSH_ASKPASS in with SSH_ASKPASS_PROMPT=confirm set as env 152 // it will expect exit code 0 or !0 and return 'yes' and 'no' respectively. 153-func AskPermission() (bool, error) { 154- a, err := ReadPassphrase("Confirm touch", RP_USE_ASKPASS|RP_ASK_PERMISSION) 155+func AskPermission(clientPID int) (bool, error) { 156+ a, err := ReadPassphrase("Confirm touch", RP_USE_ASKPASS|RP_ASK_PERMISSION, clientPID) 157 if err != nil { 158 return false, err 159 } 160diff --git a/cmd/ssh-tpm-agent/main.go b/cmd/ssh-tpm-agent/main.go 161index 1b76351..797428c 100644 162--- a/cmd/ssh-tpm-agent/main.go 163+++ b/cmd/ssh-tpm-agent/main.go 164@@ -243,7 +243,7 @@ func main() { 165 // Owner password 166 func() ([]byte, error) { 167 if askOwnerPassword { 168- return askpass.ReadPassphrase("Enter owner password for TPM", askpass.RP_USE_ASKPASS) 169+ return askpass.ReadPassphrase("Enter owner password for TPM", askpass.RP_USE_ASKPASS, 0) 170 } else { 171 ownerPassword := os.Getenv("SSH_TPM_AGENT_OWNER_PASSWORD") 172 return []byte(ownerPassword), nil 173@@ -253,7 +253,7 @@ func main() { 174 // PIN Callback with caching 175 // SSHKeySigner in signer/signer.go resets this value if 176 // we get a TPMRCAuthFail 177- func(key key.SSHTPMKeys) ([]byte, error) { 178+ func(key key.SSHTPMKeys, clientPID int) ([]byte, error) { 179 auth, err := agentkeyring.ReadKey(key.Fingerprint()) 180 if err == nil { 181 slog.Debug("providing cached userauth for key", slog.String("fp", key.Fingerprint())) 182@@ -261,8 +261,8 @@ func main() { 183 return auth.Read(), nil 184 } else if errors.Is(err, syscall.ENOKEY) || errors.Is(err, syscall.EACCES) { 185 keyInfo := fmt.Sprintf("Enter passphrase for (%s): ", key.GetDescription()) 186- // TODOt kjk: askpass should box the byte slice 187- userauth, err := askpass.ReadPassphrase(keyInfo, askpass.RP_USE_ASKPASS) 188+ // TODO: askpass should box the byte slice 189+ userauth, err := askpass.ReadPassphrase(keyInfo, askpass.RP_USE_ASKPASS, clientPID) 190 fmt.Println(err) 191 if !noCache && err == nil { 192 slog.Debug("caching userauth for key in keyring", slog.String("fp", key.Fingerprint())) 193diff --git a/cmd/ssh-tpm-agent/main_test.go b/cmd/ssh-tpm-agent/main_test.go 194index 051febf..d2ff3c4 100644 195--- a/cmd/ssh-tpm-agent/main_test.go 196+++ b/cmd/ssh-tpm-agent/main_test.go 197@@ -144,7 +144,7 @@ func runSSHAuth(t *testing.T, keytype tpm2.TPMAlgID, bits int, pin []byte, keyfn 198 // Owner password 199 func() ([]byte, error) { return []byte(""), nil }, 200 // PIN Callback 201- func(_ key.SSHTPMKeys) ([]byte, error) { 202+ func(_ key.SSHTPMKeys, _ int) ([]byte, error) { 203 return pin, nil 204 }, 205 ) 206diff --git a/cmd/ssh-tpm-keygen/main.go b/cmd/ssh-tpm-keygen/main.go 207index f5d9421..12073b0 100644 208--- a/cmd/ssh-tpm-keygen/main.go 209+++ b/cmd/ssh-tpm-keygen/main.go 210@@ -89,11 +89,11 @@ Example: 211 212 func getPin() ([]byte, error) { 213 for { 214- pin1, err := askpass.ReadPassphrase("Enter passphrase (empty for no passphrase): ", askpass.RP_ALLOW_STDIN|askpass.RP_NEWLINE) 215+ pin1, err := askpass.ReadPassphrase("Enter passphrase (empty for no passphrase): ", askpass.RP_ALLOW_STDIN|askpass.RP_NEWLINE, 0) 216 if err != nil { 217 return nil, err 218 } 219- pin2, err := askpass.ReadPassphrase("Enter same passphrase again: ", askpass.RP_ALLOW_STDIN|askpass.RP_NEWLINE) 220+ pin2, err := askpass.ReadPassphrase("Enter same passphrase again: ", askpass.RP_ALLOW_STDIN|askpass.RP_NEWLINE, 0) 221 if err != nil { 222 return nil, err 223 } 224@@ -106,7 +106,7 @@ func getPin() ([]byte, error) { 225 } 226 227 func getOwnerPassword() ([]byte, error) { 228- return askpass.ReadPassphrase("Enter owner password: ", askpass.RP_ALLOW_STDIN) 229+ return askpass.ReadPassphrase("Enter owner password: ", askpass.RP_ALLOW_STDIN, 0) 230 } 231 232 func doHostKeys(tpm transport.TPMCloser, outputFile string, ownerPassword []byte, hierarchy string) { 233@@ -191,7 +191,7 @@ func doChangePin(tpm transport.TPMCloser, passphrase, keyPin, ownerPassword []by 234 fmt.Printf("Key has comment '%s'\n", k.Description) 235 } 236 if outputFile == "" { 237- f, err := askpass.ReadPassphrase(fmt.Sprintf("Enter file in which the key is (%s): ", filename), askpass.RP_ALLOW_STDIN|askpass.RPP_ECHO_ON) 238+ f, err := askpass.ReadPassphrase(fmt.Sprintf("Enter file in which the key is (%s): ", filename), askpass.RP_ALLOW_STDIN|askpass.RPP_ECHO_ON, 0) 239 if err != nil { 240 return err 241 } 242@@ -199,18 +199,18 @@ func doChangePin(tpm transport.TPMCloser, passphrase, keyPin, ownerPassword []by 243 } 244 245 if len(passphrase) == 0 { 246- passphrase, err = askpass.ReadPassphrase("Enter old passphrase: ", askpass.RP_ALLOW_STDIN|askpass.RP_NEWLINE) 247+ passphrase, err = askpass.ReadPassphrase("Enter old passphrase: ", askpass.RP_ALLOW_STDIN|askpass.RP_NEWLINE, 0) 248 if err != nil { 249 return err 250 } 251 } 252 253 if len(keyPin) == 0 { 254- keyPin, err = askpass.ReadPassphrase("Enter new passphrase (empty for no passphrase): ", askpass.RP_ALLOW_STDIN|askpass.RP_NEWLINE) 255+ keyPin, err = askpass.ReadPassphrase("Enter new passphrase (empty for no passphrase): ", askpass.RP_ALLOW_STDIN|askpass.RP_NEWLINE, 0) 256 if err != nil { 257 return err 258 } 259- newPin, err := askpass.ReadPassphrase("Enter same passphrase: ", askpass.RP_ALLOW_STDIN) 260+ newPin, err := askpass.ReadPassphrase("Enter same passphrase: ", askpass.RP_ALLOW_STDIN, 0) 261 if err != nil { 262 return err 263 } 264@@ -256,7 +256,7 @@ func doWrapWith(supportedECCBitsizes []int, wrap, wrapWith string, keyParentHand 265 rawKey, err = ssh.ParseRawPrivateKey(pem) 266 if errors.As(err, &kerr) { 267 for { 268- pin, err := askpass.ReadPassphrase("Enter existing passphrase (empty for no passphrase): ", askpass.RP_ALLOW_STDIN|askpass.RP_NEWLINE) 269+ pin, err := askpass.ReadPassphrase("Enter existing passphrase (empty for no passphrase): ", askpass.RP_ALLOW_STDIN|askpass.RP_NEWLINE, 0) 270 if err != nil { 271 log.Fatal(err) 272 } 273@@ -353,7 +353,7 @@ func supportedECCBitsizes(tpm transport.TPMCloser) []int { 274 func checkFile(f string) error { 275 if utils.FileExists(f) { 276 fmt.Printf("%s already exists.\n", f) 277- s, err := askpass.ReadPassphrase("Overwrite (y/n)? ", askpass.RP_ALLOW_STDIN|askpass.RPP_ECHO_ON) 278+ s, err := askpass.ReadPassphrase("Overwrite (y/n)? ", askpass.RP_ALLOW_STDIN|askpass.RPP_ECHO_ON, 0) 279 if err != nil { 280 return err 281 } 282@@ -373,7 +373,7 @@ func doImportKey(tpm transport.TPMCloser, keyParentHandle tpm2.TPMHandle, ownerP 283 rawKey, err = ssh.ParseRawPrivateKey(pem) 284 if errors.As(err, &kerr) { 285 for { 286- pin, err := askpass.ReadPassphrase("Enter existing passphrase (empty for no passphrase): ", askpass.RP_ALLOW_STDIN|askpass.RP_NEWLINE) 287+ pin, err := askpass.ReadPassphrase("Enter existing passphrase (empty for no passphrase): ", askpass.RP_ALLOW_STDIN|askpass.RP_NEWLINE, 0) 288 if err != nil { 289 return nil, err 290 } 291@@ -665,7 +665,7 @@ func main() { 292 // Else create a normal key 293 fmt.Printf("Generating a sealed public/private %s key pair.\n", keyType) 294 if outputFile == "" { 295- f, err := askpass.ReadPassphrase(fmt.Sprintf("Enter file in which to save the key (%s): ", filename), askpass.RP_ALLOW_STDIN|askpass.RPP_ECHO_ON) 296+ f, err := askpass.ReadPassphrase(fmt.Sprintf("Enter file in which to save the key (%s): ", filename), askpass.RP_ALLOW_STDIN|askpass.RPP_ECHO_ON, 0) 297 if err != nil { 298 log.Fatal(err) 299 } 300diff --git a/internal/keytest/keytest.go b/internal/keytest/keytest.go 301index ade4ad8..90fcf77 100644 302--- a/internal/keytest/keytest.go 303+++ b/internal/keytest/keytest.go 304@@ -121,7 +121,7 @@ func NewTestAgent(t *testing.T, tpm transport.TPMCloser) *agent.Agent { 305 func() *keyring.ThreadKeyring { return &keyring.ThreadKeyring{} }, 306 func() transport.TPMCloser { return tpm }, 307 func() ([]byte, error) { return []byte(""), nil }, 308- func(_ key.SSHTPMKeys) ([]byte, error) { 309+ func(_ key.SSHTPMKeys, _ int) ([]byte, error) { 310 return []byte(""), nil 311 }, 312 )