I wanted to authenticate users without have a separate set of passwords. I found this authentication backend, but it doesn't work with the latest version of DokuWiki. I therefore set about writing my own authentication backend, which I will post here. I haven't tested it extensively, but it seems to work for me
The backend extends the auth_plain backend and overrides the checkPass() function to authenticate against PAM instead of the text file. The text file is still used to store users' names, email addresses and groups. Users must exist in both the text file (this can be done with the User Manager) and in PAM before they can login. A random password is stored in the text file, but this is simply ignored.
The backend requires the PHP PAM module to be installed. If your PHP configuration does not allow dynamic loading of modules (enable_dl = Off) then you need to load the extension by adding extension=pam.so to your php.ini. Make sure you follow the instructions when installing the PAM module – you must configure PAM with a php service.
Ubuntu has this module available in a package. To install it and setup PAM simply run the following commands:
sudo aptitude install php5-auth-pam sudo cp /usr/share/doc/php5-auth-pam/examples/php /etc/pam.d/php
Remember to restart your webserver.
Save the following file as inc/auth/pam.class.php.
<?php /** * PAM authentication backend * @author Michael Gorven <michael003+dokuwiki@gmail.com> * @license GPL2 http://www.gnu.org/licenses/gpl.html * @version 0.2 * @date March 2008 */ # This class requires the PHP PAM module # The Ubuntu package renames it to "pam_auth", so we check both if ( !extension_loaded('pam') && !extension_loaded('pam_auth') ) if ( !dl('pam.so') && !dl('pam_auth.so') ) msg( "PHP PAM module cannot be loaded", -1 ); define('DOKU_AUTH', dirname(__FILE__)); require_once(DOKU_AUTH.'/plain.class.php'); class auth_pam extends auth_plain { /** * Constructor * * Calls the auth_plain constructor which sets the backend's capabilities. * The change password capability is then removed since we can't change * passwords through PAM without knowing the current password. * */ function auth_pam() { // Call parent constructor if (method_exists($this, 'auth_plain')) parent::auth_plain(); // Remove change password capability $this->cando['modPass'] = false; } /** * Checks the provided username and password using PAM. * * @param string $user Username * @param string $pass Password * @return boolean True if authentication is successful */ function checkPass( $user, $pass ) { // Check that user exists if ( parent::getUserData($user) === false ) return false; // Check password else if( pam_auth( $user, $pass, &$error ) ) return true; // Authentication failed else return false; } /** * Creates a new user. * * Uses the createUser() method in auth_plain to actually add the user. * This only adds the user to the list of DokuWiki users -- they must * separately be added to PAM and assigned a password. * * @param string $user Username * @param string $pass Password (will be blank) * @param string $name Full name * @param string $mail Email address * @param string $grps List of groups * @return bool False if user already exists, null if error occurred, true if successful */ function createUser($user,$pwd,$name,$mail,$grps=null) { // createUser() returns the password if successful. We therefore need to // set it to something non-empty otherwise it gets treated as false return parent::createUser( $user, time(), $name, $mail, $grps ); } }
I'm encountering warnings in my Apache logs: “PHP Warning: Call-time pass-by-reference has been deprecated; If you would like to pass it by reference, modify the declaration of pam_auth(). If you would like to enable call-time pass-by-reference, you can set allow_call_time_pass_reference to true in your INI file.”
I simply removed the ”&” ampersand in front of the $error parameter in the pam_auth() function call. This seems to work…with no negative repercussions (true?). The warnings no longer appear (as expected with this change).
— poonh [at] mcmaster [dot] ca 2008-Apr-01 03:00 EDT
You then need to fix (what I think is) a bug in the User Manager. It won't create a user if no password is specified, but if the authentication backend cannot set passwords then the password box is disabled! The following patch makes the User Manager ignore empty passwords if the authentication backend can't change passwords. Save this in a file called admin.php.diff in your home directory, and then run patch -p1 < ~/admin.php.diff in lib/plugins/usermanager.
--- admin.php.orig 2008-03-13 14:48:57.000000000 +0200 +++ admin.php 2008-03-13 14:57:01.000000000 +0200 @@ -339,7 +339,8 @@ list($user,$pass,$name,$mail,$grps) = $this->_retrieveUser(); if (empty($user)) return false; - if (empty($pass) || empty($name) || empty($mail)){ + // PATCH: Don't fail on empty password if auth backend can't change passwords + if ( (empty($pass)&&$this->_auth->canDo('modPass')) || empty($name) || empty($mail)){ msg($this->lang['add_fail'], -1); return false; }
You then need to configure DokuWiki to use this authentication backend. Add the following line to local.php:
$conf['authtype'] = 'pam';
If you want to prevent users from registering themselves, add the following line as well:
$conf['disableactions'] = 'register';