From 5103d984ae72c7f293450d8cf9fa8d7cdc8da728 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Fri, 14 Jun 2019 14:38:37 +0200 Subject: [PATCH 1/2] remove auth2_ssl (#33992) --- src/authentic2/auth2_auth/auth2_ssl/README | 180 ------------------ .../auth2_auth/auth2_ssl/__init__.py | 15 -- src/authentic2/auth2_auth/auth2_ssl/admin.py | 25 --- .../auth2_auth/auth2_ssl/app_settings.py | 51 ----- .../auth2_auth/auth2_ssl/authentic_ssl.vhost | 52 ----- .../auth2_auth/auth2_ssl/authenticators.py | 44 ----- .../auth2_auth/auth2_ssl/backends.py | 157 --------------- .../auth2_ssl/locale/fr/LC_MESSAGES/django.po | 89 --------- .../auth2_auth/auth2_ssl/middleware.py | 32 ---- .../migrations/0003_auto_20190614_1438.py | 22 +++ src/authentic2/auth2_auth/auth2_ssl/models.py | 40 ---- .../templates/auth/account_linking_ssl.html | 45 ----- .../templates/auth/login_form_ssl.html | 14 -- .../auth2_ssl/templates/ssl/profile.html | 33 ---- src/authentic2/auth2_auth/auth2_ssl/urls.py | 33 ---- src/authentic2/auth2_auth/auth2_ssl/util.py | 104 ---------- src/authentic2/auth2_auth/auth2_ssl/views.py | 141 -------------- .../locale/fr/LC_MESSAGES/django.po | 67 ------- src/authentic2/settings.py | 1 - 19 files changed, 22 insertions(+), 1123 deletions(-) delete mode 100644 src/authentic2/auth2_auth/auth2_ssl/README delete mode 100644 src/authentic2/auth2_auth/auth2_ssl/admin.py delete mode 100644 src/authentic2/auth2_auth/auth2_ssl/app_settings.py delete mode 100644 src/authentic2/auth2_auth/auth2_ssl/authentic_ssl.vhost delete mode 100644 src/authentic2/auth2_auth/auth2_ssl/authenticators.py delete mode 100644 src/authentic2/auth2_auth/auth2_ssl/backends.py delete mode 100644 src/authentic2/auth2_auth/auth2_ssl/locale/fr/LC_MESSAGES/django.po delete mode 100644 src/authentic2/auth2_auth/auth2_ssl/middleware.py create mode 100644 src/authentic2/auth2_auth/auth2_ssl/migrations/0003_auto_20190614_1438.py delete mode 100644 src/authentic2/auth2_auth/auth2_ssl/models.py delete mode 100644 src/authentic2/auth2_auth/auth2_ssl/templates/auth/account_linking_ssl.html delete mode 100644 src/authentic2/auth2_auth/auth2_ssl/templates/auth/login_form_ssl.html delete mode 100644 src/authentic2/auth2_auth/auth2_ssl/templates/ssl/profile.html delete mode 100644 src/authentic2/auth2_auth/auth2_ssl/urls.py delete mode 100644 src/authentic2/auth2_auth/auth2_ssl/util.py delete mode 100644 src/authentic2/auth2_auth/auth2_ssl/views.py delete mode 100644 src/authentic2/auth2_auth/locale/fr/LC_MESSAGES/django.po diff --git a/src/authentic2/auth2_auth/auth2_ssl/README b/src/authentic2/auth2_auth/auth2_ssl/README deleted file mode 100644 index db2fb044..00000000 --- a/src/authentic2/auth2_auth/auth2_ssl/README +++ /dev/null @@ -1,180 +0,0 @@ -================================ -Enable SSL Client authentication -================================ - -Intro -===== -Tested with Apache 2 and mod_ssl. -Django over mod_wsgi. From http://docs.djangoproject.com/en/dev/howto/deployment/modwsgi/ -"Deploying Django with Apache and mod_wsgi is the recommended way to get Django into production." - -Generate Keys -============= -* Create a CA (passphrase) -openssl genrsa -des3 -out ca.key 2048 -openssl req -new -x509 -days 3650 -key ca.key -out ca.crt -openssl x509 -in ca.crt -text -noout -* Server key material (challenge) -openssl genrsa -des3 -out server.key 1024 -openssl req -new -key server.key -out server.csr -openssl x509 -req -in server.csr -out server.crt -sha1 -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 -openssl x509 -in server.crt -text -noout -* User Key material (challenge/password) -openssl genrsa -des3 -out c.key 1024 -openssl req -new -key c.key -out c.csr -openssl x509 -req -in c.csr -out c.crt -sha1 -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 -openssl pkcs12 -export -in c.crt -inkey c.key -name "Mikael Ates" -out c.p12 -openssl pkcs12 -in c.p12 -clcerts -nokeys -info - -Configure Apache and WSGI -========================= -Add a file django.wsgi, e.g.: -""" -import os -import sys - -sys.path.append("/usr/local/lib/python2.6/site-packages/") -try: - import lasso -except: - print("Unable to import Lasso.", file=sys.stderr) - -apache_configuration= os.path.dirname(__file__) -project = os.path.dirname(apache_configuration) -sys.path.append(project) -try: - import authentic2.settings - os.environ['DJANGO_SETTINGS_MODULE'] = 'authentic2.settings' -except: - print("Unable to import settings.", file=sys.stderr) - -import django.core.handlers.wsgi -application = django.core.handlers.wsgi.WSGIHandler() -""" - -Activate apache2 modules: -* a2enmod wsgi -* a2enmod ssl - -Add a Apache vhost for SSL. -""" - - - -LimitInternalRecursion 1000 -ServerAdmin webmaster@entrouvert.org -ServerName localhost - -Alias /media/admin/ /usr/local/lib/python2.6/dist-packages/django/contrib/admin/media/ - -WSGIScriptAlias / /Donnees/devs/authentic/apache/django.wsgi - - -SSLVerifyClient optional_no_ca -Options Indexes MultiViews FollowSymLinks -AllowOverride None -Order deny,allow -Allow from all - - -SSLEngine on -SSLCipherSuite HIGH:MEDIUM -SSLProtocol all -SSLv2 - -SSLCertificateFile /Donnees/devs/authentic/apache/key_mat/server.crt -SSLCertificateKeyFile /Donnees/devs/authentic/apache/key_mat/server.key - -SSLCertificateChainFile /Donnees/devs/authentic/apache/key_mat/ca.crt -SSLCACertificateFile /Donnees/devs/authentic/apache/key_mat/ca.crt - -SSLOptions +StdEnvVars +ExportCertData - -BrowserMatch "MSIE [2-6]" \ - nokeepalive ssl-unclean-shutdown \ - downgrade-1.0 force-response-1.0 -BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown - - - -""" - -Give rights to Apache on your Authentic directory. -Reload Apache. - -Configure Authentic -=================== - -Key Description --------------------------- ---------------------------------------- -ACCEPT_SELF_SIGNED accept certificate for which the validation failed, - default: False -STRICT_MATCH do a binary compare to match certificate and users, - default: False -SUBJECT_MATCH_KEYS SSL information to use to match recorded - certificates. default: ('subject_dn', 'issuer_dn'), - possible values: serial, subject_dn, issuer_dn, cert. -CREATE_USERNAME_CALLBACK function receiving a SSLInfo object as first - parameter and returning a username, default: None -CREATE_USER function receiving a SSLInfo object as first - parameter and returning a user, default: None -USE_COOKIE to be described - -in settings.py: -Set AUTH_SSL = True -To create a user with the mail adress as identifier: -SSLAUTH_CREATE_USER = True -To use another identifier: -def myusernamegen(ssl_info): - import re - if(ssl_info.subject_cn): - return return re.sub('[^a-zA-Z0-9]', '_', ssl_info.subject_cn) - else: - return return re.sub('[^a-zA-Z0-9]', '_', ssl_info.serial) -SSLAUTH_CREATE_USERNAME_CALLBACK = myusernamegen - - -Nginx configuration -=================== - -You must be able to retrieve SSL environment variable, for example with the -SCGI backend you must add those lines to /etc/nginx/scgi_params:: - - scgi_param SSL_CLIENT_CERT $ssl_client_cert; - scgi_param SSL_CLIENT_RAW_CERT $ssl_client_raw_cert; - scgi_param SSL_CLIENT_S_DN $ssl_client_s_dn; - scgi_param SSL_CLIENT_I_DN $ssl_client_i_dn; - scgi_param SSL_CLIENT_SERIAL $ssl_client_serial; - scgi_param SSL_CLIENT_M_SERIAL $ssl_client_serial; - scgi_param SSL_CLIENT_VERIFY $ssl_client_verify; - -It would be the same with FCGI but using the fcgi_param directive in the -fcgi_params file. It does not currently work when using proxy_pass. - -A virtualhost configuration example:: - - server { - listen 80; - server_name authentic.localhost; - - rewrite ^ https://$server_name$request_uri? permanent; - } - - server { - listen 443; - server_name authentic.localhost; - - ssl on; - ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem; - ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key; - ssl_verify_client optional_no_ca; - - location / { - include scgi_params; - scgi_pass localhost:8000; - } - } - -The serveur must be run using the SCGI protocol, with this command line for -example:: - - ./manage.py runfcgi protocol=scgi method=threaded daemonize=false host=localhost port=8000 diff --git a/src/authentic2/auth2_auth/auth2_ssl/__init__.py b/src/authentic2/auth2_auth/auth2_ssl/__init__.py index e585021f..8d9278db 100644 --- a/src/authentic2/auth2_auth/auth2_ssl/__init__.py +++ b/src/authentic2/auth2_auth/auth2_ssl/__init__.py @@ -16,20 +16,5 @@ class Plugin(object): - def get_before_urls(self): - from . import app_settings - from django.conf.urls import include, url - from authentic2.decorators import setting_enabled, required - - return required( - setting_enabled('ENABLE', settings=app_settings), - [url(r'^accounts/sslauth/', include(__name__ + '.urls'))]) - def get_apps(self): return [__name__] - - def get_authentication_backends(self): - return ['authentic2.auth2_auth.auth2_ssl.backends.SSLBackend'] - - def get_authenticators(self): - return ['authentic2.auth2_auth.auth2_ssl.authenticators.SSLAuthenticator'] diff --git a/src/authentic2/auth2_auth/auth2_ssl/admin.py b/src/authentic2/auth2_auth/auth2_ssl/admin.py deleted file mode 100644 index dd0767aa..00000000 --- a/src/authentic2/auth2_auth/auth2_ssl/admin.py +++ /dev/null @@ -1,25 +0,0 @@ -# authentic2 - versatile identity manager -# Copyright (C) 2010-2019 Entr'ouvert -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU Affero 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 Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . - -from django.contrib import admin - -from . import models - - -class ClientCertificateAdmin(admin.ModelAdmin): - list_display = ('user', 'subject_dn', 'issuer_dn', 'serial') - -admin.site.register(models.ClientCertificate, ClientCertificateAdmin) diff --git a/src/authentic2/auth2_auth/auth2_ssl/app_settings.py b/src/authentic2/auth2_auth/auth2_ssl/app_settings.py deleted file mode 100644 index 24911d44..00000000 --- a/src/authentic2/auth2_auth/auth2_ssl/app_settings.py +++ /dev/null @@ -1,51 +0,0 @@ -# authentic2 - versatile identity manager -# Copyright (C) 2010-2019 Entr'ouvert -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU Affero 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 Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . - -import sys - - -class AppSettings(object): - '''Thanks django-allauth''' - __DEFAULTS = dict( - # settings for TEST only, make it easy to simulate the SSL - # environment - ENABLE=False, - FORCE_ENV={}, - ACCEPT_SELF_SIGNED=False, - STRICT_MATCH=False, - SUBJECT_MATCH_KEYS=('subject_dn', 'issuer_dn'), - CREATE_USERNAME_CALLBACK=None, - USE_COOKIE=False, - CREATE_USER=False, - ) - - def __init__(self, prefix): - self.prefix = prefix - - def _setting(self, name, dflt): - from django.conf import settings - return getattr(settings, self.prefix + name, dflt) - - def __getattr__(self, name): - if name not in self.__DEFAULTS: - raise AttributeError(name) - return self._setting(name, self.__DEFAULTS[name]) - - -app_settings = AppSettings('SSLAUTH_') -app_settings.__name__ = __name__ -app_settings.__file__ = __file__ -sys.modules[__name__] = app_settings diff --git a/src/authentic2/auth2_auth/auth2_ssl/authentic_ssl.vhost b/src/authentic2/auth2_auth/auth2_ssl/authentic_ssl.vhost deleted file mode 100644 index 7508018b..00000000 --- a/src/authentic2/auth2_auth/auth2_ssl/authentic_ssl.vhost +++ /dev/null @@ -1,52 +0,0 @@ - - - -LimitInternalRecursion 1000 -ServerAdmin webmaster@entrouvert.org -ServerName localhost - -#Alias /media/ /Donnees/devs/Authentic/authentic/media/ -Alias /media/admin/ /usr/local/lib/python2.6/dist-packages/django/contrib/admin/media/ - -WSGIScriptAlias / /Donnees/devs/Authentic/authentic/apache/django.wsgi - - - -Options Indexes MultiViews FollowSymLinks -AllowOverride None -Order deny,allow -Allow from all - - - - - -SSLVerifyClient require - -Options Indexes MultiViews FollowSymLinks -AllowOverride None -Order deny,allow -Allow from all - - - -SSLEngine on -SSLCipherSuite HIGH:MEDIUM -SSLProtocol all -SSLv2 - -SSLCertificateFile /Donnees/devs/Authentic/authentic/apache/key_mat/server.crt -SSLCertificateKeyFile /Donnees/devs/Authentic/authentic/apache/key_mat/server.key - -SSLCertificateChainFile /Donnees/devs/Authentic/authentic/apache/key_mat/ca.crt -SSLCACertificateFile /Donnees/devs/Authentic/authentic/apache/key_mat/ca.crt - -SSLOptions +StdEnvVars +ExportCertData -#SSLProtocol all - - BrowserMatch "MSIE [2-6]" \ - nokeepalive ssl-unclean-shutdown \ - downgrade-1.0 force-response-1.0 - BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown - - - diff --git a/src/authentic2/auth2_auth/auth2_ssl/authenticators.py b/src/authentic2/auth2_auth/auth2_ssl/authenticators.py deleted file mode 100644 index ee7a7709..00000000 --- a/src/authentic2/auth2_auth/auth2_ssl/authenticators.py +++ /dev/null @@ -1,44 +0,0 @@ -# authentic2 - versatile identity manager -# Copyright (C) 2010-2019 Entr'ouvert -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU Affero 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 Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . - -from django.utils.translation import ugettext_lazy as _ -import django.forms - -from . import views, app_settings -from authentic2.utils import redirect_to_login - - -class SSLAuthenticator(object): - def enabled(self): - return app_settings.ENABLE - - def id(self): - return 'ssl' - - def name(self): - return _('SSL with certificates') - - def form(self): - return django.forms.Form - - def post(self, request, form, nonce, next_url): - return redirect_to_login(request, login_url='user_signin_ssl',) - - def template(self): - return 'auth/login_form_ssl.html' - - def profile(self, request, *args, **kwargs): - return views.profile(request, *args, **kwargs) diff --git a/src/authentic2/auth2_auth/auth2_ssl/backends.py b/src/authentic2/auth2_auth/auth2_ssl/backends.py deleted file mode 100644 index 13627031..00000000 --- a/src/authentic2/auth2_auth/auth2_ssl/backends.py +++ /dev/null @@ -1,157 +0,0 @@ -# authentic2 - versatile identity manager -# Copyright (C) 2010-2019 Entr'ouvert -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU Affero 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 Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . - -from django.contrib.auth import get_user_model -from django.db.models import Q -import logging - -from authentic2.backends import is_user_authenticable - -from . import models, app_settings - -logger = logging.getLogger(__name__) - -User = get_user_model() - - -class AuthenticationError(Exception): - pass - - -class SSLBackend: - """ - authenticates a client certificate against the records stored - in ClientCertificate model and looks up the corresponding django user - - In all methods, the ssl_info parameter is supposed to be an SSLInfo - instance - """ - supports_object_permissions = False - supports_anonymous_user = False - - def authenticate(self, ssl_info): - cert = self.get_certificate(ssl_info) - if cert is None: - return None - else: - if not is_user_authenticable(cert.user): - logger.info('SSLAuth: authentication refused by user filters') - return None - return cert.user - - def get_user(self, user_id): - """ - simply return the user object. That way, we only need top look-up the - certificate once, when loggin in - """ - try: - return User.objects.get(id=user_id) - except User.DoesNotExist: - return None - - def get_certificate(self, ssl_info): - """ - returns a ClientCertificate object for the passed - cert data or None if not found - """ - - if app_settings.STRICT_MATCH: - # compare complete certificate in strict match - if not ssl_info.cert: - logger.error('SSLAuth: strict match required but PEM encoded certificate ' - 'not found in environment. Check your server settings') - return None - query = Q(cert=ssl_info.cert) - else: - query_args = {} - for key in app_settings.SUBJECT_MATCH_KEYS: - if not ssl_info.get(key): - logger.error(u'SSLAuth: key %s is missing from ssl_info', key) - return None - query_args[key] = ssl_info.get(key) - - query = Q(**query_args) - try: - cert = models.ClientCertificate.objects.select_related().get(query) - return cert - except models.ClientCertificate.DoesNotExist: - return None - - def create_user(self, ssl_info): - """ - This method creates a new django User and ClientCertificate record - for the passed certificate info. It does not create an issuer record, - just a subject for the ClientCertificate. - """ - # auto creation only created a DN for the subject, not the issuer - - # get username and check if the user exists already - if app_settings.CREATE_USERNAME_CALLBACK: - build_username = app_settings.CEATE_USERNAME_CALLBACK - else: - build_username = self.build_username - - username = build_username(ssl_info) - - try: - user = User.objects.get(username=username) - except User.DoesNotExist: - if app_settings.CREATE_USER_CALLBACK: - build_user = app_settings.CREATE_USER_CALLBACK - else: - build_user = self.build_user - user = build_user(username, ssl_info) - - # create the certificate record and save - self.link_user(ssl_info, user) - return user - - def link_user(self, ssl_info, user): - """ - This method creates a new django User and ClientCertificate record - for the passed certificate info. It does not create an issuer record, - just a subject for the ClientCertificate. - """ - # create the certificate record and save - cert = models.ClientCertificate() - cert.user = user - cert.subject_dn = ssl_info.subject_dn - cert.issuer_dn = ssl_info.issuer_dn - cert.serial = ssl_info.serial - cert.cert = ssl_info.cert - cert.save() - - return user - - def build_user(self, username, ssl_info): - """ - create a valid (and stored) django user to be associated with the - newly created certificate record. This method can be "overwritten" by - using the SSLAUTH_CREATE_USER_CALLBACK setting. - """ - User = get_user_model() - user = User() - setattr(user, User.USERNAME_FIELD, username) - if hasattr(User, 'set_unusable_password'): - user.set_unusable_password() - user.is_active = True - user.save() - return user - - @classmethod - def get_saml2_authn_context(cls): - from authentic2.compat_lasso import lasso - return lasso.SAML2_AUTHN_CONTEXT_X509 diff --git a/src/authentic2/auth2_auth/auth2_ssl/locale/fr/LC_MESSAGES/django.po b/src/authentic2/auth2_auth/auth2_ssl/locale/fr/LC_MESSAGES/django.po deleted file mode 100644 index 4702d272..00000000 --- a/src/authentic2/auth2_auth/auth2_ssl/locale/fr/LC_MESSAGES/django.po +++ /dev/null @@ -1,89 +0,0 @@ -# authentic2 auth ssl french l10n -# Copyright (C) 2015 Entr'ouvert -# This file is distributed under the same license as the Authentic package. -# Frederic Peters , 2010. -# -msgid "" -msgstr "" -"Project-Id-Version: Authentic\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-03-08 10:43+0100\n" -"PO-Revision-Date: 2013-07-23 17:41+0200\n" -"Last-Translator: Mikaël Ates \n" -"Language-Team: None\n" -"Language: fr\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=n>1;\n" - -#: src/authentic2/auth2_auth/auth2_ssl/frontends.py:16 -msgid "SSL with certificates" -msgstr "Certificats SSL" - -#: src/authentic2/auth2_auth/auth2_ssl/templates/auth/account_linking_ssl.html:5 -#: src/authentic2/auth2_auth/auth2_ssl/templates/auth/account_linking_ssl.html:9 -msgid "Log in to link your certificate with an existing account" -msgstr "connectez-vous pour lier votre certificat avec un compte existant" - -#: src/authentic2/auth2_auth/auth2_ssl/templates/auth/account_linking_ssl.html:18 -#: src/authentic2/auth2_auth/auth2_ssl/templates/auth/account_linking_ssl.html:25 -msgid "Username:" -msgstr "Nom d'utilisateur :" - -#: src/authentic2/auth2_auth/auth2_ssl/templates/auth/account_linking_ssl.html:21 -#: src/authentic2/auth2_auth/auth2_ssl/templates/auth/account_linking_ssl.html:29 -msgid "Password:" -msgstr "Mot de passe :" - -#: src/authentic2/auth2_auth/auth2_ssl/templates/auth/account_linking_ssl.html:34 -msgid "Create me a new account" -msgstr "Me créer un nouveau compte" - -#: src/authentic2/auth2_auth/auth2_ssl/templates/auth/account_linking_ssl.html:38 -#: src/authentic2/auth2_auth/auth2_ssl/templates/auth/login_form_ssl.html:9 -msgid "Log in" -msgstr "S'identifier" - -#: src/authentic2/auth2_auth/auth2_ssl/templates/auth/login_form_ssl.html:4 -msgid "Login using a certificate." -msgstr "Connexion par certificat." - -#: src/authentic2/auth2_auth/auth2_ssl/templates/auth/login_form_ssl.html:11 -msgid "Cancel" -msgstr "Annuler" - -#: src/authentic2/auth2_auth/auth2_ssl/templates/ssl/profile.html:3 -msgid "SSL Certificates" -msgstr "Certificats SSL" - -#: src/authentic2/auth2_auth/auth2_ssl/templates/ssl/profile.html:21 -msgid "Delete" -msgstr "Supprimer" - -#: src/authentic2/auth2_auth/auth2_ssl/templates/ssl/profile.html:28 -msgid "Add a certificate?" -msgstr "Ajouter un certificat ?" - -#: src/authentic2/auth2_auth/auth2_ssl/templates/ssl/profile.html:30 -msgid "Add" -msgstr "Ajouter" - -#: src/authentic2/auth2_auth/auth2_ssl/views.py:28 -msgid "SSL Client Authentication failed. No client certificate found." -msgstr "Echec de l'authentification cliente SSL. Aucun certificat trouvé." - -#: src/authentic2/auth2_auth/auth2_ssl/views.py:35 -msgid "SSL Client Authentication failed. Your client certificate is not valid." -msgstr "" -"Echec de l'authentification cliente SSL. Votre certificat n'est pas valide." - -#: src/authentic2/auth2_auth/auth2_ssl/views.py:54 -#: src/authentic2/auth2_auth/auth2_ssl/views.py:70 -#: src/authentic2/auth2_auth/auth2_ssl/views.py:118 -msgid "SSL Client Authentication failed. Internal server error." -msgstr "Echec de l'authentification SSL. Erreur interne du serveur." - -#: src/authentic2/auth2_auth/auth2_ssl/views.py:140 -msgid "Certificate deleted." -msgstr "Certificat supprimé." diff --git a/src/authentic2/auth2_auth/auth2_ssl/middleware.py b/src/authentic2/auth2_auth/auth2_ssl/middleware.py deleted file mode 100644 index f8a3a958..00000000 --- a/src/authentic2/auth2_auth/auth2_ssl/middleware.py +++ /dev/null @@ -1,32 +0,0 @@ -# authentic2 - versatile identity manager -# Copyright (C) 2010-2019 Entr'ouvert -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU Affero 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 Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . - -from django.contrib.auth import authenticate, login - -from . import util, app_settings - - -class SSLAuthMiddleware(object): - """ - attempts to find a valid user based on the client certificate info - """ - def process_request(self, request): - if app_settings.USE_COOKIE and request.user.is_authenticated(): - return - ssl_info = util.SSLInfo(request) - user = authenticate(ssl_info=ssl_info) - if user and request.user != user: - login(request, user) diff --git a/src/authentic2/auth2_auth/auth2_ssl/migrations/0003_auto_20190614_1438.py b/src/authentic2/auth2_auth/auth2_ssl/migrations/0003_auto_20190614_1438.py new file mode 100644 index 00000000..fb9a0a95 --- /dev/null +++ b/src/authentic2/auth2_auth/auth2_ssl/migrations/0003_auto_20190614_1438.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-06-14 12:38 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth2_ssl', '0002_auto_20150409_1840'), + ] + + operations = [ + migrations.RemoveField( + model_name='clientcertificate', + name='user', + ), + migrations.DeleteModel( + name='ClientCertificate', + ), + ] diff --git a/src/authentic2/auth2_auth/auth2_ssl/models.py b/src/authentic2/auth2_auth/auth2_ssl/models.py deleted file mode 100644 index 0057371d..00000000 --- a/src/authentic2/auth2_auth/auth2_ssl/models.py +++ /dev/null @@ -1,40 +0,0 @@ -# authentic2 - versatile identity manager -# Copyright (C) 2010-2019 Entr'ouvert -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU Affero 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 Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . - -from django.db import models -from django.conf import settings -from django.utils import six - -from . import util - - -@six.python_2_unicode_compatible -class ClientCertificate(models.Model): - serial = models.CharField(max_length=255, blank=True) - subject_dn = models.CharField(max_length=255) - issuer_dn = models.CharField(max_length=255) - cert = models.TextField() - user = models.ForeignKey(settings.AUTH_USER_MODEL) - - def __str__(self): - return self.subject_dn - - def explode_subject_dn(self): - return util.explode_dn(self.subject_dn) - - def explode_issuer_dn(self): - return util.explode_dn(self.issuer_dn) - diff --git a/src/authentic2/auth2_auth/auth2_ssl/templates/auth/account_linking_ssl.html b/src/authentic2/auth2_auth/auth2_ssl/templates/auth/account_linking_ssl.html deleted file mode 100644 index e8d3e5c9..00000000 --- a/src/authentic2/auth2_auth/auth2_ssl/templates/auth/account_linking_ssl.html +++ /dev/null @@ -1,45 +0,0 @@ -{% extends "authentic2/base-page.html" %} -{% load i18n %} - -{% block title %} -{% trans "Log in to link your certificate with an existing account" %} -{% endblock %} - -{% block content %} -

* {% trans "Log in to link your certificate with an existing account" %}

-
-
- {% csrf_token %} -
    - {% for error in form.non_field_errors %} -
  • {{ error|escape }}
  • - {% endfor %} - {% for error in form.username.errors %} -
  • {% trans "Username:" %} {{ error|escape }}
  • - {% endfor %} - {% for error in form.password.errors %} -
  • {% trans "Password:" %} {{ error|escape }}
  • - {% endfor %} -
-

- - -

-

- - -

- -

- - -

- - - -
-
- -{% endblock %} diff --git a/src/authentic2/auth2_auth/auth2_ssl/templates/auth/login_form_ssl.html b/src/authentic2/auth2_auth/auth2_ssl/templates/auth/login_form_ssl.html deleted file mode 100644 index 2965dbb2..00000000 --- a/src/authentic2/auth2_auth/auth2_ssl/templates/auth/login_form_ssl.html +++ /dev/null @@ -1,14 +0,0 @@ -{% load i18n %} -
-

-{% trans "Login using a certificate." %} -

-
-{% csrf_token %} -{{ form.as_p }} - -{% if cancel %} - -{% endif %} -
-
diff --git a/src/authentic2/auth2_auth/auth2_ssl/templates/ssl/profile.html b/src/authentic2/auth2_auth/auth2_ssl/templates/ssl/profile.html deleted file mode 100644 index 2608f69a..00000000 --- a/src/authentic2/auth2_auth/auth2_ssl/templates/ssl/profile.html +++ /dev/null @@ -1,33 +0,0 @@ -{% load i18n %} -

- {% trans "SSL Certificates" %} -

- -
-
    - {% for certificate in certificates %} -
  • -
    - {% csrf_token %} -

    -

    - {% for k, v in certificate.explode_subject_dn %} -
    {{ k }}
    -
    {{ v }}
    - {% endfor %} -
    -

    - -
    -

    - {% endfor %} -
-

-

- - - -
-

-
diff --git a/src/authentic2/auth2_auth/auth2_ssl/urls.py b/src/authentic2/auth2_auth/auth2_ssl/urls.py deleted file mode 100644 index 1b63ac4f..00000000 --- a/src/authentic2/auth2_auth/auth2_ssl/urls.py +++ /dev/null @@ -1,33 +0,0 @@ -# authentic2 - versatile identity manager -# Copyright (C) 2010-2019 Entr'ouvert -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU Affero 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 Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . - -from django.conf.urls import url -from .views import (handle_request, post_account_linking, delete_certificate, error_ssl) - -urlpatterns = [ - url(r'^$', - handle_request, - name='user_signin_ssl'), - url(r'^post_account_linking/$', - post_account_linking, - name='post_account_linking'), - url(r'^delete_certificate/(?P\d+)/$', - delete_certificate, - name='delete_certificate'), - url(r'^error_ssl/$', - error_ssl, - name='error_ssl'), -] diff --git a/src/authentic2/auth2_auth/auth2_ssl/util.py b/src/authentic2/auth2_auth/auth2_ssl/util.py deleted file mode 100644 index 0302fed7..00000000 --- a/src/authentic2/auth2_auth/auth2_ssl/util.py +++ /dev/null @@ -1,104 +0,0 @@ -# authentic2 - versatile identity manager -# Copyright (C) 2010-2019 Entr'ouvert -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU Affero 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 Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . - -import base64 -import six - -from . import app_settings - -X509_KEYS = { - 'subject_dn': 'SSL_CLIENT_S_DN', - 'issuer_dn': 'SSL_CLIENT_I_DN', - 'serial': ('SSL_CLIENT_M_SERIAL', 'SSL_CLIENT_SERIAL'), - 'cert': 'SSL_CLIENT_CERT', - 'verify': 'SSL_CLIENT_VERIFY', -} - - -def normalize_cert(certificate_pem): - '''Normalize content of the certificate''' - base64_content = ''.join(certificate_pem.splitlines()[1:-1]) - content = base64.b64decode(base64_content) - return base64.b64encode(content) - - -def explode_dn(dn): - '''Extract sub element of a DN as displayed by mod_ssl or nginx_ssl''' - dn = dn.strip('/') - parts = dn.split('/') - parts = [part.split('=') for part in parts] - parts = [(part[0], part[1].decode('string_escape').decode('utf-8')) for part in parts] - return parts - - -TRANSFORM = { - 'cert': normalize_cert, -} - - -class SSLInfo(object): - """ - Encapsulates the SSL environment variables in a read-only object. It - attempts to find the ssl vars based on the type of request passed to the - constructor. Currently only WSGIRequest and ModPythonRequest are - supported. - """ - def __init__(self, request): - name = request.__class__.__name__ - if app_settings.FORCE_ENV: - env = app_settings.FORCE_ENV - elif name == 'WSGIRequest': - env = request.environ - elif name == 'ModPythonRequest': - env = request._req.subprocess_env - else: - raise EnvironmentError('The SSL authentication currently only \ - works with mod_python or wsgi requests') - self.read_env(env) - pass - - def read_env(self, env): - for attr, keys in X509_KEYS.items(): - if isinstance(keys, six.string_types): - keys = [keys] - for key in keys: - if key in env and env[key]: - v = env[key] - if attr in TRANSFORM: - v = TRANSFORM[attr](v) - self.__dict__[attr] = v - else: - self.__dict__[attr] = None - - if self.__dict__['verify'] == 'SUCCESS': - self.__dict__['verify'] = True - else: - self.__dict__['verify'] = False - - def get(self, attr): - return self.__getattr__(attr) - - def __getattr__(self, attr): - if attr in self.__dict__: - return self.__dict__[attr] - else: - raise AttributeError('SSLInfo does not contain key %s' % attr) - - def __setattr__(self, attr, value): - raise AttributeError('SSL vars are read only!') - - def __repr__(self): - return '' % self.__dict__ diff --git a/src/authentic2/auth2_auth/auth2_ssl/views.py b/src/authentic2/auth2_auth/auth2_ssl/views.py deleted file mode 100644 index 30540fa4..00000000 --- a/src/authentic2/auth2_auth/auth2_ssl/views.py +++ /dev/null @@ -1,141 +0,0 @@ -# authentic2 - versatile identity manager -# Copyright (C) 2010-2019 Entr'ouvert -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU Affero 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 Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . - -import logging - -from django.utils.translation import ugettext as _ -from django.shortcuts import render -from django.views.decorators.csrf import csrf_exempt -from django.views.generic.base import TemplateView -from django.template.loader import render_to_string -from django.contrib import messages -from django.contrib.auth.forms import AuthenticationForm -from django.contrib.auth import authenticate, login - - -from authentic2.utils import continue_to_next_url, record_authentication_event, redirect, redirect_to_login - -from . import models, util, app_settings - -logger = logging.getLogger(__name__) - - -def handle_request(request): - # Check certificate validity - ssl_info = util.SSLInfo(request) - accept_self_signed = app_settings.ACCEPT_SELF_SIGNED - - if not ssl_info.cert: - logger.error('SSL Client Authentication failed: SSL CGI variable CERT is missing') - messages.add_message(request, messages.ERROR, - _('SSL Client Authentication failed. No client certificate found.')) - return redirect_to_login(request) - elif not accept_self_signed and not ssl_info.verify: - logger.error('SSL Client Authentication failed: SSL CGI variable VERIFY is not SUCCESS') - messages.add_message(request, messages.ERROR, - _('SSL Client Authentication failed. Your client certificate is not valid.')) - return redirect_to_login(request) - - # SSL entries for this certificate? - user = authenticate(ssl_info=ssl_info) - - # If the user is logged in, no need to create an account - # If there is an SSL entries, no need for account creation, - # just need to login, treated after - if 'do_creation' in request.session and not user \ - and not request.user.is_authenticated(): - from backends import SSLBackend - if SSLBackend().create_user(ssl_info): - user = authenticate(ssl_info=ssl_info) - logger.info(u'account created for %s', user) - else: - logger.error('account creation failure') - messages.add_message(request, messages.ERROR, - _('SSL Client Authentication failed. Internal server error.')) - return redirect_to_login(request) - - # No SSL entries and no user session, redirect account linking page - if not user and not request.user.is_authenticated(): - return render(request, 'auth/account_linking_ssl.html') - - # No SSL entries but active user session, perform account linking - if not user and request.user.is_authenticated(): - from backend import SSLBackend - if not SSLBackend().link_user(ssl_info, request.user): - logger.error('login() failed') - messages.add_message(request, messages.ERROR, - _('SSL Client Authentication failed. Internal server error.')) - return redirect_to_login(request) - logger.info('Successful linking of the SSL Certificate to an account') - - # SSL Entries found for this certificate, - # if the user is logged out, we login - if not request.user.is_authenticated(): - login(request, user) - record_authentication_event(request, how='ssl') - return continue_to_next_url(request) - - # SSL Entries found for this certificate, if the user is logged in, we - # check that the SSL entry for the certificate is this user. - # else, we make this certificate point on that user. - if user.username != request.user.username: - logger.warning(u'The certificate belongs to %s, but %s is logged with, we change the association!', - user, request.user) - from backends import SSLBackend - cert = SSLBackend().get_certificate(ssl_info) - cert.user = request.user - cert.save() - return continue_to_next_url(request) - - -@csrf_exempt -def post_account_linking(request): - if request.method == "POST": - if 'do_creation' in request.POST and request.POST['do_creation'] == 'on': - request.session['do_creation'] = 'do_creation' - return redirect_to_login(request, login_url='user_signin_ssl') - form = AuthenticationForm(data=request.POST) - if form.is_valid(): - user = form.get_user() - login(request, user) - record_authentication_event(request, how='password') - return redirect_to_login(request, login_url='user_signin_ssl') - else: - return render(request, 'auth/account_linking_ssl.html') - else: - return render(request, 'auth/account_linking_ssl.html') - - -def profile(request, template_name='ssl/profile.html', *args, **kwargs): - context = kwargs.pop('context', {}) - certificates = models.ClientCertificate.objects.filter(user=request.user) - context.update({'certificates': certificates}) - return render_to_string(template_name, context, request=request) - - -def delete_certificate(request, certificate_pk): - qs = models.ClientCertificate.objects.filter(pk=certificate_pk) - count = qs.count() - qs.delete() - if count: - logger.info('client certificate %s deleted', certificate_pk) - messages.info(request, _('Certificate deleted.')) - return redirect(request, 'account_management', fragment='a2-ssl-certificate-profile') - - -class SslErrorView(TemplateView): - template_name = 'error_ssl.html' -error_ssl = SslErrorView.as_view() diff --git a/src/authentic2/auth2_auth/locale/fr/LC_MESSAGES/django.po b/src/authentic2/auth2_auth/locale/fr/LC_MESSAGES/django.po deleted file mode 100644 index 4faa8c5e..00000000 --- a/src/authentic2/auth2_auth/locale/fr/LC_MESSAGES/django.po +++ /dev/null @@ -1,67 +0,0 @@ -# French translation of Authentic -# Copyright (C) 2010, 2011 Entr'ouvert -# This file is distributed under the same license as the Authentic package. -# Frederic Peters , 2010. -# -msgid "" -msgstr "" -"Project-Id-Version: Authentic\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-07-23 18:01+0200\n" -"PO-Revision-Date: 2013-07-23 18:01+0200\n" -"Last-Translator: Mikaël Ates \n" -"Language-Team: None\n" -"Language: fr\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=n>1;\n" - -#: backend.py:17 templates/auth/login_password_profile.html:2 -msgid "Password" -msgstr "Mot de passe" - -#: models.py:23 -#, python-format -msgid "Authentication of %(who)s by %(how)s at %(when)s" -msgstr "Authentification de %(who)s par la méthode %(how)s à %(when)s" - -#: templates/error_ssl.html:4 -msgid "Error: authentication failure" -msgstr "Erreur: Echec de l'authentification" - -#: templates/error_ssl.html:8 -msgid "Authentication failure" -msgstr "Échec d'authentification" - -#: templates/error_ssl.html:10 -msgid "The SSL authentication has failed" -msgstr "L'authentification par certificat électronique a échouée." - -#: templates/auth/login.html:5 templates/auth/login_form.html:6 -msgid "Log in" -msgstr "S'identifier" - -#: templates/auth/login_form.html:8 -msgid "Cancel" -msgstr "Annuler" - -#: templates/auth/login_form.html:14 -msgid "Forgot password?" -msgstr "Mot de passe oublié ?" - -#: templates/auth/login_form.html:14 -msgid "Reset it!" -msgstr "Le réinitialiser !" - -#: templates/auth/login_form.html:15 -msgid "Not a member?" -msgstr "Pas un membre ?" - -#: templates/auth/login_form.html:15 -msgid "Register!" -msgstr "S'inscrire !" - -#: templates/auth/login_password_profile.html:6 -msgid "Change password" -msgstr "Modifier votre mot de passe" diff --git a/src/authentic2/settings.py b/src/authentic2/settings.py index 210db386..f09c7fc6 100644 --- a/src/authentic2/settings.py +++ b/src/authentic2/settings.py @@ -132,7 +132,6 @@ INSTALLED_APPS = ( 'authentic2.saml', 'authentic2.idp', 'authentic2.idp.saml', - 'authentic2.auth2_auth', 'authentic2.attribute_aggregator', 'authentic2.disco_service', 'authentic2.manager', -- 2.20.1