URL: https://github.com/freeipa/freeipa/pull/1416 Author: felipevolpone Title: #1416: Do not allow users delete their last otp token Action: opened
PR body: """ This adds a new verification on the ipa_otp_lasttoken 389 plugin, in order to do not allow users delete their last otp token. The verification is done checking if the global configuration is set to otp in `cn=ipaConfig,cn=etc` Fixes: [7012](https://pagure.io/freeipa/issue/7012) """ To pull the PR as Git branch: git remote add ghfreeipa https://github.com/freeipa/freeipa git fetch ghfreeipa pull/1416/head:pr1416 git checkout pr1416
From 99991f626781d0aaa8866d248abcbc8aedb943c7 Mon Sep 17 00:00:00 2001 From: Felipe Barreto <fbarr...@redhat.com> Date: Wed, 20 Dec 2017 09:44:20 -0200 Subject: [PATCH] Do not allow users delete their last otp token This adds a new verification on the ipa_otp_lasttoken 389 plugin, in order to do not allow users delete their last otp token. The verification is done checking if the global configuration is set to otp in cn=ipaConfig,cn=etc. Fixes: 7012 --- .../ipa-otp-lasttoken/ipa_otp_lasttoken.c | 38 +++++++++++++++ ipatests/test_integration/test_otp.py | 54 ++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 ipatests/test_integration/test_otp.py diff --git a/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c b/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c index a085a3a328..3f59f08840 100644 --- a/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c +++ b/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c @@ -105,6 +105,41 @@ static bool sdn_is_only_enabled_token(Slapi_DN *target_sdn, const char *user_dn) return result; } +static bool is_otp_enabled(const char *user_dn) +{ + char *attrs[] = { "ipaUserAuthType", NULL }; + Slapi_Entry *entry = NULL; + Slapi_DN *sdn; + const Slapi_DN *base; + uint32_t authtypes; + int search_result = 0; + char *authConfigDN; + + sdn = slapi_sdn_new_dn_byval(user_dn); + base = slapi_get_suffix_by_dn(sdn); + + authConfigDN = slapi_ch_smprintf("cn=ipaConfig,cn=etc,%s", + slapi_sdn_get_dn(base)); + sdn = slapi_sdn_new_dn_byval(authConfigDN); + + search_result = slapi_search_internal_get_entry(sdn, attrs, &entry, + otp_config_plugin_id(otp_config)); + if (search_result != LDAP_SUCCESS) { + LOG_TRACE("File '%s' line %d: Unable to access LDAP entry '%s'. " + "Perhaps it doesn't exist? Error code: %d\n", __FILE__, + __LINE__, slapi_sdn_get_dn(sdn), search_result); + } + + slapi_sdn_free(&sdn); + if (entry == NULL) + return false; + + authtypes = otp_config_auth_types(otp_config, entry); + slapi_entry_free(entry); + + return authtypes & OTP_CONFIG_AUTH_TYPE_OTP; +} + static bool is_pwd_enabled(const char *user_dn) { char *attrs[] = { "ipaUserAuthType", NULL }; @@ -159,6 +194,9 @@ static bool is_allowed(Slapi_PBlock *pb, Slapi_Entry *entry) if (!sdn_is_only_enabled_token(target_sdn, bind_dn)) return true; + if (is_otp_enabled(bind_dn)) + return false; + if (is_pwd_enabled(bind_dn)) return true; diff --git a/ipatests/test_integration/test_otp.py b/ipatests/test_integration/test_otp.py new file mode 100644 index 0000000000..d6935886d1 --- /dev/null +++ b/ipatests/test_integration/test_otp.py @@ -0,0 +1,54 @@ +# +# Copyright (C) 2017 FreeIPA Contributors see COPYING for license +# + +from ipatests.test_integration.base import IntegrationTest +from ipatests.pytest_plugins.integration import tasks + + +class TestOTPTokenCommand(IntegrationTest): + """Test functionality of the ipa otptoken-* commands""" + + topology = 'line' + + def test_delete_last_active_otp_token(self): + """Test if a user is able to delete their last token""" + + pwd = '12345678' + new_pwd = 'Secret123' + user_login = 'test1' + + tasks.kinit_admin(self.master) + self.master.run_command(['ipa', 'user-add', user_login, + '--first', 'test', '--last', 'user', + '--password'], + stdin_text=pwd) + + self.master.run_command(['ipa', 'passwd', user_login], + stdin_text=new_pwd) + + # set the global configs + self.master.run_command(['ipa', 'config-mod', + '--user-auth-type', 'otp']) + + self.master.run_command(['kdestroy', '-A']) + + # write the password down three times as it's needed when + # doing "kinit" for the first time + user_kinit_stdin_text = "%s\n%s\n%s\n" % (new_pwd, new_pwd, new_pwd) + self.master.run_command(['kinit', user_login], + stdin_text=user_kinit_stdin_text) + + result = self.master.run_command(['ipa', 'otptoken-add']) + assert 'Added OTP token' in result.stdout_text + + otp_result = self.master.run_command(['ipa', 'otptoken-find']) + + # example of output from otptoken-find command: + # ['-----', '1 OTP token matched', '-----', + # Unique ID: 7a09e308-e6ab-4318-aaf4-f00d57ed32de', + token = otp_result.stdout_text.split('\n')[3].split('ID:')[1].strip() + + result = self.master.run_command(['ipa', 'otptoken-del', token], + raiseonerr=False) + assert "Can't delete last active token" in result.stderr_text
_______________________________________________ FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org