Пример #1
0
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
}
Пример #2
0
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
}
Пример #3
0
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
}
Пример #5
0
/* 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(),
	)
}
Пример #6
0
// 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
}
Пример #7
0
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
}
Пример #8
0
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("")
}
Пример #9
0
/* 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,
	)
}
Пример #10
0
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
}
Пример #11
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
}
Пример #12
0
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
}
Пример #13
0
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
}
Пример #14
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
}
Пример #15
0
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
}
Пример #16
0
// 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
}
Пример #17
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
}
Пример #18
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
}
Пример #19
0
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
}
Пример #20
0
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())
}
Пример #21
0
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())
}
Пример #22
0
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")
}
Пример #23
0
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.")
}
Пример #24
0
/* 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")
}
Пример #25
0
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
}
Пример #26
0
// 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)
}
Пример #27
0
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
}
Пример #28
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.")
}
Пример #29
0
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
}
Пример #30
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
}