* Copyright 2016-2017 Gary Kramlich <grim@reaperworld.com> * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. "golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh/agent" // KeysAvailable returns True if there is at least one key that the ssh agent // knows about, otherwise false. err will be set if there is an error along func KeysAvailable(identites []string) (bool, error) { sshAgent, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")) return keysAvailable(sshAgent, identites) func keysAvailable(rw io.ReadWriter, identities []string) (bool, error) { keys, err := agent.NewClient(rw).List() // this runs in O(m * n) but thankful the number of keys should be low. for _, identity := range identities { // if the user doesn't care which key and we have a key, return true // if the user doesn't care which key but we have no keys, return an error return false, fmt.Errorf("no ssh keys available") uIdentity := strings.ToUpper(identity) for _, pubKey := range keys { fpSHA256 := strings.ToUpper(ssh.FingerprintSHA256(pubKey)) fpMD5 := strings.ToUpper(ssh.FingerprintLegacyMD5(pubKey)) if strings.HasPrefix(uIdentity, "SHA256:") { if uIdentity == fpSHA256 { } else if strings.HasPrefix(uIdentity, "MD5:") { if uIdentity[4:] == fpMD5 { // no known prefix check sha256 then md5, then give up if uIdentity == fpSHA256[7:] || uIdentity == fpMD5 { err = fmt.Errorf("no usable ssh identities found") func ShouldEnable(identities []string) (bool, error) { if len(identities) <= 0 { haveKeys, err := KeysAvailable(identities) return false, fmt.Errorf("error talking to ssh-agent: %s", err) return false, fmt.Errorf("no keys available in ssh-agent")