Extension:SSL authentication

From MediaWiki.org
Jump to: navigation, search
MediaWiki extensions manual
Crystal Clear action run.png
SSL Authentication

Release status: stable

Implementation User identity, Special page
Description Automagic login with certificates using Apache2 mod_ssl clientside
Author(s) Martin Johnson
Latest version 1.1.6 (2013-05-18)
MediaWiki 1.10.x, 1.11.x, 1.12.x, 1.13.x, 1.15.x, 1.17.x, 1.18.x, 1.20.x
License No license specified
Download this page

Translate the SSL authentication extension if it is available at translatewiki.net

Check usage and version matrix; code metrics

SSL Authentication is an extension that automatically logs users into the wiki using their SSL certificate. It uses mod_ssl in Apache to fetch the DN from the client certificate and maps that to a MediaWiki user name. All users are automatically logged in, and all users are required to use certificates. These certificates must be vouched for by one of the certification authorities on file, specified by SSLCACertificateFile option. Wiki user names are taken from the user's certificate (SSL_CLIENT_S_DN_CN), and if that user name does not already exist, it is created.

I started this work for MediaWiki version 1.5.3 and we have used it for some months. A couple of weeks ago, I discovered Extension:Shibboleth Authentication by Djcapelis and wow! That made it easy to rewrite my code as an extension and upgrade to the latest MediaWiki version.

Over time more people have been contributing, and in particular I want to say thanks to Krzysztof Kozlowski and D.J. Capelis for their help.

I still have some minor things to work out. I now use firstname + lastname (or CN in the user certificate) as the login name and uses DN for the real name, but firstname + lastname is probably not unique in a larger environment, DN should be but it's not usable as a user name in MW. Maybe an md5 hash of the DN, but that makes for an ugly user name... You probably know the best way to resolve this for your own environment.

As you can see, there are some glitches in this documentation and you are welcome to help. :-)

Clientside certificate and SSL[edit | edit source]

Generally, this refers to a certificate signed by some authority - a 'Certificate Authority' or 'CA' - known to both the server and the client. An organization may acquire its certificate from Verisign, for example, or from one of many other well-known 'trusted' authorities. The organization can then issue - and sign - certificates for use by its clients.

It is also possible for an organization to self-sign its certificates; IE, to be its own Certificate Authority.

Configure Apache[edit | edit source]

For a start, you need some prerequisites. First, you need certificates for all your users. Take a look at OpenCA or the community driven non-profit CAcert.org that issues certificates to it's community members free of charge, if you don't have certificates. Maybe windowscertificates can be used?

We use smartcards for all our users.

Then you need to configure your Apache to use SSL. This is my no-comments code for httpd.conf to setup this:

SSLEngine on
SSLProtocol -all +TLSv1 +SSLv3
SSLCipherSuite HIGH:MEDIUM
SSLProxyEngine off
SSLCertificateFile /etc/apache2/ssl.crt/server.crt
SSLCertificateKeyFile /etc/apache2/ssl.key/server.key
SSLCertificateChainFile /etc/apache2/ssl.crt/ca.crt
SSLCACertificateFile /etc/apache2/ssl.crt/ca-dskort.crt
SSLOptions +StrictRequire +OptRenegotiate +StdEnvVars +ExportCertData

SSLVerifyClient require
SSLVerifyDepth 1

SetEnvIf User-Agent ".*MSIE.*" \
    nokeepalive ssl-unclean-shutdown \
    downgrade-1.0 force-response-1.0

CustomLog /var/log/apache2/ssl_request_log   ssl_combined

<Directory "/srv/www/htdocs/wiki/">
    Options None
    AllowOverride None
    Order allow,deny
    Allow from all
    SSLRequireSSL
    SSLRequire  %{SSL_CLIENT_S_DN}  =~ m/.*serialNumber=<personnummer>$/
</Directory>

We use SSLRequire to restrict usage of our wiki to certain users, with certificates enrolled by our CA which is stored in SSLCACertificateFile. Find some unique thing or add all users DN in this list. If you have used SSL and client certificates, you know what to do.

LocalSettings.php[edit | edit source]

Add this to your LocalSettings.php to init the extension

#Load SSLAuthPlugin
require_once('extensions/SSL authentication/SSLAuthPlugin.php');
 
#Feel free to use extra PHP code to munge the variables if you'd like
#Additionally if you wish to only map some of the name data, set this to true
#and either blank ssl_RN and ssl_email or comment them out entirely.
$ssl_map_info = false;
 
#Ssssh.... quiet down errors
#$olderror = error_reporting(E_ALL ^ E_NOTICE);

#Map Real Name from certificate
#Can be DN but is it right?
if(isset($_SERVER['SSL_CLIENT_S_DN_CN'])){
  $ssl_RN = $_SERVER['SSL_CLIENT_S_DN_CN'];
  };
 
#MW username is required to map to something
#You should beware of possible namespace collisions, it is best to chose
#something that will not violate MW's usual restrictions on characters

#Just using Firstname + Lastname (CN) from Certificate 'will' make collisions... but what to use?
#UN could be md5-hash of DN, but its ugly to use...

if(isset($_SERVER['SSL_CLIENT_S_DN_CN'])){
  $ssl_UN = $_SERVER['SSL_CLIENT_S_DN_CN'];
  };
 
#Map e-mail to something close?
#Will throw warnings if E-Mail is not set in certificate.
#If so, comment out the next three lines and set $ssl_email empty.
if(isset($_SERVER['SSL_CLIENT_S_DN_Email'])){
  if ($_SERVER['SSL_CLIENT_S_DN_Email'] != '')
        $ssl_email = $_SERVER['SSL_CLIENT_S_DN_Email'];
  else
        $ssl_email = '';
  };
 
 
#Turn error reporting back on
#error_reporting($olderror);

#execute the code from the sections below pasted into extensions/SSLAuthPlugin.php as directed
require_once( "$IP/extensions/SSLAuthPlugin.php" );
 
#Activate SSL Plugin
SSLAuthSetup();

SSLAuthPlugin.php (up to MW 1.10)[edit | edit source]

Copypaste this code to the new file extensions/SSLAuthPlugin.php

<?php
 
/**
 * Version 1.1 (Works out of box with MW 1.10.0)
 *
 * Authentication Plugin for Apache2 mod_ssl
 * Derived from AuthPlugin.php and
 * http://meta.wikimedia.org/wiki/Shibboleth_Authentication
 *
 * Much of the commenting comes straight from AuthPlugin.php
 *
 * Portions Copyright 2006, 2007 Martin Johnson
 * Portions Copyright 2006, 2007 Regents of the University of California
 * Portions Copyright 2007 Steven Langenaken
 * Portions Copyright 2007 Krzysztof Kozlowski
 * Released under the GNU General Public License
 *
 * Changes between 1.1 and 1.0.2:
 * == 1.10 compatibility fixes
 
 * Changes between 1.0.2 and 1.0.1:
 * = Merge changes from Shibboleth Authentication: (By DJC)
 * == More 1.9 compatibility fixes and less ugly code
 *
 * Changes between 1.0.1 and 1.0:
 * = Merge changes from Shibboleth Authentication: (By DJC)
 * == Compatible with MW 1.9+ again (By DJC)
 * == Minor fix in loginform handling (By Steven Langenaken)
 *
 * Documentation at http://www.mediawiki.org/wiki/Extension:SSL_authentication
 */
 
require_once('AuthPlugin.php');
 
class SSLAuthPlugin extends AuthPlugin {
	/**
	 * See AuthPlugin.php for specific information
	 */
	function userExists( $username ) {
		return true;
	}
 
	/**
	 * See AuthPlugin.php for specific information
	 */
	function authenticate( $username, $password ) {
		global $ssl_UN;
 
		return $username == $ssl_UN;
	}
 
	/**
	 * See AuthPlugin.php for specific information
	 */
	function modifyUITemplate( &$template ) {
		$template->set( 'usedomain', false );
	}
 
	/**
	 * See AuthPlugin.php for specific information
	 */
	function setDomain( $domain ) {
		$this->domain = $domain;
	}
 
	/**
	 * See AuthPlugin.php for specific information
	 */
	function validDomain( $domain ) {
		return true;
	}
 
	/**
	 * See AuthPlugin.php for specific information
	 */
	function updateUser( &$user ) {
		global $ssl_map_info;
		global $ssl_email;
		global $ssl_RN;
 
		//Map extra info or not?
		if($ssl_map_info == true) {
			//If Email, set info in MW
			if($ssl_email != null)
			$user->setEmail($ssl_email);
 
			//If realName, set info in MW
			if($ssl_RN != null)
			$user->setRealName($ssl_RN);
 
			$user->saveSettings();
		}
 
 
		//For security, set password to a non-existant hash.
		$user->load();
		if($user->mPassword != "nologin") {
			$user->mPassword = "nologin";
			$user->saveSettings();
		}
 
		return true;
	}
 
 
	/**
	 * See AuthPlugin.php for specific information
	 */
	function autoCreate() {
		return true;
	}
 
	/**
	 * See AuthPlugin.php for specific information
	 */
	function allowPasswordChange() {
		return false;
	}
 
	/**
	 * See AuthPlugin.php for specific information
	 */
	function setPassword( $password ) {
		return false;
	}
 
	/**
	 * See AuthPlugin.php for specific information
	 */
	function updateExternalDB( $user ) {
		//Not really, but wiki thinks we did...
		return true;
	}
 
	/**
	 * See AuthPlugin.php for specific information
	 */
	function canCreateAccounts() {
		return false;
	}
 
	/**
	 * See AuthPlugin.php for specific information
	 */
	function addUser( $user, $password, $email='', $realname='' ) {
		return false;
	}
 
	/**
	 * See AuthPlugin.php for specific information
	 */
	function strict() {
		return false;
	}
 
	/**
	 * See AuthPlugin.php for specific information
	 */
	function initUser( &$user ) {
		//Update MW with new user information
		$this->updateUser($user);
	}
 
	/**
	 * See AuthPlugin.php for specific information
	 */
	function getCanonicalName( $username ) {
		return $username;
	}
}
 
/**
 * End of AuthPlugin Code, beginning of hook code and auth functions
 */
 
/**
 * Some extension information init
 */
$wgExtensionFunctions[] = 'SSLAuthSetup';
$wgExtensionCredits['other'][] = array(
	'name' => 'SSLAuth',
	'version' => '1.1',
	'author' => 'Martin Johnson',
	'description' => 'Automagic login with certificates using Apache2 mod_ssl clientside',
	'url' => 'http://www.mediawiki.org/wiki/Extension:SSL_authentication'
);
 
/**
 * Setup extensionfunctions
 */
function SSLAuthSetup() {
	global $ssl_UN;
	global $wgHooks;
	global $wgAuth;
 
	if($ssl_UN != null) {
		$wgHooks['AutoAuthenticate'][] = 'SSLAuth'; /* Hook for magical authN */
		$wgHooks['PersonalUrls'][] = 'NoLogout'; /* Disallow logout link */
		$wgAuth = new SSLAuthPlugin();
	}
}
 
/* No logout link in MW */
function NoLogout(&$personal_urls, $title) {
	$personal_urls['logout'] = null;
}
 
/* Tries to be magical about when to log in users and when not to. */
function SSLAuth(&$user) {
	global $ssl_UN, $wgUser, $wgContLang, $wgHooks;
 
	//Give us a user, see if we're around
	//$tmpuser = User::LoadFromSession(); // Pre MediaWiki 1.10
	$tmpuser = User::newFromSession(); // For MediaWiki 1.10.0 and up
 
	//They already with us?  If so, quit this function.
	if($tmpuser->isLoggedIn())
	return;
 
	//Is the user already in the database?
	$tmpuser = User::newFromName($ssl_UN);
 
	//If exists, log them in
	if($tmpuser->getID() != 0) {
		$wgUser = &$tmpuser;
		$wgUser->setupSession();
		$wgUser->setCookies();
		return;
	}
 
	//Okay, kick this up a notch then...
	$wgUser = &$tmpuser;
	$wgUser->setName($wgContLang->ucfirst($ssl_UN));
 
	/*
	 * Some magic that Shibboleth Authentication does and I just copy
	 */
	require_once('SpecialUserlogin.php');
 
	//This section contains a silly hack for MW
	global $wgLang, $wgContLang, $wgRequest;
	if(!isset($wgLang)) {
		$wgLang = $wgContLang;
		$wgLangUnset = true;
	}
 
	//Temporarily kill The AutoAuth Hook to prevent recursion
	foreach ($wgHooks['AutoAuthenticate'] as $key => $value) {
		if($value == 'SSLAuth')
		$wgHooks['AutoAuthenticate'][$key] = 'BringBackAA';
	}
 
	//This creates our form that'll do black magic
	$lf = new LoginForm($wgRequest);
 
	//Place the hook back (Not strictly necessarily MW Ver >= 1.9)
	BringBackAA();
 
	//And now we clean up our hack
	if($wgLangUnset == true) {
		unset($wgLang);
		unset($wgLangUnset);
	}
 
	//Now we _do_ the black magic
	$lf->mRemember = false;
	$lf->initUser($wgUser);
 
	//Finish it off
	$wgUser->saveSettings();
	$wgUser->setupSession();
	$wgUser->setCookies();
}
 
/* Puts the auto-auth hook back into the hooks array */
function BringBackAA() {
	global $wgHooks;
	foreach ($wgHooks['AutoAuthenticate'] as $key => $value) {
		if($value == 'BringBackAA')
		$wgHooks['AutoAuthenticate'][$key] = 'SSLAuth';
	}
}

SSLAuthPlugin.php (MW 1.11 & 1.12)[edit | edit source]

Copypaste this code to the new file extensions/SSLAuthPlugin.php

<?php
 
/**
 * Version 1.1.2 (Works out of box with MW 1.11.0 and MW 1.12.0)
 *
 * Authentication Plugin for Apache2 mod_ssl
 * Derived from AuthPlugin.php and
 * http://meta.wikimedia.org/wiki/Shibboleth_Authentication
 *
 * Much of the commenting comes straight from AuthPlugin.php
 *
 * Portions Copyright 2006, 2007 Martin Johnson
 * Portions Copyright 2006, 2007 Regents of the University of California
 * Portions Copyright 2007 Steven Langenaken
 * Portions Copyright 2007 Krzysztof Kozlowski
 * compatibility fixes for 1.11 / 1.12  by datenritter.de
 * Released under the GNU General Public License
 *
 * Changes between 1.1.2 and 1.1
 * == 1.11 + 1.12 compatibility fixes
 
 * Changes between 1.1 and 1.0.2:
 * == 1.10 compatibility fixes
 
 * Changes between 1.0.2 and 1.0.1:
 * = Merge changes from Shibboleth Authentication: (By DJC)
 * == More 1.9 compatibility fixes and less ugly code
 *
 * Changes between 1.0.1 and 1.0:
 * = Merge changes from Shibboleth Authentication: (By DJC)
 * == Compatible with MW 1.9+ again (By DJC)
 * == Minor fix in loginform handling (By Steven Langenaken)
 *
 * Documentation at http://www.mediawiki.org/wiki/Extension:SSL_authentication
 */
 
require_once('AuthPlugin.php');
 
class SSLAuthPlugin extends AuthPlugin {
        /**
         * See AuthPlugin.php for specific information
         */
        function userExists( $username ) {
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function authenticate( $username, $password ) {
                global $ssl_UN;
 
                return $username == $ssl_UN;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function modifyUITemplate( &$template ) {
                $template->set( 'usedomain', false );
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function setDomain( $domain ) {
                $this->domain = $domain;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function validDomain( $domain ) {
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function updateUser( &$user ) {
                global $ssl_map_info;
                global $ssl_email;
                global $ssl_RN;
 
                //Map extra info or not?
                if($ssl_map_info == true) {
                        //If Email, set info in MW
                        if($ssl_email != null)
                        $user->setEmail($ssl_email);
 
                        //If realName, set info in MW
                        if($ssl_RN != null)
                        $user->setRealName($ssl_RN);
 
                        $user->saveSettings();
                }
 
 
                //For security, set password to a non-existant hash.
                $user->load();
                if($user->mPassword != "nologin") {
                        $user->mPassword = "nologin";
                        $user->saveSettings();
                }
 
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function autoCreate() {
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function allowPasswordChange() {
                return false;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function setPassword( $password ) {
                return false;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function updateExternalDB( $user ) {
                //Not really, but wiki thinks we did...
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function canCreateAccounts() {
                return false;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function addUser( $user, $password, $email='', $realname='' ) {
                return false;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function strict() {
                return false;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function initUser( &$user ) {
                //Update MW with new user information
                $this->updateUser($user);
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function getCanonicalName( $username ) {
                return $username;
        }
}
 
/**
 * End of AuthPlugin Code, beginning of hook code and auth functions
 */
 
/**
 * Some extension information init
 */
$wgExtensionFunctions[] = 'SSLAuthSetup';
$wgExtensionCredits['other'][] = array(
	'name' => 'SSLAuth',
	'version' => '1.1.2',
	'author' => 'Martin Johnson',
	'description' => 'Automagic login with certificates using Apache2 mod_ssl clientside',
	'url' => 'http://www.mediawiki.org/wiki/Extension:SSL_authentication'
);
 
/**
 * Setup extensionfunctions
 */
function SSLAuthSetup() {
        global $ssl_UN, $wgHooks, $wgAuth;
 
        if($ssl_UN != null) {
                $wgHooks['AutoAuthenticate'][] = 'SSLAuth'; /* Hook for magical authN */
                $wgHooks['PersonalUrls'][] = 'NoLogout'; /* Disallow logout link */
                $wgAuth = new SSLAuthPlugin();
        }
}
 
/* No logout link in MW */
function NoLogout(&$personal_urls, $title) {
        $personal_urls['logout'] = null;
	return true;
}
 
/* Tries to be magical about when to log in users and when not to. */
function SSLAuth(&$user) {
        global $ssl_UN, $wgUser, $wgContLang, $wgHooks;
 
        //Give us a user, see if we're around
        //$tmpuser = User::LoadFromSession(); // Pre MediaWiki 1.10
        $tmpuser = User::newFromSession(); // For MediaWiki 1.10.0 and up
 
        //They already with us?  If so, quit this function.
        if($tmpuser->isLoggedIn())
        return true;
 
        //Is the user already in the database?
        $tmpuser = User::newFromName($ssl_UN);
 
        //If exists, log them in
        if($tmpuser->getID() != 0) {
                $wgUser = &$tmpuser;
                $wgUser->setupSession();
                $wgUser->setCookies();
                return true;
        }
 
        //Okay, kick this up a notch then...
        $wgUser = &$tmpuser;
        $wgUser->setName($wgContLang->ucfirst($ssl_UN));
 
        /*
         * Some magic that Shibboleth Authentication does and I just copy
         */
        require_once('SpecialUserlogin.php');
 
        //This section contains a silly hack for MW
        global $wgLang, $wgContLang, $wgRequest;
        if(!isset($wgLang)) {
                $wgLang = $wgContLang;
                $wgLangUnset = true;
        }
 
        //Temporarily kill The AutoAuth Hook to prevent recursion
        foreach ($wgHooks['AutoAuthenticate'] as $key => $value) {
                if($value == 'SSLAuth')
                $wgHooks['AutoAuthenticate'][$key] = 'BringBackAA';
        }
 
        //This creates our form that'll do black magic
        $lf = new LoginForm($wgRequest);
 
        //Place the hook back (Not strictly necessarily MW Ver >= 1.9)
        BringBackAA();
 
        //And now we clean up our hack
        if($wgLangUnset == true) {
                unset($wgLang);
                unset($wgLangUnset);
        }
 
        //Now we _do_ the black magic
        $lf->mRemember = false;
        $lf->initUser($wgUser, true);
 
        //Finish it off
        $wgUser->saveSettings();
        $wgUser->setupSession();
        $wgUser->setCookies();
}
 
/* Puts the auto-auth hook back into the hooks array */
function BringBackAA() {
        global $wgHooks;
        foreach ($wgHooks['AutoAuthenticate'] as $key => $value) {
                if($value == 'BringBackAA')
                $wgHooks['AutoAuthenticate'][$key] = 'SSLAuth';
        }
	return true;
}

SSLAuthPlugin.php (MW 1.13)[edit | edit source]

Copypaste this code to the new file extensions/SSLAuthPlugin.php

<?php
/**
 */
# Version 1.1.3 (Works out of box with MW 1.13.0)
#
# Authentication Plugin for Apache2 mod_ssl
# Derived from AuthPlugin.php and
# http://meta.wikimedia.org/wiki/Shibboleth_Authentication
#
# Much of the commenting comes straight from AuthPlugin.php
#
# Portions Copyright 2006, 2007 Martin Johnson
# Portions Copyright 2006, 2007 Regents of the University of California
# Portions Copyright 2007 Steven Langenaken
# Portions Copyright 2007 Krzysztof Kozlowski
# compatibility fixes for 1.11 / 1.12  by datenritter.de
# compatibility fixes for 1.13  by Philippe Marty
# Released under the GNU General Public License

/**
 * Changes between 1.1.3 and 1.1.2
 * == 1.13 compatibility fixes
 *
 * Changes between 1.1.2 and 1.1
 * == 1.11 / 1.12 compatibility fixes
 *
 * Changes between 1.1 and 1.0.2:
 * == 1.10 compatibility fixes
 *
 * Changes between 1.0.2 and 1.0.1:
 * = Merge changes from Shibboleth Authentication: (By DJC)
 * == More 1.9 compatibility fixes and less ugly code
 *
 * Changes between 1.0.1 and 1.0:
 * = Merge changes from Shibboleth Authentication: (By DJC)
 * == Compatible with MW 1.9+ again (By DJC)
 * == Minor fix in loginform handling (By Steven Langenaken)
 *
 * Documentation at http://www.mediawiki.org/wiki/Extension:SSL_authentication
 * require_once('AuthPlugin.php');
 */
 
class SSLAuthPlugin extends AuthPlugin {
        /**
         * See AuthPlugin.php for specific information
         */
        function userExists( $username ) {
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function authenticate( $username, $password ) {
                global $ssl_UN;
 
                return $username == $ssl_UN;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function modifyUITemplate( &$template ) {
                $template->set( 'usedomain', false );
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function setDomain( $domain ) {
                $this->domain = $domain;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function validDomain( $domain ) {
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function updateUser( &$user ) {
                global $ssl_map_info;
                global $ssl_email;
                global $ssl_RN;
 
                //Map extra info or not?
                if($ssl_map_info == true) {
                        //If Email, set info in MW
                        if($ssl_email != null)
                        $user->setEmail($ssl_email);
 
                        //If realName, set info in MW
                        if($ssl_RN != null)
                        $user->setRealName($ssl_RN);
 
                        $user->saveSettings();
                }
 
 
                //For security, set password to a non-existant hash.
                $user->load();
                if($user->mPassword != "nologin") {
                        $user->mPassword = "nologin";
                        $user->saveSettings();
                }
 
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function autoCreate() {
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function allowPasswordChange() {
                return false;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function setPassword( $password ) {
                return false;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function updateExternalDB( $user ) {
                //Not really, but wiki thinks we did...
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function canCreateAccounts() {
                return false;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function addUser( $user, $password, $email='', $realname='' ) {
                return false;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function strict() {
                return false;
        }
	function strictUserAuth( $username ) {
		return false;
	}
 
        /**
         * See AuthPlugin.php for specific information
         */
        function initUser( &$user, $autocreate ) {
                //Update MW with new user information
                $this->updateUser($user);
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function getCanonicalName( $username ) {
                return $username;
        }
}
 
/**
 * End of AuthPlugin Code, beginning of hook code and auth functions
 */
 
/**
 * Some extension information init
 */
$wgExtensionFunctions[] = 'SSLAuthSetup';
$wgExtensionCredits['other'][] = array(
        'name' => 'SSLAuth',
        'version' => '1.1.3',
        'author' => 'Martin Johnson',
        'description' => 'Automagic login with certificates using Apache2 mod_ssl clientside',
        'url' => 'http://www.mediawiki.org/wiki/Extension:SSL_authentication'
);
 
/**
 * Setup extensionfunctions
 */
function GetSSLAuthHook() {
	global $wgVersion;
	if ($wgVersion >= "1.13") {
		return 'UserLoadFromSession';
	} else {
		return 'AutoAuthenticate';
	}
}
 
function SSLAuthSetup() {
        global $ssl_UN, $wgHooks, $wgAuth;
 
        if($ssl_UN != null) {
                $wgHooks[GetSSLAuthHook()][] = 'SSLAuth'.GetSSLAuthHook(); /* Hook for magical authN */
                $wgHooks['PersonalUrls'][] = 'NoLogout'; /* Disallow logout link */
                $wgAuth = new SSLAuthPlugin();
        }
}
 
/* No logout link in MW */
function NoLogout(&$personal_urls, $title) {
        $personal_urls['logout'] = null;
        return true;
}
 
/* Tries to be magical about when to log in users and when not to. */
function SSLAuthAutoAuthenticate(&$user) {
	SSLAuthUserLoadFromSession($user, true);
}
 
function SSLAuthUserLoadFromSession(&$user, &$result) {
        global $ssl_UN, $wgUser, $wgContLang, $wgHooks;
 
        //ShibAuthPlugin added this function call here also, and indeed it made things work ;)
        KillAA();
 
        //Give us a user, see if we're around
        //$tmpuser = User::LoadFromSession(); // Pre MediaWiki 1.10
        $tmpuser = User::newFromSession(); // For MediaWiki 1.10.0 and up
 
        //They already with us?  If so, quit this function.
        if($tmpuser->isLoggedIn())
        return true;
 
        //Is the user already in the database?
        $tmpuser = User::newFromName($ssl_UN);
 
        //If exists, log them in
        if($tmpuser->getID() != 0) {
                $wgUser = &$tmpuser;
                $wgUser->setupSession();
                $wgUser->setCookies();
                return true;
        }
 
        //ShibAuthPlugin added this function call here also, and indeed it made things work ;)
        BringBackAA();
 
        //Okay, kick this up a notch then...
        $wgUser = &$tmpuser;
        $wgUser->setName($wgContLang->ucfirst($ssl_UN));
 
        /*
         * Some magic that Shibboleth Authentication does and I just copy
         */
        require_once('SpecialUserlogin.php');
 
        //This section contains a silly hack for MW
        global $wgLang, $wgContLang, $wgRequest;
        if(!isset($wgLang)) {
                $wgLang = $wgContLang;
                $wgLangUnset = true;
        }
 
        //Temporarily kill The AutoAuth Hook to prevent recursion
        KillAA();
 
        //This creates our form that'll do black magic
        $lf = new LoginForm($wgRequest);
 
        //Place the hook back (Not strictly necessarily MW Ver >= 1.9)
        BringBackAA();
 
        //And now we clean up our hack
        if($wgLangUnset == true) {
                unset($wgLang);
                unset($wgLangUnset);
        }
 
        //Now we _do_ the black magic
        $lf->mRemember = false;
        $lf->initUser($wgUser, true);
 
        //Finish it off
        $wgUser->saveSettings();
        $wgUser->setupSession();
        $wgUser->setCookies();
#	return true; //looks unuseful here, but it appeared in ShibAuthPlugin... let _real_ developpers decide ;)
}
 
/* Temporarily kill The AutoAuth Hook to prevent recursion */
function KillAA()
{
	global $wgHooks;
#	global $wgAuth; //looks unuseful here, but it appeared in ShibAuthPlugin... let _real_ developpers decide ;)
 
        foreach ($wgHooks[GetSSLAuthHook()] as $key => $value) {
                if($value == 'SSLAuth'.GetSSLAuthHook())
                $wgHooks[GetSSLAuthHook()][$key] = 'BringBackAA';
        }
}
 
/* Puts the auto-auth hook back into the hooks array */
function BringBackAA() {
        global $wgHooks;
#	global $wgAuth; //looks unuseful here, but it appeared in ShibAuthPlugin... let _real_ developpers decide ;)

        foreach ($wgHooks[GetSSLAuthHook()] as $key => $value) {
                if($value == 'BringBackAA')
                $wgHooks[GetSSLAuthHook()][$key] = 'SSLAuth'.GetSSLAuthHook();
        }
        return true;
}

SSLAuthPlugin.php (MW 1.15+)[edit | edit source]

Copypaste this code to the new file extensions/SSLAuthPlugin.php

<?php
/**
 */
# Version 1.1.4 (Works out of box with MW 1.15.1 and 1.17.0)
#
# Authentication Plugin for Apache2 mod_ssl
# Derived from AuthPlugin.php and
# http://meta.wikimedia.org/wiki/Shibboleth_Authentication
#
# Much of the commenting comes straight from AuthPlugin.php
#
# Portions Copyright 2006, 2007 Martin Johnson
# Portions Copyright 2006, 2007 Regents of the University of California
# Portions Copyright 2007 Steven Langenaken
# Portions Copyright 2007 Krzysztof Kozlowski
# compatibility fixes for 1.11 / 1.12  by datenritter.de
# compatibility fixes for 1.13  by Philippe Marty
# compatibility fixes for 1.15  by Christophe Jacquet
# Released under the GNU General Public License

/**
 * Changes between 1.1.4 and 1.1.3
 * == 1.15 compatibility fixes
 *
 * Changes between 1.1.3 and 1.1.2
 * == 1.13 compatibility fixes
 *
 * Changes between 1.1.2 and 1.1
 * == 1.11 / 1.12 compatibility fixes
 *
 * Changes between 1.1 and 1.0.2:
 * == 1.10 compatibility fixes
 *
 * Changes between 1.0.2 and 1.0.1:
 * = Merge changes from Shibboleth Authentication: (By DJC)
 * == More 1.9 compatibility fixes and less ugly code
 *
 * Changes between 1.0.1 and 1.0:
 * = Merge changes from Shibboleth Authentication: (By DJC)
 * == Compatible with MW 1.9+ again (By DJC)
 * == Minor fix in loginform handling (By Steven Langenaken)
 *
 * Documentation at http://www.mediawiki.org/wiki/Extension:SSL_authentication
 * require_once('AuthPlugin.php');
 */
 
class SSLAuthPlugin extends AuthPlugin {
        /**
         * See AuthPlugin.php for specific information
         */
        function userExists( $username ) {
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function authenticate( $username, $password ) {
                global $ssl_UN;
 
                return $username == User::getCanonicalName($ssl_UN);
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function modifyUITemplate( &$template ) {
                $template->set( 'usedomain', false );
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function setDomain( $domain ) {
                $this->domain = $domain;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function validDomain( $domain ) {
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function updateUser( &$user ) {
                global $ssl_map_info;
                global $ssl_email;
                global $ssl_RN;
 
                //Map extra info or not?
                if($ssl_map_info == true) {
                        //If Email, set info in MW
                        if($ssl_email != null)
                        $user->setEmail($ssl_email);
 
                        //If realName, set info in MW
                        if($ssl_RN != null)
                        $user->setRealName($ssl_RN);
 
                        $user->saveSettings();
                }
 
 
                //For security, set password to a non-existant hash.
                $user->load();
                if($user->mPassword != "nologin") {
                        $user->mPassword = "nologin";
                        $user->saveSettings();
                }
 
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function autoCreate() {
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function allowPasswordChange() {
                return false;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function setPassword( $password ) {
                return false;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function updateExternalDB( $user ) {
                //Not really, but wiki thinks we did...
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function canCreateAccounts() {
                return false;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function addUser( $user, $password, $email='', $realname='' ) {
                return false;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function strict() {
                return false;
        }
	function strictUserAuth( $username ) {
		return false;
	}
 
        /**
         * See AuthPlugin.php for specific information
         */
        function initUser( &$user, $autocreate ) {
                //Update MW with new user information
                $this->updateUser($user);
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function getCanonicalName( $username ) {
                return $username;
        }
}
 
/**
 * End of AuthPlugin Code, beginning of hook code and auth functions
 */
 
/**
 * Some extension information init
 */
$wgExtensionFunctions[] = 'SSLAuthSetup';
$wgExtensionCredits['other'][] = array(
        'name' => 'SSL Authentication',
        'version' => '1.1.4',
        'author' => 'Martin Johnson and others',
        'description' => 'Automatic login with certificates using Apache2 mod_ssl clientside',
        'url' => 'http://www.mediawiki.org/wiki/Extension:SSL_authentication'
);
 
/**
 * Setup extensionfunctions
 */
function GetSSLAuthHook() {
	global $wgVersion;
	if ($wgVersion >= "1.13") {
		return 'UserLoadFromSession';
	} else {
		return 'AutoAuthenticate';
	}
}
 
function SSLAuthSetup() {
        global $ssl_UN, $wgHooks, $wgAuth;
 
        if($ssl_UN != null) {
                $wgHooks[GetSSLAuthHook()][] = 'SSLAuth'.GetSSLAuthHook(); /* Hook for magical authN */
                $wgHooks['PersonalUrls'][] = 'NoLogout'; /* Disallow logout link */
                $wgAuth = new SSLAuthPlugin();
        }
}
 
/* No logout link in MW */
function NoLogout(&$personal_urls, $title) {
        $personal_urls['logout'] = null;
        return true;
}
 
/* Tries to be magical about when to log in users and when not to. */
function SSLAuthAutoAuthenticate(&$user) {
	SSLAuthUserLoadFromSession($user, true);
}
 
function SSLAuthUserLoadFromSession($user, &$result) {
        global $ssl_UN, $wgUser, $wgContLang, $wgHooks;
 
        //ShibAuthPlugin added this function call here also, and indeed it made things work ;)
        KillAA();
 
        //Give us a user, see if we're around
        //$tmpuser = User::LoadFromSession(); // Pre MediaWiki 1.10
        $tmpuser = User::newFromSession(); // For MediaWiki 1.10.0 and up
 
        //They already with us?  If so, quit this function.
        if($tmpuser->isLoggedIn())
        return true;
 
        //Is the user already in the database?
        $tmpuser = User::newFromName($ssl_UN);
 
        //If exists, log them in
        if($tmpuser->getID() != 0) {
                $wgUser = &$tmpuser;
                $wgUser->setupSession();
                $wgUser->setCookies();
                return true;
        }
 
        //ShibAuthPlugin added this function call here also, and indeed it made things work ;)
        BringBackAA();
 
        //Okay, kick this up a notch then...
        $wgUser = &$tmpuser;
        $wgUser->setName($wgContLang->ucfirst($ssl_UN));
 
        /*
         * Some magic that Shibboleth Authentication does and I just copy
         */
        require_once('includes/specials/SpecialUserlogin.php');
 
        //This section contains a silly hack for MW
        global $wgLang, $wgContLang, $wgRequest;
        if(!isset($wgLang)) {
                $wgLang = $wgContLang;
                $wgLangUnset = true;
        }
 
        //Temporarily kill The AutoAuth Hook to prevent recursion
        KillAA();
 
        //This creates our form that'll do black magic
        $lf = new LoginForm($wgRequest);
 
        //Place the hook back (Not strictly necessarily MW Ver >= 1.9)
        BringBackAA();
 
        //And now we clean up our hack
        if($wgLangUnset == true) {
                unset($wgLang);
                unset($wgLangUnset);
        }
 
        //Now we _do_ the black magic
        $lf->mRemember = false;
        $lf->initUser($wgUser, true);
 
        //Finish it off
        $wgUser->saveSettings();
        $wgUser->setupSession();
        $wgUser->setCookies();
	return true; // needed in MediaWiki 1.15
}
 
/* Temporarily kill The AutoAuth Hook to prevent recursion */
function KillAA()
{
	global $wgHooks;
#	global $wgAuth; //looks unuseful here, but it appeared in ShibAuthPlugin... let _real_ developpers decide ;)
 
        foreach ($wgHooks[GetSSLAuthHook()] as $key => $value) {
                if($value == 'SSLAuth'.GetSSLAuthHook())
                $wgHooks[GetSSLAuthHook()][$key] = 'BringBackAA';
        }
}
 
/* Puts the auto-auth hook back into the hooks array */
function BringBackAA() {
        global $wgHooks;
#	global $wgAuth; //looks unuseful here, but it appeared in ShibAuthPlugin... let _real_ developpers decide ;)

        foreach ($wgHooks[GetSSLAuthHook()] as $key => $value) {
                if($value == 'BringBackAA')
                $wgHooks[GetSSLAuthHook()][$key] = 'SSLAuth'.GetSSLAuthHook();
        }
        return true;
}

SSLAuthPlugin.php (MW 1.18)[edit | edit source]

Copypaste this code to the new file extensions/SSLAuthPlugin.php

<?php
/**
 */
# Version 1.1.5 (Works out of box with MW 1.18.0)
#
# Authentication Plugin for Apache2 mod_ssl
# Derived from AuthPlugin.php and
# http://meta.wikimedia.org/wiki/Shibboleth_Authentication
#
# Much of the commenting comes straight from AuthPlugin.php
#
# Portions Copyright 2006, 2007 Martin Johnson
# Portions Copyright 2006, 2007 Regents of the University of California
# Portions Copyright 2007 Steven Langenaken
# Portions Copyright 2007 Krzysztof Kozlowski
# compatibility fixes for 1.11 / 1.12  by datenritter.de
# compatibility fixes for 1.13  by Philippe Marty
# compatibility fixes for 1.15  by Christophe Jacquet
# compatibility fixes for 1.18  by Team Sweeps
# Released under the GNU General Public License

/**
 * Changes between 1.1.5 and 1.1.4
 * == 1.18 compatibility fixes
 
 * Changes between 1.1.4 and 1.1.3
 * == 1.15 compatibility fixes
 *
 * Changes between 1.1.3 and 1.1.2
 * == 1.13 compatibility fixes
 *
 * Changes between 1.1.2 and 1.1
 * == 1.11 / 1.12 compatibility fixes
 *
 * Changes between 1.1 and 1.0.2:
 * == 1.10 compatibility fixes
 *
 * Changes between 1.0.2 and 1.0.1:
 * = Merge changes from Shibboleth Authentication: (By DJC)
 * == More 1.9 compatibility fixes and less ugly code
 *
 * Changes between 1.0.1 and 1.0:
 * = Merge changes from Shibboleth Authentication: (By DJC)
 * == Compatible with MW 1.9+ again (By DJC)
 * == Minor fix in loginform handling (By Steven Langenaken)
 *
 * Documentation at http://www.mediawiki.org/wiki/Extension:SSL_authentication
 * require_once('AuthPlugin.php');
 */
 
class SSLAuthPlugin extends AuthPlugin {
        /**
         * See AuthPlugin.php for specific information
         */
        function userExists( $username ) {
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function authenticate( $username, $password ) {
                global $ssl_UN;
 
                return $username == $ssl_UN;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function modifyUITemplate( &$template ) {
                $template->set( 'usedomain', false );
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function setDomain( $domain ) {
                $this->domain = $domain;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function validDomain( $domain ) {
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function updateUser( &$user ) {
                global $ssl_map_info;
                global $ssl_email;
                global $ssl_RN;
 
                //Map extra info or not?
                if($ssl_map_info == true) {
                        //If Email, set info in MW
                        if($ssl_email != null)
                        $user->setEmail($ssl_email);
 
                        //If realName, set info in MW
                        if($ssl_RN != null)
                        $user->setRealName($ssl_RN);
 
                        $user->saveSettings();
                }
 
 
                //For security, set password to a non-existant hash.
                $user->load();
                if($user->mPassword != "nologin") {
                        $user->mPassword = "nologin";
                        $user->saveSettings();
                }
 
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function autoCreate() {
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function allowPasswordChange() {
                return false;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function setPassword( $password ) {
                return false;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function updateExternalDB( $user ) {
                //Not really, but wiki thinks we did...
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function canCreateAccounts() {
                return false;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function addUser( $user, $password, $email='', $realname='' ) {
                return false;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function strict() {
                return false;
        }
	function strictUserAuth( $username ) {
		return false;
	}
 
        /**
         * See AuthPlugin.php for specific information
         */
        function initUser( &$user, $autocreate ) {
                //Update MW with new user information
                $this->updateUser($user);
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function getCanonicalName( $username ) {
                return $username;
        }
}
 
/**
 * End of AuthPlugin Code, beginning of hook code and auth functions
 */
 
/**
 * Some extension information init
 */
$wgExtensionFunctions[] = 'SSLAuthSetup';
$wgExtensionCredits['other'][] = array(
        'name' => 'SSL Authentication',
        'version' => '1.1.4',
        'author' => 'Martin Johnson and others',
        'description' => 'Automatic login with certificates using Apache2 mod_ssl clientside',
        'url' => 'http://www.mediawiki.org/wiki/Extension:SSL_authentication'
);
 
/**
 * Setup extensionfunctions
 */
function GetSSLAuthHook() {
	global $wgVersion;
	if ($wgVersion >= "1.13") {
		return 'UserLoadFromSession';
	} else {
		return 'AutoAuthenticate';
	}
}
 
function SSLAuthSetup() {
        global $ssl_UN, $wgHooks, $wgAuth;
 
        if($ssl_UN != null) {
                $wgHooks[GetSSLAuthHook()][] = 'SSLAuth'.GetSSLAuthHook(); /* Hook for magical authN */
                $wgHooks['PersonalUrls'][] = 'NoLogout'; /* Disallow logout link */
                $wgAuth = new SSLAuthPlugin();
        }
}
 
/* No logout link in MW */
function NoLogout(&$personal_urls, $title) {
        $personal_urls['logout'] = null;
        return true;
}
 
/* Tries to be magical about when to log in users and when not to. */
function SSLAuthAutoAuthenticate(&$user) {
	SSLAuthUserLoadFromSession($user, true);
}
 
function SSLAuthUserLoadFromSession($user, &$result) {
        global $ssl_UN, $wgUser, $wgContLang, $wgHooks;
 
        //ShibAuthPlugin added this function call here also, and indeed it made things work ;)
        KillAA();
 
        //Give us a user, see if we're around
        //$tmpuser = User::LoadFromSession(); // Pre MediaWiki 1.10
        $tmpuser = User::newFromSession(); // For MediaWiki 1.10.0 and up
 
        //They already with us?  If so, quit this function.
        if($tmpuser->isLoggedIn())
        return true;
 
        //Is the user already in the database?
        $tmpuser = User::newFromName($ssl_UN);
 
        //If exists, log them in
        if($tmpuser->getID() != 0) {
                $wgUser = &$tmpuser;
                wfSetupSession();
                $wgUser->setCookies();
                return true;
        }
 
        //ShibAuthPlugin added this function call here also, and indeed it made things work ;)
        BringBackAA();
 
        //Okay, kick this up a notch then...
        $wgUser = &$tmpuser;
        $wgUser->setName($wgContLang->ucfirst($ssl_UN));
 
        /*
         * Some magic that Shibboleth Authentication does and I just copy
         */
        require_once('includes/specials/SpecialUserlogin.php');
 
        //This section contains a silly hack for MW
        global $wgLang, $wgContLang, $wgRequest;
        if(!isset($wgLang)) {
                $wgLang = $wgContLang;
                $wgLangUnset = true;
        }
 
        //Temporarily kill The AutoAuth Hook to prevent recursion
        KillAA();
 
        //This creates our form that'll do black magic
        $lf = new LoginForm($wgRequest);
 
        //Place the hook back (Not strictly necessarily MW Ver >= 1.9)
        BringBackAA();
 
        //And now we clean up our hack
        if($wgLangUnset == true) {
                unset($wgLang);
                unset($wgLangUnset);
        }
 
        //Now we _do_ the black magic
        $lf->mRemember = false;
        $lf->initUser($wgUser, true);
 
        //Finish it off
        $wgUser->saveSettings();
        wfSetupSession();
        $wgUser->setCookies();
	return true; // needed in MediaWiki 1.15
}
 
/* Temporarily kill The AutoAuth Hook to prevent recursion */
function KillAA()
{
	global $wgHooks;
#	global $wgAuth; //looks unuseful here, but it appeared in ShibAuthPlugin... let _real_ developpers decide ;)
 
        foreach ($wgHooks[GetSSLAuthHook()] as $key => $value) {
                if($value == 'SSLAuth'.GetSSLAuthHook())
                $wgHooks[GetSSLAuthHook()][$key] = 'BringBackAA';
        }
}
 
/* Puts the auto-auth hook back into the hooks array */
function BringBackAA() {
        global $wgHooks;
#	global $wgAuth; //looks unuseful here, but it appeared in ShibAuthPlugin... let _real_ developpers decide ;)

        foreach ($wgHooks[GetSSLAuthHook()] as $key => $value) {
                if($value == 'BringBackAA')
                $wgHooks[GetSSLAuthHook()][$key] = 'SSLAuth'.GetSSLAuthHook();
        }
        return true;
}

SSLAuthPlugin.php (MW 1.20)[edit | edit source]

Copypaste this code to the new file extensions/SSLAuthPlugin.php

<?php
/**
 */
# Version 1.1.6 (Works out of box with MW 1.20.0)
#
# Authentication Plugin for Apache2 mod_ssl
# Derived from AuthPlugin.php and
# http://meta.wikimedia.org/wiki/Shibboleth_Authentication
#
# Much of the commenting comes straight from AuthPlugin.php
#
# Portions Copyright 2006, 2007 Martin Johnson
# Portions Copyright 2006, 2007 Regents of the University of California
# Portions Copyright 2007 Steven Langenaken
# Portions Copyright 2007 Krzysztof Kozlowski
# compatibility fixes for 1.11 / 1.12  by datenritter.de
# compatibility fixes for 1.13  by Philippe Marty
# compatibility fixes for 1.15  by Christophe Jacquet
# compatibility fixes for 1.18  by Team Sweeps
# compatibility fixes for 1.20  by S-1-5-7
# Released under the GNU General Public License

/**
 * Changes between 1.1.6 and 1.1.5
 * == 1.20 compatibility fixes
 
 * Changes between 1.1.5 and 1.1.4
 * == 1.18 compatibility fixes
 
 * Changes between 1.1.4 and 1.1.3
 * == 1.15 compatibility fixes
 *
 * Changes between 1.1.3 and 1.1.2
 * == 1.13 compatibility fixes
 *
 * Changes between 1.1.2 and 1.1
 * == 1.11 / 1.12 compatibility fixes
 *
 * Changes between 1.1 and 1.0.2:
 * == 1.10 compatibility fixes
 *
 * Changes between 1.0.2 and 1.0.1:
 * = Merge changes from Shibboleth Authentication: (By DJC)
 * == More 1.9 compatibility fixes and less ugly code
 *
 * Changes between 1.0.1 and 1.0:
 * = Merge changes from Shibboleth Authentication: (By DJC)
 * == Compatible with MW 1.9+ again (By DJC)
 * == Minor fix in loginform handling (By Steven Langenaken)
 *
 * Documentation at http://www.mediawiki.org/wiki/Extension:SSL_authentication
 * require_once('AuthPlugin.php');
 */
 
class SSLAuthPlugin extends AuthPlugin {
        /**
         * See AuthPlugin.php for specific information
         */
        function userExists( $username ) {
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function authenticate( $username, $password ) {
                global $ssl_UN;
 
                return $username == $ssl_UN;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function modifyUITemplate( &$template, &$type ) {
                $template->set( 'usedomain', false );
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function setDomain( $domain ) {
                $this->domain = $domain;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function validDomain( $domain ) {
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function updateUser( &$user ) {
                global $ssl_map_info;
                global $ssl_email;
                global $ssl_RN;
 
                //Map extra info or not?
                if($ssl_map_info == true) {
                        //If Email, set info in MW
                        if($ssl_email != null)
                        $user->setEmail($ssl_email);
 
                        //If realName, set info in MW
                        if($ssl_RN != null)
                        $user->setRealName($ssl_RN);
 
                        $user->saveSettings();
                }
 
 
                //For security, set password to a non-existant hash.
                $user->load();
                if($user->mPassword != "nologin") {
                        $user->mPassword = "nologin";
                        $user->saveSettings();
                }
 
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function autoCreate() {
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function allowPasswordChange() {
                return false;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function setPassword( $user, $password ) {
                return false;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function updateExternalDB( $user ) {
                //Not really, but wiki thinks we did...
                return true;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function canCreateAccounts() {
                return false;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function addUser( $user, $password, $email='', $realname='' ) {
                return false;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function strict() {
                return false;
        }
        function strictUserAuth( $username ) {
                return false;
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function initUser( &$user, $autocreate = false ) {
                //Update MW with new user information
                $this->updateUser($user);
        }
 
        /**
         * See AuthPlugin.php for specific information
         */
        function getCanonicalName( $username ) {
                return $username;
        }
}
 
/**
 * End of AuthPlugin Code, beginning of hook code and auth functions
 */
 
/**
 * Some extension information init
 */
$wgExtensionFunctions[] = 'SSLAuthSetup';
$wgExtensionCredits['other'][] = array(
        'name' => 'SSL Authentication',
        'version' => '1.1.6',
        'author' => 'Martin Johnson and others',
        'description' => 'Automatic login with certificates using Apache2 mod_ssl clientside',
        'url' => 'http://www.mediawiki.org/wiki/Extension:SSL_authentication'
);
 
/**
 * Setup extensionfunctions
 */
function GetSSLAuthHook() {
        global $wgVersion;
        if ($wgVersion >= "1.13") {
                return 'UserLoadFromSession';
        } else {
                return 'AutoAuthenticate';
        }
}
 
function SSLAuthSetup() {
        global $ssl_UN, $wgHooks, $wgAuth;
 
        if($ssl_UN != null) {
                $wgHooks[GetSSLAuthHook()][] = 'SSLAuth'.GetSSLAuthHook(); /* Hook for magical authN */
                $wgHooks['PersonalUrls'][] = 'NoLogout'; /* Disallow logout link */
                $wgAuth = new SSLAuthPlugin();
        }
}
 
/* No logout link in MW */
function NoLogout(&$personal_urls, $title) {
        $personal_urls['logout'] = array( 'text' => '', 'href' => '' );
        return true;
}
 
/* Tries to be magical about when to log in users and when not to. */
function SSLAuthAutoAuthenticate(&$user) {
        SSLAuthUserLoadFromSession($user, true);
}
 
function SSLAuthUserLoadFromSession($user, &$result) {
        global $ssl_UN, $wgUser, $wgContLang, $wgHooks;
 
        //ShibAuthPlugin added this function call here also, and indeed it made things work ;)
        KillAA();
 
        //Give us a user, see if we're around
        //$tmpuser = User::LoadFromSession(); // Pre MediaWiki 1.10
        $tmpuser = User::newFromSession(); // For MediaWiki 1.10.0 and up
 
        //They already with us?  If so, quit this function.
        if($tmpuser->isLoggedIn())
        return true;
 
        //Is the user already in the database?
        $tmpuser = User::newFromName($ssl_UN);
 
        //If exists, log them in
        if($tmpuser->getID() != 0) {
                $wgUser = &$tmpuser;
                wfSetupSession();
                $wgUser->setCookies();
                return true;
        }
 
        //ShibAuthPlugin added this function call here also, and indeed it made things work ;)
        BringBackAA();
 
        //Okay, kick this up a notch then...
        $wgUser = &$tmpuser;
        $wgUser->setName($wgContLang->ucfirst($ssl_UN));
 
        /*
         * Some magic that Shibboleth Authentication does and I just copy
         */
        require_once('includes/specials/SpecialUserlogin.php');
 
        //This section contains a silly hack for MW
        global $wgLang, $wgContLang, $wgRequest;
        global $wgLangUnset;
        if(!isset($wgLang)) {
                $wgLang = $wgContLang;
                $wgLangUnset = true;
        }
 
        //Temporarily kill The AutoAuth Hook to prevent recursion
        KillAA();
 
        //This creates our form that'll do black magic
        $lf = new LoginForm($wgRequest);
 
        //Place the hook back (Not strictly necessarily MW Ver >= 1.9)
        BringBackAA();
 
        //And now we clean up our hack
        if($wgLangUnset == true) {
                unset($wgLang);
                unset($wgLangUnset);
        }
 
        //Now we _do_ the black magic
        $lf->mRemember = false;
        $lf->initUser($wgUser, true);
 
        //Finish it off
        $wgUser->saveSettings();
        wfSetupSession();
        $wgUser->setCookies();
        return true; // needed in MediaWiki 1.15
}
 
/* Temporarily kill The AutoAuth Hook to prevent recursion */
function KillAA()
{
        global $wgHooks;
#       global $wgAuth; //looks unuseful here, but it appeared in ShibAuthPlugin... let _real_ developpers decide ;)
 
        foreach ($wgHooks[GetSSLAuthHook()] as $key => $value) {
                if($value == 'SSLAuth'.GetSSLAuthHook())
                $wgHooks[GetSSLAuthHook()][$key] = 'BringBackAA';
        }
}
 
/* Puts the auto-auth hook back into the hooks array */
function BringBackAA() {
        global $wgHooks;
#       global $wgAuth; //looks unuseful here, but it appeared in ShibAuthPlugin... let _real_ developpers decide ;)

        foreach ($wgHooks[GetSSLAuthHook()] as $key => $value) {
                if($value == 'BringBackAA')
                $wgHooks[GetSSLAuthHook()][$key] = 'SSLAuth'.GetSSLAuthHook();
        }
        return true;
}