Elia Bellussi
Elia Bellussi

Reputation: 21

Mojo::UserAgent certificate verify failed

I want to access a website where the certificate cannot be verified (hostname not correct and I cannot change/update the certificate on the server which my application point). I'm using Mojo::UserAgent to get request. So how would go about ignoring this and continues to connect to the website? I've seen that there is not an option.

I don't want to use LWP::UserAgent.

I've done it using WWW::Curl and WWW::Curl::Easy but I want to clean the code using Mojo::UserAgent (as used in my entire application).

Upvotes: 2

Views: 1989

Answers (3)

Hugh Barnard
Hugh Barnard

Reputation: 352

This is an old question, but Mojolicious is alive and kicking. As such I've battled with this recently. Directly from the documents:

my $bool = $ua->insecure;
$ua      = $ua->insecure($bool);

Do not require a valid TLS certificate to access HTTPS/WSS sites, defaults to the value of the MOJO_INSECURE environment variable.

# Disable TLS certificate verification for testing
say $ua->insecure(1)->get('https://127.0.0.1:3000')->result->code;

In my application $bool is set from a configuration file, so I can switch it back on, where we need it.

Upvotes: 2

Steffen Ullrich
Steffen Ullrich

Reputation: 123639

hostname not correct ... So how would go about ignoring this and continues to connect to the website?

It is a very bad idea just to abandon any kind of validation just because the hostname does not match the certificate. Why do you use TLS at all?

A much better way is to know up front which certificate you expect and verify that you exactly get this one. This can easily be done with the option SSL_fingerprint. Unfortunately Mojo::UserAgent does not offer a way to set connection specific arguments, so you need to set it immediately before the connection and back before you do other connections:

use IO::Socket::SSL 1.980;
IO::Socket::SSL::set_client_defaults(
    SSL_fingerprint => "sha256$55a5dfaaf..."
);
... use Mojo::UserAgent to connect ..
IO::Socket::SSL::set_client_defaults(); # set back

For more information about to use this option and how to get the fingerprint see Certificate error in Perl.

Another way in case only the hostname is bad would be to use the SSL_verifycn_name option to specify the hostname you expect inside the certificate.

IO::Socket::SSL::set_client_defaults(
    SSL_verifycn_name => 'foo.example.com',
);

Another way could be done with the set_args_filter_hack function which is intended to deal with modules which set strange defaults or which don't let the user set its own values:

my $hostname = undef;
IO::Socket::SSL::set_args_filter_hack(
    sub {
        my ($is_server,$args) = @_;
        $args->{SSL_verifycn_name} = $hostname if $hostname;
    }
);
...
$hostname = 'foo.example.com';
... do something with Mojo::UserAgent ...
$hostname = undef;

This way you can adapt the settings for each SSL handshake.

For more information see the documentation of IO::Socket::SSL, especially the part about the common usage errors. This part also documents what you should do instead of disabling any kind of validation if some part of the certificate is wrong.


'SSL connect attempt failed error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol'
curl ... SSL connection using TLS_RSA_WITH_RC4_128_MD5

My guess is what you are facing here is unrelated to the certificate validation. Given that this server is using a very old cipher RC4-MD5 I will assume that the server can only handle SSL 3.0. This version is disabled since a while for security reasons in IO::Socket::SSL. To explicitly use this insecure version temporarily:

IO::Socket::SSL::set_client_defaults(
    SSL_version => 'SSLv3'
);

Upvotes: 4

hobbs
hobbs

Reputation: 240759

Mojo::UserAgent uses IO::Socket::SSL for SSL/TLS support, so you can disable server certificate verification using

IO::Socket::SSL::set_defaults(
    SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE,
);

Upvotes: 2

Related Questions