some comments inline: > diff --git a/PVE/HTTPServer.pm b/PVE/HTTPServer.pm > index 1c7d033..5ddbd07 100755 > --- a/PVE/HTTPServer.pm > +++ b/PVE/HTTPServer.pm > @@ -105,6 +105,53 @@ sub get_login_formatter { > return $info->{func}; > } > > +my $cert_cache_nodes = {}; > +my $cert_cache_fingerprints = {}; > +sub update_cert_cache { > + my ($node) = @_; > + > + if (!defined($node)) { > + for $node (keys %$cert_cache_nodes) { > + update_cert_cache($node);
please can we avoid the recursive call here? my $list = defined($node) ? [ $node ] : [ keys %$cert_cache_nodes ]; foreach my $node (@$list) { # do your work here } > + } > + return; > + } > + > + if (my $old_fp = $cert_cache_nodes->{$node}) { > + delete $cert_cache_fingerprints->{$old_fp}; I would do that later, after we successfully read the new data. > + } > + > + my $cert_path = "/etc/pve/nodes/$node/pve-ssl.pem"; > + my $custom_cert_path = "/etc/pve/nodes/$node/pveproxy-ssl.pem"; > + $cert_path = $custom_cert_path if -f $custom_cert_path; > + my $bio = Net::SSLeay::BIO_new_file($cert_path, 'r'); > + my $cert = Net::SSLeay::PEM_read_bio_X509($bio); > + Net::SSLeay::BIO_free($bio); What if any of these methods raise exceptions? > + > + my $fp = Net::SSLeay::X509_get_fingerprint($cert, 'sha256'); > + return if !defined($fp); > + > + $cert_cache_fingerprints->{$fp} = 1; > + $cert_cache_nodes->{$node} = $fp; > +} > + > +sub check_cert_fp { Please use a better name: check_cert_fingerprints() > + my ($fp) = @_; > + > + my $check = sub { > + for my $expected (keys %$cert_cache_fingerprints) { > + return 1 if $fp eq $expected; > + } > + return 0; > + }; > + > + return 1 if &$check(); > + > + # refresh cache and retry once > + update_cert_cache(); > + return &$check(); > +} > + > # server implementation > > sub log_request { > @@ -601,6 +648,28 @@ sub proxy_request { > } > } > > + my $tls = { > + # TLS 1.x only, with certificate pinning > + method => 'any', > + sslv2 => 0, > + sslv3 => 0, > + verify => 1, > + verify_cb => sub { > + my (undef, undef, undef, $depth, undef, undef, $cert) = @_; > + # we don't care about intermediate or root certificates > + return 0 if $depth != 0; > + > + # get fingerprint of server certificate > + my $fp = Net::SSLeay::X509_get_fingerprint($cert, 'sha256'); > + return 0 if !defined($fp); # error > + return check_cert_fp($fp); # check against cache of pinned FPs I would merge this code with check_cert_fp, so that we have a single method (maybe call it 'tls_verify_callback'? > + }, > + }; > + > + # load and cache cert fingerprint if first time we proxy to this node > + update_cert_cache($node) > + if defined($node) && !defined($cert_cache_nodes->{$node}); > + > my $w; $w = http_request( > $method => $target, > headers => $headers, > @@ -609,7 +678,7 @@ sub proxy_request { > proxy => undef, # avoid use of $ENV{HTTP_PROXY} > keepalive => $keep_alive, > body => $content, > - tls_ctx => $self->{tls_ctx}, > + tls_ctx => AnyEvent::TLS->new(%{$tls}), > sub { > my ($body, $hdr) = @_; > > -- > 2.1.4 > > > _______________________________________________ > pve-devel mailing list > pve-devel@pve.proxmox.com > http://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel _______________________________________________ pve-devel mailing list pve-devel@pve.proxmox.com http://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel