func (dpa *DiegoProxyAuthenticator) Authenticate(metadata ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) { logger := dpa.logger.Session("authenticate") logger.Info("authentication-starting") defer logger.Info("authentication-finished") if !DiegoUserRegex.MatchString(metadata.User()) { logger.Error("regex-match-fail", InvalidDomainErr) return nil, InvalidDomainErr } if !bytes.Equal(dpa.receptorCreds, password) { logger.Error("invalid-credentials", InvalidCredentialsErr) return nil, InvalidCredentialsErr } guidAndIndex := DiegoUserRegex.FindStringSubmatch(metadata.User()) processGuid := guidAndIndex[1] index, err := strconv.Atoi(guidAndIndex[2]) if err != nil { logger.Error("atoi-failed", err) return nil, err } permissions, err := sshPermissionsFromProcess(processGuid, index, dpa.receptorClient, metadata.RemoteAddr()) if err != nil { logger.Error("building-ssh-permissions-failed", err) } return permissions, err }
func (cfa *CFAuthenticator) Authenticate(metadata ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) { logger := cfa.logger.Session("authenticate") if !CFRealmRegex.Match([]byte(metadata.User())) { return nil, InvalidDomainErr } principal := CFRealmRegex.FindStringSubmatch(metadata.User())[1] if !CFPrincipalRegex.Match([]byte(principal)) { return nil, InvalidCredentialsErr } guidAndIndex := CFPrincipalRegex.FindStringSubmatch(principal) index, err := strconv.Atoi(guidAndIndex[2]) if err != nil { logger.Error("atoi-failed", err) return nil, InvalidCredentialsErr } appGuid := guidAndIndex[1] path := fmt.Sprintf("%s/internal/apps/%s/ssh_access", cfa.ccURL, appGuid) req, err := http.NewRequest("GET", path, nil) if err != nil { logger.Error("creating-request-failed", InvalidRequestErr) return nil, InvalidRequestErr } req.Header.Add("Authorization", string(password)) resp, err := cfa.ccClient.Do(req) if err != nil { logger.Error("fetching-app-failed", err) return nil, err } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { logger.Error("fetching-app-failed", FetchAppFailedErr, lager.Data{ "StatusCode": resp.Status, "ResponseBody": resp.Body, }) return nil, FetchAppFailedErr } var app AppSSHResponse err = json.NewDecoder(resp.Body).Decode(&app) if err != nil { logger.Error("invalid-cc-response", err) return nil, InvalidCCResponse } permissions, err := sshPermissionsFromProcess(app.ProcessGuid, index, cfa.receptorClient, metadata.RemoteAddr()) if err != nil { logger.Error("building-ssh-permissions-failed", err) } return permissions, err }
func (a *CompositeAuthenticator) Authenticate(metadata ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) { if parts := strings.SplitN(metadata.User(), ":", 2); len(parts) == 2 { authenticator := a.authenticatorMap[parts[0]] if authenticator != nil { return authenticator.Authenticate(metadata, password) } } return nil, InvalidCredentialsErr }
func (a *CompositeAuthenticator) Authenticate(metadata ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) { for userRegexp, authenticator := range a.authenticators { if userRegexp.MatchString(metadata.User()) { return authenticator.Authenticate(metadata, password) } } return nil, InvalidCredentialsErr }
/* ci returns a string containing info from an ssh.ConnMetadata */ func ci(m ssh.ConnMetadata) string { return fmt.Sprintf( "Address:%v Target:%v Version:%q User:%q", m.RemoteAddr(), victimName(m), m.ClientVersion(), m.User(), ) }
// authPassword records any incoming request trying to auth with a username/password func authPassword(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) { log.Printf("sshPass: %s %s %s\n", conn.RemoteAddr().String(), conn.User(), strconv.QuoteToASCII(string(password))) return nil, errAuthenticationFailed }
func baseAlertMap(metadata ssh.ConnMetadata) map[string]string { meta := make(map[string]string) meta["service"] = "ssh" meta["user"] = metadata.User() meta["remote"] = metadata.RemoteAddr().String() meta["local"] = metadata.LocalAddr().String() return meta }
func (s *Server) PublicKeyCallback(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { s.mu.Lock() si := s.sessionInfo[string(conn.SessionID())] si.User = conn.User() si.Keys = append(si.Keys, key) s.sessionInfo[string(conn.SessionID())] = si s.mu.Unlock() // Never succeed a key, or we might not see the next. See KeyboardInteractiveCallback. return nil, errors.New("") }
/* logAttempt logs an authorization attempt. */ func logAttempt(conn ssh.ConnMetadata, method, cred string, suc bool) { log.Printf( "Address:%v Authorization Attempt Version:%q User:%q %v:%q "+ "Successful:%v", conn.RemoteAddr(), string(conn.ClientVersion()), conn.User(), method, cred, suc, ) }
func (s ScriptPassAuth) Auth(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) { cmd := exec.Command(config.PassAuthLocation, conn.User(), conn.RemoteAddr().String()) passReader := bytes.NewReader(password) cmd.Stdin = passReader output, err := cmd.CombinedOutput() if err != nil { config.Log.Error("password authentication: %s\n%v", output, err) return nil, err } // nil permissions is success? return nil, nil }
// 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 }
func passwordCallback(conn ssh.ConnMetadata, password []byte) (perm *ssh.Permissions, err error) { if conn.User() == "jonny.quest" && string(password) == "bandit" { // Add username to permissions perm = &ssh.Permissions{ Extensions: map[string]string{ "username": conn.User(), }, } } else { err = fmt.Errorf("Invalid username or password") } return }
func passAuthCallback(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) { guid := uuid.NewV4() ip, remotePort := parseIpPortFrom(conn) login := SshLogin{RemoteAddr: ip, RemotePort: remotePort, Username: conn.User(), Password: string(password), Guid: guid.String(), Version: string(conn.ClientVersion()), LoginType: "password", } login.Save() return &ssh.Permissions{Extensions: map[string]string{"guid": guid.String()}}, 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 }
func (s *Server) authUser(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) { // no auth - allow all if len(s.Users) == 0 { return nil, nil } // authenticate user n := c.User() u, ok := s.Users[n] if !ok || u.Pass != string(pass) { s.Debugf("Login failed: %s", n) return nil, errors.New("Invalid auth") } //insert session s.sessions[string(c.SessionID())] = u return nil, nil }
// authPassword records any incoming request trying to auth with a username/password func authPassword(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) { r := &AuthEvent{ Time: fmt.Sprintf("%d", time.Now().Unix()), AuthType: "sshPass", SrcIP: strings.Split(conn.RemoteAddr().String(), ":")[0], DestIP: extIP, User: conn.User(), TypeData: fmt.Sprintf("client-version: %s", strconv.QuoteToASCII(string(conn.ClientVersion()))), Credentials: strconv.QuoteToASCII(string(password)), } addToBatch(r) return nil, errAuthenticationFailed }
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 }
// 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 (sshd *SSHD) passwordCallback(meta ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) { user := sshd.getUsername(meta.User()) container := sshd.getContainerId(meta.User()) if len(container) != 12 { return nil, ErrInvalidContainerName } stmt, err := sshd.db.Prepare("select id, password from users where name = ?") if err != nil { return nil, err } var ( savedPass string uid int hasContainer int ) err = stmt.QueryRow(user).Scan(&uid, &savedPass) stmt.Close() if err != nil { log.Error("Scan: ", err) return nil, ErrInvalidPassword } err = bcrypt.CompareHashAndPassword([]byte(savedPass), pass) if err != nil { return nil, ErrInvalidPassword } stmt, err = sshd.db.Prepare("select 1 from containers where user_id = ? and cid like ?") if err != nil { return nil, err } stmt.QueryRow(uid, container+"%").Scan(&hasContainer) stmt.Close() if hasContainer != 1 { return nil, ErrAccessDenied } return nil, nil }
func pubkeyCallback(c ssh.ConnMetadata, pubkey ssh.PublicKey) (*ssh.Permissions, error) { log.Printf("login: '******'. pubkey fingerprint: %s", c.User(), fingerprintKey(pubkey)) if c.User() == USER { return nil, nil } return nil, fmt.Errorf("pubkey rejected for user %s", c.User()) }
func passwordCallback(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) { log.Printf("login: '******' with password '%s'", c.User(), string(pass)) if c.User() == USER && string(pass) == PASS { return nil, nil } return nil, fmt.Errorf("password rejected for user %s", c.User()) }
func handleAuth(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { if *authHook == "" { // allow all return &ssh.Permissions{ Extensions: map[string]string{ "user": conn.User(), }, }, nil } keydata := string(bytes.TrimSpace(ssh.MarshalAuthorizedKey(key))) cmd, err := handlerCmd(*authHook, conn.User(), keydata) if err != nil { return nil, err } var output bytes.Buffer cmd.Stdout = &output cmd.Stderr = &output status, err := exitStatus(cmd.Run()) if err != nil { return nil, err } if status.Status == 0 { return &ssh.Permissions{ Extensions: map[string]string{ "environ": strings.Trim(output.String(), "\n"), "user": conn.User(), }, }, nil } debug("authentication hook status:", status.Status) return nil, fmt.Errorf("authentication failed") }
func keyAuth(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { log.Printf("(keyAuth) >> New client conn from '%s' authenticating with '%s'\n", conn.RemoteAddr(), key.Type()) // Check if the user is allowed to connect at all (meaning: the must be a subdirectory in the 'data' dir // matching the provided SSH username). authorizedPubKey, err := getPubKeyForUser(conn.User()) if err != nil { return nil, fmt.Errorf("(keyAuth) >> No pub key for user '%s' found / user not allowed to connect.", conn.User()) } fpProvidedPubKey, err := pubKeyFingerprint(key) if err != nil { log.Printf("(keyAuth) >> Error: Unable to create fingerprint for provided PubKey: %s\n", err.Error()) } log.Printf("(keyAuth) >> Fingerprint of provided PubKey : %s\n", fpProvidedPubKey) fpAuthorizedPubKey, err := pubKeyFingerprint(authorizedPubKey) if err != nil { log.Printf("(keyAuth) >> Error: Unable to create fingerprint for authorized PubKey: %s\n", err.Error()) } log.Printf("(keyAuth) >> Fingerprint of authorized PubKey: %s\n", fpAuthorizedPubKey) // Check if username and Public Key combination is allowed to establish a connection. if theseTwoPublicKeysAreEqual(key, authorizedPubKey) { log.Printf("(keyAuth) >> Correct username '%s' and public key provided.", conn.User()) // Signaling success / authentication passed. return nil, nil } log.Printf("(keyAuth) >> Wrong username '%s' and/or public key provided.", conn.User()) return nil, fmt.Errorf("Wrong username and/or public key.") }
/* logKeyInt logs a keyboard-interactive attempt */ func logKeyInt( conn ssh.ConnMetadata, client ssh.KeyboardInteractiveChallenge, ) (*ssh.Permissions, error) { /* Send a welcome and the prompt */ a, err := client( conn.User(), "", []string{"Password: "******"%v error sending keyboard-interactive prompt: %v", ci(conn), err, ) } else if 0 == len(a) { /* Didn't get an answer */ log.Printf("%v no keyboard-interactive answer") } else if 1 < len(a) { /* We mysteriously got back too many answers */ for i, v := range a { log.Printf( "%v Keyboard-Interactive-%v/%v: %q", ci(conn), i, len(a), v, ) } } else { /* Got just one answer */ log.Printf( "%v Keyboard-Interactive:%q", ci(conn), a[0], ) } return nil, fmt.Errorf("invalid password") }
func (sshClient *sshClient) passwordCallback(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) { var sshPasswordPayload struct { SessionId string `json:"SessionId"` SshPassword string `json:"SshPassword"` } err := json.Unmarshal(password, &sshPasswordPayload) if err != nil { // Backwards compatibility case: instead of a JSON payload, older clients // send the hex encoded session ID prepended to the SSH password. // Note: there's an even older case where clients don't send any session ID, // but that's no longer supported. if len(password) == 2*psiphon.PSIPHON_API_CLIENT_SESSION_ID_LENGTH+2*SSH_PASSWORD_BYTE_LENGTH { sshPasswordPayload.SessionId = string(password[0 : 2*psiphon.PSIPHON_API_CLIENT_SESSION_ID_LENGTH]) sshPasswordPayload.SshPassword = string(password[2*psiphon.PSIPHON_API_CLIENT_SESSION_ID_LENGTH : len(password)]) } else { return nil, psiphon.ContextError(fmt.Errorf("invalid password payload for %q", conn.User())) } } if !isHexDigits(sshClient.sshServer.support, sshPasswordPayload.SessionId) { return nil, psiphon.ContextError(fmt.Errorf("invalid session ID for %q", conn.User())) } userOk := (subtle.ConstantTimeCompare( []byte(conn.User()), []byte(sshClient.sshServer.support.Config.SSHUserName)) == 1) passwordOk := (subtle.ConstantTimeCompare( []byte(sshPasswordPayload.SshPassword), []byte(sshClient.sshServer.support.Config.SSHPassword)) == 1) if !userOk || !passwordOk { return nil, psiphon.ContextError(fmt.Errorf("invalid password for %q", conn.User())) } psiphonSessionID := sshPasswordPayload.SessionId sshClient.Lock() sshClient.psiphonSessionID = psiphonSessionID geoIPData := sshClient.geoIPData sshClient.Unlock() // Store the GeoIP data associated with the session ID. This makes the GeoIP data // available to the web server for web transport Psiphon API requests. sshClient.sshServer.support.GeoIPService.SetSessionCache( psiphonSessionID, geoIPData) return nil, nil }
// PublicKeyCallback is called when the user tries to authenticate using an SSH public key func (s *Server) PublicKeyCallback(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { username := conn.User() clientID := conn.RemoteAddr().String() keyText := strings.TrimSpace(string(ssh.MarshalAuthorizedKey(key))) log.Debugf("PublicKeyCallback: %q %q", username, keyText) // sessionID := conn.SessionID() config := s.ClientConfigs[clientID] if config == nil { s.ClientConfigs[clientID] = &ClientConfig{ RemoteUser: username, ImageName: username, Keys: []string{}, AuthenticationMethod: "noauth", AuthenticationAttempts: 0, AuthenticationComment: "", Env: make(envhelper.Environment, 0), } } config = s.ClientConfigs[clientID] config.Keys = append(config.Keys, keyText) return nil, s.CheckConfig(config) }
func handleAuth(handler []string, conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { var output bytes.Buffer keydata := string(bytes.TrimSpace(ssh.MarshalAuthorizedKey(key))) cmd := exec.Command(handler[0], append(handler[1:], conn.User(), keydata)...) cmd.Stdout = &output cmd.Stderr = &output status, err := exitStatus(cmd.Run()) if err != nil { return nil, err } if status.Status == 0 { return &ssh.Permissions{ Extensions: map[string]string{ "environ": strings.Trim(output.String(), "\n"), "user": conn.User(), }, }, nil } else { log.Println("auth-handler status:", status.Status) } return nil, ErrUnauthorized }
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 (cfa *CFAuthenticator) Authenticate(metadata ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) { logger := cfa.logger.Session("cf-authenticate") logger.Info("authenticate-starting") defer logger.Info("authenticate-finished") if !CFUserRegex.MatchString(metadata.User()) { logger.Error("regex-match-fail", InvalidCredentialsErr) return nil, InvalidCredentialsErr } guidAndIndex := CFUserRegex.FindStringSubmatch(metadata.User()) appGuid := guidAndIndex[1] index, err := strconv.Atoi(guidAndIndex[2]) if err != nil { logger.Error("atoi-failed", err) return nil, InvalidCredentialsErr } cred, err := cfa.exchangeAccessCodeForToken(logger, string(password)) if err != nil { return nil, err } processGuid, err := cfa.checkAccess(logger, appGuid, index, string(cred)) if err != nil { return nil, err } permissions, err := cfa.permissionsBuilder.Build(processGuid, index, metadata) if err != nil { logger.Error("building-ssh-permissions-failed", err) } return permissions, err }
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 }