[Freeipa-devel] [PATCH] 0002 Added support for authentication with user certificate

Alexander Bokovoy abokovoy at redhat.com
Fri Aug 5 13:19:37 UTC 2016


On Fri, 05 Aug 2016, Tibor Dudlak wrote:
>Hi,
>
>I have extended my previous patch for authentication with user
>certificate/smartcard. This patch includes patches and plugin described
>here: http://www.freeipa.org/page/V4/External_Authentication/Setup
>Page also contains steps to configure and test this feature. Once this
>patch is merged and released we will simplify this page to not confuse
>customers.
>Addressing ticket: https://fedorahosted.org/freeipa/ticket/5764
>
>Thanks.
>
>-- 
>Tibor Dudlák
>Intern - Identity management Special Projects
>Red Hat

>From e22843f6ab1556528b307951fbcc2476a61a417f Mon Sep 17 00:00:00 2001
>From: Tiboris <tibor.dudlak at gmail.com>
>Date: Fri, 5 Aug 2016 11:47:06 +0200
>Subject: [PATCH] Added support for authentication with user certificate
>
>https://fedorahosted.org/freeipa/ticket/5764
>---
> freeipa.spec.in                             |   5 +
> install/conf/ipa.conf                       |  14 +++
> install/ui/src/freeipa/plugins/cert_auth.js | 179 ++++++++++++++++++++++++++++
> ipaserver/plugins/xmlserver.py              |   3 +-
> ipaserver/rpcserver.py                      |   5 +
> 5 files changed, 205 insertions(+), 1 deletion(-)
> create mode 100644 install/ui/src/freeipa/plugins/cert_auth.js
>
>diff --git a/freeipa.spec.in b/freeipa.spec.in
>index 135e9c980011c6c2730c6c29a3c22098e48270d5..2b95b83613ca3720c95f255f7f64dc029195452c 100644
>--- a/freeipa.spec.in
>+++ b/freeipa.spec.in
>@@ -817,6 +817,8 @@ install daemons/dnssec/ipa-ods-exporter %{buildroot}%{_libexecdir}/ipa/ipa-ods-e
> 
> # Web UI plugin dir
> mkdir -p %{buildroot}%{_usr}/share/ipa/ui/js/plugins
>+mkdir -p %{buildroot}%{_usr}/share/ipa/ui/js/plugins-dist/cert_auth
>+install install/ui/src/freeipa/plugins/cert_auth.js %{buildroot}%{_usr}/share/ipa/ui/js/plugins-dist/cert_auth/cert_auth.js
> 
> # DNSSEC config
> mkdir -p %{buildroot}%{_sysconfdir}/ipa/dnssec
>@@ -1210,6 +1212,9 @@ fi
> %{_usr}/share/ipa/ui/js/freeipa/app.js
> %{_usr}/share/ipa/ui/js/freeipa/core.js
> %dir %{_usr}/share/ipa/ui/js/plugins
>+%dir %{_usr}/share/ipa/ui/js/plugins-dist
>+%dir %{_usr}/share/ipa/ui/js/plugins-dist/cert_auth
>+%{_usr}/share/ipa/ui/js/plugins-dist/cert_auth/cert_auth.js
Can you rename plugins-dist to something like 'plugins.d'?
This would be more in line with other parts where multiple additions
supposed to come and also in line with other projects where a drop-in
directory is supported.

> %dir %{_usr}/share/ipa/ui/images
> %{_usr}/share/ipa/ui/images/*.jpg
> %{_usr}/share/ipa/ui/images/*.png
>diff --git a/install/conf/ipa.conf b/install/conf/ipa.conf
>index 3e7435903b2ad8c4ae5bfc48c0c9fca733757d5d..c37819ff2bd2c045404a383631435ad6c24fdaa3 100644
>--- a/install/conf/ipa.conf
>+++ b/install/conf/ipa.conf
>@@ -77,6 +77,20 @@ WSGIScriptReloading Off
>   Header always append Content-Security-Policy "frame-ancestors 'none'"
> </Location>
> 
>+# Login with user certificate/smartcard configuration
>+<Location "/ipa/session/login_x509">
>+  AuthType none
>+  GssapiCredStore keytab:/etc/httpd/conf/ipa.keytab
>+  GssapiCredStore client_keytab:/etc/httpd/conf/ipa.keytab
>+  GssapiDelegCcacheDir /var/run/httpd/ipa/clientcaches
>+  GssapiImpersonate On
>+  NSSVerifyClient require
>+  NSSUserName SSL_CLIENT_CERT
>+  LookupUserByCertificate On
>+  WSGIProcessGroup ipa
>+  WSGIApplicationGroup ipa
>+</Location>
>+
> # Turn off Apache authentication for sessions
> <Location "/ipa/session/json">
>   Satisfy Any
>diff --git a/install/ui/src/freeipa/plugins/cert_auth.js b/install/ui/src/freeipa/plugins/cert_auth.js
>new file mode 100644
>index 0000000000000000000000000000000000000000..282883d6fe82258405afb167dd61b5d6b0f1a7bd
>--- /dev/null
>+++ b/install/ui/src/freeipa/plugins/cert_auth.js
>@@ -0,0 +1,179 @@
>+/*  Authors:
>+ *    Petr Vobornik <pvoborni at redhat.com>
>+ *    Tibor Dudlák <tdudlak at redhat.com>
>+ *
>+ * Copyright (C) 2016 Red Hat
>+ * see file 'COPYING' for use and warranty information
>+ *
>+ * 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/>.
>+*/
>+/*
>+    Plugin to add a button with aside text to FreeiPA login screen
>+
>+    Tested against FreeIPA 4.4
>+
>+    Limitation: only one such plugin can be installed - one can override
>+    functionality of the other
>+ */
>+
>+// we can also depend on other plugin
>+define([
>+        'dojo/Deferred',
>+        'dojo/dom-construct',
>+        'dojo/_base/declare',
>+        'freeipa/jquery',
>+        'freeipa/_base/Spec_mod',
>+        'freeipa/ipa',
>+        'freeipa/auth',
>+        'freeipa/phases',
>+        'freeipa/reg',
>+        'freeipa/plugins/login',
>+        'freeipa/widgets/LoginScreen',
>+        ],
>+            function(Deferred, construct, declare, $, SpecMod, IPA, auth, phases,
>+                      reg, mod_login, LoginScreen) {
>+
>+
>+var exp = {}; // module object (export)
>+
>+exp.CustomLoginScreen = declare([LoginScreen], {
>+
>+    crtauth_btn_node: null,
>+
>+    auth_failed: "Authentication with personal certificate failed",
>+
>+    msg: "<p><i class=\"fa fa-info-circle\"></i> To login with <strong>Smart Card</strong>," +
>+          "please make sure you have valid personal certificate. </p>",
>+
>+    login_url: '/ipa/session/login_x509',
>+
>+    render_buttons: function(container) {
>+        // add button node to DOM
>+        this.crtauth_btn_node = IPA.button({
>+            name: 'crtauth',
>+            title:"Login using personal certificate",
>+            label: "Smart Card Login",
>+            button_class: 'btn btn-link',
>+            click: this.crt_login.bind(this)
>+        })[0];
>+
>+        // similar to jquery.append(node, container)
>+        construct.place(this.crtauth_btn_node, container);
>+        construct.place(document.createTextNode(" "), container);
>+
>+        // call base class method to create other buttons
>+        this.inherited(arguments);
>+    },
>+
>+    crt_login: function() {
>+        // add custom auth login here
>+        this.lookup_credentials().then(function(status) {
>+            if (status === 200) {
>+                this.emit('logged_in');
>+            } else {
>+                var val_summary = this.get_widget('validation');
>+                val_summary.add_error('login', this.auth_failed);
>+            }
>+        }.bind(this));
>+    },
>+
>+    lookup_credentials: function() {
>+        var status;
>+        var d = new Deferred();
>+
>+        function error_handler(xhr, text_status, error_thrown) {
>+            d.resolve(xhr.status);
>+            IPA.hide_activity_icon();
>+        }
>+
>+        function success_handler(data, text_status, xhr) {
>+            auth.current.set_authenticated(true, 'kerberos');
>+            d.resolve(xhr.status);
>+            IPA.hide_activity_icon();
>+        }
>+
>+        var request = {
>+            url: this.login_url,
>+            cache: false,
>+            type: "GET",
>+            success: success_handler,
>+            error: error_handler
>+        };
>+        IPA.display_activity_icon();
>+        $.ajax(request);
>+
>+        return d.promise;
>+    },
>+
>+    show_login_view: function() {
>+
>+        this.inherited(arguments);
>+        // make sure that crtauth button is also shown when switching from sync form
>+        // a bit of hack because, we need to use the exact buttons which were defined
>+        // in original LoginScreen -> does't scale if some button is added in later
>+        // versions
>+        this.set_visible_buttons(['crtauth', 'sync', 'login']);
>+    },
>+
>+    set_login_aside_text: function() {
>+        // allow to set aside text (the text on right side with help text)
>+
>+        // generate original
>+        this.inherited(arguments);
>+
>+        // add own
>+        var aside = this.aside;
>+        aside += this.msg;
>+        this.set('aside', aside);
>+
>+        //alternative solution:
>+        // $(this.aside_node).append($("<p/>", { text: "My text"}));
>+    }
>+});
>+
>+
>+exp.replace_login_screen_spec = function(entity) {
>+
>+    var mod = new SpecMod();
>+
>+    var diff = {
>+        $replace: [
>+            [
>+                'widgets',
>+                [[{ name: 'login_screen'},
>+                {
>+                    $type: 'custom_login_screen',
>+                    name: 'login_screen'
>+                }]]
>+            ]
>+        ]
>+    };
>+    mod.mod(mod_login.facet_spec, diff);
>+};
>+
>+exp.override = function() {
>+
>+    exp.replace_login_screen_spec();
>+};
>+
>+exp.register = function() {
>+    var w = reg.widget;
>+    w.register('custom_login_screen', exp.CustomLoginScreen );
>+};
>+
>+phases.on('registration', exp.register);
>+phases.on('customization', exp.override);
>+
>+return exp;
>+});
>diff --git a/ipaserver/plugins/xmlserver.py b/ipaserver/plugins/xmlserver.py
>index d8fe24e0cb407603e9898e934229c9373f3c8b62..1843c0568543951f2c817616d9e988deaab47056 100644
>--- a/ipaserver/plugins/xmlserver.py
>+++ b/ipaserver/plugins/xmlserver.py
>@@ -28,12 +28,13 @@ register = Registry()
> 
> 
> if api.env.context in ('server', 'lite'):
>-    from ipaserver.rpcserver import wsgi_dispatch, xmlserver, jsonserver_kerb, jsonserver_session, login_kerberos, login_password, change_password, sync_token, xmlserver_session
>+    from ipaserver.rpcserver import wsgi_dispatch, xmlserver, jsonserver_kerb, jsonserver_session, login_kerberos, login_x509, login_password, change_password, sync_token, xmlserver_session
>     register()(wsgi_dispatch)
>     register()(xmlserver)
>     register()(jsonserver_kerb)
>     register()(jsonserver_session)
>     register()(login_kerberos)
>+    register()(login_x509)
>     register()(login_password)
>     register()(change_password)
>     register()(sync_token)
>diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py
>index d036f3c27521f17709672b830d5aa58167c76b34..a181ecfcb1d01b1c2dd5ee6cb9721d69be8c1863 100644
>--- a/ipaserver/rpcserver.py
>+++ b/ipaserver/rpcserver.py
>@@ -876,6 +876,11 @@ class login_kerberos(Backend, KerberosSession, HTTP_Status):
> 
>         return self.finalize_kerberos_acquisition('login_kerberos', user_ccache_name, environ, start_response)
> 
>+
>+class login_x509(login_kerberos, KerberosSession, HTTP_Status):
>+    key = '/session/login_x509'
>+
>+
> class login_password(Backend, KerberosSession, HTTP_Status):
> 
>     content_type = 'text/plain'
>-- 
>2.7.4
>

>-- 
>Manage your subscription for the Freeipa-devel mailing list:
>https://www.redhat.com/mailman/listinfo/freeipa-devel
>Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code


-- 
/ Alexander Bokovoy




More information about the Freeipa-devel mailing list