Skip to content

Commit

Permalink
authentication: add no pin for passkey and pin as Enter key
Browse files Browse the repository at this point in the history
Signed-off-by: Madhuri Upadhye <[email protected]>
  • Loading branch information
madhuriupadhye committed Sep 18, 2024
1 parent 0b213ff commit 53809b1
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 14 deletions.
58 changes: 58 additions & 0 deletions .idea/workspace.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

79 changes: 65 additions & 14 deletions sssd_test_framework/utils/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from datetime import datetime
from typing import Any
from enum import Enum

from pytest_mh import MultihostHost, MultihostUtility
from pytest_mh.conn import Connection, ProcessResult
Expand All @@ -22,6 +23,11 @@
DEFAULT_AUTHENTICATION_TIMEOUT: int = 60
"""Default timeout for authentication failure."""

class PasskeyAuthenticationUseCases(Enum):
PASSKEY_WITH_PIN = 0,
PASSKEY_WITH_PIN_AND_PROMPTS = 1,
PASSKEY_WITHOUT_PIN = 2,
PASSKEY_FALLBACK_TO_PASSWORD = 3,

class AuthenticationUtils(MultihostUtility[MultihostHost]):
"""
Expand Down Expand Up @@ -341,7 +347,10 @@ def password_expired(self, username: str, password: str, new_password: str) -> b
return result.rc == 0

def passkey_with_output(
self, username: str, *, pin: str | int, device: str, ioctl: str, script: str, command: str = "exit 0"
self, username: str, *, device: str, ioctl: str, script: str, pin: str | int | None = None,
interactive_prompt: str = "Insert your Passkey device, then press ENTER.",
touch_prompt: str = "Please touch the device.", command: str = "exit 0",
auth_method: PasskeyAuthenticationUseCases = PasskeyAuthenticationUseCases.PASSKEY_WITH_PIN
) -> tuple[int, int, str, str]:
"""
Call ``su - $username`` and authenticate the user with passkey.
Expand All @@ -360,6 +369,13 @@ def passkey_with_output(
:type command: str
:return: Tuple containing [return code, command code, stdout, stderr].
:rtype: Tuple[int, int, str, str]
pin plus touch => default => (Insert your Passkey device, then press ENTER.Enter PIN:)
no pin => (insert your Passkey device, then press ENTER)
pin plus password => (insert your Passkey device, then press ENTER, Enter PIN:<enter>,
Password:<password>)
default plus touch and interactive prompt =>
"""
self.fs.backup("/usr/libexec/sssd/passkey_child")
self.fs.copy("/usr/libexec/sssd/passkey_child", "/usr/libexec/sssd/passkey_child.orig")
Expand All @@ -368,6 +384,16 @@ def passkey_with_output(
ioctl_path = self.fs.upload_to_tmp(ioctl, mode="a=r")
script_path = self.fs.upload_to_tmp(script, mode="a=r")

match auth_method:
case (PasskeyAuthenticationUseCases.PASSKEY_WITH_PIN,
PasskeyAuthenticationUseCases.PASSKEY_WITH_PIN_AND_PROMPTS):
if pin is None:
raise ValueError(f"PIN is required for {str(auth_method)}")
case (PasskeyAuthenticationUseCases.PASSKEY_WITHOUT_PIN,
PasskeyAuthenticationUseCases.PASSKEY_FALLBACK_TO_PASSWORD):
if pin is not None:
raise ValueError(f"PIN is not required for {str(auth_method)}")

run_su = self.fs.mktmp(
rf"""
#!/bin/bash
Expand All @@ -385,7 +411,6 @@ def passkey_with_output(
""",
mode="a=rx",
)

playback_umockdev = self.fs.mktmp(
rf"""
#!/bin/bash
Expand All @@ -399,6 +424,7 @@ def passkey_with_output(
mode="a=rx",
)

import pdb; pdb.set_trace()
result = self.host.conn.expect(
rf"""
# Disable debug output
Expand All @@ -422,29 +448,56 @@ def passkey_with_output(
set timeout {DEFAULT_AUTHENTICATION_TIMEOUT}
set prompt "\n.*\[#\$>\] $"
set command "{command}"
set auth_method "{auth_method}"
spawn "{playback_umockdev}"
expect {{
"Insert your passkey device, then press ENTER*" {{send -- "\n"}}
"{interactive_prompt}*" {{ send -- "\n"}}
timeout {{exitmsg "Unexpected output" 201}}
eof {{exitmsg "Unexpected end of file" 202}}
}}
expect {{
"Enter PIN:*" {{send -- "{pin}\r"}}
timeout {{exitmsg "Unexpected output" 201}}
eof {{exitmsg "Unexpected end of file" 202}}
if {{ ($auth_method eq "{PasskeyAuthenticationUseCases.PASSKEY_WITH_PIN}") || ($auth_method eq
"{PasskeyAuthenticationUseCases.PASSKEY_WITH_PIN_AND_PROMPTS}")}} {{
expect {{
"Enter PIN:*" {{send -- "{pin}\r"}}
timeout {{exitmsg "Unexpected output" 401}}
eof {{exitmsg "Unexpected end of file" 402}}
}}
if {{ $auth_method eq "{PasskeyAuthenticationUseCases.PASSKEY_WITH_PIN_AND_PROMPTS}" }} {{
expect {{
"{touch_prompt}*" {{ send -- "\n"}}
eof {{exitmsg "Password authentication successful" 0}}
timeout {{exitmsg "Unexpected output" 501}}
}}
}}
}} elseif {{ $auth_method eq "{PasskeyAuthenticationUseCases.PASSKEY_FALLBACK_TO_PASSWORD}" }} {{
expect {{
"Enter PIN:*" {{send -- "\r"}}
timeout {{exitmsg "Unexpected output" 201}}
eof {{exitmsg "Unexpected end of file" 202}}
}}
expect {{
"Password:*" {{send -- "Secret123\r"}}
timeout {{exitmsg "Unexpected output" 301}}
eof {{exitmsg "Unexpected end of file" 302}}
}}
}} elseif {{ $auth_method eq "{PasskeyAuthenticationUseCases.PASSKEY_WITHOUT_PIN}" }} {{
expect {{
"{touch_prompt}*" {{ send -- "\n"}}
eof {{exitmsg "Password authentication successful" 0}}
timeout {{exitmsg "Unexpected output" 501}}
}}
}}
expect {{
"Authentication failure" {{exitmsg "Authentication failure" 1}}
eof {{exitmsg "Password authentication successful" 0}}
timeout {{exitmsg "Unexpected output" 201}}
timeout {{exitmsg "Unexpected output" 601}}
}}
exitmsg "Unexpected code path" 203
exitmsg "Unexpected code path" 803
""",
verbose=False,
)
Expand All @@ -464,9 +517,7 @@ def passkey_with_output(

return result.rc, cmdrc, stdout, result.stderr

def passkey(
self, username: str, *, pin: str | int, device: str, ioctl: str, script: str, command: str = "exit 0"
) -> bool:
def passkey(self, username: str, *, device: str, ioctl: str, script: str, pin: str | int | None = None, command: str = "exit 0") -> bool:
"""
Call ``su - $username`` and authenticate the user with passkey.
Expand Down

0 comments on commit 53809b1

Please sign in to comment.