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.

add_mqtt
Isaac Connor 2021-12-14 10:04:35 -05:00
parent cfcc39defb
commit fe72fd83f8
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