DokuWiki

It's better when it's simple

User Tools

Site Tools


auth:phpbb3

This is an old revision of the document!


PHPBB3.0.x authentication

Save this file as inc/auth/phpbb3.class.php

<?php
 
/**
*
* A very simple authentication class against a phpBB3.0.x system.
* 
* Writing phpBB3.0.x integration is not actually as difficult as it seems
* you just lift a couple functions from the inc/functions.php file.
* Cut'n'paste them into your own class and there you are.
*
* The only "sudoku" part comes from the way phpBB3.0.x handles profiles.
* The name of the user is not found from the xxxx_users table but
* from the profile. The column where it lies in the profile (three tables) is
* language and installation dependend. So, when you look at
* the "other class" you should pay attention to the selects and
* tune them to match your phpBB3.0 installation.
*
* This is the file that should be put into dokuwiki's inc/auth-directory.
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author  Mauri Sahlberg
* @see	   http://www.iki.fi/mos
*
* The second php-file should be placed somewhere else and the next require
* should point to it.
*
* Thanks to Carsten Fuchs for exellent idea and an example. Your code
* was too complicated for me to understand and I decided to honor the
* good old tradition of open source development - never reuse when
* you can rewrite, which is plain stupid. But here were are. Enjoy.
*
* TODO: write some installation instructions! <an evil grin>
*/
require_once('replace this with your own savepath/phpbb3authClass.php');
 
class auth_phpbb3 extends auth_basic {
	var $theBackend;
 
	/**
	* The so called constructor
	*
	**/
	function auth_phpbb3() {
		$this->success = true;
		$this->theBackend = new phpbb3authClass();
//		echo "Constrictor boa!";
	}
	/**
	* Call the backend class to check the password
	* against phpbb3.
	*
	* @param $user string case sensitive username
	* @param $pass string plaintext password for the user
	* @return boolean true for match, false for everything else
	*/
	function checkPass($user, $pass) {
		$res=$this->theBackend->checkPassword($user, $pass);
		if($res===false) {
//			die("Kilroy! $user, $pass");
			return false;
		}	
		//print_r($res);
		//die("Gargamel: $user, $pass");	
		return $res;
	}
 
	/**
	* Call the backend class to fetch user details from
	* phpbb3.
	*
	* @param user string case sensitive username
	* @return array/boolean false for error conditions and an array for success
	* array['email'] string users email address
	* array['name'] string users full name
	* array['grps'] array of group names the user belongs to
	*/
	function getUserData($user) {
		return $this->theBackend->getUserData($user);
	}
}
?>

Save this file as phpbb3authClass.php to somewhere it can be required by the previous file. Fix the path in the first file. This file should be on a place where it can require your phpBB3.0.x configuration file (config.php at the root of your forum installation) and fix the require in this file.

<?php
 
class phpbb3authClass {
/**
 * Part of this code is shamelessly copied from phpbb3/include/functions.php
 * This is all that is needed to check hashes against a 3.0.x phpbb3.
 *
 * This cut'n'pasting was done by daFool/Mauri Sahlberg @ 2012. 
 * Read the the comment below to see what applies to the "lifted" code.
 * The other parts of the code are:
 * @author Mauri Sahlberg
 * @see http://www.iki.fi/mos
 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
 *
 * The lifted code begins with "Here be the dragons..." and ends with
 * "Back to the known waters of boring..."
 *
 * Have you hugged your inner child today? Coding is supposed to be fun and creative.
 **/
 
/**
*
* @version Version 0.1 / slightly modified for phpBB 3.0.x (using $H$ as hash type identifier)
*
* Portable PHP password hashing framework.
*
* Written by Solar Designer <solar at openwall.com> in 2004-2006 and placed in
* the public domain.
*
* There's absolutely no warranty.
*
* The homepage URL for this framework is:
*
*	http://www.openwall.com/phpass/
*
* Please be sure to update the Version line if you edit this file in any way.
* It is suggested that you leave the main version number intact, but indicate
* your project name (after the slash) and add your own revision information.
*
* Please do not change the "private" password hashing method implemented in
* here, thereby making your hashes incompatible.  However, if you must, please
* change the hash type identifier (the "$P$") to something different.
*
* Obviously, since this code is in the public domain, the above are not
* requirements (there can be none), but merely suggestions.
*
*
*/
    var $dbh;		// @var $dh, the database handle from dbo
    var $table_prefix;	// @var $table_prefix, table prefix from phpbb3 config
 
    /**
    * There is the new way, the old way and the highway. My way is to have an init
    * function the both php5 and php4 constructors are calling.
    *
    * You should tune the require to point to the location of your phpBB3-config file.
    * We are lifting part of the database connection parameters from there.
    *
    * Note that I'm lazy bastard, I assume that the database backend is mysql.
    * you should fix the dsn accordingly if you are using something else.
    *
    * Also if that something else doesn't support joins then you have a lot
    * of more work ahead and you should rewrite the queries down below on the
    * waters of boring.
    **/	
    function init() {
	require_once('replace this with path to phpBB3 forum installation/config.php');
        $this->table_prefix=$table_prefix;
 
        try {
            $dsn = "mysql:dbname=$dbname;host=$dbhost";
//	    echo $dsn;
            $this->dbh=new PDO($dsn, $dbuser, $dbpasswd);
        } catch (PDOException $e) {
//	    echo "No DB hose, you're hosed: $dsn, $dbuser, $dbpasswd";
            $this->dbh=null;
        }
    }
    /**
    * The old style phpBB3 constructor
    **/	
    function phpbb3authClass() {
	$this->init();
//	echo "Old reptilians can't be buggered at all.";
    }	
   /**
   * The new style phpBB3 constructor
   **/
   function __constructor() {
	$this->init();
//	echo "Oh baby, baby...";
   }
//
// Here be the Dragons and other sea monsters 
//
    /**
    * Check for correct password
    *
    * @param string $password The password in plain text
    * @param string $hash The stored password hash
    *
    * @return bool Returns true if the password is correct, false if not.
    */
    function phpbb_check_hash($password, $hash)
    {
            $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
            if (strlen($hash) == 34)
            {
                    return ($this->_hash_crypt_private($password, $hash, $itoa64) === $hash) ? true : false;
            }
 
            return (md5($password) === $hash) ? true : false;
    }
 
    /**
    * Encode hash
    */
    function _hash_encode64($input, $count, &$itoa64)
    {
            $output = '';
            $i = 0;
 
            do
            {
                    $value = ord($input[$i++]);
                    $output .= $itoa64[$value & 0x3f];
 
                    if ($i < $count)
                    {
                            $value |= ord($input[$i]) << 8;
                    }
 
                    $output .= $itoa64[($value >> 6) & 0x3f];
 
                    if ($i++ >= $count)
                    {
                            break;
                    }
 
                    if ($i < $count)
                    {
                            $value |= ord($input[$i]) << 16;
                    }
 
                    $output .= $itoa64[($value >> 12) & 0x3f];
 
                    if ($i++ >= $count)
                    {
                            break;
                    }
 
                    $output .= $itoa64[($value >> 18) & 0x3f];
            }
            while ($i < $count);
 
            return $output;
    }
 
 
    /**
    * The crypt function/replacement
    */
    function _hash_crypt_private($password, $setting, &$itoa64)
    {
            $output = '*';
 
            // Check for correct hash
            if (substr($setting, 0, 3) != '$H$' && substr($setting, 0, 3) != '$P$')
            {
                    return $output;
            }
 
            $count_log2 = strpos($itoa64, $setting[3]);
 
            if ($count_log2 < 7 || $count_log2 > 30)
            {
                    return $output;
            }
 
            $count = 1 << $count_log2;
            $salt = substr($setting, 4, 8);
 
            if (strlen($salt) != 8)
            {
                    return $output;
            }
 
            /**
            * We're kind of forced to use MD5 here since it's the only
            * cryptographic primitive available in all versions of PHP
            * currently in use.  To implement our own low-level crypto
            * in PHP would result in much worse performance and
            * consequently in lower iteration counts and hashes that are
            * quicker to crack (by non-PHP code).
            */
            if (PHP_VERSION >= 5)
            {
                    $hash = md5($salt . $password, true);
                    do
                    {
                            $hash = md5($hash . $password, true);
                    }
                    while (--$count);
            }
            else
            {
                    $hash = pack('H*', md5($salt . $password));
                    do
                    {
                            $hash = pack('H*', md5($hash . $password));
                    }
                    while (--$count);
            }
 
            $output = substr($setting, 0, 12);
            $output .= $this->_hash_encode64($hash, 16, $itoa64);
 
            return $output;
    }
//
// Back to the known waters of boring.
//
    /**
    * Did we screw up the database connection on the very beginning of
    * the time? If we did, no point of trying anything complicated.
    *
    * @return boolean true if we have a connection, false otherwise
    **/	
    function checkHandle() {
        return $this->dbh!=null ? true : false;
    }
 
    /**
    * Fetches the password hash from database
    * 	
    * @param $user string case sensitive username to find
    * @param $password string plaintext password
    * @return boolean true for matches, false for everything else.
    **/
    function checkPassword($user, $password) {
        $table_prefix=$this->table_prefix;
        if ($this->checkHandle()) {
            $s = "select * from ${table_prefix}users where username=:user;";
            $sth = $this->dbh->prepare($s);
            $sth->execute(array(":user"=>$user));
            $user=$sth->fetchAll();
	    if($user!==false) {
		$pw=$user[0]['user_password'];
		if($this->phpbb_check_hash($password,$pw))
			return true;		
	    }
	    return false;	
        }
	// echo "Too hot to handle?";
	return false;
    }
 
   /**
   * Fetches the user data from tables: users, groups and profile_fields_data. Uses user_group to find groups the user belongs to.
   *
   * @param $user string case sensitive username
   * @return boolean/array false if nothing was found, an array if something was found.
   * array['email'] string user's email
   * array['name'] string user''s full name
   * array['grps'] array, strings of groupnames the users has.
   **/
   function getUserData($user) {
 
	// nimi => 5
	$table_prefix=$this->table_prefix;
	if($this->checkHandle()) {
// select username_clean, user_email, group_name from phpbb3_users as u join phpbb3_user_group as ug on (u.username='daFool' and ug.user_id=u.user_id)join phpbb3_groups as g on (g.group_id=ug.group_id);
 
		$s = "select username_clean, user_email, group_name, pf_nimi from ${table_prefix}users as u join ${table_prefix}user_group as ug ";
		$s .= "on (u.username=:user and ug.user_id=u.user_id)join ${table_prefix}groups as g";
		$s .= " on (g.group_id=ug.group_id) join";
		$s .= " ${table_prefix}profile_fields_data as pf on (u.user_id=pf.user_id);";
//		echo "$s\n";
		$sth = $this->dbh->prepare($s);
		$sth->execute(array(":user"=>$user));
		$groups=$sth->fetchAll();
		$mygrps=array();
		$i=0;
		foreach($groups as $group) {
			$email=$group['user_email'];
			$name=$group['pf_nimi'];
			$mygrps[$i++]=$group['group_name'];
		}
		if ($i==0)
			return false;
		$result = array(
			"name"=>$name,
			"email"=>$email,
			"grps"=>$mygrps
		);
//		print_r($result);
//		die("WTF?");
		return $result;
	}
	return false;
  }
}
//
// Yes, this is a real username and a real password! I have no clue on which system this password 
// matches this username. Feel free to email me if you find one.
//
 
/* $koe=new phpbb3authClass();
$res=$koe->checkPassword('daFool','foobar');
 
echo $res ? "True<br>>" : "False<br>"; 
print_r($koe->getUserData('daFool')); */
?>

Edit the local.php file in dokuwiki/config to have lines like this:

$conf['superuser'] = '@admin,@Hallitus';
$conf['authtype'] = "phpbb3";

Where the @Hallitus should be case sensitive name of the phpBB3-group who should have admin access to your wiki. If anything fails you could uncomment parts of the code to see where it fails. You should also take a peek on your forums table: profile_fields_data and find out which field contains the name of the user. Replace the pf_nimi with this field on getUserdata.

auth/phpbb3.1329046420.txt.gz · Last modified: 2012-02-12 12:33 by 80.223.223.99

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