- # Now look up the user's HA1 from the database, and calculate HA2.
- my ($user, $takenby) = extract_takenby($auth{'username'});
- my $ref = $dbh->selectrow_hashref('SELECT digest_ha1_hex FROM users WHERE username=? AND vhost=?',
- undef, $user, $r->get_server_name);
- if (!defined($ref)) {
- output_401($r);
- return undef;
- }
- if (!defined($ref->{'digest_ha1_hex'}) || $ref->{'digest_ha1_hex'} !~ /^[0-9a-f]{32}$/) {
- # A user that exists but has empty HA1 is a user that's not
- # ready for digest auth, so we hack it and resend 401,
- # only this time without digest auth.
- output_401($r, DigestAuth => 0);
- return undef;
- }
- my $ha1 = $ref->{'digest_ha1_hex'};
- my $ha2 = Digest::MD5::md5_hex($r->method . ':' . $auth{'uri'});
- my $response;
- if (exists($auth{'qop'}) && $auth{'qop'} eq 'auth') {
- unless (exists($auth{'nc'}) && exists($auth{'cnonce'})) {
- output_401($r);
- return undef;
- }
-
- $response = $ha1;
- $response .= ':' . $auth{'nonce'};
- $response .= ':' . $auth{'nc'};
- $response .= ':' . $auth{'cnonce'};
- $response .= ':' . $auth{'qop'};
- $response .= ':' . $ha2;
- } else {
- $response = $ha1;
- $response .= ':' . $auth{'nonce'};
- $response .= ':' . $ha2;
- }
- if ($auth{'response'} ne Digest::MD5::md5_hex($response)) {
- output_401($r);
+ if (!defined($ref) || (!$sha1_matches && !$bcrypt_matches)) {
+ $r->content_type('text/plain; charset=utf-8');
+ log_warn($r, "Authentication failed for $user/$takenby");