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 }
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 }
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 }