Kayako logo
Modifications & Addon Releases Modification guides and addons are posted here to share with the community. Do not post requests in here!

Notices

Reply
 
LinkBack Thread Tools Search this Thread Rate Thread Display Modes
  (#1) Old
welch Offline
New Member
 
Posts: 29
Join Date: Oct 2007
Location: Lawrence
phpBB3 LoginShare - 27-12-2007, 04:17 PM

This may have already been done, but did not have very much success in finding it, so my small version of the phpbb.login.php for phpBB3

PHP Code:
<?php
//=======================================
//###################################
// Created by Andrew "Lord d'Eath" Gillard - http://www.lorddeath.net/
//
// Created for Craig Brass - http://www.subsonicsolutions.com/
// Updated by Matt Welch - http://tootight.net/
//###################################
//=======================================


if (!defined("INSWIFT")) {
    
trigger_error("Unable to process $PHP_SELF"E_USER_ERROR);
}

/**
* Initialization function. You can connect to your database etc over here.
*/
function loginShareInit()
{
    global 
$loginshare;

    
$loginshare->moduleloaded true;
}

/**
* Authorize a user based on email and password
*/
function loginShareAuthorize($username$password)
{
    global 
$dbCore$_SWIFT$loginshare$settings;

    
$_loginshare $settings->getSection("loginshare");
    
$dbLoginShare = new dbCore($_loginshare["phpbbhostname"], $_loginshare["phpbbdbuser"], $_loginshare["phpbbdbpass"], $_loginshare["phpbbdbname"], "mysql"false);

    
$_user $dbLoginShare->queryFetch("SELECT * FROM `"$_loginshare["phpbbdbprefix"] ."users` WHERE `username` = '"$dbCore->escape($username) ."';");
    if (empty(
$_user["user_id"]))
    {
        return 
false;
    }

    class 
PasswordHash {
       var 
$itoa64;
       var 
$iteration_count_log2;
       var 
$portable_hashes;
       var 
$random_state;

       function 
PasswordHash($iteration_count_log2$portable_hashes)
       {
          
$this->itoa64 './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';

          if (
$iteration_count_log2 || $iteration_count_log2 31)
             
$iteration_count_log2 8;
          
$this->iteration_count_log2 $iteration_count_log2;

          
$this->portable_hashes $portable_hashes;

          
$this->random_state microtime() . getmypid();
       }

       function 
get_random_bytes($count)
       {
          
$output '';
          if ((
$fh = @fopen('/dev/urandom''rb'))) {
             
$output fread($fh$count);
             
fclose($fh);
          }

          if (
strlen($output) < $count) {
             
$output '';
             for (
$i 0$i $count$i += 16) {
                
$this->random_state =
                    
md5(microtime() . $this->random_state);
                
$output .=
                    
pack('H*'md5($this->random_state));
             }
             
$output substr($output0$count);
          }

          return 
$output;
       }

       function 
encode64($input$count)
       {
          
$output '';
          
$i 0;
          do {
             
$value ord($input[$i++]);
             
$output .= $this->itoa64[$value 0x3f];
             if (
$i $count)
                
$value |= ord($input[$i]) << 8;
             
$output .= $this->itoa64[($value >> 6) & 0x3f];
             if (
$i++ >= $count)
                break;
             if (
$i $count)
                
$value |= ord($input[$i]) << 16;
             
$output .= $this->itoa64[($value >> 12) & 0x3f];
             if (
$i++ >= $count)
                break;
             
$output .= $this->itoa64[($value >> 18) & 0x3f];
          } while (
$i $count);

          return 
$output;
       }

       function 
gensalt_private($input)
       {
          
$output '$H$';
          
$output .= $this->itoa64[min($this->iteration_count_log2 +
             ((
PHP_VERSION >= '5') ? 3), 30)];
          
$output .= $this->encode64($input6);

          return 
$output;
       }

       function 
crypt_private($password$setting)
       {
          
$output '*0';
          if (
substr($setting02) == $output)
             
$output '*1';

          if (
substr($setting03) != '$H$')
             return 
$output;

          
$count_log2 strpos($this->itoa64$setting[3]);
          if (
$count_log2 || $count_log2 30)
             return 
$output;

          
$count << $count_log2;

          
$salt substr($setting48);
          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 $passwordTRUE);
             do {
                
$hash md5($hash $passwordTRUE);
             } while (--
$count);
          } else {
             
$hash pack('H*'md5($salt $password));
             do {
                
$hash pack('H*'md5($hash $password));
             } while (--
$count);
          }

          
$output substr($setting012);
          
$output .= $this->encode64($hash16);

          return 
$output;
       }

       function 
gensalt_extended($input)
       {
          
$count_log2 min($this->iteration_count_log2 824);
          
# This should be odd to not reveal weak DES keys, and the
          # maximum valid value is (2**24 - 1) which is odd anyway.
          
$count = (<< $count_log2) - 1;

          
$output '_';
          
$output .= $this->itoa64[$count 0x3f];
          
$output .= $this->itoa64[($count >> 6) & 0x3f];
          
$output .= $this->itoa64[($count >> 12) & 0x3f];
          
$output .= $this->itoa64[($count >> 18) & 0x3f];

          
$output .= $this->encode64($input3);

          return 
$output;
       }

       function 
gensalt_blowfish($input)
       {
          
# This one needs to use a different order of characters and a
          # different encoding scheme from the one in encode64() above.
          # We care because the last character in our encoded string will
          # only represent 2 bits.  While two known implementations of
          # bcrypt will happily accept and correct a salt string which
          # has the 4 unused bits set to non-zero, we do not want to take
          # chances and we also do not want to waste an additional byte
          # of entropy.
          
$itoa64 './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';

          
$output '$2a$';
          
$output .= chr(ord('0') + $this->iteration_count_log2 10);
          
$output .= chr(ord('0') + $this->iteration_count_log2 10);
          
$output .= '$';

          
$i 0;
          do {
             
$c1 ord($input[$i++]);
             
$output .= $itoa64[$c1 >> 2];
             
$c1 = ($c1 0x03) << 4;
             if (
$i >= 16) {
                
$output .= $itoa64[$c1];
                break;
             }

             
$c2 ord($input[$i++]);
             
$c1 |= $c2 >> 4;
             
$output .= $itoa64[$c1];
             
$c1 = ($c2 0x0f) << 2;

             
$c2 ord($input[$i++]);
             
$c1 |= $c2 >> 6;
             
$output .= $itoa64[$c1];
             
$output .= $itoa64[$c2 0x3f];
          } while (
1);

          return 
$output;
       }

       function 
HashPassword($password)
       {
          
$random '';

          if (
CRYPT_BLOWFISH == && !$this->portable_hashes) {
             
$random $this->get_random_bytes(16);
             
$hash =
                 
crypt($password$this->gensalt_blowfish($random));
             if (
strlen($hash) == 60)
                return 
$hash;
          }

          if (
CRYPT_EXT_DES == && !$this->portable_hashes) {
             if (
strlen($random) < 3)
                
$random $this->get_random_bytes(3);
             
$hash =
                 
crypt($password$this->gensalt_extended($random));
             if (
strlen($hash) == 20)
                return 
$hash;
          }

          if (
strlen($random) < 6)
             
$random $this->get_random_bytes(6);
          
$hash =
              
$this->crypt_private($password,
              
$this->gensalt_private($random));
          if (
strlen($hash) == 34)
             return 
$hash;

          
# Returning '*' on error is safe here, but would _not_ be safe
          # in a crypt(3)-like function used _both_ for generating new
          # hashes and for validating passwords against existing hashes.
          
return '*';
       }

       function 
CheckPassword($password$stored_hash)
       {
          
$hash $this->crypt_private($password$stored_hash);
          if (
$hash[0] == '*')
             
$hash crypt($password$stored_hash);

          return 
$hash == $stored_hash;
       }
    }

    
$t_hasher = new PasswordHash(8TRUE);
    
$hash $_user["user_password"]; //from database
    
$check $t_hasher->CheckPassword($password$hash);
    
//$check will be true or false if the passwords match
    
unset($t_hasher); //cleanup


    
$userpassword md5($password);
    
    
$regpassword substr(buildHash(),0,8);

    if (
$check == true && !empty($_user["user_password"]))
    {        
        
// We have a match, Seems like a valid user.. now see if he is registered..
        
$userid getLoginShareUser(LOGINAPI_PHPBB$_user["user_id"]);
        if (!
$userid)
        {
            
// Not registered, Register him
            
$userid insertUser(true$_user["user_email"], $regpassword$_SWIFT["tgroup"]["regusergroupid"], LOGINAPI_PHPBB$_user["user_id"], $username$_SWIFT["tgroup"]["languageid"], 0false1true);
        }

        if (!
$userid)
        {
            return 
false;
        }

        
$_swiftuser $loginshare->loadSWIFTUser($userid);
        if (!
$_swiftuser)
        {
            return 
false;
        }

        
$_SWIFT["user"] = $_swiftuser;

        return 
$_swiftuser["userid"];
    }

    return 
false;
}

/**
* Return the Unique User ID of the current user
*/
function loginShareUserID()
{
    global 
$_SWIFT;

    if (empty(
$_SWIFT["user"]["userid"]))
    {
        return 
false;
    } else {
        return 
$_SWIFT["user"]["userid"];
    }
}

/**
* Logout the current user
*/
function loginShareLogout()
{
    global 
$session$_SWIFT;

    
$session->updateSession($_SWIFT["session"]["sessionid"], 0);

    return 
true;
}

/**
* Load the user credentials into current workspace. The following variables should be declared for proper working:
* userid - User id that is set in the "users" table
* fullname
* email - Array
* password (MD5 Hashed)
* usergroupid - If this is not set, then it will use the default registered user group for this template group
*/
function loginShareLoadUser()
{
    global 
$dbCore$_SWIFT$loginshare;

    if (empty(
$_SWIFT["session"]["typeid"]))
    {
        
$_SWIFT["user"]["loggedin"] = false;
        return 
false;
    }

    
$_user $loginshare->loadSWIFTUser($_SWIFT["session"]["typeid"]);
    if (!
$_user)
    {
        
$_SWIFT["user"]["loggedin"] = false;

        return 
false;
    }

    
$_SWIFT["user"] = $_user;

    return 
true;
}

/**
* Renders the Login Share Form
*/
function renderLoginShareForm()
{
    global 
$_SWIFT;

    
$forms = array();

    
$forms[0]["title"] = $_SWIFT["language"]["hostname"];
    
$forms[0]["name"] = "phpbbhostname";
    
$forms[1]["title"] = $_SWIFT["language"]["dbname"];
    
$forms[1]["name"] = "phpbbdbname";
    
$forms[2]["title"] = $_SWIFT["language"]["dbuser"];
    
$forms[2]["name"] = "phpbbdbuser";
    
$forms[3]["title"] = $_SWIFT["language"]["dbpass"];
    
$forms[3]["name"] = "phpbbdbpass";
    
$forms[4]["title"] = "Table Prefix";
    
$forms[4]["name"] = "phpbbdbprefix";

    return 
$forms;

}
?>
   
Reply With Quote
  (#2) Old
Jamie Edwards Offline
Operations Manager
 
Jamie Edwards's Avatar
 
Posts: 5,033
Join Date: Jan 2006
Location: United Kingdom
27-12-2007, 04:22 PM

Thank you for sharing, welch Would you have any problems if I passed this to our developers for review and inclusion in SupportSuite?


Jamie Edwards (jamie.edwards ]at[ kayako.com)
----------------------------------------------------------------
---
  • New to the forum? New user's guide here.
  • Submit bug reports here.
  • Submit support tickets via the members area.
  • Submit sales queries either via live chat or via e-mail.
  • There is no official ETA on Version 4.
   
Reply With Quote
  (#3) Old
welch Offline
New Member
 
Posts: 29
Join Date: Oct 2007
Location: Lawrence
27-12-2007, 05:25 PM

Nope, not at all. I know the new phpBB has a new hashing method, so its got the class included in one file instead of having two. Maybe they can find a good way to clean it up
   
Reply With Quote
  (#4) Old
craigbrass Offline
Senior Member
 
Posts: 5,326
Join Date: Jun 2005
Location: Cumbria, UK
27-12-2007, 05:26 PM

Yup, this needs including with SupportSuite as phpbb3.login.php.


Craig Brass - Kayako Forum Squatter (Note: I am NOT a staff member)

Icon Headquarters - Its Elixir - Web2Messenger
   
Reply With Quote
  (#5) Old
Jamie Edwards Offline
Operations Manager
 
Jamie Edwards's Avatar
 
Posts: 5,033
Join Date: Jan 2006
Location: United Kingdom
27-12-2007, 05:37 PM

Quote:
Originally Posted by welch
Nope, not at all. I know the new phpBB has a new hashing method, so its got the class included in one file instead of having two. Maybe they can find a good way to clean it up
It would probably be best to include the PHP file rather than copy/paste it in - our developers will take a look. Thanks again

Quote:
Originally Posted by craigbrass View Post
Yup, this needs including with SupportSuite as phpbb3.login.php.
Of course, that is why I asked permission from the author to include it..


Jamie Edwards (jamie.edwards ]at[ kayako.com)
----------------------------------------------------------------
---
  • New to the forum? New user's guide here.
  • Submit bug reports here.
  • Submit support tickets via the members area.
  • Submit sales queries either via live chat or via e-mail.
  • There is no official ETA on Version 4.

Last edited by Jamie Edwards; 27-12-2007 at 05:47 PM.
   
Reply With Quote
  (#6) Old
craigbrass Offline
Senior Member
 
Posts: 5,326
Join Date: Jun 2005
Location: Cumbria, UK
27-12-2007, 06:54 PM

I disagree. It would be best to copy / paste it in as this would mean the two programs could be on separate servers with no access to each other.

Reason I said phpbb3.login.php was because it shouldn't be replaced as this would break it for phpBB 2 users.


Craig Brass - Kayako Forum Squatter (Note: I am NOT a staff member)

Icon Headquarters - Its Elixir - Web2Messenger
   
Reply With Quote
  (#7) Old
Jamie Edwards Offline
Operations Manager
 
Jamie Edwards's Avatar
 
Posts: 5,033
Join Date: Jan 2006
Location: United Kingdom
27-12-2007, 07:11 PM

Quote:
I disagree. It would be best to copy / paste it in as this would mean the two programs could be on separate servers with no access to each other.
This is bad integration practice - it would create problems should phpBB3 update this class in some way or changed their routines. If they are on separate servers, at worse the user should have to drop-in the required file into the LoginShare folder.


Jamie Edwards (jamie.edwards ]at[ kayako.com)
----------------------------------------------------------------
---
  • New to the forum? New user's guide here.
  • Submit bug reports here.
  • Submit support tickets via the members area.
  • Submit sales queries either via live chat or via e-mail.
  • There is no official ETA on Version 4.
   
Reply With Quote
  (#8) Old
welch Offline
New Member
 
Posts: 29
Join Date: Oct 2007
Location: Lawrence
Include - 28-12-2007, 09:38 AM

Quote:
Originally Posted by Jamie Edwards View Post
Quote:
I disagree. It would be best to copy / paste it in as this would mean the two programs could be on separate servers with no access to each other.
This is bad integration practice - it would create problems should phpBB3 update this class in some way or changed their routines. If they are on separate servers, at worse the user should have to drop-in the required file into the LoginShare folder.
I would much rather include the class instead of having it all in one file, like he said, its bad technique. However, not know how kayako prefers to handle these situations, I put it in one file to make it easier. On my instance I include a functions file, more work when up dating but if they come out with a new way to changing hash methods, i can update one file that will update the other one. If I don't include, one would have to update the phpbb3 in an editor instead of just upload.
   
Reply With Quote
  (#9) Old
craigbrass Offline
Senior Member
 
Posts: 5,326
Join Date: Jun 2005
Location: Cumbria, UK
28-12-2007, 09:52 AM

All the other LoginShares have been MD5 / Plain Text so this has never needed to be done. I am sure the developers will make a decision when they see it tho.


Craig Brass - Kayako Forum Squatter (Note: I am NOT a staff member)

Icon Headquarters - Its Elixir - Web2Messenger
   
Reply With Quote
  (#10) Old
welch Offline
New Member
 
Posts: 29
Join Date: Oct 2007
Location: Lawrence
Fyi - 31-12-2007, 02:45 AM

I thought I should also say that for now and application deployment, this is just a replacement for the phpbb.login.php file. Do not expect to make a file phpbb3.login.php and have it just work need to add some more information to make that happen.
   
Reply With Quote
  (#11) Old
Jamie Edwards Offline
Operations Manager