Пример #1
0
// 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
}
Пример #2
0
func findKeyLocally(key ssh.PublicKey) (string, error) {
	sshDir := os.Getenv("HOME") + "/.ssh"
	dirEntries, err := ioutil.ReadDir(sshDir)
	if err != nil {
		return "", fmt.Errorf("Could not read your .ssh directory %s: %s\n", sshDir, err)
	}
	for idx := range dirEntries {
		entry := dirEntries[idx]
		if strings.HasSuffix(entry.Name(), ".pub") {
			pubKeyPath := sshDir + "/" + entry.Name()
			pubBuf, err := ioutil.ReadFile(pubKeyPath)
			if err != nil {
				fmt.Printf("Trouble reading public key %s: %s\n", pubKeyPath, err)
				continue
			}
			pubKey, _, _, _, err := ssh.ParseAuthorizedKey(pubBuf)
			if err != nil {
				fmt.Printf("Trouble parsing public key %s (might be unsupported format): %s\n", pubKeyPath, err)
				continue
			}
			if bytes.Equal(pubKey.Marshal(), key.Marshal()) {
				return pubKeyPath, nil
			}
		}
	}
	return "", fmt.Errorf("Couldn't find ssh key for cert.\n")
}
Пример #3
0
func pubkeyAuthCallback(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
	keyring.RLock()
	defer keyring.RUnlock()

	if keyring.Keys == nil {
		log.Println("rejecting authentication due to missing keyring")
		return nil, errors.New("no keyring available")
	}

	var keyFound *BenutzerDBKeyHandle
	for _, k := range *keyring.Keys {
		if k.ParsedPublicKey == nil {
			continue
		} else if bytes.Compare(key.Marshal(), k.ParsedPublicKey.Marshal()) == 0 {
			keyFound = &k
			break
		}
	}

	if keyFound == nil {
		log.Println("could not authenticate", conn.RemoteAddr().String(), " no key found")
		return nil, errors.New("invalid authentication")
	}

	log.Println("accepted key for user:"******"user_id": keyFound.Handle}}, nil
}
Пример #4
0
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 (a *publicKeyAuthenticator) Authenticate(conn ssh.ConnMetadata, publicKey ssh.PublicKey) (*ssh.Permissions, error) {
	if bytes.Equal(publicKey.Marshal(), a.marshaledPublicKey) {
		return &ssh.Permissions{}, nil
	}

	return nil, errors.New("authentication failed")
}
Пример #6
0
func (ctrl *Controller) authorizeKey(conn ssh.ConnMetadata, key ssh.PublicKey) (
	*ssh.Permissions, error) {

	marshaledKey := key.Marshal()
	for _, authorizedKey := range ctrl.authorizedKeys {
		if bytes.Compare(authorizedKey.Marshal(), marshaledKey) == 0 {
			return &ssh.Permissions{}, nil
		}
	}

	nodes, err := ctrl.cluster.GetDir("console/authorized_keys")
	if err != nil {
		if err == cluster.ErrNotFound {
			return nil, fmt.Errorf("unauthorized")
		}
		return nil, err
	}

	for path, value := range nodes {
		key, _, _, _, err := ssh.ParseAuthorizedKey([]byte(value))
		if err != nil {
			fmt.Printf("bad authorized key from etcd: %s: %s\n", path, err)
		}
		if bytes.Compare(key.Marshal(), marshaledKey) == 0 {
			return &ssh.Permissions{}, nil
		}
	}

	return nil, fmt.Errorf("unauthorized")
}
Пример #7
0
func FingerprintKey(k ssh.PublicKey) string {
	bytes := md5.Sum(k.Marshal())
	strbytes := make([]string, len(bytes))
	for i, b := range bytes {
		strbytes[i] = fmt.Sprintf("%02x", b)
	}
	return strings.Join(strbytes, ":")
}
Пример #8
0
func pubKeyFingerprint(key ssh.PublicKey) (string, error) {
	h := md5.New()
	_, err := h.Write(key.Marshal())
	if err != nil {
		return "", err
	}
	fp := fmt.Sprintf("%x", h.Sum(nil))
	return fp, nil
}
Пример #9
0
// 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
	}

	return r.removeLocked(key.Marshal())
}
Пример #10
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
}
Пример #11
0
func getFingerprint(key ssh.PublicKey) (fingerprint string) {
	md5sum := md5.Sum(key.Marshal())
	for i, c := range hex.EncodeToString(md5sum[:]) {
		if i != 0 && i%2 == 0 {
			fingerprint += ":"
		}
		fingerprint += string(c)
	}
	return
}
Пример #12
0
/* logPubKey logs a public key attempt */
func logPubKey(
	conn ssh.ConnMetadata,
	key ssh.PublicKey,
) (*ssh.Permissions, error) {
	log.Printf(
		"%v Key(%v):%02X",
		ci(conn),
		key.Type(),
		md5.Sum(key.Marshal()),
	)
	return nil, fmt.Errorf("invalid key")
}
Пример #13
0
func sshToCrypto(pk ssh.PublicKey) crypto.PublicKey {
	// Don't judge me, judge the ssh.PublicKey interface. And me. A bit.
	switch pk.Type() {
	case ssh.KeyAlgoRSA:
		return (*rsa.PublicKey)(unsafe.Pointer(reflect.ValueOf(pk).Elem().UnsafeAddr()))
	case ssh.KeyAlgoDSA:
		return (*dsa.PublicKey)(unsafe.Pointer(reflect.ValueOf(pk).Elem().UnsafeAddr()))
	case ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521:
		return (*ecdsa.PublicKey)(unsafe.Pointer(reflect.ValueOf(pk).Elem().UnsafeAddr()))
	default:
		return nil
	}
}
Пример #14
0
// authKey records any incoming request trying to auth with an ssh key
func authKey(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
	h := sha256.New()
	h.Write(key.Marshal())
	sum := h.Sum(nil)

	log.Printf("sshkey: %s %s %s %s\n",
		conn.RemoteAddr().String(),
		conn.User(),
		key.Type(),
		base64.StdEncoding.EncodeToString(sum))

	return nil, errAuthenticationFailed
}
Пример #15
0
func (s ScriptKeyAuth) Auth(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
	cmd := exec.Command(config.KeyAuthLocation, conn.User(), conn.RemoteAddr().String())
	k := fmt.Sprintf("%s\n", base64.StdEncoding.EncodeToString(key.Marshal()))
	keyReader := bytes.NewReader([]byte(k))
	cmd.Stdin = keyReader
	output, err := cmd.CombinedOutput()
	if err != nil {
		config.Log.Error("key authentication: %s\n%v", output, err)
		return nil, err
	}

	// nil permissions is success?
	return nil, nil
}
Пример #16
0
// compareKeys compares to key files and returns true of they match.
func compareKeys(a, b ssh.PublicKey) bool {
	if a.Type() != b.Type() {
		return false
	}
	// The best way to compare just the key seems to be to marshal both and
	// then compare the output byte sequence.
	return subtle.ConstantTimeCompare(a.Marshal(), b.Marshal()) == 1
}
Пример #17
0
// 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")
}
Пример #18
0
func (a *Agent) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) {
	wanted := key.Marshal()
	signers, err := a.Signers()
	if err != nil {
		return nil, err
	}

	for _, signer := range signers {
		if bytes.Equal(signer.PublicKey().Marshal(), wanted) {
			log.Printf("Signing message: key=%s", ssh.MarshalAuthorizedKey(signer.PublicKey()))
			return signer.Sign(rand.Reader, data)
		}
	}

	return nil, ErrNotFound
}
Пример #19
0
func testAgentInterface(t *testing.T, agent Agent, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) {
	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(AddedKey{
			PrivateKey:   key,
			Certificate:  cert,
			Comment:      "comment",
			LifetimeSecs: lifetimeSecs,
		})
		pubKey = cert
	} else {
		err = agent.Add(AddedKey{PrivateKey: key, Comment: "comment", LifetimeSecs: lifetimeSecs})
		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)
	}
}
Пример #20
0
func keyAuthCallback(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
	guid := uuid.NewV4()
	ip, remotePort := parseIpPortFrom(conn)
	login := SshLogin{RemoteAddr: ip,
		RemotePort: remotePort,
		Username:   conn.User(),
		Guid:       guid.String(),
		Version:    string(conn.ClientVersion()),
		PublicKey:  key.Marshal(),
		KeyType:    string(key.Type()),
		LoginType:  "key",
	}
	go login.Save()
	//log.Println("Fail to authenticate", conn, ":", err)
	//return nil, errors.New("invalid authentication")
	return &ssh.Permissions{Extensions: map[string]string{"guid": guid.String()}}, nil
}
Пример #21
0
func (s *Server) auth(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
	k := key.Marshal()
	t := key.Type()
	perm := &ssh.Permissions{
		Extensions: map[string]string{
			"pubKey":     string(k),
			"pubKeyType": t,
		},
	}

	_, err := s.Auther(conn, key)
	if err == nil {
		return perm, nil
	}

	return nil, err
}
Пример #22
0
// fingerprint generates a colon-separated fingerprint string from a public key.
func fingerprint(key ssh.PublicKey) string {
	hash := md5.Sum(key.Marshal())
	buf := make([]byte, hex.EncodedLen(len(hash)))
	hex.Encode(buf, hash[:])
	// We need this in colon notation:
	fp := make([]byte, len(buf)+15)

	i, j := 0, 0
	for ; i < len(buf); i++ {
		if i > 0 && i%2 == 0 {
			fp[j] = ':'
			j++
		}
		fp[j] = buf[i]
		j++
	}
	return string(fp)
}
Пример #23
0
// authKey records any incoming request trying to auth with an ssh key
func authKey(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {

	r := &AuthEvent{
		Time:     fmt.Sprintf("%d", time.Now().Unix()),
		AuthType: "sshKey",
		SrcIP:    strings.Split(conn.RemoteAddr().String(), ":")[0],
		DestIP:   extIP,
		User:     conn.User(),
		TypeData: fmt.Sprintf("ssh-key-type: %s client-version: %s", key.Type(), strconv.QuoteToASCII(string(conn.ClientVersion()))),
	}

	h := sha256.New()
	h.Write(key.Marshal())
	r.Credentials = base64.StdEncoding.EncodeToString(h.Sum(nil))

	addToBatch(r)

	return nil, errAuthenticationFailed
}
Пример #24
0
func (config BeaconConfig) checkHostKey(hostname string, remote net.Addr, key ssh.PublicKey) error {
	hostPublicKeyBytes, err := ioutil.ReadFile(string(config.PublicKey))
	if err != nil {
		return fmt.Errorf("failed to read host public key: %s", err)
	}

	hostPublicKey, _, _, _, err := ssh.ParseAuthorizedKey(hostPublicKeyBytes)
	if err != nil {
		return fmt.Errorf("failed to parse host public key: %s", err)
	}

	// note: hostname/addr are not verified; they may be behind a load balancer
	// so the definition gets a bit fuzzy

	if hostPublicKey.Type() != key.Type() || !bytes.Equal(hostPublicKey.Marshal(), key.Marshal()) {
		return errors.New("remote host public key mismatch")
	}

	return nil
}
Пример #25
0
// Check is called during the handshake to check the server's public key for
// unexpected changes. The key argument is in SSH wire format. It can be parsed
// using ssh.ParsePublicKey. The address before DNS resolution is passed in the
// addr argument, so the key can also be checked against the hostname.
// It returns any error encountered while checking the public key. A nil return
// value indicates that the key was either successfully verified (against an
// existing known_hosts entry), or accepted by the user as a new key.
func (kc *HostKeyChecker) Check(addr string, remote net.Addr, key gossh.PublicKey) error {
	remoteAddr, err := kc.addrToHostPort(remote.String())
	if err != nil {
		return err
	}

	algoStr := algoString(key.Type())
	keyFingerprintStr := md5String(md5.Sum(key.Marshal()))

	hostKeys, err := kc.m.GetHostKeys()
	_, ok := err.(*os.PathError)
	if err != nil && !ok {
		log.Errorf("Failed to read known_hosts file %v: %v", kc.m.String(), err)
	}

	mismatched := false
	for pattern, keys := range hostKeys {
		if !matchHost(remoteAddr, pattern) {
			continue
		}
		for _, hostKey := range keys {
			// Any matching key is considered a success, irrespective of previous failures
			if hostKey.Type() == key.Type() && bytes.Compare(hostKey.Marshal(), key.Marshal()) == 0 {
				return nil
			}
			// TODO(jonboulle): could be super friendly like the OpenSSH client
			// and note exactly which key failed (file + line number)
			mismatched = true
		}
	}

	if mismatched {
		fmt.Fprintf(os.Stderr, warningRemoteHostChanged, algoStr, keyFingerprintStr, kc.m.String())
		return ErrUnmatchKey
	}

	// If we get this far, we haven't matched on any of the hostname patterns,
	// so it's considered a new key. Prompt the user to trust it.
	if !kc.trustHost(remoteAddr, algoStr, keyFingerprintStr) {
		fmt.Fprintln(os.Stderr, "Host key verification failed.")
		return ErrUntrustHost
	}

	if err := kc.m.PutHostKey(remoteAddr, key); err != nil {
		fmt.Fprintf(os.Stderr, "Failed to add the host to the list of known hosts (%v).\n", kc.m)
		return nil
	}

	fmt.Fprintf(os.Stderr, "Warning: Permanently added '%v' (%v) to the list of known hosts.\n", remoteAddr, algoStr)
	return nil
}
Пример #26
0
// SCP Public Key authentication check
func (a authDB) AuthSCPPublicKey(cmd ssh.ConnMetadata, recvKey ssh.PublicKey) (*ssh.Permissions, error) {

	// Get the client
	c := a.findClient(cmd.RemoteAddr().String())
	if c == nil {
		return nil, fmt.Errorf("Unknown host %s", cmd.RemoteAddr().String())
	}

	// Verify there is a key configured
	goodKey := c.Protocols.SCP.parsedPublicKey
	if goodKey == nil {
		return nil, fmt.Errorf("Auth failed")
	}

	// Compare keys
	if bytes.Compare(recvKey.Marshal(), (*goodKey).Marshal()) == 0 {
		return nil, nil
	}
	return nil, fmt.Errorf("Auth failed")

}
Пример #27
0
// 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")
}
Пример #28
0
func publicKeyCallback(conn ssh.ConnMetadata, key ssh.PublicKey) (perm *ssh.Permissions, err error) {

	// Get signer
	privKey, err := ssh.ParsePrivateKey([]byte(clientPrivateKey))
	if err != nil {
		fmt.Println(err)
		err = fmt.Errorf("Unauthorized")
		return
	}
	// fmt.Printf("%#v\n", key.Marshal())
	// fmt.Printf("%#v\n", privKey.PublicKey().Marshal())

	if bytes.Equal(privKey.PublicKey().Marshal(), key.Marshal()) {
		// Add pubkey and username to permissions
		perm = &ssh.Permissions{
			Extensions: map[string]string{
				"username": conn.User(),
			},
		}
	} else {
		err = fmt.Errorf("Unauthorized")
	}
	return
}
Пример #29
0
func (inst *instance) hostKeyCallback(hostname string, remote net.Addr, key ssh.PublicKey) error {
	oldPublicKey, err := hex.DecodeString(inst.conn.Options.SSHPublicKey)
	if err != nil {
		return errors.New("XML is corrupt: " + err.Error())
	}
	newPublicKey := key.Marshal()
	//TODO correctly marshal/unmarshal into xml

	newPublicMD5 := md5.Sum(newPublicKey)
	newPublicString := hex.EncodeToString(newPublicMD5[:])

	if len(oldPublicKey) == 0 {
		color.Yellowln("Registering new SSH Public Key", key.Type(),
			newPublicString)
		inst.conn.Options.SSHPublicKey = hex.EncodeToString(newPublicKey)
		inst.changed = true
		return nil
	}

	oldPublicMD5 := md5.Sum(oldPublicKey)
	oldPublicString := hex.EncodeToString(oldPublicMD5[:])

	same := subtle.ConstantTimeCompare(newPublicKey, oldPublicKey)
	if same == 1 {
		return nil
	}
	color.Redln("-----POSSIBLE ATTACK-----\nSSH key changed! expected (md5):",
		oldPublicString,
		"got:", newPublicString, "type:", key.Type())
	inst.terminal.Stderr().Write([]byte("Accept change [Ny]? "))

	buf := make([]byte, 128)
	n, err := inst.terminal.Stdin().Read(buf)
	if err != nil {
		color.Yellowln("Error reading answer:", err)
		return err
	}
	inst.terminal.Stderr().Write([]byte{'\n'})

	text := strings.ToLower(string(buf[:n]))
	if text == "y" || text == "yes" {
		inst.conn.Options.SSHPublicKey = hex.EncodeToString(newPublicKey)
		inst.changed = true
		color.Yellowln("Saving new public key to connections.xml on exit.")
		return nil
	}
	return errors.New("Public key not accepted")
}
Пример #30
0
func keyAuth(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {

	log.Println(conn.RemoteAddr(), "authenticate with", key.Type(), "for user", conn.User())
	log.Println(base64.StdEncoding.EncodeToString(key.Marshal()))

	if isValidToken(conn.User()) {
		authRequestMap.Lock()
		authRequestMap.matches[conn.User()] = key.Type() + " " + base64.StdEncoding.EncodeToString(key.Marshal())
		authRequestMap.timestamps[conn.User()] = time.Now()
		authRequestMap.Unlock()
		return nil, nil
	}

	//Causes "Permission denied (publickey)." for openssh. How can this bubble up to the user?
	return nil, errors.New("Invalid token/username.")
}