Apache-DBI

 view release on metacpan or  search on metacpan

lib/Apache/AuthDBI.pm  view on Meta::CPAN

    else {
        # password not cached or changed
        debug (2, "$prefix passwd not found in cache");

        # connect to database, use all data_sources until the connect succeeds
        for (my $j = 0; $j <= $#data_sources; $j++) {
            last if (
                     $dbh = DBI->connect(
                                         $data_sources[$j],
                                         $usernames[$j],
                                         $passwords[$j]
                                        )
                    );
        }
        unless ($dbh) {
            $r->log_reason(
                           "$prefix db connect error with data_source " .
                           ">$Attr->{data_source}<: $DBI::errstr",
                           $r->uri
                          );
            return MP2 ? Apache2::Const::SERVER_ERROR() :
                Apache::Constants::SERVER_ERROR();
        }

        # generate statement
        my $user_sent_quoted = $dbh->quote($user_sent);
        my $select    = "SELECT $Attr->{pwd_field}";
        my $from      = "FROM $Attr->{pwd_table}";
        my $where     = ($Attr->{uidcasesensitive} eq "off") ?
            "WHERE lower($Attr->{uid_field}) =" :
                "WHERE $Attr->{uid_field} =";
        my $compare   = ($Attr->{placeholder} eq "on")  ?
            "?" : "$user_sent_quoted";
        my $statement = "$select $from $where $compare";
        $statement   .= " AND $Attr->{pwd_whereclause}"
            if $Attr->{pwd_whereclause};

        debug(2, "$prefix statement: $statement");

        # prepare statement
        my $sth;
        unless ($sth = $dbh->prepare($statement)) {
            $r->log_reason("$prefix can not prepare statement: $DBI::errstr", $r->uri);
            $dbh->disconnect;
            return MP2 ? Apache2::Const::SERVER_ERROR() :
                Apache::Constants::SERVER_ERROR();
        }

        # execute statement
        my $rv;
        unless ($rv = ($Attr->{placeholder} eq "on") ?
                $sth->execute($user_sent) : $sth->execute) {
            $r->log_reason("$prefix can not execute statement: $DBI::errstr", $r->uri);
            $dbh->disconnect;
            return MP2 ? Apache2::Const::SERVER_ERROR() :
                Apache::Constants::SERVER_ERROR();
        }

        my $password;
        $sth->execute();
        $sth->bind_columns(\$password);
        my $cnt = 0;
        while ($sth->fetch()) {
            $password =~ s/ +$// if $password;
            $passwd .= "$password$;";
            $cnt++;
        }

        chop $passwd if $passwd;
        # so we can distinguish later on between no password and empty password
        undef $passwd if 0 == $cnt;

        if ($sth->err) {
            $dbh->disconnect;
            return MP2 ? Apache2::Const::SERVER_ERROR() :
                Apache::Constants::SERVER_ERROR();
        }
        $sth->finish;

        # re-use dbh for logging option below
        $dbh->disconnect unless $Attr->{log_field} && $Attr->{log_string};
    }

    $r->subprocess_env(REMOTE_PASSWORDS => $passwd);
    debug(2, "$prefix passwd = >$passwd<");

    # check if password is needed
    unless ($passwd) { # not found in database
        # if authoritative insist that user is in database
        if ($Attr->{authoritative} eq 'on') {
            $r->log_reason("$prefix password for user $user_sent not found", $r->uri);
            $r->note_basic_auth_failure;
            return MP2 ? Apache2::Const::AUTH_REQUIRED() :
                Apache::Constants::AUTH_REQUIRED();
        }
        else {
            # else pass control to the next authentication module
            return MP2 ? Apache2::Const::DECLINED() :
                Apache::Constants::DECLINED();
        }
    }

    # allow any password if nopasswd = on and the retrieved password is empty
    if ($Attr->{nopasswd} eq 'on' && !$passwd) {
        return MP2 ? Apache2::Const::OK() : Apache::Constants::OK();
    }

    # if nopasswd is off, reject user
    unless ($passwd_sent && $passwd) {
        $r->log_reason("$prefix user $user_sent: empty password(s) rejected", $r->uri);
        $r->note_basic_auth_failure;
        return MP2 ? Apache2::Const::AUTH_REQUIRED() :
            Apache::Constants::AUTH_REQUIRED();
    }

    # compare passwords
    my $found = 0;
    foreach my $password (split /$;/, $passwd) {
        # compare all the passwords using as many encryption methods
        # in fallback as needed
        my @passwds_to_check =



( run in 0.686 second using v1.01-cache-2.11-cpan-2398b32b56e )