DokuWiki

It's better when it's simple

User Tools

Site Tools


auth:pam

This is an old revision of the document!


PAM Authentication Backend

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 ;-)

Operation

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.

PHP PAM Module

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

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.

Install pam.class.php

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

Patch User Manager

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;
         }

Configure DokuWiki

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';

Applicable Version(s)?

I've attempted to duplicate this setup using DokuWiki versions 2008-05-05 and 2007-06-26b on a SAMP stack (Solaris, Apache, MySQL, & PHP provided by CoolStack). However, I'm unsuccessful. Here are the versions I'm using;

  • Solaris 10 6/06 (Update 2)
  • Apache 2.2.3
  • PHP 5.2.0 (cli) (built: Feb 16 2007 08:19:43)
  • MySQL 5.0.33-standard

I've added the account that Apache is using to the group that can access /etc/shadow and /etc/passwd, and I've also added the following to /etc/pam.conf

  php	auth	requisite	/usr/lib/security/pam_authtok_get.so.1
  php	auth	required	/usr/lib/security/pam_unix_auth.so.1
  php	account	required	/usr/lib/security/pam_unix_account.so.1

So far I've been able to break 'plain' authentication when attempting 'pam', but I've had no luck in getting it to work. Has anyone had any recent success with this PAM method?

Eric Xeleema 2008/07/08 04:20

auth/pam.1215483800.txt.gz · Last modified: 2011-05-24 16:25 (external edit)

Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Share Alike 4.0 International
CC Attribution-Share Alike 4.0 International Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki