[Freeipa-devel] [PATCHES] OTP Patches

Nathaniel McCallum npmccallum at redhat.com
Mon Feb 17 18:42:28 UTC 2014


On Mon, 2014-02-17 at 19:44 +0200, Alexander Bokovoy wrote:
> On Mon, 17 Feb 2014, Nathaniel McCallum wrote:
> >>From 357cc6a40c58f3f88f8e86c5224f2c042ab974d8 Mon Sep 17 00:00:00 2001
> >From: Nathaniel McCallum <npmccallum at redhat.com>
> >Date: Mon, 16 Dec 2013 16:19:08 -0500
> >Subject: [PATCH 2/4] Add OTP last token plugin
> >
> >This plugin prevents the deletion or deactivation of the last
> >valid token for a user. This prevents the user from migrating
> >back to single factor authentication once OTP has been enabled.
> >
> >Thanks to Mark Reynolds for helping me with this patch.
> >---
> > daemons/configure.ac                               |   1 +
> > daemons/ipa-slapi-plugins/Makefile.am              |   1 +
> > .../ipa-otp-lasttoken/Makefile.am                  |  28 ++++
> > .../ipa-otp-lasttoken/ipa-otp-lasttoken.sym        |   1 +
> > .../ipa-otp-lasttoken/ipa_otp_lasttoken.c          | 183 +++++++++++++++++++++
> > .../ipa-otp-lasttoken/otp-lasttoken-conf.ldif      |  15 ++
> > freeipa.spec.in                                    |   2 +
> > ipaserver/install/dsinstance.py                    |   4 +
> > 8 files changed, 235 insertions(+)
> > create mode 100644 daemons/ipa-slapi-plugins/ipa-otp-lasttoken/Makefile.am
> > create mode 100644 daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa-otp-lasttoken.sym
> > create mode 100644 daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c
> > create mode 100644 daemons/ipa-slapi-plugins/ipa-otp-lasttoken/otp-lasttoken-conf.ldif
> >
> >diff --git a/daemons/configure.ac b/daemons/configure.ac
> >index e5bf7f552c0d85acc7ae14e3da05ab8c948daa93..b4507a6d972f854331925e72869898576bdfd76f 100644
> >--- a/daemons/configure.ac
> >+++ b/daemons/configure.ac
> >@@ -314,6 +314,7 @@ AC_CONFIG_FILES([
> >     ipa-slapi-plugins/ipa-dns/Makefile
> >     ipa-slapi-plugins/ipa-enrollment/Makefile
> >     ipa-slapi-plugins/ipa-lockout/Makefile
> >+    ipa-slapi-plugins/ipa-otp-lasttoken/Makefile
> >     ipa-slapi-plugins/ipa-pwd-extop/Makefile
> >     ipa-slapi-plugins/ipa-extdom-extop/Makefile
> >     ipa-slapi-plugins/ipa-winsync/Makefile
> >diff --git a/daemons/ipa-slapi-plugins/Makefile.am b/daemons/ipa-slapi-plugins/Makefile.am
> >index 40725d2259d09010d2f82381543fc77d84435040..06e6ee8b86f138cce05f2184ac98c39ffaf9757f 100644
> >--- a/daemons/ipa-slapi-plugins/Makefile.am
> >+++ b/daemons/ipa-slapi-plugins/Makefile.am
> >@@ -7,6 +7,7 @@ SUBDIRS =			\
> > 	ipa-enrollment		\
> > 	ipa-lockout		\
> > 	ipa-modrdn		\
> >+	ipa-otp-lasttoken	\
> > 	ipa-pwd-extop		\
> > 	ipa-extdom-extop	\
> > 	ipa-uuid		\
> >diff --git a/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/Makefile.am b/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/Makefile.am
> >new file mode 100644
> >index 0000000000000000000000000000000000000000..1e3869bfda9f8fd14cd4d93d0d466780932ac40f
> >--- /dev/null
> >+++ b/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/Makefile.am
> >@@ -0,0 +1,28 @@
> >+MAINTAINERCLEANFILES = *~ Makefile.in
> >+PLUGIN_COMMON_DIR = ../common
> >+AM_CPPFLAGS =							\
> >+	-I.							\
> >+	-I$(srcdir)						\
> >+	-I$(srcdir)/../libotp					\
> >+	-I$(PLUGIN_COMMON_DIR)					\
> >+	-I/usr/include/dirsrv					\
> >+	-DPREFIX=\""$(prefix)"\" 				\
> >+	-DBINDIR=\""$(bindir)"\"				\
> >+	-DLIBDIR=\""$(libdir)"\" 				\
> >+	-DLIBEXECDIR=\""$(libexecdir)"\"			\
> >+	-DDATADIR=\""$(datadir)"\"				\
> >+	$(AM_CFLAGS)						\
> >+	$(LDAP_CFLAGS)						\
> >+	$(WARN_CFLAGS)
> >+
> >+plugindir = $(libdir)/dirsrv/plugins
> >+plugin_LTLIBRARIES = libipa_otp_lasttoken.la
> >+libipa_otp_lasttoken_la_SOURCES = ipa_otp_lasttoken.c
> >+libipa_otp_lasttoken_la_LDFLAGS = -avoid-version -export-symbols ipa-otp-lasttoken.sym
> >+libipa_otp_lasttoken_la_LIBADD =		\
> >+	$(LDAP_LIBS)				\
> >+	$(builddir)/../libotp/libotp.la
> >+
> >+appdir = $(IPA_DATA_DIR)
> >+app_DATA = otp-lasttoken-conf.ldif
> >+EXTRA_DIST = $(app_DATA)
> >diff --git a/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa-otp-lasttoken.sym b/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa-otp-lasttoken.sym
> >new file mode 100644
> >index 0000000000000000000000000000000000000000..e32dc32f5693547bf604480490f42511368fdb81
> >--- /dev/null
> >+++ b/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa-otp-lasttoken.sym
> >@@ -0,0 +1 @@
> >+ipa_otp_lasttoken_init
> >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
> >new file mode 100644
> >index 0000000000000000000000000000000000000000..4abeb671e29b40cdf9b005ff5bc6b12c6d91bb30
> >--- /dev/null
> >+++ b/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c
> >@@ -0,0 +1,183 @@
> >+/** BEGIN COPYRIGHT BLOCK
> >+ * This program is free software; you can redistribute it and/or modify
> >+ * it under the terms of the GNU General Public License as published by
> >+ * the Free Software Foundation, either version 3 of the License, or
> >+ * (at your option) any later version.
> >+ *
> >+ * This program is distributed in the hope that it will be useful,
> >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
> >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> >+ * GNU General Public License for more details.
> >+ *
> >+ * You should have received a copy of the GNU General Public License
> >+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> >+ *
> >+ * Additional permission under GPLv3 section 7:
> >+ *
> >+ * In the following paragraph, "GPL" means the GNU General Public
> >+ * License, version 3 or any later version, and "Non-GPL Code" means
> >+ * code that is governed neither by the GPL nor a license
> >+ * compatible with the GPL.
> >+ *
> >+ * You may link the code of this Program with Non-GPL Code and convey
> >+ * linked combinations including the two, provided that such Non-GPL
> >+ * Code only links to the code of this Program through those well
> >+ * defined interfaces identified in the file named EXCEPTION found in
> >+ * the source code files (the "Approved Interfaces"). The files of
> >+ * Non-GPL Code may instantiate templates or use macros or inline
> >+ * functions from the Approved Interfaces without causing the resulting
> >+ * work to be covered by the GPL. Only the copyright holders of this
> >+ * Program may make changes or additions to the list of Approved
> >+ * Interfaces.
> >+ *
> >+ * Authors:
> >+ * Nathaniel McCallum <npmccallum at redhat.com>
> >+ *
> >+ * Copyright (C) 2013 Red Hat, Inc.
> >+ * All rights reserved.
> >+ * END COPYRIGHT BLOCK **/
> >+
> >+#ifdef HAVE_CONFIG_H
> >+#  include <config.h>
> >+#endif
> >+
> >+#include <libotp.h>
> >+#include <time.h>
> >+
> >+#define PLUGIN_NAME               "ipa-otp-lasttoken"
> >+#define LOG(sev, ...) \
> >+    slapi_log_error(SLAPI_LOG_ ## sev, PLUGIN_NAME, \
> >+                    "%s: %s\n", __func__, __VA_ARGS__), -1
> >+
> >+static void *plugin_id;
> >+static const Slapi_PluginDesc preop_desc = {
> >+    PLUGIN_NAME,
> >+    "FreeIPA",
> >+    "FreeIPA/1.0",
> >+    "Protect the user's last active token"
> >+};
> >+
> >+static bool
> >+target_is_only_enabled_token(Slapi_PBlock *pb)
> >+{
> >+    Slapi_DN *target_sdn = NULL;
> >+    Slapi_DN *token_sdn = NULL;
> >+    struct otptoken **tokens;
> >+    char *user_dn = NULL;
> >+    bool match;
> >+
> >+    /* Ignore internal operations. */
> >+    if (slapi_op_internal(pb))
> >+        return false;
> >+
> >+    /* Get the current user's SDN. */
> >+    slapi_pblock_get(pb, SLAPI_CONN_DN, &user_dn);
> >+    if (user_dn == NULL)
> >+        return false;
> >+
> >+    /* Get the SDN of the only enabled token. */
> >+    tokens = otptoken_find(plugin_id, user_dn, NULL, true, NULL);
> >+    if (tokens != NULL && tokens[0] != NULL && tokens[1] == NULL)
> >+        token_sdn = slapi_sdn_dup(otptoken_get_sdn(tokens[0]));
> >+    otptoken_free_array(tokens);
> >+    if (token_sdn == NULL)
> >+        return false;
> >+
> >+    /* Get the target SDN. */
> >+    slapi_pblock_get(pb, SLAPI_TARGET_SDN, &target_sdn);
> >+    if (target_sdn == NULL) {
> >+        slapi_sdn_free(&token_sdn);
> >+        return false;
> >+    }
> >+
> >+    /* Does the target SDN match the only enabled token SDN? */
> >+    match = slapi_sdn_compare(token_sdn, target_sdn) == 0;
> >+    slapi_sdn_free(&token_sdn);
> >+    return match;
> >+}
> >+
> >+static inline int
> >+send_error(Slapi_PBlock *pb, int rc, char *errstr)
> >+{
> >+    slapi_send_ldap_result(pb, rc, NULL, errstr, 0, NULL);
> >+    slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
> >+    return rc;
> >+}
> >+
> >+static int
> >+preop_del(Slapi_PBlock *pb)
> >+{
> >+    if (!target_is_only_enabled_token(pb))
> >+        return 0;
> >+
> >+    return send_error(pb, LDAP_UNWILLING_TO_PERFORM,
> >+                      "Can't delete last active token");
> >+}
> >+
> >+static int
> >+preop_mod(Slapi_PBlock *pb)
> >+{
> >+    LDAPMod **mods = NULL;
> >+
> >+    if (!target_is_only_enabled_token(pb))
> >+        return 0;
> >+
> >+    /* Do not permit deactivation of the last active token. */
> >+    slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
> >+    for (int i = 0; mods != NULL && mods[i] != NULL; i++) {
> >+        if (strcasecmp(mods[i]->mod_type, "ipatokenDisabled") == 0) {
> >+            return send_error(pb, LDAP_UNWILLING_TO_PERFORM,
> >+                              "Can't disable last active token");
> >+        }
> >+
> >+        if (strcasecmp(mods[i]->mod_type, "ipatokenOwner") == 0) {
> >+            return send_error(pb, LDAP_UNWILLING_TO_PERFORM,
> >+                              "Can't change last active token's owner");
> >+        }
> >+
> >+        if (strcasecmp(mods[i]->mod_type, "ipatokenNotBefore") == 0) {
> >+            return send_error(pb, LDAP_UNWILLING_TO_PERFORM,
> >+                              "Can't change last active token's start time");
> >+        }
> >+
> >+        if (strcasecmp(mods[i]->mod_type, "ipatokenNotAfter") == 0) {
> >+            return send_error(pb, LDAP_UNWILLING_TO_PERFORM,
> >+                              "Can't change last active token's end time");
> >+        }
> >+    }
> >+
> >+    return 0;
> >+}
> >+
> >+static int
> >+preop_init(Slapi_PBlock *pb)
> >+{
> >+    if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01))
> >+        goto error;
> >+
> >+    if (slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *) &preop_desc))
> >+        goto error;
> >+
> >+    if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN, preop_del))
> >+        goto error;
> >+
> >+    if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN, preop_mod))
> >+        goto error;
> >+
> >+    return 0;
> >+
> >+error:
> >+    return LOG(FATAL, "failed to register be_txn_pre_op plugin");
> >+}
> >+
> >+int
> >+ipa_otp_lasttoken_init(Slapi_PBlock *pb)
> >+{
> >+    slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &plugin_id);
> >+
> >+    if (slapi_register_plugin("betxnpreoperation", 1, __func__, preop_init,
> >+                              PLUGIN_NAME, NULL, plugin_id))
> >+        return LOG(FATAL, "failed to register plugin");
> I think the order is wrong here and it might be the cause for those
> messages I've been getting in the dirsrv error logs.
> 
> You need to fetch plugin identity, then set version and description,
> set callbacks, and only then register the plugin. Finally, preop_init() will
> be called and it should set the callbacks only.

Fixed.



-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Add-HOTP-support.patch
Type: text/x-patch
Size: 20756 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/freeipa-devel/attachments/20140217/096c7f0b/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0002-Add-OTP-last-token-plugin.patch
Type: text/x-patch
Size: 13035 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/freeipa-devel/attachments/20140217/096c7f0b/attachment-0001.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0003-Add-OTP-sync-support-to-ipa-pwd-extop.patch
Type: text/x-patch
Size: 56554 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/freeipa-devel/attachments/20140217/096c7f0b/attachment-0002.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0004-Teach-ipa-pwd-extop-to-respect-global-ipaUserAuthTyp.patch
Type: text/x-patch
Size: 34809 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/freeipa-devel/attachments/20140217/096c7f0b/attachment-0003.bin>


More information about the Freeipa-devel mailing list