// Remove removes all identities with the given public key. func (r *keyring) Remove(key ssh.PublicKey) error { r.mu.Lock() defer r.mu.Unlock() if r.locked { return errLocked } want := key.Marshal() found := false for i := 0; i < len(r.keys); { if bytes.Equal(r.keys[i].signer.PublicKey().Marshal(), want) { found = true r.keys[i] = r.keys[len(r.keys)-1] r.keys = r.keys[len(r.keys)-1:] continue } else { i++ } } if !found { return errors.New("agent: key not found") } return nil }
func (k KnownHosts) HostKeyCallback(hostname string, remote net.Addr, key ssh.PublicKey) error { var addr *net.TCPAddr if v, ok := remote.(*net.TCPAddr); ok { addr = v } else { return UnsupportedAddrType } keyBytes := key.Marshal() var matched []*Host for _, l := range k { if l.CertAuthority { continue } if key.Type() != l.PublicKey.Type() { continue } lKeyBytes := l.PublicKey.Marshal() for _, h := range l.Hosts { if h.Match(hostname, addr) { if !bytes.Equal(keyBytes, lKeyBytes) { return HostKeyMismatchError } if l.Revoked { return HostRevokedError } matched = append(matched, h) } } } if len(matched) == 0 { return HostNotFoundError } return nil }
func (k *storedHostKey) Check(addr string, remote net.Addr, key ssh.PublicKey) error { k.checkCount++ algo := key.Type() if k.keys == nil || bytes.Compare(key.Marshal(), k.keys[algo]) != 0 { return fmt.Errorf("host key mismatch. Got %q, want %q", key, k.keys[algo]) } return nil }
// Sign returns a signature for the data. func (r *keyring) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) { r.mu.Lock() defer r.mu.Unlock() if r.locked { return nil, errLocked } wanted := key.Marshal() for _, k := range r.keys { if bytes.Equal(k.signer.PublicKey().Marshal(), wanted) { return k.signer.Sign(rand.Reader, data) } } return nil, errors.New("not found") }
func testAgentInterface(t *testing.T, agent Agent, key interface{}, cert *ssh.Certificate) { signer, err := ssh.NewSignerFromKey(key) if err != nil { t.Fatalf("NewSignerFromKey(%T): %v", key, err) } // The agent should start up empty. if keys, err := agent.List(); err != nil { t.Fatalf("RequestIdentities: %v", err) } else if len(keys) > 0 { t.Fatalf("got %d keys, want 0: %v", len(keys), keys) } // Attempt to insert the key, with certificate if specified. var pubKey ssh.PublicKey if cert != nil { err = agent.Add(key, cert, "comment") pubKey = cert } else { err = agent.Add(key, nil, "comment") pubKey = signer.PublicKey() } if err != nil { t.Fatalf("insert(%T): %v", key, err) } // Did the key get inserted successfully? if keys, err := agent.List(); err != nil { t.Fatalf("List: %v", err) } else if len(keys) != 1 { t.Fatalf("got %v, want 1 key", keys) } else if keys[0].Comment != "comment" { t.Fatalf("key comment: got %v, want %v", keys[0].Comment, "comment") } else if !bytes.Equal(keys[0].Blob, pubKey.Marshal()) { t.Fatalf("key mismatch") } // Can the agent make a valid signature? data := []byte("hello") sig, err := agent.Sign(pubKey, data) if err != nil { t.Fatalf("Sign(%s): %v", pubKey.Type(), err) } if err := pubKey.Verify(data, sig); err != nil { t.Fatalf("Verify(%s): %v", pubKey.Type(), err) } }
// Sign has the agent sign the data using a protocol 2 key as defined // in [PROTOCOL.agent] section 2.6.2. func (c *client) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) { req := ssh.Marshal(signRequestAgentMsg{ KeyBlob: key.Marshal(), Data: data, }) msg, err := c.call(req) if err != nil { return nil, err } switch msg := msg.(type) { case *signResponseAgentMsg: var sig ssh.Signature if err := ssh.Unmarshal(msg.SigBlob, &sig); err != nil { return nil, err } return &sig, nil case *failureAgentMsg: return nil, errors.New("agent: failed to sign challenge") } panic("unreachable") }
func (c *SSHCluster) hostKeyCallback(hostname string, remote net.Addr, key ssh.PublicKey) error { if c.knownHosts == nil { if err := c.parseKnownHosts(); err != nil { return err } } err := c.knownHosts.HostKeyCallback(hostname, remote, key) if err == knownhosts.HostNotFoundError { fingerprint := c.fingerprintSSHKey(key) hostnameFormatted := hostname remoteAddr := remote.String() if remoteAddr != hostname { hostnameFormatted = fmt.Sprintf("%s (%s)", hostname, remoteAddr) } if c.base.YesNoPrompt(fmt.Sprintf("The authenticity of host '%s' can't be established.\n%s key fingerprint is %s.\nAre you sure you want to continue connecting?", hostnameFormatted, key.Type(), fingerprint)) { c.base.SendLog(fmt.Sprintf("Trusting '%s' with key fingerprint %s", hostnameFormatted, fingerprint)) file, err := os.OpenFile(c.knownHostsPath(), os.O_CREATE|os.O_WRONLY|os.O_APPEND, os.FileMode(0644)) if err != nil { c.base.SendLog(fmt.Sprintf("WARNING: Can't write to %s: %s", c.knownHostsPath(), err)) } else { defer file.Close() } c.knownHosts.AppendHost(hostname, key, file) return nil } } return err }
func (c *SSHCluster) fingerprintSSHKey(publicKey ssh.PublicKey) string { hash := sha256.New() hash.Write(publicKey.Marshal()) return fmt.Sprintf("SHA256:%s", base64.StdEncoding.EncodeToString(hash.Sum(nil))) }
func (c *client) Remove(key ssh.PublicKey) error { req := ssh.Marshal(&agentRemoveIdentityMsg{ KeyBlob: key.Marshal(), }) return c.simpleCall(req) }
func (k *storedHostKey) Add(key ssh.PublicKey) { if k.keys == nil { k.keys = map[string][]byte{} } k.keys[key.Type()] = key.Marshal() }