Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cherry pick commit from V2 #34

Merged
merged 1 commit into from
Dec 22, 2023
Merged
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
6 changes: 3 additions & 3 deletions Graphical/local-user-graphical-login.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
This module contains tests for logging into GUI using GDM.
Most of the tests are parametrized to test both
optional and required smart card in authselect.
Lock-on-removal option is not set as it is irrelevant for present tests.
The tests within the module try logging in both using password and
smart card with PIN. Both wrong password and wrong PIN are tested too.
All tests depend on SCAutolib GUI module.
Expand Down Expand Up @@ -163,7 +162,8 @@ def test_login_password_wrong(local_user):
gui.assert_text('Password')


def test_insert_card_prompt(local_user):
@pytest.mark.parametrize("lock_on_removal", [True, False])
def test_insert_card_prompt(local_user, lock_on_removal):
"""Local user tries to log in with GDM before inserting card,
with sc required.

Expand All @@ -180,7 +180,7 @@ def test_insert_card_prompt(local_user):
C. GDM shows "insert PIN" prompt
D. User is logged in successfully.
"""
with (Authselect(required=True),
with (Authselect(required=True, lock_on_removal=lock_on_removal),
local_user.card(insert=False) as card,
GUI() as gui):
gui.assert_text('insert')
Expand Down
19 changes: 12 additions & 7 deletions Local-user/test_local_user_login.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
"""Note: as all tests are executed from root user, first login to any user
do not require any credentials!
"""
import pytest
from SCAutolib.models.authselect import Authselect


def test_su_login_with_sc(local_user, user_shell):
@pytest.mark.parametrize("required", [True, False])
def test_su_login_with_sc(local_user, user_shell, required):
"""Basic su login to the user with a smart card.

Setup
Expand Down Expand Up @@ -38,7 +40,7 @@ def test_su_login_with_sc(local_user, user_shell):
- User is successfully logged in
"""

with Authselect(required=False):
with Authselect(required=required):
with local_user.card(insert=True):
cmd = f'su {local_user.username} -c "whoami"'
user_shell.sendline(cmd)
Expand All @@ -47,7 +49,8 @@ def test_su_login_with_sc(local_user, user_shell):
user_shell.expect_exact(local_user.username)


def test_su_login_with_sc_wrong(local_user, user_shell):
@pytest.mark.parametrize("required", [True, False])
def test_su_login_with_sc_wrong(local_user, user_shell, required):
"""Basic su login to the user with a smartcard when user inters wrong PIN.

Setup
Expand Down Expand Up @@ -80,7 +83,7 @@ def test_su_login_with_sc_wrong(local_user, user_shell):
- User inserts wrong PIN
- User is not logged in and error message is written to the console
"""
with Authselect(required=False):
with Authselect(required=required):
with local_user.card(insert=True):
cmd = f'su {local_user.username} -c "whoami"'
user_shell.sendline(cmd)
Expand Down Expand Up @@ -172,8 +175,10 @@ def test_su_login_without_sc(local_user, user_shell):
user_shell.sendline(local_user.password)
user_shell.expect_exact(local_user.username)


def test_su_to_root(local_user, user_shell, root_user):
@pytest.mark.parametrize(
"required,lock_on_removal", [(True, True), (True, False), (False, True), (False, False),]
)
def test_su_to_root(local_user, user_shell, root_user, required, lock_on_removal):
"""Test for smartcard login to the local user and then switching to root (su -).

Setup
Expand Down Expand Up @@ -207,7 +212,7 @@ def test_su_to_root(local_user, user_shell, root_user):
- User insert correct root password
- User is switched to the root user
"""
with Authselect():
with Authselect(required=required, lock_on_removal=lock_on_removal):
with local_user.card(insert=True):
user_shell.sendline(f"su - {local_user.username}")
user_shell.expect_exact(f"PIN for {local_user.username}:")
Expand Down
8 changes: 5 additions & 3 deletions Local-user/test_local_user_passwd.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
from SCAutolib.models.authselect import Authselect


@pytest.mark.parametrize("required", [True, False])
def test_change_local_user_passwd(local_user, user_shell, required):
@pytest.mark.parametrize(
"required,lock_on_removal", [(True, True), (True, False), (False, True), (False, False),]
)
def test_change_local_user_passwd(local_user, user_shell, required, lock_on_removal):
"""Run 'passwd' command when smartcard login is enforced and after user is
authenticated in with a smartcard.

Expand Down Expand Up @@ -37,7 +39,7 @@ def test_change_local_user_passwd(local_user, user_shell, required):
- Users is asked to change it local password
- No mentioning of the smart card
"""
with Authselect(required=required):
with Authselect(required=required, lock_on_removal=lock_on_removal):
with local_user.card(insert=True):
cmd = f"su {local_user.username} -c 'passwd'"
user_shell.sendline(cmd)
Expand Down
180 changes: 176 additions & 4 deletions Sanity/test_ttylogin.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from time import sleep

import pexpect
import pytest

from SCAutolib.models.authselect import Authselect

Expand Down Expand Up @@ -96,6 +97,48 @@ def test_login_without_sc(user):
login_shell.close()


def test_login_without_sc_wrong(user):
"""Basic login to the user without a smartcard when user enters wrong password.

Setup
1. Create local CA
2. Create virtual smart card with certs signed by created CA
3. Update /etc/sssd/sssd.conf so it contains following fields
[sssd]
debug_level = 9
services = nss, pam,
domains = shadowutils
certificate_verification = no_ocsp

[pam]
debug_level = 9
pam_cert_auth = True

[domain/shadowutils]
debug_level = 9
id_provider = files

[certmap/shadowutils/username]
matchrule = <SUBJECT>.*CN=username.*
4. Setup authselect: authselect select sssd with-smartcard
5. Insert the card
6. Try to switch user (su login) to the smartcard user


Expected result
- Users is asked for smartcard PIN
- User inserts wrong PIN
- User is not logged in and error message is written to the console
"""
with Authselect():
login_shell = login_shell_factory(user.username)
login_shell.expect(f"Password:")
login_shell.sendline("wrong")
login_shell.expect("Login incorrect")
login_shell.sendline("exit")
login_shell.close()


def test_login_with_sc_required(user):
"""Console-like login to the user with a smart card; smartcard required.
Setup
Expand Down Expand Up @@ -134,7 +177,8 @@ def test_login_with_sc_required(user):
login_shell.close()


def test_login_with_sc_wrong(user):
@pytest.mark.parametrize("required", [True, False])
def test_login_with_sc_wrong(user, required):
"""Console-like login to the user with a smart card.

Setup
Expand Down Expand Up @@ -163,7 +207,7 @@ def test_login_with_sc_wrong(user):
- User inserts wrong PIN
- User is told that the PIN is incorrect
"""
with Authselect():
with Authselect(required=required):
with user.card(insert=True):
login_shell = login_shell_factory(user.username)
login_shell.expect(f"PIN for {user.username}:")
Expand All @@ -173,7 +217,8 @@ def test_login_with_sc_wrong(user):
login_shell.close()


def test_login_sc_required(user):
@pytest.mark.parametrize("lock_on_removal", [True, False])
def test_login_sc_required(user, lock_on_removal):
"""Console-like login to the user with a smart card.

Setup
Expand Down Expand Up @@ -204,7 +249,7 @@ def test_login_sc_required(user):
- User types PIN the PIN
- User is successfully logged in
"""
with Authselect(required=True):
with Authselect(required=True, lock_on_removal=lock_on_removal):
login_shell = login_shell_factory(user.username)
login_shell.expect("Please insert smart card")

Expand All @@ -215,3 +260,130 @@ def test_login_sc_required(user):
login_shell.sendline("exit")
login_shell.close()

@pytest.mark.parametrize(
"required,lock_on_removal", [(True, True), (True, False), (False, True), (False, False),]
)
def test_login_local_user_passwd(user, required, lock_on_removal):
"""Run 'passwd' command when smartcard login is enforced and after user is
authenticated in with a smartcard.

Setup
1. Create local CA
2. Create virtual smart card with certs signed by created CA
3. Update /etc/sssd/sssd.conf so it contains following fields
[sssd]
debug_level = 9
services = nss, pam,
domains = shadowutils
certificate_verification = no_ocsp

[pam]
debug_level = 9
pam_cert_auth = True

[domain/shadowutils]
debug_level = 9
id_provider = files

[certmap/shadowutils/username]
matchrule = <SUBJECT>.*CN=username.*
4. Setup authselect: authselect select sssd with-smartcard (with-smartcard-required)
5. Login to the smart card user
6. Run 'passwd'


Expected result
- Users is asked to change it local password
- No mentioning of the smart card
"""

with Authselect(required=required, lock_on_removal=lock_on_removal):
with user.card(insert=True):
login_shell = login_shell_factory(user.username)
login_shell.expect([f"PIN for {user.username}:"])
login_shell.sendline(user.pin)
login_shell.expect([user.username])
login_shell.sendline("passwd")
login_shell.expect_exact(f"Changing password for user {user.username}.")

@pytest.mark.parametrize(
"required,lock_on_removal", [(True, True), (True, False), (False, True), (False, False),]
)
def test_login_local_su_to_root(user, root_user, required, lock_on_removal):
"""Test for smartcard login to the local user and then switching to root (su -).

Setup
1. Create local CA
2. Create virtual smart card with certs signed by created CA
3. Update /etc/sssd/sssd.conf so it contains following fields
[sssd]
debug_level = 9
services = nss, pam,
domains = shadowutils
certificate_verification = no_ocsp

[pam]
debug_level = 9
pam_cert_auth = True

[domain/shadowutils]
debug_level = 9
id_provider = files

[certmap/shadowutils/username]
matchrule = <SUBJECT>.*CN=username.*
4. Setup authselect: authselect select sssd with-smartcard
5. Insert the card
6. Switch user with 'su' command to the smartcard user
7. User is asked for smartcard PIN -> insert correct PIN
8. After successful login, try to switch to root user with 'su -'

Expected result
- Users is asked for root password
- User insert correct root password
- User is switched to the root user
"""
with Authselect(required=required, lock_on_removal=lock_on_removal):
with user.card(insert=True):
login_shell = login_shell_factory(user.username)
login_shell.expect([f"PIN for {user.username}:"])
login_shell.sendline(user.pin)
login_shell.expect([user.username])
login_shell.sendline("whoami")
login_shell.expect_exact(user.username)
login_shell.sendline('su - root -c "whoami"')
login_shell.expect_exact("Password:")
login_shell.sendline(root_user.password)
login_shell.expect_exact("root")

@pytest.mark.parametrize("required", [True, False])
def test_login_kerberos_su_to_root(ipa_user, root_user, required):
"""Kerberos user tries to switch to the root user with root password after
kerberos user is logged in with smart card.

Setup
1. General setup
2. Setup authselect: authselect select sssd with-smartcard with-smartcard-required
3. Insert the card
4. Login to kerberos user
5. System asks for smartcard PIN -> insert correct smartcard PIN
6. User is successfully logged in
7. Try to switch to root (su -)

Expected result
- User is asked to insert root password
- User inserts root password
- User is switched to the root user
"""
with Authselect(required=required):
with ipa_user.card(insert=True):
login_shell = login_shell_factory(ipa_user.username)
login_shell.expect([f"PIN for {ipa_user.username}:"])
login_shell.sendline(ipa_user.pin)
login_shell.expect([ipa_user.username])
login_shell.sendline("whoami")
login_shell.expect_exact(ipa_user.username)
login_shell.sendline('su - root -c "whoami"')
login_shell.expect_exact("Password:")
login_shell.sendline(root_user.password)
login_shell.expect_exact("root")
Loading