func (s *Server) keyAuth(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
	cid := fmt.Sprintf("conn(%v->%v, user=%v)", conn.RemoteAddr(), conn.LocalAddr(), conn.User())
	fingerprint := fmt.Sprintf("%v %v", key.Type(), sshutils.Fingerprint(key))
	log.Debugf("[SSH] %v auth attempt with key %v", cid, fingerprint)

	logger := log.WithFields(log.Fields{
		"local":       conn.LocalAddr(),
		"remote":      conn.RemoteAddr(),
		"user":        conn.User(),
		"fingerprint": fingerprint,
	})

	cert, ok := key.(*ssh.Certificate)
	if !ok {
		return nil, trace.BadParameter("unsupported key type: %v", fingerprint)
	}
	if len(cert.ValidPrincipals) == 0 {
		return nil, trace.BadParameter("need a valid principal for key %v", fingerprint)
	}
	if len(cert.KeyId) == 0 {
		return nil, trace.BadParameter("need a valid key for key %v", fingerprint)
	}
	teleportUser := cert.KeyId

	logAuditEvent := func(err error) {
		// only failed attempts are logged right now
		if err != nil {
			s.EmitAuditEvent(events.AuthAttemptEvent, events.EventFields{
				events.EventUser:          teleportUser,
				events.AuthAttemptSuccess: false,
				events.AuthAttemptErr:     err.Error(),
			})
		}
	}
	permissions, err := s.certChecker.Authenticate(conn, key)
	if err != nil {
		logAuditEvent(err)
		return nil, trace.Wrap(err)
	}
	if err := s.certChecker.CheckCert(conn.User(), cert); err != nil {
		logAuditEvent(err)
		return nil, trace.Wrap(err)
	}
	logger.Debugf("[SSH] successfully authenticated")

	// see if the host user is valid (no need to do this in proxy mode)
	if !s.proxyMode {
		_, err = user.Lookup(conn.User())
		if err != nil {
			host, _ := os.Hostname()
			logger.Warningf("host '%s' does not have OS user '%s'", host, conn.User())
			logger.Errorf("no such user")
			return nil, trace.AccessDenied("no such user: '%s'", conn.User())
		}
	}

	// this is the only way I know of to pass valid principal with the
	// connection
	permissions.Extensions[utils.CertTeleportUser] = teleportUser

	if s.proxyMode {
		return permissions, nil
	}

	err = s.checkPermissionToLogin(cert.SignatureKey, teleportUser, conn.User())
	if err != nil {
		logger.Error(err)
		logAuditEvent(err)
		return nil, trace.Wrap(err)
	}
	return permissions, nil
}
// keyAuth implements SSH client authentication using public keys and is called
// by the server every time the client connects
keyAuth implements SSH client authentication using public keys and is called
by the server every time the client connects
// keyAuth implements SSH client authentication using public keys and is called // by the server every time the client connects
func (s *Server) keyAuth(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
	cid := fmt.Sprintf("conn(%v->%v, user=%v)", conn.RemoteAddr(), conn.LocalAddr(), conn.User())
	fingerprint := fmt.Sprintf("%v %v", key.Type(), sshutils.Fingerprint(key))
	log.Debugf("[SSH] %v auth attempt with key %v", cid, fingerprint)
	logger := log.WithFields(log.Fields{
		"local":       conn.LocalAddr(),
		"remote":      conn.RemoteAddr(),
		"user":        conn.User(),
		"fingerprint": fingerprint,
	})
	cert, ok := key.(*ssh.Certificate)
	if !ok {
		return nil, trace.BadParameter("unsupported key type: %v", fingerprint)
	}
	if len(cert.ValidPrincipals) == 0 {
		return nil, trace.BadParameter("need a valid principal for key %v", fingerprint)
	}
	if len(cert.KeyId) == 0 {
		return nil, trace.BadParameter("need a valid key for key %v", fingerprint)
	}
	teleportUser := cert.KeyId
	logAuditEvent := func(err error) {
		if err != nil {
			s.EmitAuditEvent(events.AuthAttemptEvent, events.EventFields{
				events.EventUser:          teleportUser,
				events.AuthAttemptSuccess: false,
				events.AuthAttemptErr:     err.Error(),
			})
		}
	}
	permissions, err := s.certChecker.Authenticate(conn, key)
	if err != nil {
		logAuditEvent(err)
		return nil, trace.Wrap(err)
	}
	if err := s.certChecker.CheckCert(conn.User(), cert); err != nil {
		logAuditEvent(err)
		return nil, trace.Wrap(err)
	}
	logger.Debugf("[SSH] successfully authenticated")
	if !s.proxyMode {
		_, err = user.Lookup(conn.User())
		if err != nil {
			host, _ := os.Hostname()
			logger.Warningf("host '%s' does not have OS user '%s'", host, conn.User())
			logger.Errorf("no such user")
			return nil, trace.AccessDenied("no such user: '%s'", conn.User())
		}
	}
	permissions.Extensions[utils.CertTeleportUser] = teleportUser
	if s.proxyMode {
		return permissions, nil
	}
	err = s.checkPermissionToLogin(cert.SignatureKey, teleportUser, conn.User())
	if err != nil {
		logger.Error(err)
		logAuditEvent(err)
		return nil, trace.Wrap(err)
	}
	return permissions, nil
}
func ( s * Server ) keyAuth ( conn ssh . ConnMetadata , key ssh . PublicKey ) ( * ssh . Permissions , error ) { cid := fmt . Sprintf ( " " , conn . RemoteAddr ( ) , conn . LocalAddr ( ) , conn . User ( ) ) fingerprint := fmt . Sprintf ( " " , key . Type ( ) , sshutils . Fingerprint ( key ) ) log . Debugf ( " " , cid , fingerprint ) logger := log . WithFields ( log . Fields { " " : conn . LocalAddr ( ) , " " : conn . RemoteAddr ( ) , " " : conn . User ( ) , " " : fingerprint , } ) cert , ok := key . ( * ssh . Certificate ) if ! ok { return nil , trace . BadParameter ( " " , fingerprint ) } if len ( cert . ValidPrincipals ) == 0 { return nil , trace . BadParameter ( " " , fingerprint ) } if len ( cert . KeyId ) == 0 { return nil , trace . BadParameter ( " " , fingerprint ) } teleportUser := cert . KeyId logAuditEvent := func ( err error ) { if err != nil { s . EmitAuditEvent ( events . AuthAttemptEvent , events . EventFields { events . EventUser : teleportUser , events . AuthAttemptSuccess : false , events . AuthAttemptErr : err . Error ( ) , } ) } } permissions , err := s . certChecker . Authenticate ( conn , key ) if err != nil { logAuditEvent ( err ) return nil , trace . Wrap ( err ) } if err := s . certChecker . CheckCert ( conn . User ( ) , cert ) ; err != nil { logAuditEvent ( err ) return nil , trace . Wrap ( err ) } logger . Debugf ( " " ) if ! s . proxyMode { _ , err = user . Lookup ( conn . User ( ) ) if err != nil { host , _ := os . Hostname ( ) logger . Warningf ( " " , host , conn . User ( ) ) logger . Errorf ( " " ) return nil , trace . AccessDenied ( " " , conn . User ( ) ) } } permissions . Extensions [ utils . CertTeleportUser ] = teleportUser if s . proxyMode { return permissions , nil } err = s . checkPermissionToLogin ( cert . SignatureKey , teleportUser , conn . User ( ) ) if err != nil { logger . Error ( err ) logAuditEvent ( err ) return nil , trace . Wrap ( err ) } return permissions , nil }
keyAuth implements SSH client authentication using public keys and is called
by the server every time the client connects
keyAuth implements SSH client authentication using public keys and is called by the server every time the client connects
// only failed attempts are logged right now // see if the host user is valid (no need to do this in proxy mode) // this is the only way I know of to pass valid principal with the // connection