예제 #1
0
파일: knownhosts.go 프로젝트: devick/flynn
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
}
예제 #2
0
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
}
예제 #3
0
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)
	}
}
예제 #4
0
파일: ssh_cluster.go 프로젝트: devick/flynn
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
}
예제 #5
0
func (k *storedHostKey) Add(key ssh.PublicKey) {
	if k.keys == nil {
		k.keys = map[string][]byte{}
	}
	k.keys[key.Type()] = key.Marshal()
}