Fix auth not getting realm from auth headers due to them being an array now. Get auth and ip from Path if not set in ControlAddress.

This commit is contained in:
Isaac Connor 2021-12-14 10:04:35 -05:00
parent 3ee649406c
commit 4a51253aa9
1 changed files with 43 additions and 25 deletions

View File

@ -51,11 +51,21 @@ sub open {
my $self = shift; my $self = shift;
$self->loadMonitor(); $self->loadMonitor();
if ( $self->{Monitor}->{ControlAddress} !~ /^\w+:\/\// ) {
# Has no scheme at the beginning, so won't parse as a URI if ($self->{Monitor}->{ControlAddress} and ($self->{Monitor}->{ControlAddress} ne 'user:pass@ip')) {
$self->{Monitor}->{ControlAddress} = 'http://'.$self->{Monitor}->{ControlAddress}; Debug("Getting connection details from Control Address " . $self->{Monitor}->{ControlAddress});
} if ( $self->{Monitor}->{ControlAddress} !~ /^\w+:\/\// ) {
$uri = URI->new($self->{Monitor}->{ControlAddress}); # Has no scheme at the beginning, so won't parse as a URI
$self->{Monitor}->{ControlAddress} = 'http://'.$self->{Monitor}->{ControlAddress};
}
$uri = URI->new($self->{Monitor}->{ControlAddress});
} elsif ($self->{Monitor}->{Path}) {
Debug("Getting connection details from Path " . $self->{Monitor}->{Path});
$uri = URI->new($self->{Monitor}->{Path});
$uri->scheme('http');
$uri->port(80);
$uri->path('');
}
use LWP::UserAgent; use LWP::UserAgent;
$self->{ua} = LWP::UserAgent->new; $self->{ua} = LWP::UserAgent->new;
@ -64,6 +74,7 @@ sub open {
$self->{state} = 'closed'; $self->{state} = 'closed';
my ( $username, $password, $host ) = ( $uri->authority() =~ /^([^:]+):([^@]*)@(.+)$/ ); my ( $username, $password, $host ) = ( $uri->authority() =~ /^([^:]+):([^@]*)@(.+)$/ );
Debug("Have username: $username password: $password host: $host from authority:" . $uri->authority());
$uri->userinfo(undef); $uri->userinfo(undef);
@ -75,40 +86,47 @@ sub open {
# test auth # test auth
my $res = $self->{ua}->get($uri->canonical().$url); my $res = $self->{ua}->get($uri->canonical().$url);
if ( $res->is_success ) { if ($res->is_success) {
if ( $res->content() ne "Properties.PTZ.PTZ=yes\n" ) { if ($res->content() ne "Properties.PTZ.PTZ=yes\n") {
Warning('Response suggests that camera doesn\'t support PTZ. Content:('.$res->content().')'); Warning('Response suggests that camera doesn\'t support PTZ. Content:('.$res->content().')');
} }
$self->{state} = 'open'; $self->{state} = 'open';
return; return;
} }
if ($res->status_line() eq '404 Not Found') {
#older style
$url = 'axis-cgi/com/ptz.cgi';
$res = $self->{ua}->get($uri->canonical().$url);
Debug("Result from getting ".$uri->canonical().$url . ':' . $res->status_line());
}
if ( $res->status_line() eq '401 Unauthorized' ) { if ($res->status_line() eq '401 Unauthorized') {
my $headers = $res->headers(); my $headers = $res->headers();
foreach my $k ( keys %$headers ) { foreach my $k ( keys %$headers ) {
Debug("Initial Header $k => $$headers{$k}"); Debug("Initial Header $k => $$headers{$k}");
} }
if ( $$headers{'www-authenticate'} ) { if ( $$headers{'www-authenticate'} ) {
my ( $auth, $tokens ) = $$headers{'www-authenticate'} =~ /^(\w+)\s+(.*)$/; foreach my $auth_header ( ref $$headers{'www-authenticate'} eq 'ARRAY' ? @{$$headers{'www-authenticate'}} : ($$headers{'www-authenticate'})) {
if ( $tokens =~ /\w+="([^"]+)"/i ) { my ( $auth, $tokens ) = $auth_header =~ /^(\w+)\s+(.*)$/;
if ( $realm ne $1 ) { if ( $tokens =~ /\w+="([^"]+)"/i ) {
$realm = $1; if ( $realm ne $1 ) {
$self->{ua}->credentials($uri->host_port(), $realm, $username, $password); $realm = $1;
$res = $self->{ua}->get($uri->canonical().$url); $self->{ua}->credentials($uri->host_port(), $realm, $username, $password);
if ( $res->is_success() ) { $res = $self->{ua}->get($uri->canonical().$url);
Info("Auth succeeded after setting realm to $realm. You can set this value in the Control Device field to speed up connections and remove these log entries."); if ( $res->is_success() ) {
$self->{state} = 'open'; Info("Auth succeeded after setting realm to $realm. You can set this value in the Control Device field to speed up connections and remove these log entries.");
return; $self->{state} = 'open';
return;
}
Error('Authentication still failed after updating REALM status: '.$res->status_line);
} else {
Error('Authentication failed, not a REALM problem');
} }
Error('Authentication still failed after updating REALM status: '.$res->status_line);
} else { } else {
Error('Authentication failed, not a REALM problem'); Error('Failed to match realm in tokens');
} } # end if
} else { } # end foreach auth header
Error('Failed to match realm in tokens');
} # end if
} else { } else {
Debug('No headers line'); Debug('No headers line');
} # end if headers } # end if headers