From 6a3853c3daeb173a52aecde45d254dfa526e1dde Mon Sep 17 00:00:00 2001 From: "Breno G. de Oliveira" Date: Fri, 26 Apr 2024 10:51:04 -0300 Subject: [PATCH 1/4] s/http/https/g --- App-cpanminus/lib/App/cpanminus.pm | 8 ++++---- App-cpanminus/script/cpanm.PL | 14 +++++++------- Menlo-Legacy/META.json | 2 +- Menlo-Legacy/lib/Menlo/CLI/Compat.pm | 20 ++++++++++---------- Menlo/Changes | 2 +- Menlo/META.json | 2 +- Menlo/lib/Menlo/Index/MetaCPAN.pm | 2 +- Menlo/lib/Menlo/Index/MetaDB.pm | 4 ++-- 8 files changed, 27 insertions(+), 27 deletions(-) diff --git a/App-cpanminus/lib/App/cpanminus.pm b/App-cpanminus/lib/App/cpanminus.pm index dd8541218..33fd3498b 100644 --- a/App-cpanminus/lib/App/cpanminus.pm +++ b/App-cpanminus/lib/App/cpanminus.pm @@ -105,16 +105,16 @@ Module::Build (core in 5.10) =head2 How does cpanm get/parse/update the CPAN index? -It queries the CPAN Meta DB site at L. +It queries the CPAN Meta DB site at L. The site is updated at least every hour to reflect the latest changes from fast syncing mirrors. The script then also falls back to query the -module at L using its search API. +module at L using its search API. Upon calling these API hosts, cpanm (1.6004 or later) will send the local perl versions to the server in User-Agent string by default. You can turn it off with C<--no-report-perl-version> option. Read more about the option with L, and read more about the privacy policy -about this data collection at L +about this data collection at L Fetched files are unpacked in C<~/.cpanm> and automatically cleaned up periodically. You can configure the location of this with the @@ -270,7 +270,7 @@ Arnfjord Bjarmason, Eric Wilhelm, Florian Ragwitz and xaicron. =over 4 -=item L - source code repository, issue tracker +=item L - source code repository, issue tracker =item L - discussions about cpanm and its related tools diff --git a/App-cpanminus/script/cpanm.PL b/App-cpanminus/script/cpanm.PL index 0944beaeb..ad06b9a94 100755 --- a/App-cpanminus/script/cpanm.PL +++ b/App-cpanminus/script/cpanm.PL @@ -37,14 +37,14 @@ cpanm - get, unpack build and install modules from CPAN cpanm Test::More # install Test::More cpanm MIYAGAWA/Plack-0.99_05.tar.gz # full distribution path - cpanm http://example.org/LDS/CGI.pm-3.20.tar.gz # install from URL + cpanm https://example.org/LDS/CGI.pm-3.20.tar.gz # install from URL cpanm ~/dists/MyCompany-Enterprise-1.00.tar.gz # install from a local file cpanm --interactive Task::Kensho # Configure interactively cpanm . # install from local directory cpanm --installdeps . # install all the deps for the current directory cpanm -L extlib Plack # install Plack and all non-core deps into extlib - cpanm --mirror http://cpan.cpantesters.org/ DBI # use the fast-syncing mirror - cpanm --from https://cpan.metacpan.org/ Plack # use only the HTTPS mirror + cpanm --mirror https://cpan.cpantesters.org/ DBI # use the fast-syncing mirror + cpanm --from https://cpan.metacpan.org/ Plack # use a different mirror =head1 COMMANDS @@ -60,7 +60,7 @@ will all work as you expect. cpanm Plack/Request.pm cpanm MIYAGAWA/Plack-1.0000.tar.gz cpanm /path/to/Plack-1.0000.tar.gz - cpanm http://cpan.metacpan.org/authors/id/M/MI/MIYAGAWA/Plack-0.9990.tar.gz + cpanm https://cpan.metacpan.org/authors/id/M/MI/MIYAGAWA/Plack-0.9990.tar.gz cpanm git://github.com/plack/Plack.git Additionally, you can use the notation using C<~> and C<@> to specify @@ -213,7 +213,7 @@ the behaviour from before version 1.7023 =item --mirror Specifies the base URL for the CPAN mirror to use, such as -C (you can omit the trailing slash). You +C (you can omit the trailing slash). You can specify multiple mirror URLs by repeating the command line option. You can use a local directory that has a CPAN mirror structure @@ -224,7 +224,7 @@ scheme), it is considered as a file scheme as well. cpanm --mirror file:///path/to/mirror cpanm --mirror ~/minicpan # Because shell expands ~ to /home/user -Defaults to C. +Defaults to C. =item --mirror-only @@ -256,7 +256,7 @@ B It might be useful if you name these options with your shell aliases, like: alias minicpanm='cpanm --from ~/minicpan' - alias darkpan='cpanm --from http://mycompany.example.com/DPAN' + alias darkpan='cpanm --from https://mycompany.example.com/DPAN' =item --mirror-index diff --git a/Menlo-Legacy/META.json b/Menlo-Legacy/META.json index 9ff0794ef..a8988f10d 100644 --- a/Menlo-Legacy/META.json +++ b/Menlo-Legacy/META.json @@ -9,7 +9,7 @@ "perl_5" ], "meta-spec" : { - "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "url" : "https://metacpan.org/pod/CPAN::Meta::Spec", "version" : 2 }, "name" : "Menlo-Legacy", diff --git a/Menlo-Legacy/lib/Menlo/CLI/Compat.pm b/Menlo-Legacy/lib/Menlo/CLI/Compat.pm index 00f5d4bfb..2732f63f0 100644 --- a/Menlo-Legacy/lib/Menlo/CLI/Compat.pm +++ b/Menlo-Legacy/lib/Menlo/CLI/Compat.pm @@ -65,7 +65,7 @@ sub new { mirrors => [], mirror_only => undef, mirror_index => undef, - cpanmetadb => "http://cpanmetadb.plackperl.org/v1.0/", + cpanmetadb => "https://cpanmetadb.plackperl.org/v1.0/", perl => $^X, argv => [], local_lib => undef, @@ -616,7 +616,7 @@ Options: --installdeps Only install dependencies --showdeps Only display direct dependencies --reinstall Reinstall the distribution even if you already have the latest version installed - --mirror Specify the base URL for the mirror (e.g. http://cpan.cpantesters.org/) + --mirror Specify the base URL for the mirror (e.g. https://cpan.cpantesters.org/) --mirror-only Use the mirror's index file instead of the CPAN Meta DB -M,--from Use only this mirror base URL and its index file --prompt Prompt when configure/build/test fails @@ -636,18 +636,18 @@ Examples: cpanm Test::More # install Test::More cpanm MIYAGAWA/Plack-0.99_05.tar.gz # full distribution path - cpanm http://example.org/LDS/CGI.pm-3.20.tar.gz # install from URL + cpanm https://example.org/LDS/CGI.pm-3.20.tar.gz # install from URL cpanm ~/dists/MyCompany-Enterprise-1.00.tar.gz # install from a local file cpanm --interactive Task::Kensho # Configure interactively cpanm . # install from local directory cpanm --installdeps . # install all the deps for the current directory cpanm -L extlib Plack # install Plack and all non-core deps into extlib - cpanm --mirror http://cpan.cpantesters.org/ DBI # use the fast-syncing mirror + cpanm --mirror https://cpan.cpantesters.org/ DBI # use the fast-syncing mirror cpanm -M https://cpan.metacpan.org App::perlbrew # use only this secure mirror and its index You can also specify the default options in PERL_CPANM_OPT environment variable in the shell rc: - export PERL_CPANM_OPT="--prompt --reinstall -l ~/perl --mirror http://cpan.cpantesters.org" + export PERL_CPANM_OPT="--prompt --reinstall -l ~/perl --mirror https://cpan.cpantesters.org" Type `man cpanm` or `perldoc cpanm` for the more detailed explanation of the options. @@ -1163,7 +1163,7 @@ sub chdir { sub configure_mirrors { my $self = shift; unless (@{$self->{mirrors}}) { - $self->{mirrors} = [ 'http://www.cpan.org' ]; + $self->{mirrors} = [ 'https://www.cpan.org' ]; } for (@{$self->{mirrors}}) { s!^/!file:///!; @@ -1688,7 +1688,7 @@ sub cpan_dist { sub git_uri { my ($self, $uri) = @_; - # similar to http://www.pip-installer.org/en/latest/logic.html#vcs-support + # similar to https://www.pip-installer.org/en/latest/logic.html#vcs-support # git URL has to end with .git when you need to use pin @ commit/tag/branch ($uri, my $commitish) = split /(?<=\.git)@/i, $uri, 2; @@ -2703,9 +2703,9 @@ sub configure_http { unshift @try, 'Curl' if $self->{try_curl}; unshift @try, 'LWP' if $self->{try_lwp}; - my @protocol = ('http'); - push @protocol, 'https' - if grep /^https:/, @{$self->{mirrors}}; + my @protocol = ('https'); + push @protocol, 'http' + if grep /^http:/, @{$self->{mirrors}}; my $backend; for my $try (map "HTTP::Tinyish::$_", @try) { diff --git a/Menlo/Changes b/Menlo/Changes index de9690bbc..32692ea77 100644 --- a/Menlo/Changes +++ b/Menlo/Changes @@ -1,4 +1,4 @@ -See http://github.com/miyagawa/cpanminus/ for the latest development. +See https://github.com/miyagawa/cpanminus/ for the latest development. {{$NEXT}} diff --git a/Menlo/META.json b/Menlo/META.json index 4cf7fa4e2..c90414950 100644 --- a/Menlo/META.json +++ b/Menlo/META.json @@ -9,7 +9,7 @@ "perl_5" ], "meta-spec" : { - "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "url" : "https://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Menlo", diff --git a/Menlo/lib/Menlo/Index/MetaCPAN.pm b/Menlo/lib/Menlo/Index/MetaCPAN.pm index b3605a28d..904bfc956 100644 --- a/Menlo/lib/Menlo/Index/MetaCPAN.pm +++ b/Menlo/lib/Menlo/Index/MetaCPAN.pm @@ -55,7 +55,7 @@ sub search_packages { package => $args->{package}, version => $dist_meta->{version}, uri => "cpan:///distfile/$distfile", - download_uri => $self->_download_uri("http://cpan.metacpan.org", $distfile), + download_uri => $self->_download_uri("https://cpan.metacpan.org", $distfile), }; } diff --git a/Menlo/lib/Menlo/Index/MetaDB.pm b/Menlo/lib/Menlo/Index/MetaDB.pm index db31e783e..bbf489b8a 100644 --- a/Menlo/lib/Menlo/Index/MetaDB.pm +++ b/Menlo/lib/Menlo/Index/MetaDB.pm @@ -19,7 +19,7 @@ use HTTP::Tiny; sub BUILD { my $self = shift; my $uri = $self->uri; - $uri = "http://cpanmetadb.plackperl.org/v1.0/" + $uri = "https://cpanmetadb.plackperl.org/v1.0/" unless defined $uri; # ensure URI ends in '/' $uri =~ s{/?$}{/}; @@ -73,7 +73,7 @@ sub search_packages { version => $match->{version}, uri => "cpan:///distfile/$file", ($match->{latest} ? () : - (download_uri => "http://backpan.perl.org/authors/id/$match->{distfile}")), + (download_uri => "https://backpan.perl.org/authors/id/$match->{distfile}")), }; } } else { From 3efe8e25384e3ec384b699d23e3427cecd5b621a Mon Sep 17 00:00:00 2001 From: Nicolas R Date: Sat, 27 Apr 2024 15:09:40 +0100 Subject: [PATCH 2/4] Raise warnings when fail to use SSL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If none of the available clients from HTTP::Tinyish support SSL then we should die with a better error message rather than trying to use 'undef' as a backend (which fix an error when calling $backend->new a few lines later). This is also adding an extra check inside the 'mirror' function. That function is used in multiple locations without checking directly the error status. The goal is to detect invalid certificate errors when SSL is supported by the backend.. Note that depending on the backend and probably client version the error message can differ. `HTTP::Tiny` Internal Exception raised with invalid certificates: SSL connection failed for cpan.metacpan.org: Invalid certificate authority locations error:0D07A086:asn1 ... `HTTP::Tinyish::LWP` Internal Exception raised with invalid certificates: 500 Can't connect to cpan.metacpan.org:443 () `HTTP::Tinyish::Curl` Internal Exception raised with invalid certificates: curl: (60) Peer certificate cannot be authenticated with known CA certificates More details here: http://curl.haxx.se/docs/sslcerts.html `HTTP::Tinyish::Wget` Internal Exception raised with invalid certificates: ... ERROR: cannot verify cpan.metacpan.org’s certificate, issued by ... This patch accounts for all the scenarios above. Signed-off-by: Breno G. de Oliveira --- Menlo-Legacy/lib/Menlo/CLI/Compat.pm | 36 ++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/Menlo-Legacy/lib/Menlo/CLI/Compat.pm b/Menlo-Legacy/lib/Menlo/CLI/Compat.pm index 2732f63f0..c98834172 100644 --- a/Menlo-Legacy/lib/Menlo/CLI/Compat.pm +++ b/Menlo-Legacy/lib/Menlo/CLI/Compat.pm @@ -2650,11 +2650,35 @@ sub DESTROY { sub mirror { my($self, $uri, $local) = @_; - if ($uri =~ /^file:/) { - $self->file_mirror($uri, $local); - } else { - $self->{http}->mirror($uri, $local); + + die( "mirror: Undefined URI\n" ) unless defined $uri && length $uri; + + if ( $uri =~ /^file:/) { + return $self->file_mirror($uri, $local); + } + + my $reply = $self->{http}->mirror($uri, $local); + + if ( $uri =~ /^https:/ && ref $reply + && $reply->{status} && $reply->{status} == 599 + && $reply->{content} + ) { + my $invalid_cert; + if ( ref($self->{http}) =~ m{(?:Curl|HTTPTiny|Wget)} ) { + $invalid_cert = 1 if $reply->{content} =~ m{certificate}mi; + } elsif ( ref($self->{http}) =~ m{LWP} ) { + $invalid_cert = 1 if $reply->{content} =~ m{Can't connect.+?:443}mi; + } + if ( $invalid_cert ) { + die <<"DIE"; +TLS issue found while fetching $uri:\n +$reply->{content}\n +Please verify your certificates or force an HTTP-only request/mirror at your own risk. +DIE + } } + + return $reply; } sub untar { $_[0]->{_backends}{untar}->(@_) }; @@ -2721,6 +2745,10 @@ sub configure_http { } } + if ( !$backend ) { + $self->diag_fail( join( ', ', @protocol )." not supported by available HTTP Clients." ); + } + $backend->new(agent => "Menlo/$Menlo::VERSION", verify_SSL => 1); } From 6684b9349363b6b973cf973e83717ded27f586d6 Mon Sep 17 00:00:00 2001 From: Nicolas R Date: Sun, 28 Apr 2024 15:23:54 +0100 Subject: [PATCH 3/4] Add --insecure to switch to http --- App-cpanminus/script/cpanm.PL | 9 ++++++++- Menlo-Legacy/lib/Menlo/CLI/Compat.pm | 30 +++++++++++++++++++--------- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/App-cpanminus/script/cpanm.PL b/App-cpanminus/script/cpanm.PL index ad06b9a94..2baee4891 100755 --- a/App-cpanminus/script/cpanm.PL +++ b/App-cpanminus/script/cpanm.PL @@ -555,9 +555,16 @@ Defaults to true (man pages generated) unless C<-L|--local-lib-contained> option is supplied in which case it's set to false. You can disable it with C<--no-man-pages>. +=item --insecure + +By default, cpanm only uses HTTPS. If your environment lacks TLS +support, you can consider at your own risk to use HTTP instead by +using the C<--insecure> flag. +Be aware that when using that argument all requests will use HTTP. + =item --lwp -Uses L module to download stuff over HTTP. Defaults to true, and +Uses L module to download stuff over HTTPS. Defaults to true, and you can say C<--no-lwp> to disable using LWP, when you want to upgrade LWP from CPAN on some broken perl systems. diff --git a/Menlo-Legacy/lib/Menlo/CLI/Compat.pm b/Menlo-Legacy/lib/Menlo/CLI/Compat.pm index c98834172..f85aef636 100644 --- a/Menlo-Legacy/lib/Menlo/CLI/Compat.pm +++ b/Menlo-Legacy/lib/Menlo/CLI/Compat.pm @@ -79,6 +79,7 @@ sub new { try_lwp => 1, try_wget => 1, try_curl => 1, + use_http => 0, uninstall_shadows => ($] < 5.012), skip_installed => 1, skip_satisfied => 0, @@ -199,6 +200,7 @@ sub parse_options { 'lwp!' => \$self->{try_lwp}, 'wget!' => \$self->{try_wget}, 'curl!' => \$self->{try_curl}, + 'insecure!' => \$self->{use_http}, 'auto-cleanup=s' => \$self->{auto_cleanup}, 'man-pages!' => \$self->{pod2man}, 'scandeps' => \$self->{scandeps}, @@ -453,7 +455,7 @@ sub search_common { $self->chat("Found $found->{module} $found->{module_version} which doesn't satisfy $want_version.\n"); } } - + return; } @@ -977,7 +979,7 @@ sub append_args { my($self, $cmd, $phase) = @_; return $cmd if ref $cmd ne 'ARRAY'; - + if (my $args = $self->{build_args}{$phase}) { $cmd = join ' ', Menlo::Util::shell_quote(@$cmd), $args; } @@ -2657,6 +2659,10 @@ sub mirror { return $self->file_mirror($uri, $local); } + # HTTPTinyish does not provide an option to disable + # certificates check, let's switch to http on demand. + $uri =~ s/^https:/http:/ if $self->{use_http}; + my $reply = $self->{http}->mirror($uri, $local); if ( $uri =~ /^https:/ && ref $reply @@ -2673,7 +2679,8 @@ sub mirror { die <<"DIE"; TLS issue found while fetching $uri:\n $reply->{content}\n -Please verify your certificates or force an HTTP-only request/mirror at your own risk. +Please verify your certificates or force an HTTP-only request/mirror +using --insecure option at your own risk. DIE } } @@ -2722,14 +2729,16 @@ sub configure_http { require HTTP::Tinyish; + my $use_http = $self->{use_http}; + my @try = qw(HTTPTiny); unshift @try, 'Wget' if $self->{try_wget}; unshift @try, 'Curl' if $self->{try_curl}; unshift @try, 'LWP' if $self->{try_lwp}; - my @protocol = ('https'); + my @protocol = ( $use_http ? 'http' : 'https' ); push @protocol, 'http' - if grep /^http:/, @{$self->{mirrors}}; + if !$use_http && grep /^http:/, @{$self->{mirrors}}; my $backend; for my $try (map "HTTP::Tinyish::$_", @try) { @@ -2745,11 +2754,14 @@ sub configure_http { } } - if ( !$backend ) { - $self->diag_fail( join( ', ', @protocol )." not supported by available HTTP Clients." ); - } + # In case we use https protocol by default + # and then later we try to perform non https requests + # we still want these requests to succeed + # Note: this is disabling the client cache optimization above + # and will fail later for SSL requests as no clients support TLS + $backend ||= 'HTTP::Tinyish'; - $backend->new(agent => "Menlo/$Menlo::VERSION", verify_SSL => 1); + $backend->new(agent => "Menlo/$Menlo::VERSION", $use_http ? () : ( verify_SSL => 1 ) ); } sub init_tools { From 6121fa7d64f62e8f86f02aea4446578924692c12 Mon Sep 17 00:00:00 2001 From: "Breno G. de Oliveira" Date: Fri, 17 May 2024 02:46:30 -0300 Subject: [PATCH 4/4] fallback to HTTP-only when TLS is unavailable cpanm will fall back to (non-TLS) HTTP only requests when all default options are used AND TLS support is unavailable, but please note that, for security reasons, if TLS support is available but broken (e.g. invalid/expired certificates), requests will fail unless you explicitly use --insecure. Also note that if you use --insecure but provide custom HTTPS URLs, they will still fail if TLS support is not available. Similarly, if you provide custom HTTP-only URLs, they will go over plain HTTP and not require TLS support. --- Menlo-Legacy/lib/Menlo/CLI/Compat.pm | 78 +++++++++++++++++++--------- 1 file changed, 54 insertions(+), 24 deletions(-) diff --git a/Menlo-Legacy/lib/Menlo/CLI/Compat.pm b/Menlo-Legacy/lib/Menlo/CLI/Compat.pm index f85aef636..acf83b749 100644 --- a/Menlo-Legacy/lib/Menlo/CLI/Compat.pm +++ b/Menlo-Legacy/lib/Menlo/CLI/Compat.pm @@ -153,6 +153,7 @@ sub parse_options { push @ARGV, grep length, split /\s+/, $self->env('OPT'); push @ARGV, @_; + my $custom_cpanmetadb; Getopt::Long::Configure("bundling"); Getopt::Long::GetOptions( 'f|force' => sub { $self->{skip_installed} = 0; $self->{force} = 1 }, @@ -183,7 +184,7 @@ sub parse_options { $self->{mirrors} = [$_[1]]; $self->{mirror_only} = 1; }, - 'cpanmetadb=s' => \$self->{cpanmetadb}, + 'cpanmetadb=s' => \$custom_cpanmetadb, 'cascade-search!' => \$self->{cascade_search}, 'prompt!' => \$self->{prompt}, 'installdeps' => \$self->{installdeps}, @@ -235,6 +236,14 @@ sub parse_options { $self->{load_from_stdin} = 1; } + if ($custom_cpanmetadb) { + $self->{cpanmetadb} = $custom_cpanmetadb; + $self->{has_custom_cpanmetadb} = 1; + } + else { + $self->{cpanmetadb} =~ s!^https:!http:! if $self->{use_http}; + } + $self->{argv} = \@ARGV; } @@ -611,7 +620,8 @@ Options: -v,--verbose Turns on chatty output -q,--quiet Turns off the most output --interactive Turns on interactive configure (required for Task:: modules) - -f,--force force install + --insecure Use HTTP-only requests instead of HTTPS + -f,--force Force install -n,--notest Do not run unit tests --test-only Run tests only, do not install -S,--sudo sudo to run install commands @@ -628,7 +638,7 @@ Options: --auto-cleanup Number of days that cpanm's work directories expire in. Defaults to 7 Commands: - --self-upgrade upgrades itself + --self-upgrade Upgrades itself --info Displays distribution info on CPAN --look Opens the distribution with your SHELL -U,--uninstall Uninstalls the modules (EXPERIMENTAL) @@ -1165,12 +1175,22 @@ sub chdir { sub configure_mirrors { my $self = shift; unless (@{$self->{mirrors}}) { - $self->{mirrors} = [ 'https://www.cpan.org' ]; + $self->{mirrors} = [ + ($self->{use_http} ? 'http' : 'https') . '://www.cpan.org' + ]; } + + my $warned; for (@{$self->{mirrors}}) { s!^/!file:///!; s!/$!!; + + if (m/^http:/ && !$self->{use_http} && !$warned) { + warn "WARNING: you are using a non-HTTPS mirror, which is considered insecure. To remove this message, please pass the --insecure flag.\n" if !$warned; + $warned = 1; + } } + return; } sub self_upgrade { @@ -1639,6 +1659,7 @@ sub cpan_module_common { my $mirrors = $self->{mirrors}; if ($match->{download_uri}) { + $match->{download_uri} =~ s!^https:!http:! if $self->{use_http}; (my $mirror = $match->{download_uri}) =~ s!/authors/id/.*$!!; $mirrors = [$mirror]; } @@ -2679,8 +2700,7 @@ sub mirror { die <<"DIE"; TLS issue found while fetching $uri:\n $reply->{content}\n -Please verify your certificates or force an HTTP-only request/mirror -using --insecure option at your own risk. +Please verify/update your certificates. You may also force an HTTP-only mirror or use the --insecure flag. DIE } } @@ -2727,23 +2747,41 @@ sub file_mirror { sub configure_http { my $self = shift; - require HTTP::Tinyish; - - my $use_http = $self->{use_http}; - my @try = qw(HTTPTiny); unshift @try, 'Wget' if $self->{try_wget}; unshift @try, 'Curl' if $self->{try_curl}; unshift @try, 'LWP' if $self->{try_lwp}; - my @protocol = ( $use_http ? 'http' : 'https' ); - push @protocol, 'http' - if !$use_http && grep /^http:/, @{$self->{mirrors}}; + my @protocol = ('http'); + if (!$self->{use_http} || $self->{cpanmetadb} =~ /^https:/ || (grep /^https:/, @{$self->{mirrors}})) { + push @protocol, 'https'; + } + my $backend = $self->get_http_backend(\@try, \@protocol); + + # fallback to http-only if we failed using https with default options: + if (!$backend && !$self->{use_http} && !@{$self->{mirrors}} && (!$self->{has_custom_cpanmetadb} || $self->{cpanmetadb} =~ /^http:/)) { + $self->diag('WARNING: TLS support not found. Falling back to insecure HTTP-only requests'); + $self->{use_http} = 1; + @protocol = ('http'); + $backend = $self->get_http_backend(\@try, \@protocol); + } + + if ( !$backend ) { + $self->diag_fail( join( ', ', @protocol )." not supported by available HTTP Clients." ); + } + + $backend->new(agent => "Menlo/$Menlo::VERSION", verify_SSL => 1); +} + +sub get_http_backend { + my ($self, $tries, $protocols) = @_; + + require HTTP::Tinyish; my $backend; - for my $try (map "HTTP::Tinyish::$_", @try) { + for my $try (map "HTTP::Tinyish::$_", @$tries) { if (my $meta = HTTP::Tinyish->configure_backend($try)) { - if ((grep $try->supports($_), @protocol) == @protocol) { + if ((grep $try->supports($_), @$protocols) == @$protocols) { for my $tool (sort keys %$meta){ (my $desc = $meta->{$tool}) =~ s/^(.*?)\n.*/$1/s; $self->chat("You have $tool: $desc\n"); @@ -2753,15 +2791,7 @@ sub configure_http { } } } - - # In case we use https protocol by default - # and then later we try to perform non https requests - # we still want these requests to succeed - # Note: this is disabling the client cache optimization above - # and will fail later for SSL requests as no clients support TLS - $backend ||= 'HTTP::Tinyish'; - - $backend->new(agent => "Menlo/$Menlo::VERSION", $use_http ? () : ( verify_SSL => 1 ) ); + return $backend; } sub init_tools {