From 4ab45c598e0aad84b2b7da672f30c94f53abfc60 Mon Sep 17 00:00:00 2001 From: d-w-moore Date: Mon, 4 Nov 2024 04:41:16 -0500 Subject: [PATCH 01/10] [_650] new escaped character processing This fixes the approach to escaping characters from the set: [@&;=] that iRODS historically has had problems accommodating in PAM passwords in the past. Presently, for iRODS 4.2 and 4.3 we only need to consider ";" and "=" as problematic characters, due to the conflict with the use of those characters in the KVP-formatted context parameter when the AUTH_PLUG_REQ_AN api is used. --- irods/client_configuration/__init__.py | 3 +- irods/connection.py | 20 +++--- ...write_pam_credentials_to_secrets_file.bats | 64 +++++++++++++++++++ 3 files changed, 77 insertions(+), 10 deletions(-) create mode 100755 irods/test/scripts/test005_write_pam_credentials_to_secrets_file.bats diff --git a/irods/client_configuration/__init__.py b/irods/client_configuration/__init__.py index fa412a50..479d887e 100644 --- a/irods/client_configuration/__init__.py +++ b/irods/client_configuration/__init__.py @@ -88,11 +88,12 @@ def __init__(self): class LegacyAuth(iRODSConfiguration): __slots__ = ('pam',) class Pam(iRODSConfiguration): - __slots__ = ('time_to_live_in_hours', 'password_for_auto_renew', 'store_password_to_environment') + __slots__ = ('time_to_live_in_hours', 'password_for_auto_renew', 'store_password_to_environment','force_use_of_dedicated_pam_api') def __init__(self): self.time_to_live_in_hours = 0 # -> We default to the server's TTL preference. self.password_for_auto_renew = '' self.store_password_to_environment = False + self.force_use_of_dedicated_pam_api = False def __init__(self): self.pam = self.Pam() diff --git a/irods/connection.py b/irods/connection.py index 3ec587fc..946468f8 100644 --- a/irods/connection.py +++ b/irods/connection.py @@ -11,7 +11,6 @@ from ast import literal_eval as safe_eval import re -PAM_PW_ESC_PATTERN = re.compile(r'([@=&;])') from irods.message import ( @@ -460,8 +459,7 @@ def _login_pam(self): import irods.client_configuration as cfg inline_password = (self.account.authentication_scheme == self.account._original_authentication_scheme) time_to_live_in_hours = cfg.legacy_auth.pam.time_to_live_in_hours - # For certain characters in the pam password, if they need escaping with '\' then do so. - new_pam_password = PAM_PW_ESC_PATTERN.sub(lambda m: '\\'+m.group(1), self.account.password) + new_pam_password = self.account.password if not inline_password and cfg.legacy_auth.pam.password_for_auto_renew is not None: # Login using PAM password from .irodsA try: @@ -476,9 +474,13 @@ def _login_pam(self): # Login succeeded, so we're within the time-to-live and can return without error. return + # Some characters need to be escaped for the key-value format and parser. + KVP_ESCAPED_CHARS = r'\;=' + kvp_escape = lambda s:''.join((fr'\{c}' if c in KVP_ESCAPED_CHARS else c) for c in s) + # Generate a new PAM password. ctx_user = '%s=%s' % (AUTH_USER_KEY, self.account.client_user) - ctx_pwd = '%s=%s' % (AUTH_PWD_KEY, new_pam_password) + ctx_pwd = '%s=%s' % (AUTH_PWD_KEY, kvp_escape(new_pam_password)) ctx_ttl = '%s=%s' % (AUTH_TTL_KEY, str(time_to_live_in_hours)) ctx = ";".join([ctx_user, ctx_pwd, ctx_ttl]) @@ -487,16 +489,16 @@ def _login_pam(self): if getattr(self,'DISALLOWING_PAM_PLAINTEXT',True): raise PlainTextPAMPasswordError - # In general authentication API, a ';' and '=' in the password would be misinterpreted due to those - # characters' special meaning in the context string parameter. - use_dedicated_pam_api = len(ctx) >= MAX_NAME_LEN or \ - {';','='}.intersection(set(new_pam_password)) + use_dedicated_pam_api = (len(ctx) >= MAX_NAME_LEN) or \ + cfg.legacy_auth.pam.force_use_of_dedicated_pam_api if use_dedicated_pam_api: + method = "PamAuthRequest" message_body = PamAuthRequest( pamUser = self.account.client_user, pamPassword = new_pam_password, timeToLive = time_to_live_in_hours) else: + method = "PluginAuthMessage" message_body = PluginAuthMessage( auth_scheme_ = PAM_AUTH_SCHEME, context_ = ctx) auth_req = iRODSMessage( @@ -534,7 +536,7 @@ def _login_pam(self): f.write(obf.encode(auth_out.result_)) logger.debug('new PAM pw write succeeded') - logger.info("PAM authorization validated") + logger.info(f"PAM authorization validated (via {method})") def read_file(self, desc, size=-1, buffer=None): if size < 0: diff --git a/irods/test/scripts/test005_write_pam_credentials_to_secrets_file.bats b/irods/test/scripts/test005_write_pam_credentials_to_secrets_file.bats new file mode 100755 index 00000000..6dd1dd3a --- /dev/null +++ b/irods/test/scripts/test005_write_pam_credentials_to_secrets_file.bats @@ -0,0 +1,64 @@ +#!/usr/bin/env bats +# +# Test creation of .irodsA for iRODS native authentication using the free function, +# irods.client_init.write_pam_credentials_to_secrets_file + +. "$BATS_TEST_DIRNAME"/test_support_functions +PYTHON=python3 + +# Setup/prerequisites are same as for login_auth_test. +# Run as ubuntu user with sudo; python_irodsclient must be installed (in either ~/.local or a virtualenv) +# + +ALICES_OLD_PAM_PASSWD="test123" +ALICES_NEW_PAM_PASSWD="new_&@;=_pass" + +setup() +{ + setup_pam_login_for_alice "$ALICES_OLD_PAM_PASSWD" +} + +teardown() +{ + finalize_pam_login_for_alice + test_specific_cleanup +} + +@test create_secrets_file { + + # Old .irodsA is already created, so we delete it and alter the pam password. + sudo chpasswd <<<"alice:$ALICES_NEW_PAM_PASSWD" + local logfile i + for force_long_token_compatible_api in False True; do + logfile=/tmp/prc_logs.$((++i)) + sudo su - irods -c 'iadmin rpp alice' + rm -f ~/.irods/.irodsA + $PYTHON -c "import irods.client_init +import logging +logger = logging.getLogger('irods.connection') +logger.setLevel(logging.INFO) +logger.addHandler(logging.FileHandler('$logfile')) +irods.client_configuration.legacy_auth.pam.force_use_of_dedicated_pam_api = $force_long_token_compatible_api +irods.client_init.write_pam_credentials_to_secrets_file('$ALICES_NEW_PAM_PASSWD')" + + # Make sure the iinit-like routines created the catalog entry for the PAM password using the algorithm we expected it to call. + log_content=$(cat $logfile) + declare -A method=([True]=PamAuthRequest + [False]=PluginAuthMessage) + [[ $log_content =~ "PAM authorization validated (via ${method[$force_long_token_compatible_api]})" ]] + + # Define the core Python to be run, basically a minimal code block ensuring that we can authenticate to iRODS + # without an exception being raised. + + local SCRIPT=" +import irods +import irods.test.helpers as h +ses = h.make_session() +ses.collections.get(h.home_collection(ses)) +print ('env_auth_scheme=%s' % ses.pool.account._original_authentication_scheme) +" + OUTPUT=$($PYTHON -c "$SCRIPT") + # Assert passing value + [[ $OUTPUT = "env_auth_scheme=pam"* ]] + done +} From 183e6e680611dd605049d028e1707b9708b8b091 Mon Sep 17 00:00:00 2001 From: d-w-moore Date: Tue, 5 Nov 2024 20:51:58 -0500 Subject: [PATCH 02/10] [_655] Swap names of native and pam .irodsA generation test scripts. Also correct matching auth scheme names for PAM. We now compare to "pam"* so that iRODS 4.2 and 4.3 can both pass the tests. --- ...te_native_credentials_to_secrets_file.bats | 37 +++++++------------ ...write_pam_credentials_to_secrets_file.bats | 37 ++++++++++++------- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/irods/test/scripts/test002_write_native_credentials_to_secrets_file.bats b/irods/test/scripts/test002_write_native_credentials_to_secrets_file.bats index dc1837d2..1e688222 100755 --- a/irods/test/scripts/test002_write_native_credentials_to_secrets_file.bats +++ b/irods/test/scripts/test002_write_native_credentials_to_secrets_file.bats @@ -1,7 +1,7 @@ #!/usr/bin/env bats # -# Test creation of .irodsA for iRODS native authentication using the free function, -# irods.client_init.write_pam_credentials_to_secrets_file +# Test creation of .irodsA for iRODS pam_password authentication using the free function, +# irods.client_init.write_native_credentials_to_secrets_file . "$BATS_TEST_DIRNAME"/test_support_functions PYTHON=python3 @@ -10,26 +10,18 @@ PYTHON=python3 # Run as ubuntu user with sudo; python_irodsclient must be installed (in either ~/.local or a virtualenv) # -ALICES_OLD_PAM_PASSWD="test123" -ALICES_NEW_PAM_PASSWD="new_pass" +@test create_irods_secrets_file { -setup() -{ - setup_pam_login_for_alice "$ALICES_OLD_PAM_PASSWD" -} - -teardown() -{ - finalize_pam_login_for_alice - test_specific_cleanup -} - -@test create_secrets_file { - - # Old .irodsA is already created, so we delete it and alter the pam password. - sudo chpasswd <<<"alice:$ALICES_NEW_PAM_PASSWD" - rm -f ~/.irods/.irodsA - $PYTHON -c "import irods.client_init; irods.client_init.write_pam_credentials_to_secrets_file('$ALICES_NEW_PAM_PASSWD')" + rm -fr ~/.irods + mkdir ~/.irods + cat > ~/.irods/irods_environment.json <<-EOF + { "irods_host":"$(hostname)", + "irods_port":1247, + "irods_user_name":"rods", + "irods_zone_name":"tempZone" + } + EOF + $PYTHON -c "import irods.client_init; irods.client_init.write_native_credentials_to_secrets_file('rods')" # Define the core Python to be run, basically a minimal code block ensuring that we can authenticate to iRODS # without an exception being raised. @@ -42,6 +34,5 @@ print ('env_auth_scheme=%s' % ses.pool.account._original_authentication_scheme) " OUTPUT=$($PYTHON -c "$SCRIPT") # Assert passing value - [ $OUTPUT = "env_auth_scheme=pam_password" ] - + [[ $OUTPUT = "env_auth_scheme=native" ]] } diff --git a/irods/test/scripts/test003_write_pam_credentials_to_secrets_file.bats b/irods/test/scripts/test003_write_pam_credentials_to_secrets_file.bats index 4686755f..b6d4886a 100755 --- a/irods/test/scripts/test003_write_pam_credentials_to_secrets_file.bats +++ b/irods/test/scripts/test003_write_pam_credentials_to_secrets_file.bats @@ -1,7 +1,7 @@ #!/usr/bin/env bats # -# Test creation of .irodsA for iRODS pam_password authentication using the free function, -# irods.client_init.write_native_credentials_to_secrets_file +# Test creation of .irodsA for iRODS native authentication using the free function, +# irods.client_init.write_pam_credentials_to_secrets_file . "$BATS_TEST_DIRNAME"/test_support_functions PYTHON=python3 @@ -10,18 +10,26 @@ PYTHON=python3 # Run as ubuntu user with sudo; python_irodsclient must be installed (in either ~/.local or a virtualenv) # -@test create_irods_secrets_file { +ALICES_OLD_PAM_PASSWD="test123" +ALICES_NEW_PAM_PASSWD="new_pass" - rm -fr ~/.irods - mkdir ~/.irods - cat > ~/.irods/irods_environment.json <<-EOF - { "irods_host":"$(hostname)", - "irods_port":1247, - "irods_user_name":"rods", - "irods_zone_name":"tempZone" - } - EOF - $PYTHON -c "import irods.client_init; irods.client_init.write_native_credentials_to_secrets_file('rods')" +setup() +{ + setup_pam_login_for_alice "$ALICES_OLD_PAM_PASSWD" +} + +teardown() +{ + finalize_pam_login_for_alice + test_specific_cleanup +} + +@test create_secrets_file { + + # Old .irodsA is already created, so we delete it and alter the pam password. + sudo chpasswd <<<"alice:$ALICES_NEW_PAM_PASSWD" + rm -f ~/.irods/.irodsA + $PYTHON -c "import irods.client_init; irods.client_init.write_pam_credentials_to_secrets_file('$ALICES_NEW_PAM_PASSWD')" # Define the core Python to be run, basically a minimal code block ensuring that we can authenticate to iRODS # without an exception being raised. @@ -34,5 +42,6 @@ print ('env_auth_scheme=%s' % ses.pool.account._original_authentication_scheme) " OUTPUT=$($PYTHON -c "$SCRIPT") # Assert passing value - [ $OUTPUT = "env_auth_scheme=native" ] + [[ $OUTPUT = "env_auth_scheme=pam"* ]] + } From 252025316a45a9beb68bae796109f5620ddcddcc Mon Sep 17 00:00:00 2001 From: d-w-moore Date: Wed, 6 Nov 2024 06:44:41 -0500 Subject: [PATCH 03/10] codacy; and, use logging.config.dictConfig --- irods/connection.py | 2 +- ...est005_write_pam_credentials_to_secrets_file.bats | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/irods/connection.py b/irods/connection.py index 946468f8..aced8fea 100644 --- a/irods/connection.py +++ b/irods/connection.py @@ -536,7 +536,7 @@ def _login_pam(self): f.write(obf.encode(auth_out.result_)) logger.debug('new PAM pw write succeeded') - logger.info(f"PAM authorization validated (via {method})") + logger.info(f"PAM authorization validated (via %s)",method) def read_file(self, desc, size=-1, buffer=None): if size < 0: diff --git a/irods/test/scripts/test005_write_pam_credentials_to_secrets_file.bats b/irods/test/scripts/test005_write_pam_credentials_to_secrets_file.bats index 6dd1dd3a..90a04c91 100755 --- a/irods/test/scripts/test005_write_pam_credentials_to_secrets_file.bats +++ b/irods/test/scripts/test005_write_pam_credentials_to_secrets_file.bats @@ -34,10 +34,14 @@ teardown() sudo su - irods -c 'iadmin rpp alice' rm -f ~/.irods/.irodsA $PYTHON -c "import irods.client_init -import logging -logger = logging.getLogger('irods.connection') -logger.setLevel(logging.INFO) -logger.addHandler(logging.FileHandler('$logfile')) +import logging.config +logging.config.dictConfig( +{'handlers': {'file': {'class': 'logging.FileHandler', + 'filename': '$logfile'}}, + 'loggers': {'irods.connection': {'handlers': ['file'], + 'level': 'INFO'}}, + 'version': 1} +) irods.client_configuration.legacy_auth.pam.force_use_of_dedicated_pam_api = $force_long_token_compatible_api irods.client_init.write_pam_credentials_to_secrets_file('$ALICES_NEW_PAM_PASSWD')" From 530062a29e023212b0ab2a97677ac7235eff6469 Mon Sep 17 00:00:00 2001 From: d-w-moore Date: Wed, 6 Nov 2024 07:49:25 -0500 Subject: [PATCH 04/10] indentation --- .../scripts/test005_write_pam_credentials_to_secrets_file.bats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/irods/test/scripts/test005_write_pam_credentials_to_secrets_file.bats b/irods/test/scripts/test005_write_pam_credentials_to_secrets_file.bats index 90a04c91..eef2d974 100755 --- a/irods/test/scripts/test005_write_pam_credentials_to_secrets_file.bats +++ b/irods/test/scripts/test005_write_pam_credentials_to_secrets_file.bats @@ -49,7 +49,7 @@ irods.client_init.write_pam_credentials_to_secrets_file('$ALICES_NEW_PAM_PASSWD' log_content=$(cat $logfile) declare -A method=([True]=PamAuthRequest [False]=PluginAuthMessage) - [[ $log_content =~ "PAM authorization validated (via ${method[$force_long_token_compatible_api]})" ]] + [[ $log_content =~ "PAM authorization validated (via ${method[$force_long_token_compatible_api]})" ]] # Define the core Python to be run, basically a minimal code block ensuring that we can authenticate to iRODS # without an exception being raised. From e5fa4de5e2fdb3120ca9ef38f791ade7401cde73 Mon Sep 17 00:00:00 2001 From: d-w-moore Date: Thu, 7 Nov 2024 10:50:11 -0500 Subject: [PATCH 05/10] whitespace needed after comma --- irods/client_configuration/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/irods/client_configuration/__init__.py b/irods/client_configuration/__init__.py index 479d887e..c3f223e3 100644 --- a/irods/client_configuration/__init__.py +++ b/irods/client_configuration/__init__.py @@ -88,7 +88,7 @@ def __init__(self): class LegacyAuth(iRODSConfiguration): __slots__ = ('pam',) class Pam(iRODSConfiguration): - __slots__ = ('time_to_live_in_hours', 'password_for_auto_renew', 'store_password_to_environment','force_use_of_dedicated_pam_api') + __slots__ = ('time_to_live_in_hours', 'password_for_auto_renew', 'store_password_to_environment', 'force_use_of_dedicated_pam_api') def __init__(self): self.time_to_live_in_hours = 0 # -> We default to the server's TTL preference. self.password_for_auto_renew = '' From 6f59d53fd6ff013d6ee078f67402b60c458e8a2c Mon Sep 17 00:00:00 2001 From: d-w-moore Date: Fri, 8 Nov 2024 04:26:21 -0500 Subject: [PATCH 06/10] add words about the internal selection of PAM auth APIs --- irods/connection.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/irods/connection.py b/irods/connection.py index aced8fea..22abedd4 100644 --- a/irods/connection.py +++ b/irods/connection.py @@ -489,6 +489,11 @@ def _login_pam(self): if getattr(self,'DISALLOWING_PAM_PLAINTEXT',True): raise PlainTextPAMPasswordError + # Normally, we use the AUTH_PLUG_REQ_AN api ( generalized to handle both PAM and GSI, as evidenced in the gsi_client_auth_request() method.) + # However, it has a practical limit to the number of characters in a context_ parameter (defined in packStruct as str[MAX_NAME_LEN]. + # Whereas PAM_AUTH_REQUEST_AN is an older api and defines pamPassword as type str*, with apparently no length limit. + # TODO : perhaps we should always use PAM_AUTH_REQUEST_AN ?? + use_dedicated_pam_api = (len(ctx) >= MAX_NAME_LEN) or \ cfg.legacy_auth.pam.force_use_of_dedicated_pam_api From 0d5eecb5296c1181ae23f96ed4416825802be5ce Mon Sep 17 00:00:00 2001 From: d-w-moore Date: Fri, 15 Nov 2024 23:00:10 -0500 Subject: [PATCH 07/10] add README text for the force_use_of_dedicated_pam_api setting --- README.md | 7 +++++++ irods/connection.py | 7 +++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9b0effc3..e1868e36 100644 --- a/README.md +++ b/README.md @@ -557,6 +557,13 @@ variables serving as overrides: - Default Value: `False` - Environment Variable Override: `PYTHON_IRODSCLIENT_CONFIG__LEGACY_AUTH__PAM__STORE_PASSWORD_TO_ENVIRONMENT` +- Setting: Force the use of PAM_AUTH_REQUEST_AN API for entering a new PAM password into the catalog. This API accommodates longer passwords and avoids the step of parsing a semicolon-delimited + "context" parameter. + - Dotted Name: `legacy_auth.pam.force_use_of_dedicated_pam_api` + - Type: `bool` + - Default Value: `False` + - Environment Variable Override: `PYTHON_IRODSCLIENT_CONFIG__LEGACY_AUTH__PAM__FORCE_USE_OF_DEDICATED_PAM_API` + - Setting: Default choice of XML parser for all new threads. - Dotted Name: `connections.xml_parser_default` - Type: `str` diff --git a/irods/connection.py b/irods/connection.py index 22abedd4..da74af31 100644 --- a/irods/connection.py +++ b/irods/connection.py @@ -489,10 +489,9 @@ def _login_pam(self): if getattr(self,'DISALLOWING_PAM_PLAINTEXT',True): raise PlainTextPAMPasswordError - # Normally, we use the AUTH_PLUG_REQ_AN api ( generalized to handle both PAM and GSI, as evidenced in the gsi_client_auth_request() method.) - # However, it has a practical limit to the number of characters in a context_ parameter (defined in packStruct as str[MAX_NAME_LEN]. - # Whereas PAM_AUTH_REQUEST_AN is an older api and defines pamPassword as type str*, with apparently no length limit. - # TODO : perhaps we should always use PAM_AUTH_REQUEST_AN ?? + # Normally, we use the AUTH_PLUG_REQ_AN api (generalized to handle both PAM and GSI, as evidenced in the gsi_client_auth_request() method.) + # However, it has a practical limit to the number of characters in a context_ parameter (defined in packStruct as "str[MAX_NAME_LEN]". + # Whereas PAM_AUTH_REQUEST_AN is an older api and defines pamPassword as a "str*" entry, with apparently no length limit. use_dedicated_pam_api = (len(ctx) >= MAX_NAME_LEN) or \ cfg.legacy_auth.pam.force_use_of_dedicated_pam_api From feb0e044c332da72d2f45b0abab94a4b8e372f32 Mon Sep 17 00:00:00 2001 From: d-w-moore Date: Fri, 15 Nov 2024 23:43:55 -0500 Subject: [PATCH 08/10] change logging and test to use pam api name. This is for more consistent naming of things across source code bases. --- irods/connection.py | 10 ++++++---- .../test005_write_pam_credentials_to_secrets_file.bats | 10 +++++----- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/irods/connection.py b/irods/connection.py index da74af31..32b89a9d 100644 --- a/irods/connection.py +++ b/irods/connection.py @@ -493,8 +493,8 @@ def _login_pam(self): # However, it has a practical limit to the number of characters in a context_ parameter (defined in packStruct as "str[MAX_NAME_LEN]". # Whereas PAM_AUTH_REQUEST_AN is an older api and defines pamPassword as a "str*" entry, with apparently no length limit. - use_dedicated_pam_api = (len(ctx) >= MAX_NAME_LEN) or \ - cfg.legacy_auth.pam.force_use_of_dedicated_pam_api + use_dedicated_pam_api = cfg.legacy_auth.pam.force_use_of_dedicated_pam_api or ( + len(ctx) >= MAX_NAME_LEN ) if use_dedicated_pam_api: method = "PamAuthRequest" @@ -505,10 +505,12 @@ def _login_pam(self): method = "PluginAuthMessage" message_body = PluginAuthMessage( auth_scheme_ = PAM_AUTH_SCHEME, context_ = ctx) + api_name = ('PAM_AUTH_REQUEST_AN' if use_dedicated_pam_api else 'AUTH_PLUG_REQ_AN') + auth_req = iRODSMessage( msg_type='RODS_API_REQ', msg=message_body, - int_info=api_number['PAM_AUTH_REQUEST_AN' if use_dedicated_pam_api else 'AUTH_PLUG_REQ_AN'] + int_info=api_number[api_name] ) self.send(auth_req) @@ -540,7 +542,7 @@ def _login_pam(self): f.write(obf.encode(auth_out.result_)) logger.debug('new PAM pw write succeeded') - logger.info(f"PAM authorization validated (via %s)",method) + logger.info(f"PAM authorization validated (via %s)", api_name) def read_file(self, desc, size=-1, buffer=None): if size < 0: diff --git a/irods/test/scripts/test005_write_pam_credentials_to_secrets_file.bats b/irods/test/scripts/test005_write_pam_credentials_to_secrets_file.bats index eef2d974..4992b241 100755 --- a/irods/test/scripts/test005_write_pam_credentials_to_secrets_file.bats +++ b/irods/test/scripts/test005_write_pam_credentials_to_secrets_file.bats @@ -29,7 +29,7 @@ teardown() # Old .irodsA is already created, so we delete it and alter the pam password. sudo chpasswd <<<"alice:$ALICES_NEW_PAM_PASSWD" local logfile i - for force_long_token_compatible_api in False True; do + for force_flexible_pam_login_api in False True; do logfile=/tmp/prc_logs.$((++i)) sudo su - irods -c 'iadmin rpp alice' rm -f ~/.irods/.irodsA @@ -42,14 +42,14 @@ logging.config.dictConfig( 'level': 'INFO'}}, 'version': 1} ) -irods.client_configuration.legacy_auth.pam.force_use_of_dedicated_pam_api = $force_long_token_compatible_api +irods.client_configuration.legacy_auth.pam.force_use_of_dedicated_pam_api = $force_flexible_pam_login_api irods.client_init.write_pam_credentials_to_secrets_file('$ALICES_NEW_PAM_PASSWD')" # Make sure the iinit-like routines created the catalog entry for the PAM password using the algorithm we expected it to call. log_content=$(cat $logfile) - declare -A method=([True]=PamAuthRequest - [False]=PluginAuthMessage) - [[ $log_content =~ "PAM authorization validated (via ${method[$force_long_token_compatible_api]})" ]] + declare -A pam_api=([True]=PAM_AUTH_REQUEST_AN + [False]=AUTH_PLUG_REQ_AN) + [[ $log_content =~ "PAM authorization validated (via ${pam_api[$force_flexible_pam_login_api]})" ]] # Define the core Python to be run, basically a minimal code block ensuring that we can authenticate to iRODS # without an exception being raised. From 7ac84a57c45a13d69a098f77ccd6e5aaaef6c00b Mon Sep 17 00:00:00 2001 From: Daniel Moore Date: Fri, 22 Nov 2024 09:43:30 -0500 Subject: [PATCH 09/10] Update irods/connection.py Co-authored-by: Alan King --- irods/connection.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/irods/connection.py b/irods/connection.py index 32b89a9d..6d08c85d 100644 --- a/irods/connection.py +++ b/irods/connection.py @@ -490,7 +490,7 @@ def _login_pam(self): raise PlainTextPAMPasswordError # Normally, we use the AUTH_PLUG_REQ_AN api (generalized to handle both PAM and GSI, as evidenced in the gsi_client_auth_request() method.) - # However, it has a practical limit to the number of characters in a context_ parameter (defined in packStruct as "str[MAX_NAME_LEN]". + # However, it has a practical limit to the number of characters in a context_ parameter (defined in packStruct as "str[MAX_NAME_LEN]"). # Whereas PAM_AUTH_REQUEST_AN is an older api and defines pamPassword as a "str*" entry, with apparently no length limit. use_dedicated_pam_api = cfg.legacy_auth.pam.force_use_of_dedicated_pam_api or ( From bcc4b845f1dfc0670aa93bc9f4681cd2f36a4713 Mon Sep 17 00:00:00 2001 From: d-w-moore Date: Fri, 22 Nov 2024 13:34:37 -0500 Subject: [PATCH 10/10] codacy --- irods/connection.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/irods/connection.py b/irods/connection.py index 6d08c85d..ce3dde8d 100644 --- a/irods/connection.py +++ b/irods/connection.py @@ -497,12 +497,10 @@ def _login_pam(self): len(ctx) >= MAX_NAME_LEN ) if use_dedicated_pam_api: - method = "PamAuthRequest" message_body = PamAuthRequest( pamUser = self.account.client_user, pamPassword = new_pam_password, timeToLive = time_to_live_in_hours) else: - method = "PluginAuthMessage" message_body = PluginAuthMessage( auth_scheme_ = PAM_AUTH_SCHEME, context_ = ctx) api_name = ('PAM_AUTH_REQUEST_AN' if use_dedicated_pam_api else 'AUTH_PLUG_REQ_AN') @@ -542,7 +540,7 @@ def _login_pam(self): f.write(obf.encode(auth_out.result_)) logger.debug('new PAM pw write succeeded') - logger.info(f"PAM authorization validated (via %s)", api_name) + logger.info("PAM authorization validated (via %s)", api_name) def read_file(self, desc, size=-1, buffer=None): if size < 0: