diff --git a/internal/brokers/withexamples.go b/internal/brokers/withexamples.go index 30b906696a..99214ad2cb 100644 --- a/internal/brokers/withexamples.go +++ b/internal/brokers/withexamples.go @@ -13,6 +13,9 @@ import ( // useExampleBrokers starts a mock system bus and exports the examplebroker in it. func useExampleBrokers() (string, func(), error) { + if os.Getenv("AUTHD_EXAMPLE_BROKER_DISABLE") != "" { + return "", func() { /* Nothing to cleanup */ }, nil + } busCleanup, err := testutils.StartSystemBusMock() if err != nil { return "", nil, err diff --git a/internal/testutils/args.go b/internal/testutils/args.go index ee70bcadca..382d0b8a1f 100644 --- a/internal/testutils/args.go +++ b/internal/testutils/args.go @@ -92,3 +92,9 @@ func SleepMultiplier() float64 { return sleepMultiplier } + +// IsCI returns whether the test is running in CI environment. +var IsCI = sync.OnceValue(func() bool { + _, ok := os.LookupEnv("GITHUB_ACTIONS") + return ok +}) diff --git a/internal/users/db/bbolt/testutils.go b/internal/users/db/bbolt/testutils.go index 5068c56d12..3ce2aacb11 100644 --- a/internal/users/db/bbolt/testutils.go +++ b/internal/users/db/bbolt/testutils.go @@ -4,6 +4,7 @@ package bbolt // They are not exported, and guarded by testing assertions. import ( + "encoding/json" "os" "path/filepath" "strings" @@ -14,14 +15,26 @@ import ( "gopkg.in/yaml.v3" ) -// We need to replace the current time by a deterministic time in the golden files to be able to compare them. -// We use the first second of the year 2020 as a recognizable value (which is not the zero value). -var redactedCurrentTime = "2020-01-01T00:00:00Z" +const ( + // We need to replace the current time by a deterministic time in the golden files to be able to compare them. + // We use the first second of the year 2020 as a recognizable value (which is not the zero value). + redactedCurrentTime = "2020-01-01T00:00:00Z" + + // User homes can have an invalid prefix that we can adjust during tests. + redactedUserHome = "@HOME_BASE@" +) // Z_ForTests_CreateDBFromYAML creates the database inside destDir and loads the src file content into it. // // nolint:revive,nolintlint // We want to use underscores in the function name here. func Z_ForTests_CreateDBFromYAML(src, destDir string) (err error) { + return Z_ForTests_CreateDBFromYAMLWithBaseHome(src, destDir, "") +} + +// Z_ForTests_CreateDBFromYAMLWithBaseHome creates the database inside destDir and loads the src file content into it. +// +// nolint:revive,nolintlint // We want to use underscores in the function name here. +func Z_ForTests_CreateDBFromYAMLWithBaseHome(src, destDir, baseHomeDir string) (err error) { testsdetection.MustBeTesting() src, err = filepath.Abs(src) @@ -64,7 +77,26 @@ func Z_ForTests_CreateDBFromYAML(src, destDir string) (err error) { if bucketName == userByIDBucketName || bucketName == userByNameBucketName { // Replace the redacted time in the json value by a valid time. val = strings.Replace(val, redactedCurrentTime, time.Now().Format(time.RFC3339), 1) + + if baseHomeDir != "" { + var u UserDB + if err := json.Unmarshal([]byte(val), &u); err != nil { + return err + } + + u.Dir = strings.ReplaceAll(u.Dir, redactedUserHome, baseHomeDir) + if err := os.MkdirAll(u.Dir, 0700); err != nil { + return err + } + + v, err := json.Marshal(u) + if err != nil { + return err + } + val = string(v) + } } + if err := bucket.Put([]byte(key), []byte(val)); err != nil { panic("programming error: put called in a RO transaction") } diff --git a/pam/integration-tests/cli_test.go b/pam/integration-tests/cli_test.go index 214130a73c..f8602454e4 100644 --- a/pam/integration-tests/cli_test.go +++ b/pam/integration-tests/cli_test.go @@ -38,6 +38,7 @@ func TestCLIAuthenticate(t *testing.T) { socketPath string currentUserNotRoot bool wantLocalGroups bool + noConfiguredBroker bool oldDB string stopDaemonAfter time.Duration }{ @@ -189,6 +190,9 @@ func TestCLIAuthenticate(t *testing.T) { }, "Autoselect_local_broker_for_local_user": { tape: "local_user", + tapeVariables: map[string]string{ + vhsTapeUserVariable: "root", + }, }, "Autoselect_local_broker_for_local_user_preset": { tape: "local_user_preset", @@ -221,6 +225,18 @@ func TestCLIAuthenticate(t *testing.T) { tape: "local_broker", tapeSettings: []tapeSetting{{vhsHeight, 800}}, }, + "Exit_authd_if_no_broker_is_configured": { + tape: "local_user", + tapeVariables: map[string]string{ + vhsTapeUserVariable: vhsTestUserName(t, "no-broker"), + }, + noConfiguredBroker: true, + }, + "Exit_authd_if_no_broker_is_configured_with_preset_user": { + tape: "local_user_preset", + clientOptions: clientOptions{PamUser: vhsTestUserName(t, "no-broker")}, + noConfiguredBroker: true, + }, "Exit_authd_if_user_sigints": { tape: "sigint", }, @@ -244,7 +260,8 @@ func TestCLIAuthenticate(t *testing.T) { require.NoError(t, err, "Setup: symlinking the pam client") var socketPath, gpasswdOutput, groupsFile, pidFile string - if tc.wantLocalGroups || tc.currentUserNotRoot || tc.stopDaemonAfter > 0 || tc.oldDB != "" { + if tc.wantLocalGroups || tc.currentUserNotRoot || tc.stopDaemonAfter > 0 || + tc.noConfiguredBroker || tc.oldDB != "" { // For the local groups tests we need to run authd again so that it has // special environment that generates a fake gpasswd output for us to test. // Similarly for the not-root tests authd has to run in a more restricted way. @@ -253,9 +270,14 @@ func TestCLIAuthenticate(t *testing.T) { pidFile = filepath.Join(outDir, "authd.pid") + env := useOldDatabaseEnv(t, tc.oldDB) + if tc.noConfiguredBroker { + env = append(env, "AUTHD_EXAMPLE_BROKER_DISABLE=1") + } + socketPath = runAuthd(t, gpasswdOutput, groupsFile, !tc.currentUserNotRoot, testutils.WithPidFile(pidFile), - testutils.WithEnvironment(useOldDatabaseEnv(t, tc.oldDB)...)) + testutils.WithEnvironment(env...)) } else { socketPath, gpasswdOutput = sharedAuthd(t) } diff --git a/pam/integration-tests/helpers_test.go b/pam/integration-tests/helpers_test.go index eedc58da69..449f3271c0 100644 --- a/pam/integration-tests/helpers_test.go +++ b/pam/integration-tests/helpers_test.go @@ -564,7 +564,8 @@ func useOldDatabaseEnv(t *testing.T, oldDB string) []string { oldDBDir, err := os.MkdirTemp(tempDir, "old-db-path") require.NoError(t, err, "Cannot create db directory in %q", tempDir) - err = bbolt.Z_ForTests_CreateDBFromYAML(filepath.Join("testdata", "db", oldDB+".db.yaml"), oldDBDir) + err = bbolt.Z_ForTests_CreateDBFromYAMLWithBaseHome( + filepath.Join("testdata", "db", oldDB+".db.yaml"), oldDBDir, t.TempDir()) require.NoError(t, err, "Setup: creating old database") return []string{fmt.Sprintf("AUTHD_INTEGRATIONTESTS_OLD_DB_DIR=%s", oldDBDir)} diff --git a/pam/integration-tests/native_test.go b/pam/integration-tests/native_test.go index 3193bd29a6..51102a7759 100644 --- a/pam/integration-tests/native_test.go +++ b/pam/integration-tests/native_test.go @@ -37,6 +37,7 @@ func TestNativeAuthenticate(t *testing.T) { userSelection bool userSuffixSkip bool oldDB string + noConfiguredBroker bool wantLocalGroups bool wantSeparateDaemon bool skipRunnerCheck bool @@ -305,11 +306,13 @@ func TestNativeAuthenticate(t *testing.T) { "Autoselect_local_broker_for_local_user": { tape: "local_user", userSelection: true, + tapeVariables: map[string]string{vhsTapeUserVariable: "root"}, }, "Autoselect_local_broker_for_local_user_on_polkit": { tape: "local_user", userSelection: true, clientOptions: clientOptions{PamServiceName: "polkit-1"}, + tapeVariables: map[string]string{vhsTapeUserVariable: "root"}, }, "Autoselect_local_broker_for_local_user_preset": { tape: "local_user_preset", @@ -365,6 +368,27 @@ func TestNativeAuthenticate(t *testing.T) { PamServiceName: "sshd", }, }, + "Exit_authd_if_no_broker_is_configured": { + tape: "local_user", + tapeVariables: map[string]string{ + vhsTapeUserVariable: vhsTestUserName(t, "no-broker"), + }, + userSelection: true, + noConfiguredBroker: true, + }, + "Exit_authd_if_no_broker_is_configured_with_preset_user": { + tape: "local_user_preset", + clientOptions: clientOptions{PamUser: vhsTestUserName(t, "no-broker")}, + noConfiguredBroker: true, + }, + "Exit_authd_if_no_broker_is_configured_with_preset_user_on_polkit": { + tape: "local_user_preset", + clientOptions: clientOptions{ + PamServiceName: "polkit-1", + PamUser: vhsTestUserName(t, "no-broker-polkit"), + }, + noConfiguredBroker: true, + }, "Exit_if_user_is_not_pre-checked_on_custom_ssh_service_with_connection_env": { tape: "local_ssh", clientOptions: clientOptions{ @@ -403,7 +427,7 @@ func TestNativeAuthenticate(t *testing.T) { var socketPath, gpasswdOutput, groupsFile, pidFile string if tc.wantLocalGroups || tc.currentUserNotRoot || tc.wantSeparateDaemon || - tc.oldDB != "" { + tc.noConfiguredBroker || tc.oldDB != "" { // For the local groups tests we need to run authd again so that it has // special environment that generates a fake gpasswd output for us to test. // Similarly for the not-root tests authd has to run in a more restricted way. @@ -412,9 +436,14 @@ func TestNativeAuthenticate(t *testing.T) { pidFile = filepath.Join(outDir, "authd.pid") + env := useOldDatabaseEnv(t, tc.oldDB) + if tc.noConfiguredBroker { + env = append(env, "AUTHD_EXAMPLE_BROKER_DISABLE=1") + } + socketPath = runAuthd(t, gpasswdOutput, groupsFile, !tc.currentUserNotRoot, testutils.WithPidFile(pidFile), - testutils.WithEnvironment(useOldDatabaseEnv(t, tc.oldDB)...)) + testutils.WithEnvironment(env...)) } else { socketPath, gpasswdOutput = sharedAuthd(t) } diff --git a/pam/integration-tests/ssh_test.go b/pam/integration-tests/ssh_test.go index 31e12240a6..8a94abde87 100644 --- a/pam/integration-tests/ssh_test.go +++ b/pam/integration-tests/ssh_test.go @@ -74,6 +74,8 @@ func testSSHAuthenticate(t *testing.T, sharedSSHd bool) { execModule := buildExecModuleWithCFlags(t, []string{"-std=c11"}, true) execChild := buildPAMExecChild(t) + specialUserAcceptAll := "authd-test-user-sshd-accept-all" + mkHomeDirHelper, err := exec.LookPath("mkhomedir_helper") require.NoError(t, err, "Setup: mkhomedir_helper not found") pamMkHomeDirModule := buildCPAMModule(t, @@ -94,7 +96,8 @@ func testSSHAuthenticate(t *testing.T, sharedSSHd bool) { nssLibrary, nssEnv = testutils.BuildRustNSSLib(t, true) sshdPreloadLibraries = append(sshdPreloadLibraries, nssLibrary) sshdPreloaderCFlags = append(sshdPreloaderCFlags, - "-DAUTHD_TESTS_SSH_USE_AUTHD_NSS") + "-DAUTHD_TESTS_SSH_USE_AUTHD_NSS", + fmt.Sprintf("-DAUTHD_SPECIAL_USER_ACCEPT_ALL=%q", specialUserAcceptAll)) nssEnv = append(nssEnv, nssTestEnvBase(t, nssLibrary)...) } else if err != nil { t.Logf("Using the dummy library to implement NSS: %v", err) @@ -127,8 +130,9 @@ func testSSHAuthenticate(t *testing.T, sharedSSHd bool) { serviceFile := createSshdServiceFile(t, execModule, execChild, pamMkHomeDirModule, defaultSocketPath) sshdEnv = append(sshdEnv, nssEnv...) sshdEnv = append(sshdEnv, fmt.Sprintf("AUTHD_NSS_SOCKET=%s", defaultSocketPath)) - defaultSSHDPort, defaultUserHome = startSSHdForTest(t, serviceFile, sshdHostKey, - "authd-test-user-sshd-accept-all", sshdPreloadLibraries, sshdEnv, true, false) + defaultUserHome = expectedUserHome(t, specialUserAcceptAll) + defaultSSHDPort = startSSHdForTest(t, serviceFile, sshdHostKey, + defaultUserHome, specialUserAcceptAll, sshdPreloadLibraries, sshdEnv, true, false) } sshEnvVariablesRegex = regexp.MustCompile(`(?m) (PATH|HOME|PWD|SSH_[A-Z]+)=.*(\n*)($[^ ]{2}.*)?$`) @@ -139,14 +143,16 @@ func testSSHAuthenticate(t *testing.T, sharedSSHd bool) { tapeSettings []tapeSetting tapeVariables map[string]string - user string - isLocalUser bool - userPrefix string - pamServiceName string - socketPath string - daemonizeSSHd bool - interactiveShell bool - oldDB string + user string + isLocalUser bool + userPrefix string + pamServiceName string + socketPath string + daemonizeSSHd bool + interactiveShell bool + noConfiguredBroker bool + command []string + oldDB string wantUserAlreadyExist bool wantNotLoggedInUser bool @@ -163,6 +169,10 @@ func testSSHAuthenticate(t *testing.T, sharedSSHd bool) { tape: "simple_auth_with_shell", interactiveShell: true, }, + "Authenticate_user_successfully_launching_command": { + tape: "simple_auth", + command: []string{"true"}, + }, "Authenticate_user_successfully_with_upper_case": { tape: "simple_auth", user: strings.ToUpper(vhsTestUserNameFull(t, @@ -321,6 +331,7 @@ Wait@%dms`, sshDefaultFinalWaitTimeout), "Exit_authd_if_local_broker_is_selected": { tape: "local_broker", wantNotLoggedInUser: true, + daemonizeSSHd: true, tapeVariables: map[string]string{ vhsCommandFinalAuthWaitVariable: `Wait /Password:/`, }, @@ -334,6 +345,14 @@ Wait@%dms`, sshDefaultFinalWaitTimeout), vhsCommandFinalAuthWaitVariable: `Wait /Password:/`, }, }, + "Exit_authd_if_no_broker_is_configured_with_preset_user": { + tape: "local_user_preset", + noConfiguredBroker: true, + wantNotLoggedInUser: true, + tapeVariables: map[string]string{ + vhsCommandFinalAuthWaitVariable: `Wait /Password:/`, + }, + }, "Exit_authd_if_user_sigints": { tape: "sigint", wantNotLoggedInUser: true, @@ -376,13 +395,18 @@ Wait@%dms`, sshDefaultFinalWaitTimeout), } var groupsFile string - if tc.wantLocalGroups || tc.oldDB != "" { + needsLocalTestDaemonInstance := tc.wantLocalGroups || tc.noConfiguredBroker || tc.oldDB != "" + + if needsLocalTestDaemonInstance { // For the local groups tests we need to run authd again so that it has // special environment that generates a fake gpasswd output for us to test. // In the other cases this is not needed, so we can just use a shared authd. gpasswdOutput, groupsFile = prepareGPasswdFiles(t) authdEnv = append(authdEnv, useOldDatabaseEnv(t, tc.oldDB)...) + if tc.noConfiguredBroker { + authdEnv = append(authdEnv, "AUTHD_EXAMPLE_BROKER_DISABLE=1") + } socketPath = runAuthd(t, gpasswdOutput, groupsFile, true, testutils.WithEnvironment(authdEnv...)) @@ -427,7 +451,20 @@ Wait@%dms`, sshDefaultFinalWaitTimeout), sshdPort := defaultSSHDPort userHome := defaultUserHome - if !sharedSSHd || tc.wantLocalGroups || tc.oldDB != "" || + + if tc.wantUserAlreadyExist { + authdUser, err := userClient.GetUserByName(context.Background(), + &authd.GetUserByNameRequest{Name: user, ShouldPreCheck: false}) + require.NoError(t, err, "User %q should already exist in the daemon", user) + userHome = authdUser.Homedir + require.NotEmpty(t, userHome, "Setup: User HOME for known user %q is unset", user) + } + + if userHome == "" { + userHome = expectedUserHome(t, user) + } + + if !sharedSSHd || needsLocalTestDaemonInstance || tc.interactiveShell || tc.socketPath != "" { sshdEnv := sshdEnv if nssLibrary != "" { @@ -441,13 +478,20 @@ Wait@%dms`, sshDefaultFinalWaitTimeout), } serviceFile := createSshdServiceFile(t, execModule, execChild, pamMkHomeDirModule, socketPath) - sshdPort, userHome = startSSHdForTest(t, serviceFile, sshdHostKey, user, - sshdPreloadLibraries, sshdEnv, tc.daemonizeSSHd, tc.interactiveShell) + sshdPort = startSSHdForTest(t, serviceFile, sshdHostKey, + userHome, user, sshdPreloadLibraries, sshdEnv, tc.daemonizeSSHd, + tc.interactiveShell) } if !sharedSSHd { _, err := os.Stat(userHome) - require.ErrorIs(t, err, os.ErrNotExist, "Unexpected error checking for %q", userHome) + if tc.wantUserAlreadyExist { + require.NoError(t, err, os.ErrNotExist, + "User home %q must already exist", userHome) + } else { + require.ErrorIs(t, err, os.ErrNotExist, + "Unexpected error checking for %q", userHome) + } } knownHost := filepath.Join(t.TempDir(), "known_hosts") @@ -456,13 +500,7 @@ Wait@%dms`, sshDefaultFinalWaitTimeout), ), 0600) require.NoError(t, err, "Setup: can't create known hosts file") - outDir := t.TempDir() - td := newTapeData(tc.tape, append(defaultTapeSettings, tc.tapeSettings...)...) - td.Command = tapeCommand - td.Env[pam_test.RunnerEnvSupportsConversation] = "1" - td.Env["HOME"] = t.TempDir() - td.Env[pamSSHUserEnv] = user - td.Env["AUTHD_PAM_SSH_ARGS"] = strings.Join([]string{ + sshArgs := []string{ "-p", sshdPort, "-F", os.DevNull, "-i", os.DevNull, @@ -470,7 +508,20 @@ Wait@%dms`, sshDefaultFinalWaitTimeout), "-o", "PasswordAuthentication=no", "-o", "PubkeyAuthentication=no", "-o", "UserKnownHostsFile=" + knownHost, - }, " ") + } + + if tc.interactiveShell { + require.Nil(t, tc.command, "Setup: Interactive shell and commands are incompatible") + } + sshArgs = append(sshArgs, tc.command...) + + outDir := t.TempDir() + td := newTapeData(tc.tape, append(defaultTapeSettings, tc.tapeSettings...)...) + td.Command = tapeCommand + td.Env[pam_test.RunnerEnvSupportsConversation] = "1" + td.Env["HOME"] = t.TempDir() + td.Env[pamSSHUserEnv] = user + td.Env["AUTHD_PAM_SSH_ARGS"] = strings.Join(sshArgs, " ") td.Variables = tc.tapeVariables td.RunVhs(t, vhsTestTypeSSH, outDir, nil) got := sanitizeGoldenFile(t, td, outDir) @@ -486,6 +537,9 @@ Wait@%dms`, sshDefaultFinalWaitTimeout), if nssLibrary != "" { requireGetEntExists(t, nssLibrary, socketPath, user, tc.isLocalUser) } + + _, err := os.Stat(userHome) + require.Error(t, err, "User %q home %q must not exist", user, userHome) } else { require.Contains(t, got, userEnv, "Logged in user does not matches") @@ -503,12 +557,10 @@ Wait@%dms`, sshDefaultFinalWaitTimeout), } } - if !tc.wantUserAlreadyExist { - // Check if user home has been created, but only if the user is a new one. - stat, err := os.Stat(userHome) - require.NoError(t, err, "Error checking for %q", userHome) - require.True(t, stat.IsDir(), "%q is not a directory", userHome) - } + // Check if user home has been created. + stat, err := os.Stat(userHome) + require.NoError(t, err, "Error checking for %q", userHome) + require.True(t, stat.IsDir(), "User %q home %q is not a directory", user, userHome) } if tc.wantLocalGroups || tc.oldDB != "" { @@ -593,7 +645,13 @@ func createSshdServiceFile(t *testing.T, module, execChild, mkHomeModule, socket return serviceFile } -func startSSHdForTest(t *testing.T, serviceFile, hostKey, user string, preloadLibraries []string, env []string, daemonize bool, interactiveShell bool) (string, string) { +func expectedUserHome(t *testing.T, userName string) string { + t.Helper() + + return filepath.Join(t.TempDir(), strings.ToLower(userName)) +} + +func startSSHdForTest(t *testing.T, serviceFile, hostKey, userHome, user string, preloadLibraries []string, env []string, daemonize bool, interactiveShell bool) string { t.Helper() sshdConnectCommand := fmt.Sprintf( @@ -608,17 +666,18 @@ func startSSHdForTest(t *testing.T, serviceFile, hostKey, user string, preloadLi sshdConnectCommand = "/bin/sh" } - homeBase := t.TempDir() - userHome := filepath.Join(homeBase, user) + require.NotEmpty(t, user, "Setup: User name is unset") + require.NotEmpty(t, userHome, "Setup: User HOME for %q is unset", user) + sshdPort := startSSHd(t, hostKey, sshdConnectCommand, append([]string{ - fmt.Sprintf("HOME=%s", homeBase), + fmt.Sprintf("HOME=%s", t.TempDir()), fmt.Sprintf("LD_PRELOAD=%s", strings.Join(preloadLibraries, ":")), fmt.Sprintf("AUTHD_TEST_SSH_USER=%s", user), fmt.Sprintf("AUTHD_TEST_SSH_HOME=%s", userHome), fmt.Sprintf("AUTHD_TEST_SSH_PAM_SERVICE=%s", serviceFile), }, env...), daemonize) - return sshdPort, userHome + return sshdPort } func sshdCommand(t *testing.T, port, hostKey, forcedCommand string, env []string, daemonize bool) (*exec.Cmd, string, string) { @@ -677,7 +736,9 @@ func startSSHd(t *testing.T, hostKey, forcedCommand string, env []string, daemon sshd, sshdPidFile, sshdLogFile := sshdCommand(t, sshdPort, hostKey, forcedCommand, env, daemonize) sshdStderr := bytes.Buffer{} sshd.Stderr = &sshdStderr - if testing.Verbose() { + + isCIVerbose := testutils.IsCI() && testing.Verbose() + if isCIVerbose { sshd.Stdout = os.Stdout sshd.Stderr = os.Stderr } @@ -688,9 +749,14 @@ func startSSHd(t *testing.T, hostKey, forcedCommand string, env []string, daemon sshdPid := sshd.Process.Pid t.Cleanup(func() { - if testing.Verbose() || !t.Failed() { + if isCIVerbose || !t.Failed() { return } + + if testing.Verbose() { + t.Logf("SSHd log:\n%s", sshdStderr.Bytes()) + } + sshdLog := filepath.Join(t.TempDir(), "sshd.log") require.NoError(t, os.WriteFile(sshdLog, sshdStderr.Bytes(), 0600), "TearDown: Saving sshd log") diff --git a/pam/integration-tests/sshd_preloader/sshd_preloader.c b/pam/integration-tests/sshd_preloader/sshd_preloader.c index 37dcb69e4b..966f93d57b 100644 --- a/pam/integration-tests/sshd_preloader/sshd_preloader.c +++ b/pam/integration-tests/sshd_preloader/sshd_preloader.c @@ -18,7 +18,6 @@ #define AUTHD_TEST_SHELL "/bin/sh" #define AUTHD_TEST_GECOS "" #define AUTHD_DEFAULT_SSH_PAM_SERVICE_NAME "sshd" -#define AUTHD_SPECIAL_USER_ACCEPT_ALL "authd-test-user-sshd-accept-all" #define SIZE_OF_ARRAY(a) (sizeof ((a)) / sizeof (*(a))) diff --git a/pam/integration-tests/testdata/db/authd_0.4.1_bbolt_with_mixed_case_users.db.yaml b/pam/integration-tests/testdata/db/authd_0.4.1_bbolt_with_mixed_case_users.db.yaml index 568fc1bedb..70c4168212 100644 --- a/pam/integration-tests/testdata/db/authd_0.4.1_bbolt_with_mixed_case_users.db.yaml +++ b/pam/integration-tests/testdata/db/authd_0.4.1_bbolt_with_mixed_case_users.db.yaml @@ -68,23 +68,23 @@ GroupToUsers: "1911746559": '{"GID":1911746559,"UIDs":[1911746559]}' "1047623009": '{"GID":1047623009,"UIDs":[1047623009]}' UserByID: - "1031497592": '{"Name":"user-integration-WITH-Mixed-CaSe","UID":1031497592,"GID":1031497592,"Gecos":"gecos for user-integration-WITH-Mixed-CaSe","Dir":"/home/user-integration-WITH-Mixed-CaSe","Shell":"/bin/sh","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-05-30T18:17:18.01191855+02:00"}' - "1047623009": '{"Name":"user-local-groups-Mixed-Case","UID":1047623009,"GID":1047623009,"Gecos":"gecos for user-local-groups-Mixed-Case","Dir":"/home/user-local-groups-Mixed-Case","Shell":"/usr/bin/bash","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-06-02T01:05:19.742290239+02:00"}' - "1448654198": '{"Name":"user-integration-cached","UID":1448654198,"GID":1448654198,"Gecos":"gecos for user-integration-cached","Dir":"/home/user-integration-cached","Shell":"/bin/sh","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-05-30T18:16:55.049670042+02:00"}' - "1668487632": '{"Name":"user-integration-pre-check-WITH-UPPER-CASE","UID":1668487632,"GID":1668487632,"Gecos":"gecos for user-integration-pre-check-WITH-UPPER-CASE","Dir":"/home/user-integration-pre-check-WITH-UPPER-CASE","Shell":"/bin/sh","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-05-30T18:26:39.600082108+02:00"}' - "1674497680": '{"Name":"user-local-groups-UPPER-CASE","UID":1674497680,"GID":1674497680,"Gecos":"gecos for user-local-groups-UPPER-CASE","Dir":"/home/user-local-groups-UPPER-CASE","Shell":"/usr/bin/bash","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-06-02T01:08:33.759143141+02:00"}' - "1690031958": '{"Name":"user-local-groups-lower-case","UID":1690031958,"GID":1690031958,"Gecos":"gecos for user-local-groups-lower-case","Dir":"/home/user-local-groups-lower-case","Shell":"/usr/bin/bash","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-06-02T01:08:07.712846646+02:00"}' - "1911746559": '{"Name":"user-integration-UPPER-CASE","UID":1911746559,"GID":1911746559,"Gecos":"gecos for user-integration-UPPER-CASE","Dir":"/home/user-integration-UPPER-CASE","Shell":"/bin/sh","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-05-30T18:20:04.201035581+02:00"}' - "1974679960": '{"Name":"user-pre-check","UID":1974679960,"GID":1974679960,"Gecos":"gecos for user-pre-check","Dir":"/home/user-pre-check","Shell":"/bin/sh","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-05-30T18:24:42.349318925+02:00"}' + "1031497592": '{"Name":"user-integration-WITH-Mixed-CaSe","UID":1031497592,"GID":1031497592,"Gecos":"gecos for user-integration-WITH-Mixed-CaSe","Dir":"@HOME_BASE@/user-integration-WITH-Mixed-CaSe","Shell":"/bin/sh","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-05-30T18:17:18.01191855+02:00"}' + "1047623009": '{"Name":"user-local-groups-Mixed-Case","UID":1047623009,"GID":1047623009,"Gecos":"gecos for user-local-groups-Mixed-Case","Dir":"@HOME_BASE@/user-local-groups-Mixed-Case","Shell":"/usr/bin/bash","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-06-02T01:05:19.742290239+02:00"}' + "1448654198": '{"Name":"user-integration-cached","UID":1448654198,"GID":1448654198,"Gecos":"gecos for user-integration-cached","Dir":"@HOME_BASE@/user-integration-cached","Shell":"/bin/sh","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-05-30T18:16:55.049670042+02:00"}' + "1668487632": '{"Name":"user-integration-pre-check-WITH-UPPER-CASE","UID":1668487632,"GID":1668487632,"Gecos":"gecos for user-integration-pre-check-WITH-UPPER-CASE","Dir":"@HOME_BASE@/user-integration-pre-check-WITH-UPPER-CASE","Shell":"/bin/sh","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-05-30T18:26:39.600082108+02:00"}' + "1674497680": '{"Name":"user-local-groups-UPPER-CASE","UID":1674497680,"GID":1674497680,"Gecos":"gecos for user-local-groups-UPPER-CASE","Dir":"@HOME_BASE@/user-local-groups-UPPER-CASE","Shell":"/usr/bin/bash","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-06-02T01:08:33.759143141+02:00"}' + "1690031958": '{"Name":"user-local-groups-lower-case","UID":1690031958,"GID":1690031958,"Gecos":"gecos for user-local-groups-lower-case","Dir":"@HOME_BASE@/user-local-groups-lower-case","Shell":"/usr/bin/bash","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-06-02T01:08:07.712846646+02:00"}' + "1911746559": '{"Name":"user-integration-UPPER-CASE","UID":1911746559,"GID":1911746559,"Gecos":"gecos for user-integration-UPPER-CASE","Dir":"@HOME_BASE@/user-integration-UPPER-CASE","Shell":"/bin/sh","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-05-30T18:20:04.201035581+02:00"}' + "1974679960": '{"Name":"user-pre-check","UID":1974679960,"GID":1974679960,"Gecos":"gecos for user-pre-check","Dir":"@HOME_BASE@/user-pre-check","Shell":"/bin/sh","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-05-30T18:24:42.349318925+02:00"}' UserByName: - user-integration-UPPER-CASE: '{"Name":"user-integration-UPPER-CASE","UID":1911746559,"GID":1911746559,"Gecos":"gecos for user-integration-UPPER-CASE","Dir":"/home/user-integration-UPPER-CASE","Shell":"/bin/sh","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-05-30T18:20:04.201035581+02:00"}' - user-integration-WITH-Mixed-CaSe: '{"Name":"user-integration-WITH-Mixed-CaSe","UID":1031497592,"GID":1031497592,"Gecos":"gecos for user-integration-WITH-Mixed-CaSe","Dir":"/home/user-integration-WITH-Mixed-CaSe","Shell":"/bin/sh","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-05-30T18:17:18.01191855+02:00"}' - user-integration-cached: '{"Name":"user-integration-cached","UID":1448654198,"GID":1448654198,"Gecos":"gecos for user-integration-cached","Dir":"/home/user-integration-cached","Shell":"/bin/sh","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-05-30T18:16:55.049670042+02:00"}' - user-integration-pre-check-WITH-UPPER-CASE: '{"Name":"user-integration-pre-check-WITH-UPPER-CASE","UID":1668487632,"GID":1668487632,"Gecos":"gecos for user-integration-pre-check-WITH-UPPER-CASE","Dir":"/home/user-integration-pre-check-WITH-UPPER-CASE","Shell":"/bin/sh","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-05-30T18:26:39.600082108+02:00"}' - user-local-groups-Mixed-Case: '{"Name":"user-local-groups-Mixed-Case","UID":1047623009,"GID":1047623009,"Gecos":"gecos for user-local-groups-Mixed-Case","Dir":"/home/user-local-groups-Mixed-Case","Shell":"/usr/bin/bash","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-06-02T01:05:19.742290239+02:00"}' - user-local-groups-UPPER-CASE: '{"Name":"user-local-groups-UPPER-CASE","UID":1674497680,"GID":1674497680,"Gecos":"gecos for user-local-groups-UPPER-CASE","Dir":"/home/user-local-groups-UPPER-CASE","Shell":"/usr/bin/bash","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-06-02T01:08:33.759143141+02:00"}' - user-local-groups-lower-case: '{"Name":"user-local-groups-lower-case","UID":1690031958,"GID":1690031958,"Gecos":"gecos for user-local-groups-lower-case","Dir":"/home/user-local-groups-lower-case","Shell":"/usr/bin/bash","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-06-02T01:08:07.712846646+02:00"}' - user-pre-check: '{"Name":"user-pre-check","UID":1974679960,"GID":1974679960,"Gecos":"gecos for user-pre-check","Dir":"/home/user-pre-check","Shell":"/bin/sh","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-05-30T18:24:42.349318925+02:00"}' + user-integration-UPPER-CASE: '{"Name":"user-integration-UPPER-CASE","UID":1911746559,"GID":1911746559,"Gecos":"gecos for user-integration-UPPER-CASE","Dir":"@HOME_BASE@/user-integration-UPPER-CASE","Shell":"/bin/sh","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-05-30T18:20:04.201035581+02:00"}' + user-integration-WITH-Mixed-CaSe: '{"Name":"user-integration-WITH-Mixed-CaSe","UID":1031497592,"GID":1031497592,"Gecos":"gecos for user-integration-WITH-Mixed-CaSe","Dir":"@HOME_BASE@/user-integration-WITH-Mixed-CaSe","Shell":"/bin/sh","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-05-30T18:17:18.01191855+02:00"}' + user-integration-cached: '{"Name":"user-integration-cached","UID":1448654198,"GID":1448654198,"Gecos":"gecos for user-integration-cached","Dir":"@HOME_BASE@/user-integration-cached","Shell":"/bin/sh","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-05-30T18:16:55.049670042+02:00"}' + user-integration-pre-check-WITH-UPPER-CASE: '{"Name":"user-integration-pre-check-WITH-UPPER-CASE","UID":1668487632,"GID":1668487632,"Gecos":"gecos for user-integration-pre-check-WITH-UPPER-CASE","Dir":"@HOME_BASE@/user-integration-pre-check-WITH-UPPER-CASE","Shell":"/bin/sh","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-05-30T18:26:39.600082108+02:00"}' + user-local-groups-Mixed-Case: '{"Name":"user-local-groups-Mixed-Case","UID":1047623009,"GID":1047623009,"Gecos":"gecos for user-local-groups-Mixed-Case","Dir":"@HOME_BASE@/user-local-groups-Mixed-Case","Shell":"/usr/bin/bash","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-06-02T01:05:19.742290239+02:00"}' + user-local-groups-UPPER-CASE: '{"Name":"user-local-groups-UPPER-CASE","UID":1674497680,"GID":1674497680,"Gecos":"gecos for user-local-groups-UPPER-CASE","Dir":"@HOME_BASE@/user-local-groups-UPPER-CASE","Shell":"/usr/bin/bash","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-06-02T01:08:33.759143141+02:00"}' + user-local-groups-lower-case: '{"Name":"user-local-groups-lower-case","UID":1690031958,"GID":1690031958,"Gecos":"gecos for user-local-groups-lower-case","Dir":"@HOME_BASE@/user-local-groups-lower-case","Shell":"/usr/bin/bash","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-06-02T01:08:07.712846646+02:00"}' + user-pre-check: '{"Name":"user-pre-check","UID":1974679960,"GID":1974679960,"Gecos":"gecos for user-pre-check","Dir":"@HOME_BASE@/user-pre-check","Shell":"/bin/sh","LastPwdChange":-1,"MaxPwdAge":-1,"PwdWarnPeriod":-1,"PwdInactivity":-1,"MinPwdAge":-1,"ExpirationDate":-1,"LastLogin":"2025-05-30T18:24:42.349318925+02:00"}' UserToBroker: "1031497592": '"2221040704"' "1047623009": '"2221040704"' diff --git a/pam/integration-tests/testdata/golden/TestCLIAuthenticate/Exit_authd_if_local_broker_is_selected b/pam/integration-tests/testdata/golden/TestCLIAuthenticate/Exit_authd_if_local_broker_is_selected index c44bd2f032..b838885b52 100644 --- a/pam/integration-tests/testdata/golden/TestCLIAuthenticate/Exit_authd_if_local_broker_is_selected +++ b/pam/integration-tests/testdata/golden/TestCLIAuthenticate/Exit_authd_if_local_broker_is_selected @@ -2,7 +2,7 @@ Username: user name ──────────────────────────────────────────────────────────────────────────────── > ./pam_authd login socket=${AUTHD_TEST_TAPE_SOCKET} -Username: user-local-broker +Username: user-integration-cli-local-broker ──────────────────────────────────────────────────────────────────────────────── > ./pam_authd login socket=${AUTHD_TEST_TAPE_SOCKET} Select your provider @@ -20,11 +20,44 @@ Username: user-local-broker PAM Info Message: auth=incomplete PAM Authenticate() - User: "user-local-broker" + User: "user-integration-cli-local-broker" Result: error: PAM exit code: 25 The return value should be ignored by PAM dispatch PAM AcctMgmt() - User: "user-local-broker" + User: "user-integration-cli-local-broker" + Result: error: PAM exit code: 26 + Critical error - immediate abort +> +──────────────────────────────────────────────────────────────────────────────── +> +──────────────────────────────────────────────────────────────────────────────── +> ./pam_authd login socket=${AUTHD_TEST_TAPE_SOCKET} +Username: user name +──────────────────────────────────────────────────────────────────────────────── +> ./pam_authd login socket=${AUTHD_TEST_TAPE_SOCKET} +Username: user-integration-cli-local-broker +──────────────────────────────────────────────────────────────────────────────── +> ./pam_authd login socket=${AUTHD_TEST_TAPE_SOCKET} + Select your provider + +> 1. local + 2. ExampleBroker + + Press escape key to go back to user selection +──────────────────────────────────────────────────────────────────────────────── +> ./pam_authd login socket=${AUTHD_TEST_TAPE_SOCKET} + Select your provider + +> 1. local + 2. ExampleBroker + +PAM Info Message: auth=incomplete +PAM Authenticate() + User: "user-integration-cli-local-broker" + Result: error: PAM exit code: 25 + The return value should be ignored by PAM dispatch +PAM AcctMgmt() + User: "user-integration-cli-local-broker" Result: error: PAM exit code: 26 Critical error - immediate abort > diff --git a/pam/integration-tests/testdata/golden/TestCLIAuthenticate/Exit_authd_if_no_broker_is_configured b/pam/integration-tests/testdata/golden/TestCLIAuthenticate/Exit_authd_if_no_broker_is_configured new file mode 100644 index 0000000000..b520901377 --- /dev/null +++ b/pam/integration-tests/testdata/golden/TestCLIAuthenticate/Exit_authd_if_no_broker_is_configured @@ -0,0 +1,18 @@ +> ./pam_authd login socket=${AUTHD_TEST_TAPE_SOCKET} +Username: user name +──────────────────────────────────────────────────────────────────────────────── +> ./pam_authd login socket=${AUTHD_TEST_TAPE_SOCKET} +Username: user-integration-no-broker-testcliauthenticate +──────────────────────────────────────────────────────────────────────────────── +> ./pam_authd login socket=${AUTHD_TEST_TAPE_SOCKET} +PAM Info Message: auth=incomplete +PAM Authenticate() + User: "user-integration-no-broker-testcliauthenticate" + Result: error: PAM exit code: 25 + The return value should be ignored by PAM dispatch +PAM AcctMgmt() + User: "user-integration-no-broker-testcliauthenticate" + Result: error: PAM exit code: 26 + Critical error - immediate abort +> +──────────────────────────────────────────────────────────────────────────────── diff --git a/pam/integration-tests/testdata/golden/TestCLIAuthenticate/Exit_authd_if_no_broker_is_configured_with_preset_user b/pam/integration-tests/testdata/golden/TestCLIAuthenticate/Exit_authd_if_no_broker_is_configured_with_preset_user new file mode 100644 index 0000000000..bb21dc0eef --- /dev/null +++ b/pam/integration-tests/testdata/golden/TestCLIAuthenticate/Exit_authd_if_no_broker_is_configured_with_preset_user @@ -0,0 +1,24 @@ +> ./pam_authd login socket=${AUTHD_TEST_TAPE_SOCKET} +PAM Info Message: auth=incomplete +PAM Authenticate() + User: "user-integration-no-broker-testcliauthenticate" + Result: error: PAM exit code: 25 + The return value should be ignored by PAM dispatch +PAM AcctMgmt() + User: "user-integration-no-broker-testcliauthenticate" + Result: error: PAM exit code: 26 + Critical error - immediate abort +> +──────────────────────────────────────────────────────────────────────────────── +> ./pam_authd login socket=${AUTHD_TEST_TAPE_SOCKET} +PAM Info Message: auth=incomplete +PAM Authenticate() + User: "user-integration-no-broker-testcliauthenticate" + Result: error: PAM exit code: 25 + The return value should be ignored by PAM dispatch +PAM AcctMgmt() + User: "user-integration-no-broker-testcliauthenticate" + Result: error: PAM exit code: 26 + Critical error - immediate abort +> +──────────────────────────────────────────────────────────────────────────────── diff --git a/pam/integration-tests/testdata/golden/TestNativeAuthenticate/Exit_authd_if_local_broker_is_selected b/pam/integration-tests/testdata/golden/TestNativeAuthenticate/Exit_authd_if_local_broker_is_selected index 86d026813a..5b2e22b68f 100644 --- a/pam/integration-tests/testdata/golden/TestNativeAuthenticate/Exit_authd_if_local_broker_is_selected +++ b/pam/integration-tests/testdata/golden/TestNativeAuthenticate/Exit_authd_if_local_broker_is_selected @@ -29,3 +29,36 @@ PAM AcctMgmt() Critical error - immediate abort > ──────────────────────────────────────────────────────────────────────────────── +> +──────────────────────────────────────────────────────────────────────────────── +> ./pam_authd login socket=${AUTHD_TEST_TAPE_SOCKET} force_native_client=true +== Provider selection == + 1. local + 2. ExampleBroker +Choose your provider: +> +──────────────────────────────────────────────────────────────────────────────── +> ./pam_authd login socket=${AUTHD_TEST_TAPE_SOCKET} force_native_client=true +== Provider selection == + 1. local + 2. ExampleBroker +Choose your provider: +> 1 +──────────────────────────────────────────────────────────────────────────────── +> ./pam_authd login socket=${AUTHD_TEST_TAPE_SOCKET} force_native_client=true +== Provider selection == + 1. local + 2. ExampleBroker +Choose your provider: +> 1 +auth=incomplete +PAM Authenticate() + User: "user-integration-native-exit-authd-if-local-broker-is-selected" + Result: error: PAM exit code: 25 + The return value should be ignored by PAM dispatch +PAM AcctMgmt() + User: "user-integration-native-exit-authd-if-local-broker-is-selected" + Result: error: PAM exit code: 26 + Critical error - immediate abort +> +──────────────────────────────────────────────────────────────────────────────── diff --git a/pam/integration-tests/testdata/golden/TestNativeAuthenticate/Exit_authd_if_no_broker_is_configured b/pam/integration-tests/testdata/golden/TestNativeAuthenticate/Exit_authd_if_no_broker_is_configured new file mode 100644 index 0000000000..847df6a4dd --- /dev/null +++ b/pam/integration-tests/testdata/golden/TestNativeAuthenticate/Exit_authd_if_no_broker_is_configured @@ -0,0 +1,16 @@ +> ./pam_authd login socket=${AUTHD_TEST_TAPE_SOCKET} force_native_client=true +Username: +──────────────────────────────────────────────────────────────────────────────── +> ./pam_authd login socket=${AUTHD_TEST_TAPE_SOCKET} force_native_client=true +Username: user-integration-no-broker-testnativeauthenticate +auth=incomplete +PAM Authenticate() + User: "user-integration-no-broker-testnativeauthenticate" + Result: error: PAM exit code: 25 + The return value should be ignored by PAM dispatch +PAM AcctMgmt() + User: "user-integration-no-broker-testnativeauthenticate" + Result: error: PAM exit code: 26 + Critical error - immediate abort +> +──────────────────────────────────────────────────────────────────────────────── diff --git a/pam/integration-tests/testdata/golden/TestNativeAuthenticate/Exit_authd_if_no_broker_is_configured_with_preset_user b/pam/integration-tests/testdata/golden/TestNativeAuthenticate/Exit_authd_if_no_broker_is_configured_with_preset_user new file mode 100644 index 0000000000..47bfe13a13 --- /dev/null +++ b/pam/integration-tests/testdata/golden/TestNativeAuthenticate/Exit_authd_if_no_broker_is_configured_with_preset_user @@ -0,0 +1,24 @@ +> ./pam_authd login socket=${AUTHD_TEST_TAPE_SOCKET} force_native_client=true +auth=incomplete +PAM Authenticate() + User: "user-integration-no-broker-testnativeauthenticate" + Result: error: PAM exit code: 25 + The return value should be ignored by PAM dispatch +PAM AcctMgmt() + User: "user-integration-no-broker-testnativeauthenticate" + Result: error: PAM exit code: 26 + Critical error - immediate abort +> +──────────────────────────────────────────────────────────────────────────────── +> ./pam_authd login socket=${AUTHD_TEST_TAPE_SOCKET} force_native_client=true +auth=incomplete +PAM Authenticate() + User: "user-integration-no-broker-testnativeauthenticate" + Result: error: PAM exit code: 25 + The return value should be ignored by PAM dispatch +PAM AcctMgmt() + User: "user-integration-no-broker-testnativeauthenticate" + Result: error: PAM exit code: 26 + Critical error - immediate abort +> +──────────────────────────────────────────────────────────────────────────────── diff --git a/pam/integration-tests/testdata/golden/TestNativeAuthenticate/Exit_authd_if_no_broker_is_configured_with_preset_user_on_polkit b/pam/integration-tests/testdata/golden/TestNativeAuthenticate/Exit_authd_if_no_broker_is_configured_with_preset_user_on_polkit new file mode 100644 index 0000000000..becb1df76d --- /dev/null +++ b/pam/integration-tests/testdata/golden/TestNativeAuthenticate/Exit_authd_if_no_broker_is_configured_with_preset_user_on_polkit @@ -0,0 +1,24 @@ +> ./pam_authd login socket=${AUTHD_TEST_TAPE_SOCKET} force_native_client=true +auth=incomplete +PAM Authenticate() + User: "user-integration-no-broker-polkit-testnativeauthenticate" + Result: error: PAM exit code: 25 + The return value should be ignored by PAM dispatch +PAM AcctMgmt() + User: "user-integration-no-broker-polkit-testnativeauthenticate" + Result: error: PAM exit code: 26 + Critical error - immediate abort +> +──────────────────────────────────────────────────────────────────────────────── +> ./pam_authd login socket=${AUTHD_TEST_TAPE_SOCKET} force_native_client=true +auth=incomplete +PAM Authenticate() + User: "user-integration-no-broker-polkit-testnativeauthenticate" + Result: error: PAM exit code: 25 + The return value should be ignored by PAM dispatch +PAM AcctMgmt() + User: "user-integration-no-broker-polkit-testnativeauthenticate" + Result: error: PAM exit code: 26 + Critical error - immediate abort +> +──────────────────────────────────────────────────────────────────────────────── diff --git a/pam/integration-tests/testdata/golden/TestSSHAuthenticate/Authenticate_user_successfully_launching_command b/pam/integration-tests/testdata/golden/TestSSHAuthenticate/Authenticate_user_successfully_launching_command new file mode 100644 index 0000000000..00c489b7a2 --- /dev/null +++ b/pam/integration-tests/testdata/golden/TestSSHAuthenticate/Authenticate_user_successfully_launching_command @@ -0,0 +1,49 @@ +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +== Provider selection == + 1. local + 2. ExampleBroker +(user-integration-pre-check-ssh-authenticate-user-successfully-launching-command@localhost) Choose your provider: +> +──────────────────────────────────────────────────────────────────────────────── +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +== Provider selection == + 1. local + 2. ExampleBroker +(user-integration-pre-check-ssh-authenticate-user-successfully-launching-command@localhost) Choose your provider: +> 2 +──────────────────────────────────────────────────────────────────────────────── +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +== Provider selection == + 1. local + 2. ExampleBroker +(user-integration-pre-check-ssh-authenticate-user-successfully-launching-command@localhost) Choose your provider: +> 2 +== Password authentication == +Enter 'r' to cancel the request and go back to select the authentication method +(user-integration-pre-check-ssh-authenticate-user-successfully-launching-command@localhost) Gimme your password: +> +──────────────────────────────────────────────────────────────────────────────── +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +== Provider selection == + 1. local + 2. ExampleBroker +(user-integration-pre-check-ssh-authenticate-user-successfully-launching-command@localhost) Choose your provider: +> 2 +== Password authentication == +Enter 'r' to cancel the request and go back to select the authentication method +(user-integration-pre-check-ssh-authenticate-user-successfully-launching-command@localhost) Gimme your password: +> +PAM Authenticate() finished for user 'user-integration-pre-check-ssh-authenticate-user-successfully-launching-command' +PAM AcctMgmt() finished for user 'user-integration-pre-check-ssh-authenticate-user-successfully-launching-command' +Environment: + USER=user-integration-pre-check-ssh-authenticate-user-successfully-launching-command + LOGNAME=user-integration-pre-check-ssh-authenticate-user-successfully-launching-command + HOME=${AUTHD_TEST_HOME} + PATH=${AUTHD_TEST_PATH} + SHELL=/bin/sh + SSH_CLIENT=${AUTHD_TEST_SSH_CLIENT} + SSH_CONNECTION=${AUTHD_TEST_SSH_CONNECTION} + SSH_ORIGINAL_COMMAND=true + SSHD: Connected to ssh via authd module! [TestSSHAuthenticate/Authenticate_user_successfully_launching_command] +> +──────────────────────────────────────────────────────────────────────────────── diff --git a/pam/integration-tests/testdata/golden/TestSSHAuthenticate/Authenticate_user_successfully_launching_command_on_shared_SSHd b/pam/integration-tests/testdata/golden/TestSSHAuthenticate/Authenticate_user_successfully_launching_command_on_shared_SSHd new file mode 100644 index 0000000000..8b4fbe3471 --- /dev/null +++ b/pam/integration-tests/testdata/golden/TestSSHAuthenticate/Authenticate_user_successfully_launching_command_on_shared_SSHd @@ -0,0 +1,49 @@ +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +== Provider selection == + 1. local + 2. ExampleBroker +(user-integration-pre-check-ssh-authenticate-user-successfully-launching-command-on-shared-sshd@localhost) Choose your provider: +> +──────────────────────────────────────────────────────────────────────────────── +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +== Provider selection == + 1. local + 2. ExampleBroker +(user-integration-pre-check-ssh-authenticate-user-successfully-launching-command-on-shared-sshd@localhost) Choose your provider: +> 2 +──────────────────────────────────────────────────────────────────────────────── +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +== Provider selection == + 1. local + 2. ExampleBroker +(user-integration-pre-check-ssh-authenticate-user-successfully-launching-command-on-shared-sshd@localhost) Choose your provider: +> 2 +== Password authentication == +Enter 'r' to cancel the request and go back to select the authentication method +(user-integration-pre-check-ssh-authenticate-user-successfully-launching-command-on-shared-sshd@localhost) Gimme your password: +> +──────────────────────────────────────────────────────────────────────────────── +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +== Provider selection == + 1. local + 2. ExampleBroker +(user-integration-pre-check-ssh-authenticate-user-successfully-launching-command-on-shared-sshd@localhost) Choose your provider: +> 2 +== Password authentication == +Enter 'r' to cancel the request and go back to select the authentication method +(user-integration-pre-check-ssh-authenticate-user-successfully-launching-command-on-shared-sshd@localhost) Gimme your password: +> +PAM Authenticate() finished for user 'user-integration-pre-check-ssh-authenticate-user-successfully-launching-command-on-shared-sshd' +PAM AcctMgmt() finished for user 'user-integration-pre-check-ssh-authenticate-user-successfully-launching-command-on-shared-sshd' + SSHD: Connected to ssh via authd module! [TestSSHAuthenticate] + HOME=${AUTHD_TEST_HOME} + LOGNAME=user-integration-pre-check-ssh-authenticate-user-successfully-launching-command-on-shared-sshd + PATH=${AUTHD_TEST_PATH} + PWD=${AUTHD_TEST_PWD} + SHELL=/bin/sh + SSH_CLIENT=${AUTHD_TEST_SSH_CLIENT} + SSH_CONNECTION=${AUTHD_TEST_SSH_CONNECTION} + SSH_ORIGINAL_COMMAND=true + USER=user-integration-pre-check-ssh-authenticate-user-successfully-launching-command-on-shared-sshd +> +──────────────────────────────────────────────────────────────────────────────── diff --git a/pam/integration-tests/testdata/golden/TestSSHAuthenticate/Exit_authd_if_local_broker_is_selected b/pam/integration-tests/testdata/golden/TestSSHAuthenticate/Exit_authd_if_local_broker_is_selected index 618b752137..61de9e315f 100644 --- a/pam/integration-tests/testdata/golden/TestSSHAuthenticate/Exit_authd_if_local_broker_is_selected +++ b/pam/integration-tests/testdata/golden/TestSSHAuthenticate/Exit_authd_if_local_broker_is_selected @@ -22,3 +22,73 @@ PAM Authenticate() finished for user 'user-integration-pre-check-ssh-exit-authd- SSH PAM user 'user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected' using local broker (user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected@localhost) Password: ──────────────────────────────────────────────────────────────────────────────── +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +== Provider selection == + 1. local + 2. ExampleBroker +(user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected@localhost) Choose your provider: +> 1 +PAM Authenticate() finished for user 'user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected' +SSH PAM user 'user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected' using local broker +(user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected@localhost) Password: +Received disconnect from ${SSH_HOST} port ${SSH_PORT} Too many authentication failures +Disconnected from ${SSH_HOST} port ${SSH_PORT} +> +──────────────────────────────────────────────────────────────────────────────── +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +== Provider selection == + 1. local + 2. ExampleBroker +(user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected@localhost) Choose your provider: +> 1 +PAM Authenticate() finished for user 'user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected' +SSH PAM user 'user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected' using local broker +(user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected@localhost) Password: +Received disconnect from ${SSH_HOST} port ${SSH_PORT} Too many authentication failures +Disconnected from ${SSH_HOST} port ${SSH_PORT} +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +== Provider selection == + 1. local + 2. ExampleBroker +(user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected@localhost) Choose your provider: +> +──────────────────────────────────────────────────────────────────────────────── +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +== Provider selection == + 1. local + 2. ExampleBroker +(user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected@localhost) Choose your provider: +> 1 +PAM Authenticate() finished for user 'user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected' +SSH PAM user 'user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected' using local broker +(user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected@localhost) Password: +Received disconnect from ${SSH_HOST} port ${SSH_PORT} Too many authentication failures +Disconnected from ${SSH_HOST} port ${SSH_PORT} +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +== Provider selection == + 1. local + 2. ExampleBroker +(user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected@localhost) Choose your provider: +> 1 +──────────────────────────────────────────────────────────────────────────────── +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +== Provider selection == + 1. local + 2. ExampleBroker +(user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected@localhost) Choose your provider: +> 1 +PAM Authenticate() finished for user 'user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected' +SSH PAM user 'user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected' using local broker +(user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected@localhost) Password: +Received disconnect from ${SSH_HOST} port ${SSH_PORT} Too many authentication failures +Disconnected from ${SSH_HOST} port ${SSH_PORT} +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +== Provider selection == + 1. local + 2. ExampleBroker +(user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected@localhost) Choose your provider: +> 1 +PAM Authenticate() finished for user 'user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected' +SSH PAM user 'user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected' using local broker +(user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected@localhost) Password: +──────────────────────────────────────────────────────────────────────────────── diff --git a/pam/integration-tests/testdata/golden/TestSSHAuthenticate/Exit_authd_if_local_broker_is_selected_on_shared_SSHd b/pam/integration-tests/testdata/golden/TestSSHAuthenticate/Exit_authd_if_local_broker_is_selected_on_shared_SSHd index 840f377594..6c8a5f1eff 100644 --- a/pam/integration-tests/testdata/golden/TestSSHAuthenticate/Exit_authd_if_local_broker_is_selected_on_shared_SSHd +++ b/pam/integration-tests/testdata/golden/TestSSHAuthenticate/Exit_authd_if_local_broker_is_selected_on_shared_SSHd @@ -22,3 +22,73 @@ PAM Authenticate() finished for user 'user-integration-pre-check-ssh-exit-authd- SSH PAM user 'user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected-on-shared-sshd' using local broker (user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected-on-shared-sshd@localhost) Password: ──────────────────────────────────────────────────────────────────────────────── +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +== Provider selection == + 1. local + 2. ExampleBroker +(user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected-on-shared-sshd@localhost) Choose your provider: +> 1 +PAM Authenticate() finished for user 'user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected-on-shared-sshd' +SSH PAM user 'user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected-on-shared-sshd' using local broker +(user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected-on-shared-sshd@localhost) Password: +Received disconnect from ${SSH_HOST} port ${SSH_PORT} Too many authentication failures +Disconnected from ${SSH_HOST} port ${SSH_PORT} +> +──────────────────────────────────────────────────────────────────────────────── +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +== Provider selection == + 1. local + 2. ExampleBroker +(user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected-on-shared-sshd@localhost) Choose your provider: +> 1 +PAM Authenticate() finished for user 'user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected-on-shared-sshd' +SSH PAM user 'user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected-on-shared-sshd' using local broker +(user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected-on-shared-sshd@localhost) Password: +Received disconnect from ${SSH_HOST} port ${SSH_PORT} Too many authentication failures +Disconnected from ${SSH_HOST} port ${SSH_PORT} +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +== Provider selection == + 1. local + 2. ExampleBroker +(user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected-on-shared-sshd@localhost) Choose your provider: +> +──────────────────────────────────────────────────────────────────────────────── +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +== Provider selection == + 1. local + 2. ExampleBroker +(user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected-on-shared-sshd@localhost) Choose your provider: +> 1 +PAM Authenticate() finished for user 'user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected-on-shared-sshd' +SSH PAM user 'user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected-on-shared-sshd' using local broker +(user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected-on-shared-sshd@localhost) Password: +Received disconnect from ${SSH_HOST} port ${SSH_PORT} Too many authentication failures +Disconnected from ${SSH_HOST} port ${SSH_PORT} +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +== Provider selection == + 1. local + 2. ExampleBroker +(user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected-on-shared-sshd@localhost) Choose your provider: +> 1 +──────────────────────────────────────────────────────────────────────────────── +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +== Provider selection == + 1. local + 2. ExampleBroker +(user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected-on-shared-sshd@localhost) Choose your provider: +> 1 +PAM Authenticate() finished for user 'user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected-on-shared-sshd' +SSH PAM user 'user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected-on-shared-sshd' using local broker +(user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected-on-shared-sshd@localhost) Password: +Received disconnect from ${SSH_HOST} port ${SSH_PORT} Too many authentication failures +Disconnected from ${SSH_HOST} port ${SSH_PORT} +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +== Provider selection == + 1. local + 2. ExampleBroker +(user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected-on-shared-sshd@localhost) Choose your provider: +> 1 +PAM Authenticate() finished for user 'user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected-on-shared-sshd' +SSH PAM user 'user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected-on-shared-sshd' using local broker +(user-integration-pre-check-ssh-exit-authd-if-local-broker-is-selected-on-shared-sshd@localhost) Password: +──────────────────────────────────────────────────────────────────────────────── diff --git a/pam/integration-tests/testdata/golden/TestSSHAuthenticate/Exit_authd_if_no_broker_is_configured_with_preset_user b/pam/integration-tests/testdata/golden/TestSSHAuthenticate/Exit_authd_if_no_broker_is_configured_with_preset_user new file mode 100644 index 0000000000..2a2f6c3b63 --- /dev/null +++ b/pam/integration-tests/testdata/golden/TestSSHAuthenticate/Exit_authd_if_no_broker_is_configured_with_preset_user @@ -0,0 +1,10 @@ +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +PAM Authenticate() finished for user 'user-integration-pre-check-ssh-exit-authd-if-no-broker-is-configured-with-preset-user' +SSH PAM user 'user-integration-pre-check-ssh-exit-authd-if-no-broker-is-configured-with-preset-user' using local broker +(user-integration-pre-check-ssh-exit-authd-if-no-broker-is-configured-with-preset-user@localhost) Password: +──────────────────────────────────────────────────────────────────────────────── +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +PAM Authenticate() finished for user 'user-integration-pre-check-ssh-exit-authd-if-no-broker-is-configured-with-preset-user' +SSH PAM user 'user-integration-pre-check-ssh-exit-authd-if-no-broker-is-configured-with-preset-user' using local broker +(user-integration-pre-check-ssh-exit-authd-if-no-broker-is-configured-with-preset-user@localhost) Password: +──────────────────────────────────────────────────────────────────────────────── diff --git a/pam/integration-tests/testdata/golden/TestSSHAuthenticate/Exit_authd_if_no_broker_is_configured_with_preset_user_on_shared_SSHd b/pam/integration-tests/testdata/golden/TestSSHAuthenticate/Exit_authd_if_no_broker_is_configured_with_preset_user_on_shared_SSHd new file mode 100644 index 0000000000..a362aba5ea --- /dev/null +++ b/pam/integration-tests/testdata/golden/TestSSHAuthenticate/Exit_authd_if_no_broker_is_configured_with_preset_user_on_shared_SSHd @@ -0,0 +1,10 @@ +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +PAM Authenticate() finished for user 'user-integration-pre-check-ssh-exit-authd-if-no-broker-is-configured-with-preset-user-on-shared-sshd' +SSH PAM user 'user-integration-pre-check-ssh-exit-authd-if-no-broker-is-configured-with-preset-user-on-shared-sshd' using local broker +(user-integration-pre-check-ssh-exit-authd-if-no-broker-is-configured-with-preset-user-on-shared-sshd@localhost) Password: +──────────────────────────────────────────────────────────────────────────────── +> ssh ${AUTHD_PAM_SSH_USER}@localhost ${AUTHD_PAM_SSH_ARGS} +PAM Authenticate() finished for user 'user-integration-pre-check-ssh-exit-authd-if-no-broker-is-configured-with-preset-user-on-shared-sshd' +SSH PAM user 'user-integration-pre-check-ssh-exit-authd-if-no-broker-is-configured-with-preset-user-on-shared-sshd' using local broker +(user-integration-pre-check-ssh-exit-authd-if-no-broker-is-configured-with-preset-user-on-shared-sshd@localhost) Password: +──────────────────────────────────────────────────────────────────────────────── diff --git a/pam/integration-tests/testdata/tapes/cli/local_broker.tape b/pam/integration-tests/testdata/tapes/cli/local_broker.tape index cac391fb2b..f2ec2d0791 100644 --- a/pam/integration-tests/testdata/tapes/cli/local_broker.tape +++ b/pam/integration-tests/testdata/tapes/cli/local_broker.tape @@ -5,7 +5,32 @@ Wait /Username: user name\n/ Show Hide -TypeUsername "user-local-broker" +TypeUsername "user-integration-cli-local-broker" +Show + +Hide +Enter +Wait+Screen /Select your provider/ +Wait+Screen /1. local/ +Show + +Hide +Enter +${AUTHD_TEST_TAPE_COMMAND_AUTH_FINAL_WAIT} +Show + +ClearTerminal + +# Repeat the stage again, to ensure the local broker is not auto-selected + +Hide +TypeInPrompt+Shell "${AUTHD_TEST_TAPE_COMMAND}" +Enter +Wait /Username: user name\n/ +Show + +Hide +TypeUsername "user-integration-cli-local-broker" Show Hide diff --git a/pam/integration-tests/testdata/tapes/cli/local_user.tape b/pam/integration-tests/testdata/tapes/cli/local_user.tape index 2a1e8c813f..d64b458cb8 100644 --- a/pam/integration-tests/testdata/tapes/cli/local_user.tape +++ b/pam/integration-tests/testdata/tapes/cli/local_user.tape @@ -5,7 +5,7 @@ Wait /Username: user name\n/ Show Hide -TypeUsername "root" +TypeUsername "${AUTHD_TEST_TAPE_USERNAME}" Show Hide diff --git a/pam/integration-tests/testdata/tapes/native/local_broker.tape b/pam/integration-tests/testdata/tapes/native/local_broker.tape index e7482f052c..c8b5de62c9 100644 --- a/pam/integration-tests/testdata/tapes/native/local_broker.tape +++ b/pam/integration-tests/testdata/tapes/native/local_broker.tape @@ -12,3 +12,22 @@ Hide Enter ${AUTHD_TEST_TAPE_COMMAND_AUTH_FINAL_WAIT} Show + +ClearTerminal + +# Repeat the stage again, to ensure the local broker is not auto-selected + +Hide +TypeInPrompt+Shell "${AUTHD_TEST_TAPE_COMMAND}" +Enter +Wait+Prompt /Choose your provider/ +Show + +Hide +TypeInPrompt "1" +Show + +Hide +Enter +${AUTHD_TEST_TAPE_COMMAND_AUTH_FINAL_WAIT} +Show diff --git a/pam/integration-tests/testdata/tapes/native/local_user.tape b/pam/integration-tests/testdata/tapes/native/local_user.tape index 9c38c96e0b..afa8324f1e 100644 --- a/pam/integration-tests/testdata/tapes/native/local_user.tape +++ b/pam/integration-tests/testdata/tapes/native/local_user.tape @@ -5,7 +5,7 @@ Wait /Username:\n/ Show Hide -TypeUsername "root" +TypeUsername "${AUTHD_TEST_TAPE_USERNAME}" Enter ${AUTHD_TEST_TAPE_COMMAND_AUTH_FINAL_WAIT} Show diff --git a/pam/integration-tests/vhs-helpers_test.go b/pam/integration-tests/vhs-helpers_test.go index ce3771ce95..c4289cf5c5 100644 --- a/pam/integration-tests/vhs-helpers_test.go +++ b/pam/integration-tests/vhs-helpers_test.go @@ -266,6 +266,15 @@ func (td tapeData) RunVhs(t *testing.T, testType vhsTestType, outDir string, cli cmd.Env = append(cmd.Env, fmt.Sprintf("GORACE=log_path=%s exitcode=0", raceLog)) } + if testutils.IsAsan() { + if asanOptions := os.Getenv("ASAN_OPTIONS"); asanOptions != "" { + cmd.Env = append(cmd.Env, fmt.Sprintf("ASAN_OPTIONS=%s", asanOptions)) + } + if lsanOptions := os.Getenv("LSAN_OPTIONS"); lsanOptions != "" { + cmd.Env = append(cmd.Env, fmt.Sprintf("LSAN_OPTIONS=%s", lsanOptions)) + } + } + cmd.Args = append(cmd.Args, td.PrepareTape(t, testType, outDir)) out, err := cmd.CombinedOutput() if raceLog != "" { diff --git a/pam/internal/adapter/authentication.go b/pam/internal/adapter/authentication.go index ef1bf2baa6..8a7728401e 100644 --- a/pam/internal/adapter/authentication.go +++ b/pam/internal/adapter/authentication.go @@ -204,16 +204,16 @@ func (m authenticationModel) Update(msg tea.Msg) (authModel authenticationModel, return m, sendEvent(startAuthentication{}) case startAuthentication: - safeMessageDebug(msg, "current model %v, focused %v", - m.currentModel, m.Focused()) + safeMessageDebug(msg, "current model:", m.currentModel, + "focused:", m.Focused()) if !m.Focused() { return m, nil } m.inProgress = true case stopAuthentication: - safeMessageDebug(msg, "current model %v, focused %v", - m.currentModel, m.Focused()) + safeMessageDebug(msg, "current model:", m.currentModel, + "focused:", m.Focused()) m.inProgress = false case reselectAuthMode: diff --git a/pam/internal/adapter/model.go b/pam/internal/adapter/model.go index d8f7f6998b..8436a5daf4 100644 --- a/pam/internal/adapter/model.go +++ b/pam/internal/adapter/model.go @@ -271,7 +271,7 @@ func (m uiModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { // Events case BrokerListReceived: - safeMessageDebug(msg, "brokers: %#v", m.availableBrokers()) + safeMessageDebug(msg, "brokers:", m.availableBrokers()) if m.availableBrokers() == nil { return m, nil } diff --git a/pam/internal/adapter/reselectbuttonmodel.go b/pam/internal/adapter/reselectbuttonmodel.go index fa3e930de1..16e9275d10 100644 --- a/pam/internal/adapter/reselectbuttonmodel.go +++ b/pam/internal/adapter/reselectbuttonmodel.go @@ -25,7 +25,7 @@ func (b authReselectButtonModel) Init() tea.Cmd { func (b authReselectButtonModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case buttonSelectionEvent: - safeMessageDebug(msg, "button: %#v", b) + safeMessageDebug(msg, "button:", b) if msg.model == b.buttonModel { return b, sendEvent(reselectAuthMode{}) } diff --git a/pam/internal/adapter/utils.go b/pam/internal/adapter/utils.go index fe86ec549f..c7f8a2d3c2 100644 --- a/pam/internal/adapter/utils.go +++ b/pam/internal/adapter/utils.go @@ -2,6 +2,7 @@ package adapter import ( "context" + "encoding/json" "errors" "fmt" "math" @@ -16,6 +17,7 @@ import ( "github.com/ubuntu/authd/log" "github.com/ubuntu/authd/pam/internal/proto" pam_proto "github.com/ubuntu/authd/pam/internal/proto" + protbuf_proto "google.golang.org/protobuf/proto" ) var ( @@ -142,6 +144,8 @@ func maybeSendPamError(err error) tea.Cmd { var debugMessageFormatter = defaultSafeMessageFormatter func defaultSafeMessageFormatter(msg tea.Msg) string { + type jsonMarshal struct{ tea.Msg } + switch msg := msg.(type) { case newPasswordCheck: return fmt.Sprintf("%#v", @@ -164,19 +168,48 @@ func defaultSafeMessageFormatter(msg tea.Msg) string { return fmt.Sprintf("%T{%s}", msg, defaultSafeMessageFormatter(msg.isAuthenticatedRequested)) case UILayoutReceived: - return fmt.Sprintf("%T{%#v}", msg, msg.layout) + return fmt.Sprintf("%T{layouts:%s}", msg, + defaultSafeMessageFormatter(msg.layout)) case ChangeStage: return fmt.Sprintf("%T{Stage:%q}", msg, msg.Stage) case StageChanged: return fmt.Sprintf("%T{Stage:%q}", msg, msg.Stage) case nativeStageChangeRequest: return fmt.Sprintf("%T{Stage:%q}", msg, msg.Stage) + case brokersListReceived: + return fmt.Sprintf("%T{brokers:%s}", msg, + defaultSafeMessageFormatter(msg.brokers)) + case supportedUILayoutsReceived: + return fmt.Sprintf("%T{layouts:%s}", msg, + defaultSafeMessageFormatter(msg.layouts)) + case authModesReceived: + return fmt.Sprintf("%T{authModes:%s}", msg, + defaultSafeMessageFormatter(msg.authModes)) case tea.KeyMsg: if msg.Type != tea.KeyRunes { return fmt.Sprintf("%T{%s}", msg, msg) } + case []*authd.ABResponse_BrokerInfo: + return defaultSafeMessageFormatter(jsonMarshal{msg}) + case []*authd.UILayout: + return defaultSafeMessageFormatter(jsonMarshal{msg}) + case []*authd.GAMResponse_AuthenticationMode: + return defaultSafeMessageFormatter(jsonMarshal{msg}) + case protbuf_proto.Message: + return defaultSafeMessageFormatter(jsonMarshal{msg}) + case []protbuf_proto.Message: + return defaultSafeMessageFormatter(jsonMarshal{msg}) + case jsonMarshal: + b, err := json.Marshal(msg.Msg) + if err != nil { + // Use fallback mode, avoid recursion by wrapping it with an unnamed type. + b = []byte(defaultSafeMessageFormatter(struct{ tea.Msg }{msg.Msg})) + } + return fmt.Sprintf("%T{%s}", msg.Msg, b) case nil: return "" + case string: + return msg default: return fmt.Sprintf("%#v", msg) } @@ -231,7 +264,14 @@ func safeMessageDebugWithPrefix(prefix string, msg tea.Msg, formatAndArgs ...any format, ok := formatAndArgs[0].(string) if !ok || !strings.Contains(format, "%") { - log.Debug(context.Background(), append([]any{m, ", "}, formatAndArgs...)...) + args := []any{m, ", "} + for i, arg := range formatAndArgs { + args = append(args, debugMessageFormatter(arg)) + if i < len(formatAndArgs)-1 { + args = append(args, " ") + } + } + log.Debug(context.Background(), args...) return } diff --git a/pam/internal/adapter/utils_test.go b/pam/internal/adapter/utils_test.go index 2b7cbfcdbd..c24b915c74 100644 --- a/pam/internal/adapter/utils_test.go +++ b/pam/internal/adapter/utils_test.go @@ -105,6 +105,81 @@ func TestDebugMessageFormatter(t *testing.T) { }, wantSafeString: `adapter.isAuthenticatedRequestedSend{adapter.isAuthenticatedRequested{*authd.IARequest_AuthenticationData_Skip{Skip:"skip!"}}}`, }, + "brokerInfo": { + msg: &authd.ABResponse_BrokerInfo{Id: "broker-id", Name: "broker-name", BrandIcon: nil}, + wantSafeString: `*authd.ABResponse_BrokerInfo{{"id":"broker-id","name":"broker-name"}}`, + }, + "brokerInfo_slice": { + msg: []*authd.ABResponse_BrokerInfo{{Id: "broker-id", Name: "broker-name", BrandIcon: nil}}, + wantSafeString: `[]*authd.ABResponse_BrokerInfo{[{"id":"broker-id","name":"broker-name"}]}`, + }, + "brokersListReceived_empty": { + msg: brokersListReceived{}, + wantSafeString: `adapter.brokersListReceived{brokers:[]*authd.ABResponse_BrokerInfo{null}}`, + }, + "brokersListReceived_with_brokers": { + msg: brokersListReceived{[]*authd.ABResponse_BrokerInfo{{ + Id: "broker-id", Name: "broker-name", BrandIcon: nil, + }}}, + wantSafeString: `adapter.brokersListReceived{brokers:[]*authd.ABResponse_BrokerInfo{[{"id":"broker-id","name":"broker-name"}]}}`, + }, + "UILayout": { + msg: &authd.UILayout{ + Type: "Type", + Label: ptrValue("Label"), + Content: ptrValue("Content"), + Wait: ptrValue("Wait"), + Button: ptrValue("Button"), + Code: ptrValue("Code"), + Entry: ptrValue("Entry"), + }, + wantSafeString: `*authd.UILayout{{"type":"Type","label":"Label","button":"Button","wait":"Wait","entry":"Entry","content":"Content","code":"Code"}}`, + }, + "UILayout_slice": { + msg: []*authd.UILayout{{ + Type: "Type", + Label: ptrValue("Label"), + Content: ptrValue("Content"), + Wait: ptrValue("Wait"), + Button: ptrValue("Button"), + Code: ptrValue("Code"), + Entry: ptrValue("Entry"), + }}, + wantSafeString: `[]*authd.UILayout{[{"type":"Type","label":"Label","button":"Button","wait":"Wait","entry":"Entry","content":"Content","code":"Code"}]}`, + }, + "UILayoutReceived": { + msg: UILayoutReceived{&authd.UILayout{Type: "Foo"}}, + wantSafeString: `adapter.UILayoutReceived{layouts:*authd.UILayout{{"type":"Foo"}}}`, + }, + "supportedUILayoutsReceived": { + msg: supportedUILayoutsReceived{[]*authd.UILayout{{ + Type: "Type", + Label: ptrValue("Label"), + Content: ptrValue("Content"), + Wait: ptrValue("Wait"), + Button: ptrValue("Button"), + Code: ptrValue("Code"), + Entry: ptrValue("Entry"), + }, {Type: "Other"}}}, + wantSafeString: `adapter.supportedUILayoutsReceived{layouts:[]*authd.UILayout{[{"type":"Type","label":"Label","button":"Button","wait":"Wait","entry":"Entry","content":"Content","code":"Code"},{"type":"Other"}]}}`, + }, + "GAMResponse_AuthenticationMode": { + msg: &authd.GAMResponse_AuthenticationMode{Id: "id", Label: "Label"}, + wantSafeString: `*authd.GAMResponse_AuthenticationMode{{"id":"id","label":"Label"}}`, + }, + "GAMResponse_AuthenticationMode_slice": { + msg: []*authd.GAMResponse_AuthenticationMode{{Id: "id", Label: "Label"}}, + wantSafeString: `[]*authd.GAMResponse_AuthenticationMode{[{"id":"id","label":"Label"}]}`, + }, + "authModesReceived": { + msg: authModesReceived{ + authModes: []*authd.GAMResponse_AuthenticationMode{ + {Id: "id1", Label: "Label1"}, + {Id: "id2", Label: "Label2"}, + }, + }, + wantSafeString: `adapter.authModesReceived{authModes:[]*authd.GAMResponse_AuthenticationMode{[{"id":"id1","label":"Label1"},{"id":"id2","label":"Label2"}]}}`, + }, } for name, tc := range tests { @@ -164,6 +239,22 @@ func TestSafeMessageDebug(t *testing.T) { formatAndArgs: []any{true, false}, wantSafeString: "prefix: adapter.startAuthentication{}, true false", }, + "startAuthentication_message_with_prefix_and_multiple_formatted_values_suffix": { + msg: startAuthentication{}, + prefix: "prefix", + formatAndArgs: []any{ + newPasswordCheck{password: "password!"}, + UILayoutReceived{&authd.UILayout{Type: "Foo"}}, + authModesReceived{ + authModes: []*authd.GAMResponse_AuthenticationMode{ + {Id: "id1", Label: "Label1"}, + {Id: "id2", Label: "Label2"}, + }, + }, + }, + wantDebugString: `prefix: adapter.startAuthentication{}, adapter.newPasswordCheck{ctx:context.Context(nil), password:"password!"} adapter.UILayoutReceived{layouts:*authd.UILayout{{"type":"Foo"}}} adapter.authModesReceived{authModes:[]*authd.GAMResponse_AuthenticationMode{[{"id":"id1","label":"Label1"},{"id":"id2","label":"Label2"}]}}`, + wantSafeString: `prefix: adapter.startAuthentication{}, adapter.newPasswordCheck{ctx:context.Context(nil), password:"***********"} adapter.UILayoutReceived{layouts:*authd.UILayout{{"type":"Foo"}}} adapter.authModesReceived{authModes:[]*authd.GAMResponse_AuthenticationMode{[{"id":"id1","label":"Label1"},{"id":"id2","label":"Label2"}]}}`, + }, "startAuthentication_message_with_prefix_and_single_string_suffix": { msg: startAuthentication{}, prefix: "prefix", @@ -254,11 +345,12 @@ func TestSafeMessageDebug(t *testing.T) { handlerCalled := false wantCtx := context.Background() log.SetLevelHandler(log.DebugLevel, func(ctx context.Context, l log.Level, format string, args ...interface{}) { - t.Logf(format, args...) + t.Logf("Format: %q", format) + t.Log(append([]any{"Args:"}, args...)...) handlerCalled = true require.Equal(t, wantCtx, ctx, "Context should match expected") require.Equal(t, tc.wantSafeString, fmt.Sprintf(format, args...), - "Format should match") + "Format for safe usage should match") }) initialLogLevel := log.GetLevel() @@ -288,11 +380,11 @@ func TestSafeMessageDebug(t *testing.T) { log.SetLevelHandler(log.DebugLevel, func(ctx context.Context, l log.Level, format string, args ...interface{}) { t.Logf(format, args...) handlerCalled = true - t.Logf("Called with %q", format) - t.Logf("Atgs are %#v", args) + t.Logf("Format: %q", format) + t.Log(append([]any{"Args:"}, args...)...) require.Equal(t, wantCtx, ctx, "Context should match expected") require.Equal(t, tc.wantDebugString, fmt.Sprintf(format, args...), - "Format should match") + "Format for debug usage should match") }) initialLogLevel := log.GetLevel() @@ -313,3 +405,7 @@ func TestSafeMessageDebug(t *testing.T) { }) } } + +func ptrValue[T any](value T) *T { + return &value +}