Hi,

I have edited my previous patch.

On Thu, Aug 11, 2016 at 11:52 AM, Jan Cholasta <jchol...@redhat.com> wrote:

> Hi,
>
> On 11.8.2016 09:55, Tibor Dudlak wrote:
>
>> Hi,
>>
>> ...
>>
>
> +class login_x509(login_kerberos, KerberosSession, HTTP_Status):
> +    key = '/session/login_x509'
>
> login_kerberos already subclasses KerberosSession and HTTP_Status, no need
> to do it again here. In fact, it would be best to split off the bussiness
> logic from login_kerberos into a separate class and inherit both
> login_kerberos and login_x509 from it:
>
>     class KerberosLogin(Backend, KerberosSession, HTTP_Status):
>         def _on_finalize(self):
>             ...
>
>         def __call__(self, ...):
>             ...
>
>     class login_kerberos(KerberosLogin):
>         key = '/session/login_kerberos'
>
>     class login_x509(KerberosLogin):
>         key = '/session/login_x509'
>
> Honza
>
> --
> Jan Cholasta
>

Thank jcholast for review, it should be all right now.

-- 
Tibor Dudlák
Intern - Identity management Special Projects
Red Hat
From b84deeffe5ec7e5565817feffc69768aea345592 Mon Sep 17 00:00:00 2001
From: Tiboris <tibor.dud...@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                                    |   8 +
 install/conf/Makefile.am                           |   1 +
 install/conf/xx-ipa-cert-auth.conf                 |  14 ++
 .../freeipa/plugins-dist/cert_auth/cert_auth.js    | 169 +++++++++++++++++++++
 ipaserver/plugins/xmlserver.py                     |   3 +-
 ipaserver/rpcserver.py                             |  17 ++-
 6 files changed, 207 insertions(+), 5 deletions(-)
 create mode 100644 install/conf/xx-ipa-cert-auth.conf
 create mode 100644 install/ui/src/freeipa/plugins-dist/cert_auth/cert_auth.js

diff --git a/freeipa.spec.in b/freeipa.spec.in
index 135e9c980011c6c2730c6c29a3c22098e48270d5..19828bc84f1f1d13d4bb0e08a4749da626e9dbb3 100644
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -818,6 +818,10 @@ 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
 
+# Experimental external authentication UI plugin - moved into plugins-dist to be disabled by default
+mkdir -p %{buildroot}%{_usr}/share/ipa/ui/js/plugins-dist/cert_auth
+install install/ui/src/freeipa/plugins-dist/cert_auth/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 +1214,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
 %dir %{_usr}/share/ipa/ui/images
 %{_usr}/share/ipa/ui/images/*.jpg
 %{_usr}/share/ipa/ui/images/*.png
@@ -1232,6 +1239,7 @@ fi
 %{_usr}/share/ipa/ipa-rewrite.conf
 %{_usr}/share/ipa/ipa-pki-proxy.conf
 %{_usr}/share/ipa/kdcproxy.conf
+%{_usr}/share/ipa/xx-ipa-cert-auth.conf
 %ghost %attr(0644,root,apache) %config(noreplace) %{_usr}/share/ipa/html/ca.crt
 %ghost %attr(0644,root,apache) %{_usr}/share/ipa/html/kerberosauth.xpi
 %ghost %attr(0644,root,apache) %{_usr}/share/ipa/html/krb.con
diff --git a/install/conf/Makefile.am b/install/conf/Makefile.am
index 5daac776f71c5d01187b46d51044a07bf5fd717a..2e6fbb84902c843fa6e43a96191d5cc58a1213c1 100644
--- a/install/conf/Makefile.am
+++ b/install/conf/Makefile.am
@@ -6,6 +6,7 @@ app_DATA =                              \
 	ipa-kdc-proxy.conf.template	\
 	ipa-pki-proxy.conf		\
 	ipa-rewrite.conf		\
+	xx-ipa-cert-auth.conf		\
 	$(NULL)
 
 EXTRA_DIST =                            \
diff --git a/install/conf/xx-ipa-cert-auth.conf b/install/conf/xx-ipa-cert-auth.conf
new file mode 100644
index 0000000000000000000000000000000000000000..824d33113446176c0d1a9f6c99e95aa48a7a99c9
--- /dev/null
+++ b/install/conf/xx-ipa-cert-auth.conf
@@ -0,0 +1,14 @@
+# Login with user certificate/smartcard configuration
+# This configuration needs to be loaded after <Location "/ipa">
+<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>
diff --git a/install/ui/src/freeipa/plugins-dist/cert_auth/cert_auth.js b/install/ui/src/freeipa/plugins-dist/cert_auth/cert_auth.js
new file mode 100644
index 0000000000000000000000000000000000000000..7dd0c17c83ab34f0c8dc37c789f202ce42d52f52
--- /dev/null
+++ b/install/ui/src/freeipa/plugins-dist/cert_auth/cert_auth.js
@@ -0,0 +1,169 @@
+/*  Authors:
+ *    Petr Vobornik <pvobo...@redhat.com>
+ *    Tibor Dudlák <tdud...@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 adds a button-link with aside text to FreeIPA login screen to
+    support x509 authentication for experimental use
+
+    Disabled by default
+
+    Tested against FreeIPA 4.3 and 4.4
+
+    Limitation: only one such plugin can be installed - one can override
+    functionality of the other
+ */
+
+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 = {};
+
+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) {
+
+        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];
+
+        construct.place(this.crtauth_btn_node, container);
+        construct.place(document.createTextNode(" "), container);
+
+        this.inherited(arguments);
+    },
+
+    crt_login: function() {
+
+        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);
+        this.set_visible_buttons(['crtauth', 'sync', 'login']);
+    },
+
+    set_login_aside_text: function() {
+
+        this.inherited(arguments);
+        var aside = this.aside;
+        aside += this.msg;
+        this.set('aside', aside);
+    }
+});
+
+
+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..e48dc3498d6ed8feb6ea44a9a678a8b8c50e8d9b 100644
--- a/ipaserver/rpcserver.py
+++ b/ipaserver/rpcserver.py
@@ -857,16 +857,16 @@ class jsonserver_kerb(jsonserver, KerberosWSGIExecutioner):
     key = '/json'
 
 
-class login_kerberos(Backend, KerberosSession, HTTP_Status):
-    key = '/session/login_kerberos'
+class KerberosLogin(Backend, KerberosSession, HTTP_Status):
+    key = None
 
     def _on_finalize(self):
-        super(login_kerberos, self)._on_finalize()
+        super(KerberosLogin, self)._on_finalize()
         self.api.Backend.wsgi_dispatch.mount(self, self.key)
         self.kerb_session_on_finalize()
 
     def __call__(self, environ, start_response):
-        self.debug('WSGI login_kerberos.__call__:')
+        self.debug('WSGI KerberosLogin.__call__:')
 
         # Get the ccache created by mod_auth_gssapi
         user_ccache_name=environ.get('KRB5CCNAME')
@@ -876,6 +876,15 @@ class login_kerberos(Backend, KerberosSession, HTTP_Status):
 
         return self.finalize_kerberos_acquisition('login_kerberos', user_ccache_name, environ, start_response)
 
+
+class login_kerberos(KerberosLogin):
+    key = '/session/login_kerberos'
+
+
+class login_x509(KerberosLogin):
+    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

Reply via email to