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

Reply via email to