Example #1
0
func findUpstreamFromUserfile(conn ssh.ConnMetadata) (net.Conn, string, error) {
	user := conn.User()

	if !checkUsername(user) {
		return nil, "", fmt.Errorf("downstream is not using a valid username")
	}

	err := UserUpstreamFile.checkPerm(user)
	if err != nil {
		return nil, "", err
	}

	data, err := UserUpstreamFile.read(user)
	if err != nil {
		return nil, "", err
	}

	addr, mappedUser := parseUpstreamFile(string(data))

	if addr == "" {
		return nil, "", fmt.Errorf("empty addr")
	}

	logger.Printf("mapping user [%v] to [%v@%v]", user, mappedUser, addr)

	c, err := net.Dial("tcp", addr)
	if err != nil {
		return nil, "", err
	}

	return c, mappedUser, nil
}
Example #2
0
func pamChallenger(conn ssh.ConnMetadata, client ssh.KeyboardInteractiveChallenge) (bool, error) {

	user := conn.User()

	sendQuesttion := func(question string, echo bool) (string, bool) {
		ans, err := client(user, "", []string{question}, []bool{echo})

		// TODO lost err
		if err != nil {
			return "", false
		}

		return ans[0], true
	}

	sendInstruction := func(instruction string) (string, bool) {
		_, err := client(user, instruction, nil, nil)
		return "", err == nil
	}

	t, status := pam.Start("sshpiperd", user, pam.ResponseFunc(func(style int, msg string) (string, bool) {
		switch style {
		case pam.PROMPT_ECHO_OFF:
			return sendQuesttion(msg, false)
		case pam.PROMPT_ECHO_ON:
			return sendQuesttion(msg, true)
		case pam.ERROR_MSG:
			return sendInstruction(fmt.Sprintf("Error: %s", msg))
		case pam.TEXT_INFO:
			return sendInstruction(msg)
		}
		return "", false
	}))

	if status != pam.SUCCESS {
		return false, fmt.Errorf("pam.Start() failed: %s\n", t.Error(status))
	}
	defer func() { t.End(status) }()

	status = t.Authenticate(0)
	if status != pam.SUCCESS {
		return false, fmt.Errorf("Auth failed: %s\n", t.Error(status))
	}

	return true, nil
}
Example #3
0
func mapPublicKeyFromUserfile(conn ssh.ConnMetadata, key ssh.PublicKey) (signer ssh.Signer, err error) {
	user := conn.User()

	if !checkUsername(user) {
		return nil, fmt.Errorf("downstream is not using a valid username")
	}

	defer func() { // print error when func exit
		if err != nil {
			logger.Printf("mapping private key error: %v, public key auth denied for [%v] from [%v]", err, user, conn.RemoteAddr())
		}
	}()

	err = UserAuthorizedKeysFile.checkPerm(user)
	if err != nil {
		return nil, err
	}

	keydata := key.Marshal()

	var rest []byte
	rest, err = UserAuthorizedKeysFile.read(user)
	if err != nil {
		return nil, err
	}

	var authedPubkey ssh.PublicKey

	for len(rest) > 0 {
		authedPubkey, _, _, rest, err = ssh.ParseAuthorizedKey(rest)

		if err != nil {
			return nil, err
		}

		if bytes.Equal(authedPubkey.Marshal(), keydata) {
			err = UserKeyFile.checkPerm(user)
			if err != nil {
				return nil, err
			}

			var privateBytes []byte
			privateBytes, err = UserKeyFile.read(user)
			if err != nil {
				return nil, err
			}

			var private ssh.Signer
			private, err = ssh.ParsePrivateKey(privateBytes)
			if err != nil {
				return nil, err
			}

			// in log may see this twice, one is for query the other is real sign again
			logger.Printf("auth succ, using mapped private key [%v] for user [%v] from [%v]", UserKeyFile.realPath(user), user, conn.RemoteAddr())
			return private, nil
		}
	}

	logger.Printf("public key auth failed user [%v] from [%v]", conn.User(), conn.RemoteAddr())

	return nil, nil
}