[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