Robin Bowes said the following on 29/12/2005 13:20:
> Hi,
> 
> I'd like to enable SMTP Auth against an existing htpasswd-generated file.
> 
> Passwords in the auth file are encrypted using MD5, e.g.:
> 
> htpasswd -c -m -b htpasswd user1 pass1
> htpasswd -m -b htpasswd user2 pass2
> 
> Resulting file:
> 
> user1:$apr1$I8RWV...$hMZbY.7S1n3ccgUKySa141
> user2:$apr1$7W/ed/..$rgXQa3tbPnPcVzcSKtOAC.
> 
> Will auth_flat_file support this? Or do I need to modify it to work with
> htpasswd-generated files?
> 
> Am I right in thinking that all I need to do is generate an MD5 hash of
> the supplied password and compare it to the encrypted passwd in the
> passwd file?

OK, I've written a plugin (attached) to authenticate against an apache
htpasswd file.

It requires Apache::Htpasswd and (if MD5 encryption is required)
perl-Crypt-PasswdMD5

Obviously, the htpasswd file has to be readable by the qpsmtpd process.

One issue I have is that it only uses auth-plain. I'd like to use
auth-cram-md5 if possible, but I'm not sure if that's possible without
knowing the plain text passwords (which I don't as they're encrypted
with MD5 in the htpasswd file).

I'd appreciate any comments.

R.
=head1 NAME

auth_htpasswd - auth plugin using apache htpasswd file

=head1 SYNOPSIS

in config/plugins:

  auth/auth_htpasswd auth_file=/path/to/htpasswd/file MD5=1

=head1 DESCRIPTION

This plugin authenticates against an existing apache htpasswd file.

MD5 encryption is optional.

Requires Apache::Htpasswd and (if MD5 encryption is required) 
perl-Crypt-PasswdMD5 

=cut

use Apache::Htpasswd;

sub register {
    my ( $self, $qp, %args ) = @_;

    if ( defined( $args{auth_file} ) ) {
        $self->{_auth_file} = $args{auth_file};
        $self->log( LOGINFO, "auth_file is $self->{_auth_file}" );
    }
    else {
        $self->log( LOGERROR, "auth_file not defined in config/plugins" );
        return ( DENY, "Auth configuration error" );
    }

    if ( !-e $self->{_auth_file} ) {
        $self->log( LOGERROR, "$self->{_auth_file} not found" );
        return ( DENY, "Auth configuration error" );
    }

    if ( !-r $self->{_auth_file} ) {
        $self->log( LOGERROR,
            "$self->{_auth_file} not readable by qpsmtpd process" );
        return ( DENY, "Auth configuration error" );
    }

    $self->{_MD5} = 0;
    if ( defined( $args{MD5} ) ) {
        if ( $args{MD5} ) {
            $self->{_MD5} = 1;
        }
    }

    $self->log( LOGINFO, "MD5 is $self->{_MD5}" );

    $self->register_hook( "auth-plain", "auth_htpasswd" );
}

sub auth_htpasswd {
    my ( $self, $transaction, $method, $user, $passClear, $passHash, $ticket )
        = @_;

    $self->log( LOGINFO, "Authenticating $user" );

    my $htpasswd = Apache::Htpasswd->new(
        {   passwdFile => $self->{_auth_file},
            ReadOnly   => 1,
            UseMD5     => $self->{_MD5},
        }
    );

    if ( $htpasswd->htCheckPassword( $user, $passClear ) ) {
        return ( OK, "Authenticated $user" );
    }
    else {
        return ( DENY, "Authentication failed for $user" );
    }
}

Reply via email to