Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion pam/integration-tests/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ func TestCLIAuthenticate(t *testing.T) {
socketPath string
currentUserNotRoot bool
wantLocalGroups bool
skipRunnerCheck bool
oldDB string
stopDaemonAfter time.Duration
}{
Expand Down Expand Up @@ -228,6 +229,14 @@ func TestCLIAuthenticate(t *testing.T) {
tape: "authd_stopped",
stopDaemonAfter: sleepDuration(defaultSleepValues[authdSleepLong] * 5),
},
"Exit_the_pam_client_if_parent_pam_application_is_stopped": {
tape: "pam_app_killed",
tapeVariables: map[string]string{
"AUTHD_TEST_TAPE_AUTHD_PAM_BINARY_NAME": authdPamBinaryName,
vhsCommandFinalAuthWaitVariable: "",
},
skipRunnerCheck: true,
},

"Error_if_cannot_connect_to_authd": {
tape: "connection_error",
Expand Down Expand Up @@ -284,7 +293,9 @@ func TestCLIAuthenticate(t *testing.T) {

localgroupstestutils.RequireGroupFile(t, groupFileOutput, golden.Path(t))

requireRunnerResultForUser(t, authd.SessionMode_LOGIN, tc.clientOptions.PamUser, got)
if !tc.skipRunnerCheck {
requireRunnerResultForUser(t, authd.SessionMode_LOGIN, tc.clientOptions.PamUser, got)
}
})
}
}
Expand Down
32 changes: 20 additions & 12 deletions pam/integration-tests/cmd/exec-client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@ import (
)

var (
pamFlags = flag.Int64("flags", 0, "pam flags")
serverAddress = flag.String("server-address", "", "the dbus connection address to use to communicate with module")
logFile = flag.String("client-log", "", "the file where to save logs")
argsFile = flag.String("client-args-file", "", "the file where arguments are saved")
pamFlags = flag.Int64("flags", 0, "pam flags")
logFile = flag.String("client-log", "", "the file where to save logs")
argsFile = flag.String("client-args-file", "", "the file where arguments are saved")
)

func main() {
Expand All @@ -52,20 +51,29 @@ func mainFunc() error {
return fmt.Errorf("%w: not enough arguments", pam_test.ErrInvalid)
}

serverAddressEnv := os.Getenv("AUTHD_PAM_SERVER_ADDRESS")
if serverAddressEnv != "" {
*serverAddress = serverAddressEnv
}

if serverAddress == nil {
serverAddress := os.Getenv("AUTHD_PAM_SERVER_ADDRESS")
if serverAddress == "" {
return fmt.Errorf("%w: no connection provided", pam_test.ErrInvalid)
}

mTx, closeFunc, err := newModuleWrapper(*serverAddress)
mTx, closeFunc, err := newModuleWrapper(serverAddress)
if err != nil {
return fmt.Errorf("%w: can't connect to server: %w", pam_test.ErrInvalid, err)
}
defer closeFunc()

clientReturned := make(chan struct{})
defer func() {
close(clientReturned)
closeFunc()
}()

go func() {
select {
case <-clientReturned:
case <-mTx.Context().Done():
panic(fmt.Sprintf("D-Bus Connection lost: %v", mTx.Context().Err()))
}
}()

action, args := args[0], args[1:]

Expand Down
20 changes: 11 additions & 9 deletions pam/integration-tests/cmd/exec-client/modulewrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,33 +18,35 @@ import (
)

type moduleWrapper struct {
pam.ModuleTransaction
dbusmodule.Transaction
}

func newModuleWrapper(serverAddress string) (pam.ModuleTransaction, func(), error) {
// Statically Ensure that [moduleWrapper] implements [pam.ModuleTransaction].
var _ pam.ModuleTransaction = &moduleWrapper{}

func newModuleWrapper(serverAddress string) (moduleWrapper, func(), error) {
mTx, closeFunc, err := dbusmodule.NewTransaction(context.TODO(), serverAddress)
return &moduleWrapper{mTx}, closeFunc, err
return moduleWrapper{mTx}, closeFunc, err
}

// SimulateClientPanic forces the client to panic with the provided text.
func (m *moduleWrapper) CallUnhandledMethod() error {
func (m moduleWrapper) CallUnhandledMethod() error {
method := "com.ubuntu.authd.pam.UnhandledMethod"
tx, _ := m.ModuleTransaction.(*dbusmodule.Transaction)
return tx.BusObject().Call(method, dbus.FlagNoAutoStart).Err
return m.BusObject().Call(method, dbus.FlagNoAutoStart).Err
}

// SimulateClientPanic forces the client to panic with the provided text.
func (m *moduleWrapper) SimulateClientPanic(text string) {
func (m moduleWrapper) SimulateClientPanic(text string) {
panic(text)
}

// SimulateClientError forces the client to return a new Go error with no PAM type.
func (m *moduleWrapper) SimulateClientError(errorMsg string) error {
func (m moduleWrapper) SimulateClientError(errorMsg string) error {
return errors.New(errorMsg)
}

// SimulateClientSignal sends a signal to the child process.
func (m *moduleWrapper) SimulateClientSignal(sig syscall.Signal, shouldExit bool) {
func (m moduleWrapper) SimulateClientSignal(sig syscall.Signal, shouldExit bool) {
pid := os.Getpid()
log.Debugf(context.Background(), "Sending signal %v to self pid (%v)",
sig, pid)
Expand Down
4 changes: 3 additions & 1 deletion pam/integration-tests/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import (
"gorbe.io/go/osrelease"
)

const authdPamBinaryName = "authd-pam"

var (
authdTestSessionTime = time.Now()
authdArtifactsDir string
Expand Down Expand Up @@ -220,7 +222,7 @@ func buildPAMExecChild(t *testing.T) string {
cmd.Args = append(cmd.Args, "-tags=pam_debug")
cmd.Env = append(os.Environ(), `CGO_CFLAGS=-O0 -g3`)

authdPam := filepath.Join(t.TempDir(), "authd-pam")
authdPam := filepath.Join(t.TempDir(), authdPamBinaryName)
t.Logf("Compiling Exec child at %s", authdPam)
t.Log(strings.Join(cmd.Args, " "))

Expand Down
9 changes: 9 additions & 0 deletions pam/integration-tests/native_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,15 @@ func TestNativeAuthenticate(t *testing.T) {
tape: "authd_stopped",
wantSeparateDaemon: true,
},
"Exit_the_pam_client_if_parent_pam_application_is_stopped": {
tape: "pam_app_killed",
tapeVariables: map[string]string{
"AUTHD_TEST_TAPE_AUTHD_PAM_BINARY_NAME": authdPamBinaryName,
vhsCommandFinalAuthWaitVariable: "",
},
userSelection: true,
skipRunnerCheck: true,
},

"Error_if_cannot_connect_to_authd": {
tape: "connection_error",
Expand Down
2 changes: 1 addition & 1 deletion pam/integration-tests/ssh_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ func createSshdServiceFile(t *testing.T, module, execChild, mkHomeModule, socket
"socket=" + socketPath,
fmt.Sprintf("connection_timeout=%d", defaultConnectionTimeout),
"debug=true",
"logfile=" + os.Stderr.Name(),
"logfile=/dev/stderr",
"--exec-debug",
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
>
────────────────────────────────────────────────────────────────────────────────
>
────────────────────────────────────────────────────────────────────────────────
>
────────────────────────────────────────────────────────────────────────────────
./pam_authd login socket=${AUTHD_TEST_TAPE_SOCKET}
Terminateduser name
>
────────────────────────────────────────────────────────────────────────────────
>
────────────────────────────────────────────────────────────────────────────────
Parent Process killed
>
────────────────────────────────────────────────────────────────────────────────
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
>
────────────────────────────────────────────────────────────────────────────────
>
────────────────────────────────────────────────────────────────────────────────
>
────────────────────────────────────────────────────────────────────────────────
./pam_authd login socket=${AUTHD_TEST_TAPE_SOCKET} force_native_client=true
Terminated
>
────────────────────────────────────────────────────────────────────────────────
>
────────────────────────────────────────────────────────────────────────────────
Parent Process killed
>
────────────────────────────────────────────────────────────────────────────────
34 changes: 34 additions & 0 deletions pam/integration-tests/testdata/tapes/cli/pam_app_killed.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
Hide
TypeInPrompt+Shell "${AUTHD_TEST_TAPE_COMMAND} &"
Enter
Wait

Type "clear"
Enter
Wait

# Find out the PID of the authd PAM binary process, so that we can kill it later.
Type `while true; do sleep 0.2 && child_pid=$(pgrep -f "${AUTHD_TEST_TAPE_AUTHD_PAM_BINARY_NAME} .* socket=${AUTHD_TEST_TAPE_SOCKET}"); [ -n "${child_pid}" ] && break; done`
Enter
Wait

Type "clear"
Enter
Wait

# Get back to the PAM application to foreground, while killing it in the background.
Type `"$0" -c 'sleep 5 && pkill -f "${AUTHD_TEST_TAPE_COMMAND}" &' && clear && fg`
Enter
Wait /Username: user name\n/
Wait
Show

ClearTerminal

Hide
# Ensure that the child PID has been killed when destroying the parent application.
Type `if kill -0 "${child_pid}" &>/dev/null; then clear && echo "Parent process still alive"; else clear && echo Parent Process killed; fi`
Enter
Wait /Parent Process killed\n/
Wait ${AUTHD_TEST_TAPE_COMMAND_AUTH_FINAL_WAIT}
Show
33 changes: 33 additions & 0 deletions pam/integration-tests/testdata/tapes/native/pam_app_killed.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
Hide
TypeInPrompt+Shell "${AUTHD_TEST_TAPE_COMMAND} &"
Enter
Wait

Type "clear"
Enter
Wait

# Find out the PID of the authd PAM binary process, so that we can kill it later.
Type `while true; do sleep 0.2 && child_pid=$(pgrep -f "${AUTHD_TEST_TAPE_AUTHD_PAM_BINARY_NAME} .* socket=${AUTHD_TEST_TAPE_SOCKET}"); [ -n "${child_pid}" ] && break; done`
Enter
Wait

Type "clear"
Enter
Wait

# Get back to the PAM application to foreground, while killing it in the background.
Type `"$0" -c 'sleep 5 && pkill -f "${AUTHD_TEST_TAPE_COMMAND}" &' && clear && fg`
Enter
Wait
Show

ClearTerminal

Hide
# Ensure that the child PID has been killed when destroying the parent application.
Type `if kill -0 "${child_pid}" &>/dev/null; then clear && echo "Parent process still alive"; else clear && echo Parent Process killed; fi`
Enter
Wait /Parent Process killed\n/
Wait ${AUTHD_TEST_TAPE_COMMAND_AUTH_FINAL_WAIT}
Show
Loading
Loading