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") }
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 }
// 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 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") }
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") }
// 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 }
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, ":") }
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 }
// 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()) }
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 }
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 }
/* 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") }
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) } }
// 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 }
// 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 }
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 }
// 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 (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") }
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 }
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.") }
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 }
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 }
// 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) }
// 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 }
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 }
// 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") }
// 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 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 }
func (c *client) Remove(key ssh.PublicKey) error { req := ssh.Marshal(&agentRemoveIdentityMsg{ KeyBlob: key.Marshal(), }) return c.simpleCall(req) }