[rt-users] RT::Authen::ExternalAuth with PHPass (phpbb3);

Ruslan Zakirov ruz at bestpractical.com
Wed Nov 16 10:04:29 EST 2011


Hello,

I didn't read full thread, but long time ago I talked with zordrak
about how password checking is wrong and not flexible. The current set
of options is not suitable for many cases. I've cooked a patch [1].
The following config with patched extension can check any format
supported by Authen::Passphrase framework:

...
p_check => sub {
    my ($hash, $pass) = @_;
    use Authen::Passphrase;
    return Authen::Passphrase->from_crypt($hash || '*')->match($pass);
},
...

Above covers HASH schemes described in [2]. If stored hash doesn't
have $schema$ prefix then code needs a little bit of change.

However, I didn't test the patch.

[1] https://github.com/bestpractical/rt-authen-externalauth/commit/22ba2bfa8d59a00354712e63daaa5d622e39cf4d
[2] http://search.cpan.org/~zefram/Authen-Passphrase-0.007/lib/Authen/Passphrase.pm#CONSTRUCTORS

On Wed, Nov 16, 2011 at 4:27 PM, Adrian Stel <adisan82 at gmail.com> wrote:
> Hi,
>
>
> I get some info from PHPass but I don't know how use it ;/ any
> sugestion from your site ?
>
>
>>'p_enc_pkg'                 =>  'Authen::Passphrase::PHPass',
>>'p_enc_sub'                 =>  'cost',
>
> The comment above, the example below, and a bit of googling all show that
> p_enc_pkg and p_enc_sub are together meant to name a hash function.
> Your password string will be passed through the function, and the
> resulting hash value is then managed by RT.  The clearest example:
>
>>#'p_enc_pkg'                 =>  'Crypt::MySQL',
>>#'p_enc_sub'                 =>  'password41',
>
> Crypt::MySQL::password41() is a function to which you pass a password
> string and it returns a hash.  For example, password41("hunter2") returns
> "*58815970BE77B3720276F63DB198B1FA42E5CC02".
>
> Authen::Passphrase::PHPass::cost is not a hashing function.  It's
> not meant to be called as a standalone function at all.  It's the
> implementation of the ->cost method on the Authen::Passphrase::PHPass
> class, and so expects to be passed an A:P:PHPass object, not a string.
> A:P:PHPass doesn't actually expose the hash function on its own, so you
> can't use it this way.
>
> In fact, the PHPass hash algorithm *can't* be properly used by RT,
> because it takes a salt input, and apparently RT can't perform salting.
> (There's a p_salt parameter, which appears to be a *fixed* salt, defeating
> the purpose.)
>
> You could write a wrapper function around A:P:PHPass that creates a
> recogniser for a supplied password and then just extracts the hash.
> The wrapper would have to fix the cost parameter and the salt.  It looks
> like this:
>
>       use Authen::Passphrase::PHPass ();
>       sub phpass_10_aaaaaaaa($) {
>               return Authen::Passphrase::PHPass->new(
>                       cost=>10,
>                       passphrase=>$_[0],
>                       salt=>"aaaaaaaa",
>               )->hash_base64;
>       }
>
> phpass_10_aaaaaaaa("hunter2") returns "LvYU3dRamxKB1.lRa4ow1/".  *This*
> is a hash function and could be used by RT via p_enc_pkg and p_enc_sub.
>
> It's a bit of an abstraction inversion to use A:P:PHPass just for
> its hash function.  If A:P:PHPass were wrapping some other module
> that just provides the hash then I'd point you at the other module.
> Most A:P modules do this, such as A:P:MySQL323 wrapping Crypt::MySQL.
> But A:P:PHPass implements the hash itself.  Also, if there were a module
> exposing the PHPass algorithm on its own, you'd still have to write a
> wrapper, because of the cost parameter that RT has no idea how to handle.
>
>
>
> 2011/11/16 Adrian Stel <adisan82 at gmail.com>:
>> Hi,
>>
>>
>> DBI.pm
>>  this is the place with p_enc_sub:
>>
>>
>> sub GetAuth {
>>
>>    my ($service, $username, $password) = @_;
>>
>>    my $config = $RT::ExternalSettings->{$service};
>>    $RT::Logger->debug( "Trying external auth service:",$service);
>>
>>    my $db_table        = $config->{'table'};
>>    my $db_u_field      = $config->{'u_field'};
>>    my $db_p_field          = $config->{'p_field'};
>>    my $db_p_enc_pkg    = $config->{'p_enc_pkg'};
>>    my $db_p_enc_sub    = $config->{'p_enc_sub'};
>>    my $db_p_salt       = $config->{'p_salt'};
>>
>>
>>
>> Place where the password is submitted to that method as a string parameter.
>>
>> In my opinion could be here:
>>
>>  # Get the user's password from the database query result
>>    my $pass_from_db = $results_hashref->{$username}->{$db_p_field};
>>
>>    # This is the encryption package & subroutine passed in by the config file
>>    $RT::Logger->debug( "Encryption Package:",
>>                        $db_p_enc_pkg);
>>    $RT::Logger->debug( "Encryption Subroutine:",
>>                        $db_p_enc_sub);
>>
>>    # Use config info to auto-load the perl package needed for
>> password encryption
>>    # I know it uses a string eval - but I don't think there's a
>> better way to do this
>>    # Jump to next external authentication service on failure
>>    eval "require $db_p_enc_pkg" or
>>        $RT::Logger->error("AUTH FAILED, Couldn't Load Password
>> Encryption Package. Error: $@") && return 0;
>>
>>    my $encrypt = $db_p_enc_pkg->can($db_p_enc_sub);
>>    if (defined($encrypt)) {
>>        # If the package given can perform the subroutine given, then
>> use it to compare the
>>        # password given with the password pulled from the database.
>>        # Jump to the next external authentication service if they don't match
>>        if(defined($db_p_salt)) {
>>            $RT::Logger->debug("Using salt:",$db_p_salt);
>>            if(${encrypt}->($password,$db_p_salt) ne $pass_from_db){
>>                $RT::Logger->info(  $service,
>>                                    "AUTH FAILED",
>>                                    $username,
>>                                    "Password Incorrect");
>>                return 0;
>>            }
>>        } else {
>>            if(${encrypt}->($password) ne $pass_from_db){
>>                $RT::Logger->info(  $service,
>>                                    "AUTH FAILED",
>>                                    $username,
>>                                    "Password Incorrect");
>>                return 0;
>>            }
>>        }
>>    } else {
>>        # If the encryption package can't perform the request subroutine,
>>        # dump an error and jump to the next external authentication service.
>>        $RT::Logger->error($service,
>>                            "AUTH FAILED",
>>                            "The encryption package you gave me (",
>>                            $db_p_enc_pkg,
>>                            ") does not support the encryption method
>> you specified (",
>>                            $db_p_enc_sub,
>>                            ")");
>>    return 0;
>>    }
>>
>>
>> But i'm not shure where exactly. And how I can convert string to hash.
>>
>> I'm not familiar with perl ;/
>>
>>
>>
>> Best
>> Adrian
>>
>> 2011/11/15 Zordrak <zordrak at tpa.me.uk>:
>>> Adrian Stel wrote:
>>>> Hi,
>>>>
>>>>
>>>> Can't use string ("user password") as a HASH ref while "strict refs"
>>>> in use at /usr/local/share/perl/5.10.1/Authen/Passphrase/PHPass.pm
>>>> line 278.
>>>>
>>>> Problem is with type of user password.
>>>>
>>>> Still need to know where I should search.
>>>
>>> Search for the text "p_enc_sub". There's only one place it should be
>>> defined and it will be very close to where the password is submitted to
>>> that method as a string parameter.
>>> --
>>> Zordrak
>>> zordrak at tpa.me.uk
>>>
>>>
>>
>>
>>
>> --
>> Pozdrawiam
>> Adrian Stelmaszyk
>>
>
>
>
> --
> Pozdrawiam
> Adrian Stelmaszyk
> --------
> RT Training Sessions (http://bestpractical.com/services/training.html)
> *  Barcelona, Spain  November 28 & 29, 2011
>



-- 
Best regards, Ruslan.



More information about the rt-users mailing list