VYPR
High severityNVD Advisory· Published Oct 3, 2024· Updated Nov 22, 2024

CVE-2024-9313

CVE-2024-9313

Description

Authd PAM module before version 0.3.5 can allow broker-managed users to impersonate any other user managed by the same broker and perform any PAM operation with it, including authenticating as them.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/ubuntu/authdGo
< 0.0.0-20240930103526-63e527496b010.0.0-20240930103526-63e527496b01
github.com/ubuntu/authdGo
>= 0.1.0, < 0.3.50.3.5

Affected products

1

Patches

1
63e527496b01

fix(pam): Do not allow changing user name if provided by PAM (#3)

https://github.com/ubuntu/authdMarco TrevisanSep 30, 2024via ghsa
20 files changed · +1157 171
  • pam/integration-tests/cli_test.go+2 0 modified
    @@ -61,6 +61,8 @@ func TestCLIAuthenticate(t *testing.T) {
     		"Autoselect local broker for local user":        {tape: "local_user"},
     		"Autoselect local broker for local user preset": {tape: "local_user_preset"},
     
    +		"Prevent user from switching username": {tape: "switch_preset_username", pamUser: "user-integration-pam-preset"},
    +
     		"Deny authentication if current user is not considered as root": {tape: "not_root", currentUserNotRoot: true},
     
     		"Deny authentication if max attempts reached":                         {tape: "max_attempts"},
    
  • pam/integration-tests/native_test.go+3 1 modified
    @@ -44,7 +44,7 @@ func TestNativeAuthenticate(t *testing.T) {
     		"Authenticate user with qr code in a TTY":                              {tape: "qr_code", pamUser: "user-integration-qr-code-tty", termEnv: "linux"},
     		"Authenticate user with qr code in a TTY session":                      {tape: "qr_code", pamUser: "user-integration-qr-code-tty-session", termEnv: "xterm-256color", sessionEnv: "tty"},
     		"Authenticate user with qr code in screen":                             {tape: "qr_code", pamUser: "user-integration-qr-code-screen", termEnv: "screen"},
    -		"Authenticate user with qr code in polkit":                             {tape: "qr_code", pamUser: "user-integration-qr-code-screen", pamServiceName: "polkit-1"},
    +		"Authenticate user with qr code in polkit":                             {tape: "qr_code", pamUser: "user-integration-qr-code-polkit", pamServiceName: "polkit-1"},
     		"Authenticate user with qr code in ssh":                                {tape: "qr_code", pamUser: "user-integration-pre-check-ssh-service-qr-code", pamServiceName: "sshd"},
     		"Authenticate user and reset password while enforcing policy":          {tape: "mandatory_password_reset"},
     		"Authenticate user with mfa and reset password while enforcing policy": {tape: "mfa_reset_pwquality_auth"},
    @@ -70,6 +70,8 @@ func TestNativeAuthenticate(t *testing.T) {
     		"Deny authentication if user does not exist and matches cancel key":   {tape: "cancel_key_user"},
     		"Deny authentication if newpassword does not match required criteria": {tape: "bad_password"},
     
    +		"Prevent preset user from switching username": {tape: "switch_preset_username", pamUser: "user-integration-pam-preset"},
    +
     		"Exit authd if local broker is selected":                                    {tape: "local_broker"},
     		"Exit if user is not pre-checked on ssh service":                            {tape: "local_ssh", pamUser: "user-integration-ssh-service", pamServiceName: "sshd"},
     		"Exit if user is not pre-checked on custom ssh service with connection env": {tape: "local_ssh", pamUser: "user-integration-ssh-connection", pamEnvs: []string{"SSH_CONNECTION=foo-connection"}},
    
  • pam/integration-tests/testdata/tapes/cli/switch_preset_username.tape+58 0 added
    @@ -0,0 +1,58 @@
    +Output switch_preset_username.txt
    +Output switch_preset_username.gif # If we don't specify a .gif output, it will create a default out.gif file.
    +
    +# Configuration header to standardize the output.
    +# Does not work with the "Source" command.
    +Set Width 800
    +Set Height 500
    +# TODO: Ideally, we should use Ubuntu Mono. However, the github runner is still on Jammy, which does not have it.
    +# We should update this to use Ubuntu Mono once the runner is updated.
    +Set FontFamily "Monospace"
    +Set FontSize 13
    +Set Padding 0
    +Set Margin 0
    +Set Shell bash
    +
    +Hide
    +Type "./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK}"
    +Enter
    +Sleep 300ms
    +Show
    +
    +Hide
    +Escape
    +Sleep 300ms
    +Show
    +
    +Hide
    +Type "2"
    +Sleep 300ms
    +Show
    +
    +Hide
    +Escape
    +Sleep 300ms
    +Show
    +
    +Hide
    +Escape
    +Sleep 300ms
    +Show
    +
    +Hide
    +Escape 10
    +Sleep 300ms
    +Show
    +
    +Hide
    +Type "2"
    +Sleep 300ms
    +Show
    +
    +Hide
    +Type "goodpass"
    +Enter
    +Sleep 2s
    +Show
    +
    +Sleep 300ms
    
  • pam/integration-tests/testdata/tapes/native/simple_auth.tape+0 2 modified
    @@ -20,8 +20,6 @@ Sleep 300ms
     Show
     
     Hide
    -Escape
    -Backspace
     Type "user1"
     Sleep 300ms
     Show
    
  • pam/integration-tests/testdata/tapes/native/switch_preset_username.tape+70 0 added
    @@ -0,0 +1,70 @@
    +Output switch_preset_username.txt
    +Output switch_preset_username.gif # If we don't specify a .gif output, it will create a default out.gif file.
    +
    +# Configuration header to standardize the output.
    +# Does not work with the "Source" command.
    +Set Width 800
    +Set Height 700
    +# TODO: Ideally, we should use Ubuntu Mono. However, the github runner is still on Jammy, which does not have it.
    +# We should update this to use Ubuntu Mono once the runner is updated.
    +Set FontFamily "Monospace"
    +Set FontSize 13
    +Set Padding 0
    +Set Margin 0
    +Set Shell bash
    +
    +Hide
    +Type "./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true"
    +Enter
    +Sleep 300ms
    +Show
    +
    +Hide
    +Type "r"
    +Enter
    +Sleep 300ms
    +Show
    +
    +Hide
    +Type "2"
    +Enter
    +Sleep 500ms
    +Show
    +
    +Hide
    +Type "r"
    +Enter
    +Sleep 300ms
    +Show
    +
    +Hide
    +Type "r"
    +Enter
    +Sleep 300ms
    +Show
    +
    +Hide
    +Type "r"
    +Enter
    +Sleep 300ms
    +Show
    +
    +Hide
    +Type "r"
    +Enter
    +Sleep 300ms
    +Show
    +
    +Hide
    +Type "2"
    +Enter
    +Sleep 500ms
    +Show
    +
    +Hide
    +Type "goodpass"
    +Enter
    +Sleep 2s
    +Show
    +
    +Sleep 300ms
    
  • pam/integration-tests/testdata/TestCLIAuthenticate/golden/prevent_user_from_switching_username+297 0 added
    @@ -0,0 +1,297 @@
    +> ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK}
    +  Select your provider
    +
    +> 1. local
    +  2. ExampleBroker
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +────────────────────────────────────────────────────────────────────────────────
    +> ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK}
    +  Select your provider
    +
    +> 1. local
    +  2. ExampleBroker
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +────────────────────────────────────────────────────────────────────────────────
    +> ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK}
    +Gimme your password
    +>
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +────────────────────────────────────────────────────────────────────────────────
    +> ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK}
    +  Select your authentication method
    +
    +> 1. Password authentication
    +  2. Send URL to user-integration-pam-preset@gmail.com
    +  3. Use your fido device foo
    +  4. Use your phone +33…
    +  5. Use your phone +1…
    +  6. Use a QR code
    +  7. Authentication code
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +────────────────────────────────────────────────────────────────────────────────
    +> ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK}
    +  Select your provider
    +
    +  1. local
    +> 2. ExampleBroker
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +────────────────────────────────────────────────────────────────────────────────
    +> ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK}
    +  Select your provider
    +
    +  1. local
    +> 2. ExampleBroker
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +────────────────────────────────────────────────────────────────────────────────
    +> ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK}
    +Gimme your password
    +>
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +────────────────────────────────────────────────────────────────────────────────
    +> ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK}
    +Gimme your password
    +PAM Authenticate() for user "user-integration-pam-preset" exited with success
    +PAM AcctMgmt() exited with success
    +>
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +────────────────────────────────────────────────────────────────────────────────
    +> ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK}
    +Gimme your password
    +PAM Authenticate() for user "user-integration-pam-preset" exited with success
    +PAM AcctMgmt() exited with success
    +>
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +────────────────────────────────────────────────────────────────────────────────
    
  • pam/integration-tests/testdata/TestNativeAuthenticate/golden/authenticate_user_on_ssh_service+4 4 modified
    @@ -1,5 +1,5 @@
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker:
    @@ -32,7 +32,7 @@ Select broker:
     
     ────────────────────────────────────────────────────────────────────────────────
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -65,7 +65,7 @@ Gimme your password:
     
     ────────────────────────────────────────────────────────────────────────────────
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -98,7 +98,7 @@ PAM AcctMgmt() exited with success
     
     ────────────────────────────────────────────────────────────────────────────────
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    
  • pam/integration-tests/testdata/TestNativeAuthenticate/golden/authenticate_user_on_ssh_service_with_custom_name_and_auth_info_env+4 4 modified
    @@ -1,5 +1,5 @@
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker:
    @@ -32,7 +32,7 @@ Select broker:
     
     ────────────────────────────────────────────────────────────────────────────────
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -65,7 +65,7 @@ Gimme your password:
     
     ────────────────────────────────────────────────────────────────────────────────
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -98,7 +98,7 @@ PAM AcctMgmt() exited with success
     
     ────────────────────────────────────────────────────────────────────────────────
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    
  • pam/integration-tests/testdata/TestNativeAuthenticate/golden/authenticate_user_on_ssh_service_with_custom_name_and_connection_env+4 4 modified
    @@ -1,5 +1,5 @@
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker:
    @@ -32,7 +32,7 @@ Select broker:
     
     ────────────────────────────────────────────────────────────────────────────────
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -65,7 +65,7 @@ Gimme your password:
     
     ────────────────────────────────────────────────────────────────────────────────
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -98,7 +98,7 @@ PAM AcctMgmt() exited with success
     
     ────────────────────────────────────────────────────────────────────────────────
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    
  • pam/integration-tests/testdata/TestNativeAuthenticate/golden/authenticate_user_successfully_with_preset_user+4 4 modified
    @@ -1,6 +1,6 @@
     > env AUTHD_PAM_CLI_USER=user3 ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOC
     K} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker:
    @@ -33,7 +33,7 @@ Select broker:
     ────────────────────────────────────────────────────────────────────────────────
     > env AUTHD_PAM_CLI_USER=user3 ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOC
     K} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -66,7 +66,7 @@ Gimme your password:
     ────────────────────────────────────────────────────────────────────────────────
     > env AUTHD_PAM_CLI_USER=user3 ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOC
     K} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -99,7 +99,7 @@ PAM AcctMgmt() exited with success
     ────────────────────────────────────────────────────────────────────────────────
     > env AUTHD_PAM_CLI_USER=user3 ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOC
     K} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    
  • pam/integration-tests/testdata/TestNativeAuthenticate/golden/authenticate_user_with_qr_code+11 11 modified
    @@ -1,5 +1,5 @@
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker:
    @@ -232,7 +232,7 @@ Select broker:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -465,7 +465,7 @@ Gimme your password:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -698,7 +698,7 @@ Select authentication mode:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -931,7 +931,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -1164,7 +1164,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -1397,7 +1397,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -1630,7 +1630,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -1863,7 +1863,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -2096,7 +2096,7 @@ Select action: 1
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -2329,7 +2329,7 @@ PAM AcctMgmt() exited with success
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    
  • pam/integration-tests/testdata/TestNativeAuthenticate/golden/authenticate_user_with_qr_code_in_a_tty+11 11 modified
    @@ -1,5 +1,5 @@
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker:
    @@ -232,7 +232,7 @@ Select broker:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -465,7 +465,7 @@ Gimme your password:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -698,7 +698,7 @@ Select authentication mode:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -931,7 +931,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -1164,7 +1164,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -1397,7 +1397,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -1630,7 +1630,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -1863,7 +1863,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -2096,7 +2096,7 @@ Select action: 1
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -2329,7 +2329,7 @@ PAM AcctMgmt() exited with success
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    
  • pam/integration-tests/testdata/TestNativeAuthenticate/golden/authenticate_user_with_qr_code_in_a_tty_session+11 11 modified
    @@ -1,5 +1,5 @@
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker:
    @@ -232,7 +232,7 @@ Select broker:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -465,7 +465,7 @@ Gimme your password:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -698,7 +698,7 @@ Select authentication mode:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -931,7 +931,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -1164,7 +1164,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -1397,7 +1397,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -1630,7 +1630,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -1863,7 +1863,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -2096,7 +2096,7 @@ Select action: 1
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -2329,7 +2329,7 @@ PAM AcctMgmt() exited with success
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    
  • pam/integration-tests/testdata/TestNativeAuthenticate/golden/authenticate_user_with_qr_code_in_polkit+22 22 modified
    @@ -1,5 +1,5 @@
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker:
    @@ -232,7 +232,7 @@ Select broker:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -465,15 +465,15 @@ Gimme your password:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
     Insert 'r' to cancel the request and go back
     Gimme your password:
     == Authentication mode selection (use 'r' to go back) ==
     1 - Password authentication
    -2 - Send URL to user-integration-qr-code-screen@gmail.com
    +2 - Send URL to user-integration-qr-code-polkit@gmail.com
     3 - Use your fido device foo
     4 - Use your phone +33…
     5 - Use your phone +1…
    @@ -698,15 +698,15 @@ Select authentication mode:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
     Insert 'r' to cancel the request and go back
     Gimme your password:
     == Authentication mode selection (use 'r' to go back) ==
     1 - Password authentication
    -2 - Send URL to user-integration-qr-code-screen@gmail.com
    +2 - Send URL to user-integration-qr-code-polkit@gmail.com
     3 - Use your fido device foo
     4 - Use your phone +33…
     5 - Use your phone +1…
    @@ -931,15 +931,15 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
     Insert 'r' to cancel the request and go back
     Gimme your password:
     == Authentication mode selection (use 'r' to go back) ==
     1 - Password authentication
    -2 - Send URL to user-integration-qr-code-screen@gmail.com
    +2 - Send URL to user-integration-qr-code-polkit@gmail.com
     3 - Use your fido device foo
     4 - Use your phone +33…
     5 - Use your phone +1…
    @@ -1164,15 +1164,15 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
     Insert 'r' to cancel the request and go back
     Gimme your password:
     == Authentication mode selection (use 'r' to go back) ==
     1 - Password authentication
    -2 - Send URL to user-integration-qr-code-screen@gmail.com
    +2 - Send URL to user-integration-qr-code-polkit@gmail.com
     3 - Use your fido device foo
     4 - Use your phone +33…
     5 - Use your phone +1…
    @@ -1397,15 +1397,15 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
     Insert 'r' to cancel the request and go back
     Gimme your password:
     == Authentication mode selection (use 'r' to go back) ==
     1 - Password authentication
    -2 - Send URL to user-integration-qr-code-screen@gmail.com
    +2 - Send URL to user-integration-qr-code-polkit@gmail.com
     3 - Use your fido device foo
     4 - Use your phone +33…
     5 - Use your phone +1…
    @@ -1630,15 +1630,15 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
     Insert 'r' to cancel the request and go back
     Gimme your password:
     == Authentication mode selection (use 'r' to go back) ==
     1 - Password authentication
    -2 - Send URL to user-integration-qr-code-screen@gmail.com
    +2 - Send URL to user-integration-qr-code-polkit@gmail.com
     3 - Use your fido device foo
     4 - Use your phone +33…
     5 - Use your phone +1…
    @@ -1863,15 +1863,15 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
     Insert 'r' to cancel the request and go back
     Gimme your password:
     == Authentication mode selection (use 'r' to go back) ==
     1 - Password authentication
    -2 - Send URL to user-integration-qr-code-screen@gmail.com
    +2 - Send URL to user-integration-qr-code-polkit@gmail.com
     3 - Use your fido device foo
     4 - Use your phone +33…
     5 - Use your phone +1…
    @@ -2096,15 +2096,15 @@ Select action: 1
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
     Insert 'r' to cancel the request and go back
     Gimme your password:
     == Authentication mode selection (use 'r' to go back) ==
     1 - Password authentication
    -2 - Send URL to user-integration-qr-code-screen@gmail.com
    +2 - Send URL to user-integration-qr-code-polkit@gmail.com
     3 - Use your fido device foo
     4 - Use your phone +33…
     5 - Use your phone +1…
    @@ -2152,7 +2152,7 @@ https://ubuntu.com
     1 - Wait for the QR code scan result
     2 - Regenerate code
     Select action: 1
    -PAM Authenticate() for user "user-integration-qr-code-screen" exited with success
    +PAM Authenticate() for user "user-integration-qr-code-polkit" exited with success
     PAM AcctMgmt() exited with success
     >
     
    @@ -2329,15 +2329,15 @@ PAM AcctMgmt() exited with success
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
     Insert 'r' to cancel the request and go back
     Gimme your password:
     == Authentication mode selection (use 'r' to go back) ==
     1 - Password authentication
    -2 - Send URL to user-integration-qr-code-screen@gmail.com
    +2 - Send URL to user-integration-qr-code-polkit@gmail.com
     3 - Use your fido device foo
     4 - Use your phone +33…
     5 - Use your phone +1…
    @@ -2385,7 +2385,7 @@ https://ubuntu.com
     1 - Wait for the QR code scan result
     2 - Regenerate code
     Select action: 1
    -PAM Authenticate() for user "user-integration-qr-code-screen" exited with success
    +PAM Authenticate() for user "user-integration-qr-code-polkit" exited with success
     PAM AcctMgmt() exited with success
     >
     
    
  • pam/integration-tests/testdata/TestNativeAuthenticate/golden/authenticate_user_with_qr_code_in_screen+11 11 modified
    @@ -1,5 +1,5 @@
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker:
    @@ -232,7 +232,7 @@ Select broker:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -465,7 +465,7 @@ Gimme your password:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -698,7 +698,7 @@ Select authentication mode:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -931,7 +931,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -1164,7 +1164,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -1397,7 +1397,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -1630,7 +1630,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -1863,7 +1863,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -2096,7 +2096,7 @@ Select action: 1
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -2329,7 +2329,7 @@ PAM AcctMgmt() exited with success
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    
  • pam/integration-tests/testdata/TestNativeAuthenticate/golden/authenticate_user_with_qr_code_in_ssh+11 11 modified
    @@ -1,5 +1,5 @@
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker:
    @@ -232,7 +232,7 @@ Select broker:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -465,7 +465,7 @@ Gimme your password:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -698,7 +698,7 @@ Select authentication mode:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -931,7 +931,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -1164,7 +1164,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -1397,7 +1397,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -1630,7 +1630,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -1863,7 +1863,7 @@ Select action:
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -2096,7 +2096,7 @@ Select action: 1
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    @@ -2329,7 +2329,7 @@ PAM AcctMgmt() exited with success
     ────────────────────────────────────────────────────────────────────────────────
     > if [ -v AUTHD_PAM_CLI_TERM ]; then export TERM=${AUTHD_PAM_CLI_TERM}; fi
     > ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    -== Broker selection (use 'r' to go back) ==
    +== Broker selection ==
     1 - local
     2 - ExampleBroker
     Select broker: 2
    
  • pam/integration-tests/testdata/TestNativeAuthenticate/golden/prevent_preset_user_from_switching_username+470 0 added
    @@ -0,0 +1,470 @@
    +> ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker:
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +────────────────────────────────────────────────────────────────────────────────
    +> ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: r
    +PAM Error Message: Provided input can't be parsed as integer value
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker:
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +────────────────────────────────────────────────────────────────────────────────
    +> ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: r
    +PAM Error Message: Provided input can't be parsed as integer value
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: 2
    +Insert 'r' to cancel the request and go back
    +Gimme your password:
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +────────────────────────────────────────────────────────────────────────────────
    +> ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: r
    +PAM Error Message: Provided input can't be parsed as integer value
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: 2
    +Insert 'r' to cancel the request and go back
    +Gimme your password:
    +== Authentication mode selection (use 'r' to go back) ==
    +1 - Password authentication
    +2 - Send URL to user-integration-pam-preset@gmail.com
    +3 - Use your fido device foo
    +4 - Use your phone +33…
    +5 - Use your phone +1…
    +6 - Pin code
    +7 - Use a QR code
    +8 - Authentication code
    +Select authentication mode:
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +────────────────────────────────────────────────────────────────────────────────
    +> ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: r
    +PAM Error Message: Provided input can't be parsed as integer value
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: 2
    +Insert 'r' to cancel the request and go back
    +Gimme your password:
    +== Authentication mode selection (use 'r' to go back) ==
    +1 - Password authentication
    +2 - Send URL to user-integration-pam-preset@gmail.com
    +3 - Use your fido device foo
    +4 - Use your phone +33…
    +5 - Use your phone +1…
    +6 - Pin code
    +7 - Use a QR code
    +8 - Authentication code
    +Select authentication mode: r
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker:
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +────────────────────────────────────────────────────────────────────────────────
    +> ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: r
    +PAM Error Message: Provided input can't be parsed as integer value
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: 2
    +Insert 'r' to cancel the request and go back
    +Gimme your password:
    +== Authentication mode selection (use 'r' to go back) ==
    +1 - Password authentication
    +2 - Send URL to user-integration-pam-preset@gmail.com
    +3 - Use your fido device foo
    +4 - Use your phone +33…
    +5 - Use your phone +1…
    +6 - Pin code
    +7 - Use a QR code
    +8 - Authentication code
    +Select authentication mode: r
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: r
    +PAM Error Message: Provided input can't be parsed as integer value
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker:
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +────────────────────────────────────────────────────────────────────────────────
    +> ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: r
    +PAM Error Message: Provided input can't be parsed as integer value
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: 2
    +Insert 'r' to cancel the request and go back
    +Gimme your password:
    +== Authentication mode selection (use 'r' to go back) ==
    +1 - Password authentication
    +2 - Send URL to user-integration-pam-preset@gmail.com
    +3 - Use your fido device foo
    +4 - Use your phone +33…
    +5 - Use your phone +1…
    +6 - Pin code
    +7 - Use a QR code
    +8 - Authentication code
    +Select authentication mode: r
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: r
    +PAM Error Message: Provided input can't be parsed as integer value
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: r
    +PAM Error Message: Provided input can't be parsed as integer value
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker:
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +────────────────────────────────────────────────────────────────────────────────
    +> ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: r
    +PAM Error Message: Provided input can't be parsed as integer value
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: 2
    +Insert 'r' to cancel the request and go back
    +Gimme your password:
    +== Authentication mode selection (use 'r' to go back) ==
    +1 - Password authentication
    +2 - Send URL to user-integration-pam-preset@gmail.com
    +3 - Use your fido device foo
    +4 - Use your phone +33…
    +5 - Use your phone +1…
    +6 - Pin code
    +7 - Use a QR code
    +8 - Authentication code
    +Select authentication mode: r
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: r
    +PAM Error Message: Provided input can't be parsed as integer value
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: r
    +PAM Error Message: Provided input can't be parsed as integer value
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: 2
    +Insert 'r' to cancel the request and go back
    +Gimme your password:
    +
    +
    +
    +
    +
    +
    +
    +
    +────────────────────────────────────────────────────────────────────────────────
    +> ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: r
    +PAM Error Message: Provided input can't be parsed as integer value
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: 2
    +Insert 'r' to cancel the request and go back
    +Gimme your password:
    +== Authentication mode selection (use 'r' to go back) ==
    +1 - Password authentication
    +2 - Send URL to user-integration-pam-preset@gmail.com
    +3 - Use your fido device foo
    +4 - Use your phone +33…
    +5 - Use your phone +1…
    +6 - Pin code
    +7 - Use a QR code
    +8 - Authentication code
    +Select authentication mode: r
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: r
    +PAM Error Message: Provided input can't be parsed as integer value
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: r
    +PAM Error Message: Provided input can't be parsed as integer value
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: 2
    +Insert 'r' to cancel the request and go back
    +Gimme your password:
    +PAM Authenticate() for user "user-integration-pam-preset" exited with success
    +PAM AcctMgmt() exited with success
    +>
    +
    +
    +
    +
    +
    +────────────────────────────────────────────────────────────────────────────────
    +> ./pam_authd login socket=${AUTHD_TESTS_CLI_AUTHENTICATE_TESTS_SOCK} force_native_client=true
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: r
    +PAM Error Message: Provided input can't be parsed as integer value
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: 2
    +Insert 'r' to cancel the request and go back
    +Gimme your password:
    +== Authentication mode selection (use 'r' to go back) ==
    +1 - Password authentication
    +2 - Send URL to user-integration-pam-preset@gmail.com
    +3 - Use your fido device foo
    +4 - Use your phone +33…
    +5 - Use your phone +1…
    +6 - Pin code
    +7 - Use a QR code
    +8 - Authentication code
    +Select authentication mode: r
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: r
    +PAM Error Message: Provided input can't be parsed as integer value
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: r
    +PAM Error Message: Provided input can't be parsed as integer value
    +== Broker selection ==
    +1 - local
    +2 - ExampleBroker
    +Select broker: 2
    +Insert 'r' to cancel the request and go back
    +Gimme your password:
    +PAM Authenticate() for user "user-integration-pam-preset" exited with success
    +PAM AcctMgmt() exited with success
    +>
    +
    +
    +
    +
    +
    +────────────────────────────────────────────────────────────────────────────────
    
  • pam/internal/adapter/model.go+3 1 modified
    @@ -147,7 +147,9 @@ func (m *UIModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
     			var cmd tea.Cmd
     			switch m.currentStage() {
     			case pam_proto.Stage_brokerSelection:
    -				cmd = m.changeStage(pam_proto.Stage_userSelection)
    +				if m.userSelectionModel.Enabled() {
    +					cmd = m.changeStage(pam_proto.Stage_userSelection)
    +				}
     			case pam_proto.Stage_authModeSelection:
     				cmd = m.changeStage(pam_proto.Stage_brokerSelection)
     			case pam_proto.Stage_challenge:
    
  • pam/internal/adapter/nativemodel.go+133 71 modified
    @@ -18,6 +18,7 @@ import (
     	"github.com/ubuntu/authd/internal/brokers"
     	"github.com/ubuntu/authd/internal/log"
     	"github.com/ubuntu/authd/pam/internal/proto"
    +	pam_proto "github.com/ubuntu/authd/pam/internal/proto"
     	"golang.org/x/term"
     )
     
    @@ -30,9 +31,10 @@ type nativeModel struct {
     	selectedAuthMode string
     	uiLayout         *authd.UILayout
     
    -	serviceName  string
    -	currentStage proto.Stage
    -	busy         bool
    +	serviceName          string
    +	currentStage         proto.Stage
    +	busy                 bool
    +	userSelectionAllowed bool
     }
     
     const (
    @@ -41,9 +43,12 @@ const (
     	polkitServiceName = "polkit-1"
     )
     
    -// nativeBrokerSelection is the internal event to notify that a stage change is requested.
    +// nativeChangeStage is the internal event to notify that a stage change has happened.
     type nativeChangeStage ChangeStage
     
    +// nativeStageChangeRequest is the internal event to request that a stage change.
    +type nativeStageChangeRequest ChangeStage
    +
     // nativeUserSelection is the internal event that an user needs to be (re)set.
     type nativeUserSelection struct{}
     
    @@ -68,8 +73,6 @@ var errNotAnInteger = errors.New("parsed value is not an integer")
     
     // Init initializes the main model orchestrator.
     func (m *nativeModel) Init() tea.Cmd {
    -	m.currentStage = proto.Stage(-1)
    -
     	var err error
     	m.serviceName, err = m.pamMTx.GetItem(pam.Service)
     	if err != nil {
    @@ -125,23 +128,49 @@ func (m nativeModel) changeStage(stage proto.Stage) tea.Cmd {
     	return sendEvent(nativeChangeStage{stage})
     }
     
    +func (m nativeModel) requestStageChange(stage proto.Stage) tea.Cmd {
    +	return sendEvent(nativeStageChangeRequest{stage})
    +}
    +
     func (m nativeModel) Update(msg tea.Msg) (nativeModel, tea.Cmd) {
     	log.Debugf(context.TODO(), "Native model update: %#v", msg)
     
     	switch msg := msg.(type) {
     	case nativeChangeStage:
     		m.currentStage = msg.Stage
     
    +	case nativeStageChangeRequest:
    +		var baseCmd tea.Cmd
    +		if m.currentStage != msg.Stage {
    +			m.currentStage = msg.Stage
    +			baseCmd = sendEvent(ChangeStage(msg))
    +		}
    +
    +		switch m.currentStage {
    +		case proto.Stage_userSelection:
    +			return m, tea.Sequence(baseCmd, sendEvent(nativeUserSelection{}))
    +		case proto.Stage_brokerSelection:
    +			return m, tea.Sequence(baseCmd, sendEvent(nativeBrokerSelection{}))
    +		case proto.Stage_authModeSelection:
    +			return m, tea.Sequence(baseCmd, sendEvent(nativeAuthSelection{}))
    +		case proto.Stage_challenge:
    +			return m, tea.Sequence(baseCmd, sendEvent(nativeChallengeRequested{}))
    +		}
    +
     	case nativeAsyncOperationCompleted:
     		m.busy = false
     
     	case nativeGoBack:
    -		return m, m.goBackCommand()
    +		return m.goBackCommand()
     
     	case userRequired:
    -		return m, sendEvent(nativeUserSelection{})
    +		m.userSelectionAllowed = true
    +		return m, m.requestStageChange(pam_proto.Stage_userSelection)
     
     	case nativeUserSelection:
    +		if m.currentStage != proto.Stage_userSelection {
    +			return m, nil
    +		}
     		if m.busy {
     			// We may receive multiple concurrent requests, but due to the sync nature
     			// of this model, we can't just accept them once we've one in progress already
    @@ -155,11 +184,6 @@ func (m nativeModel) Update(msg tea.Msg) (nativeModel, tea.Cmd) {
     
     		return m.startAsyncOp(m.userSelection)
     
    -	case userSelected:
    -		if err := m.pamMTx.SetItem(pam.User, msg.username); err != nil {
    -			return m, maybeSendPamError(err)
    -		}
    -
     	case brokersListReceived:
     		m.availableBrokers = msg.brokers
     
    @@ -179,10 +203,14 @@ func (m nativeModel) Update(msg tea.Msg) (nativeModel, tea.Cmd) {
     			return m, maybeSendPamError(err)
     		}
     		return m.startAsyncOp(func() tea.Cmd {
    -			return m.maybePreCheckUser(user, sendEvent(nativeBrokerSelection{}))
    +			return m.maybePreCheckUser(user,
    +				m.requestStageChange(pam_proto.Stage_brokerSelection))
     		})
     
     	case nativeBrokerSelection:
    +		if m.currentStage != proto.Stage_brokerSelection {
    +			return m, nil
    +		}
     		if m.busy {
     			// We may receive multiple concurrent requests, but due to the sync nature
     			// of this model, we can't just accept them once we've one in progress already
    @@ -204,6 +232,18 @@ func (m nativeModel) Update(msg tea.Msg) (nativeModel, tea.Cmd) {
     		return m.startAsyncOp(m.brokerSelection)
     
     	case nativeAuthSelection:
    +		if m.currentStage != proto.Stage_authModeSelection {
    +			return m, nil
    +		}
    +		if m.busy {
    +			// We may receive multiple concurrent requests, but due to the sync nature
    +			// of this model, we can't just accept them once we've one in progress already
    +			log.Debug(context.TODO(), "Authentication selection already in progress")
    +			return m, nil
    +		}
    +		if m.selectedAuthMode != "" {
    +			return m, nil
    +		}
     		if len(m.authModes) < 1 {
     			return m, sendEvent(pamError{
     				status: pam.ErrSystem,
    @@ -215,28 +255,7 @@ func (m nativeModel) Update(msg tea.Msg) (nativeModel, tea.Cmd) {
     			return m, sendEvent(authModeSelected{id: m.authModes[0].Id})
     		}
     
    -		var choices []choicePair
    -		for _, am := range m.authModes {
    -			choices = append(choices, choicePair{id: am.Id, label: am.Label})
    -		}
    -
    -		id, err := m.promptForChoice("Authentication mode selection", choices,
    -			"Select authentication mode")
    -		if errors.Is(err, errGoBack) {
    -			m.authModes = nil
    -			return m, sendEvent(nativeGoBack{})
    -		}
    -		if errors.Is(err, errEmptyResponse) {
    -			return m, sendEvent(nativeChallengeRequested{})
    -		}
    -		if err != nil {
    -			return m, sendEvent(pamError{
    -				status: pam.ErrSystem,
    -				msg:    fmt.Sprintf("broker selection error: %v", err),
    -			})
    -		}
    -
    -		return m, sendEvent(authModeSelected{id: id})
    +		return m.startAsyncOp(m.authModeSelection)
     
     	case authModeSelected:
     		m.selectedAuthMode = msg.id
    @@ -245,9 +264,12 @@ func (m nativeModel) Update(msg tea.Msg) (nativeModel, tea.Cmd) {
     		m.uiLayout = msg.layout
     
     	case startAuthentication:
    -		return m, sendEvent(nativeChallengeRequested{})
    +		return m, m.requestStageChange(pam_proto.Stage_challenge)
     
     	case nativeChallengeRequested:
    +		if m.currentStage != pam_proto.Stage_challenge {
    +			return m, nil
    +		}
     		return m, m.startChallenge()
     
     	case newPasswordCheckResult:
    @@ -284,30 +306,30 @@ func (m nativeModel) Update(msg tea.Msg) (nativeModel, tea.Cmd) {
     		}
     
     	case isAuthenticatedCancelled:
    -		m.uiLayout = nil
    -		return m, sendEvent(nativeGoBack{})
    +		return m.goBackCommand()
     	}
     
     	return m, nil
     }
     
    -func checkForPromptReplyValidity(reply string) error {
    +func (m nativeModel) checkForPromptReplyValidity(reply string) error {
     	switch reply {
     	case nativeCancelKey:
    -		return errGoBack
    +		if m.canGoBack() {
    +			return errGoBack
    +		}
     	case "", "\n":
     		return errEmptyResponse
    -	default:
    -		return nil
     	}
    +	return nil
     }
     
     func (m nativeModel) promptForInput(style pam.Style, prompt string) (string, error) {
     	resp, err := m.pamMTx.StartStringConvf(style, "%s: ", prompt)
     	if err != nil {
     		return "", err
     	}
    -	return resp.Response(), checkForPromptReplyValidity(resp.Response())
    +	return resp.Response(), m.checkForPromptReplyValidity(resp.Response())
     }
     
     func (m nativeModel) promptForNumericInput(style pam.Style, prompt string) (int, error) {
    @@ -365,13 +387,17 @@ type choicePair struct {
     }
     
     func (m nativeModel) promptForChoice(title string, choices []choicePair, prompt string) (string, error) {
    -	for {
    -		msg := fmt.Sprintf("== %s (use '%s' to go back) ==\n", title, nativeCancelKey)
    -		for i, choice := range choices {
    -			msg += fmt.Sprintf("%d - %s\n", i+1, choice.label)
    -		}
    +	if m.canGoBack() {
    +		title = fmt.Sprintf("%s (use '%s' to go back)", title, nativeCancelKey)
    +	}
     
    -		msg += prompt
    +	msg := fmt.Sprintf("== %s ==\n", title)
    +	for i, choice := range choices {
    +		msg += fmt.Sprintf("%d - %s\n", i+1, choice.label)
    +	}
    +	msg += prompt
    +
    +	for {
     		idx, err := m.promptForNumericInputUntilValid(pam.PromptEchoOn, msg)
     		if err != nil {
     			return "", err
    @@ -405,7 +431,7 @@ func (m nativeModel) userSelection() tea.Cmd {
     	if errors.Is(err, errEmptyResponse) {
     		return sendEvent(nativeUserSelection{})
     	}
    -	if err != nil && !errors.Is(err, errGoBack) {
    +	if err != nil {
     		return maybeSendPamError(err)
     	}
     
    @@ -451,6 +477,30 @@ func (m nativeModel) brokerSelection() tea.Cmd {
     	return sendEvent(brokerSelected{brokerID: id})
     }
     
    +func (m nativeModel) authModeSelection() tea.Cmd {
    +	var choices []choicePair
    +	for _, am := range m.authModes {
    +		choices = append(choices, choicePair{id: am.Id, label: am.Label})
    +	}
    +
    +	id, err := m.promptForChoice("Authentication mode selection", choices,
    +		"Select authentication mode")
    +	if errors.Is(err, errGoBack) {
    +		return sendEvent(nativeGoBack{})
    +	}
    +	if errors.Is(err, errEmptyResponse) {
    +		return m.requestStageChange(pam_proto.Stage_challenge)
    +	}
    +	if err != nil {
    +		return sendEvent(pamError{
    +			status: pam.ErrSystem,
    +			msg:    fmt.Sprintf("broker selection error: %v", err),
    +		})
    +	}
    +
    +	return sendEvent(authModeSelected{id: id})
    +}
    +
     func (m nativeModel) startChallenge() tea.Cmd {
     	if m.uiLayout == nil {
     		return sendEvent(pamError{
    @@ -785,31 +835,43 @@ func (m nativeModel) newPasswordChallenge(previousChallenge *string) tea.Cmd {
     	})
     }
     
    -func (m nativeModel) goBackCommand() tea.Cmd {
    -	return func() tea.Cmd {
    -		if m.uiLayout != nil {
    -			return sendEvent(isAuthenticatedCancelled{})
    -		}
    +func (m nativeModel) goBackCommand() (nativeModel, tea.Cmd) {
    +	if m.currentStage >= proto.Stage_challenge && m.uiLayout != nil {
    +		m.uiLayout = nil
    +		return m, sendEvent(isAuthenticatedCancelled{})
    +	}
    +	if m.currentStage >= proto.Stage_authModeSelection {
    +		m.selectedAuthMode = ""
    +	}
    +	if m.currentStage == proto.Stage_authModeSelection {
    +		m.authModes = nil
    +	}
     
    -		if m.currentStage > proto.Stage_authModeSelection && len(m.authModes) > 1 {
    -			return tea.Sequence(
    -				sendEvent(ChangeStage{proto.Stage_authModeSelection}),
    -				sendEvent(nativeAuthSelection{}),
    -			)
    -		}
    -		if m.currentStage > proto.Stage_brokerSelection && len(m.availableBrokers) > 1 {
    -			return tea.Sequence(
    -				sendEvent(ChangeStage{proto.Stage_brokerSelection}),
    -				sendEvent(nativeBrokerSelection{}),
    -			)
    +	return m, func() tea.Cmd {
    +		if !m.canGoBack() {
    +			return nil
     		}
    -		return tea.Sequence(
    -			sendEvent(ChangeStage{proto.Stage_userSelection}),
    -			sendEvent(nativeUserSelection{}),
    -		)
    +		return m.requestStageChange(m.previousStage())
     	}()
     }
     
    +func (m nativeModel) canGoBack() bool {
    +	if m.userSelectionAllowed {
    +		return m.currentStage > proto.Stage_userSelection
    +	}
    +	return m.previousStage() > proto.Stage_userSelection
    +}
    +
    +func (m nativeModel) previousStage() pam_proto.Stage {
    +	if m.currentStage > proto.Stage_authModeSelection && len(m.authModes) > 1 {
    +		return proto.Stage_authModeSelection
    +	}
    +	if m.currentStage > proto.Stage_brokerSelection && len(m.availableBrokers) > 1 {
    +		return proto.Stage_brokerSelection
    +	}
    +	return proto.Stage_userSelection
    +}
    +
     func sendAuthWaitCommand() tea.Cmd {
     	return sendEvent(isAuthenticatedRequested{
     		item: &authd.IARequest_AuthenticationData_Wait{Wait: "true"},
    
  • pam/internal/adapter/userselection.go+28 3 modified
    @@ -2,6 +2,7 @@ package adapter
     
     import (
     	"context"
    +	"fmt"
     
     	"github.com/charmbracelet/bubbles/cursor"
     	"github.com/charmbracelet/bubbles/textinput"
    @@ -17,6 +18,7 @@ type userSelectionModel struct {
     
     	pamMTx     pam.ModuleTransaction
     	clientType PamClientType
    +	enabled    bool
     }
     
     // userSelected events to report that a new username has been selected.
    @@ -71,20 +73,38 @@ func (m userSelectionModel) Update(msg tea.Msg) (userSelectionModel, tea.Cmd) {
     	switch msg := msg.(type) {
     	case userSelected:
     		log.Debugf(context.TODO(), "%#v", msg)
    +		currentUser, err := m.pamMTx.GetItem(pam.User)
    +		if err != nil {
    +			return m, sendEvent(pamError{status: pam.ErrSystem, msg: err.Error()})
    +		}
    +		if !m.enabled && currentUser != "" && msg.username != currentUser {
    +			sendEvent(pamError{
    +				status: pam.ErrPermDenied,
    +				msg:    fmt.Sprintf("Changing username %s to %s is not allowed", m.Value(), msg.username),
    +			})
    +			return m, nil
    +		}
    +		if msg.username != "" && currentUser != msg.username {
    +			if err := m.pamMTx.SetItem(pam.User, msg.username); err != nil {
    +				return m, sendEvent(pamError{status: pam.ErrSystem, msg: err.Error()})
    +			}
    +		}
     		if msg.username != "" {
     			// synchronise our internal validated field and the text one.
     			m.SetValue(msg.username)
    -			if err := m.pamMTx.SetItem(pam.User, msg.username); err != nil {
    -				return m, sendEvent(pamError{status: pam.ErrAbort, msg: err.Error()})
    -			}
     			return m, sendEvent(UsernameOrBrokerListReceived{})
     		}
     		return m, nil
     
     	case userRequired:
    +		m.enabled = true
     		return m, sendEvent(ChangeStage{Stage: proto.Stage_userSelection})
     	}
     
    +	if !m.enabled {
    +		return m, nil
    +	}
    +
     	if m.clientType != InteractiveTerminal {
     		return m, nil
     	}
    @@ -107,3 +127,8 @@ func (m userSelectionModel) Update(msg tea.Msg) (userSelectionModel, tea.Cmd) {
     	m.Model, cmd = m.Model.Update(msg)
     	return m, cmd
     }
    +
    +// Enabled returns whether the interactive user selection is enabled.
    +func (m userSelectionModel) Enabled() bool {
    +	return m.enabled
    +}
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.