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.