Skip to content
Open
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
36 changes: 36 additions & 0 deletions irods/test/scripts/files_for_test012/pam_clear_token.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
To build, you need the PAM development library. Once installed,
run the following:

gcc -fPIC -fno-stack-protector -o pam_clear_token.o -c main.c
gcc -shared -o pam_clear_token.so pam_clear_token.o
*/

#include <security/pam_modules.h>
#include <security/pam_ext.h>
#include <security/pam_appl.h>

#include <stdlib.h>

PAM_EXTERN int pam_sm_authenticate(pam_handle_t* pamh, int flags, int argc, const char** argv)
{
(void) flags;
(void) argc;
(void) argv;

// Clear the current auth token.
pam_set_item(pamh, PAM_AUTHTOK, NULL);
pam_set_item(pamh, PAM_OLDAUTHTOK, NULL);

return PAM_SUCCESS;
}

PAM_EXTERN int pam_sm_setcred(pam_handle_t* pamh, int flags, int argc, const char** argv)
{
(void) pamh;
(void) flags;
(void) argc;
(void) argv;

return PAM_SUCCESS;
}
17 changes: 17 additions & 0 deletions irods/test/scripts/files_for_test012/pam_interactive
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# This file is for testing PAM authentication with iRODS
# using the pam_interactive authentication scheme.

# Prompt for the first password, from /etc/shadow.
auth required pam_unix.so

# This is a custom PAM module that clears the success token. Without
# this, the "auth" lines which follow are skipped.
auth required /t012/pam_clear_token.so

# Prompt for the second password, from the user database file created
# earlier. The use of "crypt=crypt" is required for this to work. It
# tells the module that the passwords are encrypted.
auth required pam_userdb.so db=/t012/pam_userdb crypt=crypt

# Do the normal user account stuff.
account required pam_unix.so
46 changes: 46 additions & 0 deletions irods/test/scripts/test011_pam_interactive.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env bats

# The tests in this BATS module must be run as a (passwordless) sudo-enabled user.
# It is also required that the python irodsclient be installed under irods' ~/.local environment.

. $BATS_TEST_DIRNAME/test_support_functions

setup() {
[ -f /tmp/test011_flag ] || {
rm -fr ~/.irods
/prc/test_harness/utility/iinit.py host localhost \
port 1247 \
zone tempZone \
user rods \
password rods \

## Because iRODS 5+ negotiates for SSL automatically:
CLIENT_JSON=~/.irods/irods_environment.json
jq '.irods_client_server_policy="CS_NEG_REFUSE"' >$CLIENT_JSON.$$ <$CLIENT_JSON && \
mv $CLIENT_JSON.$$ $CLIENT_JSON

sudo apt install irods-auth-plugin-pam-interactive-{client,server}

setup_pam_login_for_user "rods" alice

# Tests require only the irods_environment.json
rm -f ~/.irods/.irodsA

## Switch over to scheme to be tested.
jq '.irods_authentication_scheme="pam_interactive"' >$CLIENT_JSON.$$ <$CLIENT_JSON && \
mv $CLIENT_JSON.$$ $CLIENT_JSON
}
touch /tmp/test011_flag
}

original_test_suite()
{
local USER="alice"
local PASSWORD="rods"
sudo chpasswd <<<"$USER:$PASSWORD"
python -m unittest irods.test.pam_interactive_test_must_run_manually
}

@test "original_pam_interactive_tests" {
original_test_suite
}
88 changes: 88 additions & 0 deletions irods/test/scripts/test012_pam_interactive_multistep.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/usr/bin/env bats

# The tests in this BATS module must be run as a (passwordless) sudo-enabled user.
# It is also required that the python irodsclient be installed under irods' ~/.local environment.

SKIP_IINIT_FOR_PASSWORD=yes

. $BATS_TEST_DIRNAME/test_support_functions

export TESTUSER=alice
export FIRST_PASSWORD=somerods
export SECOND_PASSWORD=otherrods

setup() {
[ -f /tmp/test012_flag ] || {
rm -fr ~/.irods
/prc/test_harness/utility/iinit.py host localhost \
port 1247 \
zone tempZone \
user rods \
password rods \

sudo apt update
sudo apt install -y db-util libpam0g-dev

## Because iRODS 5+ negotiates for SSL automatically:
CLIENT_JSON=~/.irods/irods_environment.json
jq '.irods_client_server_policy="CS_NEG_REFUSE"' >$CLIENT_JSON.$$ <$CLIENT_JSON && \
mv $CLIENT_JSON.$$ $CLIENT_JSON

sudo apt install irods-auth-plugin-pam-interactive-{client,server}

setup_pam_login_for_user "${FIRST_PASSWORD}" $TESTUSER
sudo cp $BATS_TEST_DIRNAME/files_for_test012/pam_interactive /etc/pam.d/irods
sudo mkdir /t012 && sudo gcc -o /t012/pam_clear_token.so -fno-stack-protector -shared -fPIC $BATS_TEST_DIRNAME/files_for_test012/pam_clear_token.c

db_file=/t012/pam_userdb.db
sudo db_load -T -t hash "$db_file" <<<"${TESTUSER}"$'\n'"${SECOND_PASSWORD}"
sudo chown root:root "$db_file"
sudo chmod 600 "$db_file"

# Tests require only the irods_environment.json
rm -f ~/.irods/.irodsA

## Switch over to scheme to be tested.
jq '.irods_authentication_scheme="pam_interactive"' >$CLIENT_JSON.$$ <$CLIENT_JSON && \
mv $CLIENT_JSON.$$ $CLIENT_JSON
}
touch /tmp/test012_flag
}

@test "pam_interactive_test_multistep_with_correct_passwords" {
:
python -c"
import getpass
import irods
import os
from unittest.mock import patch

def getpass_new_callable(answers=()):
class iterate_answers:
def __init__(self,answers = answers):
self.answers = answers
self.count = 0
def __call__(self,*_):
count = self.count
self.count += 1
ans = self.answers[count]
print ('*** giving answer:', ans)
return ans
return lambda : iterate_answers()

home = None

with patch(
'getpass.getpass',
new_callable=getpass_new_callable(answers=[os.environ['FIRST_PASSWORD'],os.environ['SECOND_PASSWORD']])
):
sess = irods.helpers.make_session(test_server_version=False)
home = sess.collections.get(f'/{sess.zone}/home/{sess.username}')

if home is None:
exit(2)
username = os.environ['TESTUSER']
if not home.path.endswith(f'/{username}'):
exit(1)
"
}
13 changes: 12 additions & 1 deletion test_harness/single_node/docker_container_driver.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

# Options:

ENV_VARS=()
IRODS_CONTROL_PATH=""
KILL_TEST_CONTAINER=1
RUN_AS_USER=""
Expand All @@ -26,6 +27,9 @@ usage() {
$0 [options] /external/path/to/script"

echo 'Options :
-E SETTING set in docker environment: argument is a single env setting like: "ENVVAR=<value>" where
<value> can may contain whitespace. "-E" may occur multiple times.
-e SETTINGS set in docker environment: argument is a list of env settings (format: VAR=VAL) separated by spaces
-V (extra verbosity). Prints out useful stuff including VERSION information
-u USERNAME run test in container as this USERNAME
-i invoke container with -i and -t
Expand Down Expand Up @@ -60,6 +64,13 @@ while [[ $1 = -* ]]; do
elif [ "$1" = -r ]; then
REMOVE_OPTION="$2"
shift 2
elif [ "$1" = -E ]; then
ENV_VARS+=(-e "$2")
shift 2
elif [ "$1" = -e ]; then
ENV_VAR_ARRAY=($2)
ENV_VARS="${ENV_VAR_ARRAY[*]/#/-e }"
shift 2
elif [ "$1" = -w ]; then
EXPLICIT_WORKDIR="$2"
shift 2
Expand Down Expand Up @@ -126,7 +137,7 @@ INNER_MOUNT=/prc

# Start the container.
echo image="[$image]"
CONTAINER=$($DOCKER run -d -v "$reporoot:$INNER_MOUNT:ro" $INTERACTIVE_OPTION $REMOVE_OPTION \
CONTAINER=$($DOCKER run "${ENV_VARS[@]}" -d -v "$reporoot:$INNER_MOUNT:ro" $INTERACTIVE_OPTION $REMOVE_OPTION \
-e "IRODS_CONTROL_PATH=$IRODS_CONTROL_PATH" $image)

# Wait for iRODS and database to start up.
Expand Down
2 changes: 2 additions & 0 deletions test_harness/single_node/test_script_parameters
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ declare -A wrappers=(
[test008_prc_write_irodsA_utility_in_native_mode.bats]=../login_auth_test.sh
[test009_test_special_characters_in_pam_passwords_auth_framework.bats]=../login_auth_test.sh
[test010_issue_362_rogue_chars_in_pam_password.bats]=../login_auth_test.sh
[test011_pam_interactive.bats]=../login_auth_test.sh
[test012_pam_interactive_multistep.bats]=../login_auth_test.sh
)

# keys for Image and User refer to the basename after resolution to a wrapper if one is used
Expand Down
Loading