Skip to content

Commit fa1a4dd

Browse files
committed
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.
1 parent b686ffc commit fa1a4dd

File tree

1 file changed

+54
-24
lines changed

1 file changed

+54
-24
lines changed

Menlo-Legacy/lib/Menlo/CLI/Compat.pm

+54-24
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ sub parse_options {
153153
push @ARGV, grep length, split /\s+/, $self->env('OPT');
154154
push @ARGV, @_;
155155

156+
my $custom_cpanmetadb;
156157
Getopt::Long::Configure("bundling");
157158
Getopt::Long::GetOptions(
158159
'f|force' => sub { $self->{skip_installed} = 0; $self->{force} = 1 },
@@ -183,7 +184,7 @@ sub parse_options {
183184
$self->{mirrors} = [$_[1]];
184185
$self->{mirror_only} = 1;
185186
},
186-
'cpanmetadb=s' => \$self->{cpanmetadb},
187+
'cpanmetadb=s' => \$custom_cpanmetadb,
187188
'cascade-search!' => \$self->{cascade_search},
188189
'prompt!' => \$self->{prompt},
189190
'installdeps' => \$self->{installdeps},
@@ -235,6 +236,14 @@ sub parse_options {
235236
$self->{load_from_stdin} = 1;
236237
}
237238

239+
if ($custom_cpanmetadb) {
240+
$self->{cpanmetadb} = $custom_cpanmetadb;
241+
$self->{has_custom_cpanmetadb} = 1;
242+
}
243+
else {
244+
$self->{cpanmetadb} =~ s!^https:!http:! if $self->{use_http};
245+
}
246+
238247
$self->{argv} = \@ARGV;
239248
}
240249

@@ -611,7 +620,8 @@ Options:
611620
-v,--verbose Turns on chatty output
612621
-q,--quiet Turns off the most output
613622
--interactive Turns on interactive configure (required for Task:: modules)
614-
-f,--force force install
623+
--insecure Use HTTP-only requests instead of HTTPS
624+
-f,--force Force install
615625
-n,--notest Do not run unit tests
616626
--test-only Run tests only, do not install
617627
-S,--sudo sudo to run install commands
@@ -628,7 +638,7 @@ Options:
628638
--auto-cleanup Number of days that cpanm's work directories expire in. Defaults to 7
629639
630640
Commands:
631-
--self-upgrade upgrades itself
641+
--self-upgrade Upgrades itself
632642
--info Displays distribution info on CPAN
633643
--look Opens the distribution with your SHELL
634644
-U,--uninstall Uninstalls the modules (EXPERIMENTAL)
@@ -1165,12 +1175,22 @@ sub chdir {
11651175
sub configure_mirrors {
11661176
my $self = shift;
11671177
unless (@{$self->{mirrors}}) {
1168-
$self->{mirrors} = [ 'https://www.cpan.org' ];
1178+
$self->{mirrors} = [
1179+
($self->{use_http} ? 'http' : 'https') . '://www.cpan.org'
1180+
];
11691181
}
1182+
1183+
my $warned;
11701184
for (@{$self->{mirrors}}) {
11711185
s!^/!file:///!;
11721186
s!/$!!;
1187+
1188+
if (m/^http:/ && !$self->{use_http} && !$warned) {
1189+
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;
1190+
$warned = 1;
1191+
}
11731192
}
1193+
return;
11741194
}
11751195

11761196
sub self_upgrade {
@@ -1639,6 +1659,7 @@ sub cpan_module_common {
16391659

16401660
my $mirrors = $self->{mirrors};
16411661
if ($match->{download_uri}) {
1662+
$match->{download_uri} =~ s!^https:!http:! if $self->{use_http};
16421663
(my $mirror = $match->{download_uri}) =~ s!/authors/id/.*$!!;
16431664
$mirrors = [$mirror];
16441665
}
@@ -2679,8 +2700,7 @@ sub mirror {
26792700
die <<"DIE";
26802701
TLS issue found while fetching $uri:\n
26812702
$reply->{content}\n
2682-
Please verify your certificates or force an HTTP-only request/mirror
2683-
using --insecure option at your own risk.
2703+
Please verify/update your certificates. You may also force an HTTP-only mirror or use the --insecure flag.
26842704
DIE
26852705
}
26862706
}
@@ -2727,23 +2747,41 @@ sub file_mirror {
27272747
sub configure_http {
27282748
my $self = shift;
27292749

2730-
require HTTP::Tinyish;
2731-
2732-
my $use_http = $self->{use_http};
2733-
27342750
my @try = qw(HTTPTiny);
27352751
unshift @try, 'Wget' if $self->{try_wget};
27362752
unshift @try, 'Curl' if $self->{try_curl};
27372753
unshift @try, 'LWP' if $self->{try_lwp};
27382754

2739-
my @protocol = ( $use_http ? 'http' : 'https' );
2740-
push @protocol, 'http'
2741-
if !$use_http && grep /^http:/, @{$self->{mirrors}};
2755+
my @protocol = ('http');
2756+
if (!$self->{use_http} || $self->{cpanmetadb} =~ /^https:/ || (grep /^https:/, @{$self->{mirrors}})) {
2757+
push @protocol, 'https';
2758+
}
27422759

2760+
my $backend = $self->get_http_backend(\@try, \@protocol);
2761+
2762+
# fallback to http-only if we failed using https with default options:
2763+
if (!$backend && !$self->{use_http} && && !@{$self->{mirrors}} && (!$self->{has_custom_cpanmetadb} || $self->{cpanmetadb} =~ /^http:/)) {
2764+
$self->diag('WARNING: TLS support not found. Falling back to insecure HTTP-only requests');
2765+
$self->{use_http} = 1;
2766+
@protocol = ('http');
2767+
$backend = $self->get_http_backend(\@try, \@protocol);
2768+
}
2769+
2770+
if ( !$backend ) {
2771+
$self->diag_fail( join( ', ', @protocol )." not supported by available HTTP Clients." );
2772+
}
2773+
2774+
$backend->new(agent => "Menlo/$Menlo::VERSION", verify_SSL => 1);
2775+
}
2776+
2777+
sub get_http_backend {
2778+
my ($self, $tries, $protocols) = @_;
2779+
2780+
require HTTP::Tinyish;
27432781
my $backend;
2744-
for my $try (map "HTTP::Tinyish::$_", @try) {
2782+
for my $try (map "HTTP::Tinyish::$_", @$tries) {
27452783
if (my $meta = HTTP::Tinyish->configure_backend($try)) {
2746-
if ((grep $try->supports($_), @protocol) == @protocol) {
2784+
if ((grep $try->supports($_), @$protocols) == @$protocols) {
27472785
for my $tool (sort keys %$meta){
27482786
(my $desc = $meta->{$tool}) =~ s/^(.*?)\n.*/$1/s;
27492787
$self->chat("You have $tool: $desc\n");
@@ -2753,15 +2791,7 @@ sub configure_http {
27532791
}
27542792
}
27552793
}
2756-
2757-
# In case we use https protocol by default
2758-
# and then later we try to perform non https requests
2759-
# we still want these requests to succeed
2760-
# Note: this is disabling the client cache optimization above
2761-
# and will fail later for SSL requests as no clients support TLS
2762-
$backend ||= 'HTTP::Tinyish';
2763-
2764-
$backend->new(agent => "Menlo/$Menlo::VERSION", $use_http ? () : ( verify_SSL => 1 ) );
2794+
return $backend;
27652795
}
27662796

27672797
sub init_tools {

0 commit comments

Comments
 (0)