use XML::Parser;
use Digest::SHA;
use Digest::HMAC_SHA1;
+use Net::SSLeay;
use PVE::Tools;
use PVE::INotify;
use PVE::IPCC;
return $exists;
}
+# X509 Certificate cache helper
+
+my $cert_cache_nodes = {};
+my $cert_cache_timestamp = time();
+my $cert_cache_fingerprints = {};
+
+sub update_cert_cache {
+ my ($update_node, $clear) = @_;
+
+ syslog('info', "Clearing outdated entries from certificate cache")
+ if $clear;
+
+ $cert_cache_timestamp = time() if !defined($update_node);
+
+ my $node_list = defined($update_node) ?
+ [ $update_node ] : [ keys %$cert_cache_nodes ];
+
+ foreach my $node (@$node_list) {
+ my $clear_old = sub {
+ if (my $old_fp = $cert_cache_nodes->{$node}) {
+ # distrust old fingerprint
+ delete $cert_cache_fingerprints->{$old_fp};
+ # ensure reload on next proxied request
+ delete $cert_cache_nodes->{$node};
+ }
+ };
+
+ 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 $cert;
+ eval {
+ my $bio = Net::SSLeay::BIO_new_file($cert_path, 'r');
+ $cert = Net::SSLeay::PEM_read_bio_X509($bio);
+ Net::SSLeay::BIO_free($bio);
+ };
+ my $err = $@;
+ if ($err || !defined($cert)) {
+ &$clear_old() if $clear;
+ next;
+ }
+
+ my $fp;
+ eval {
+ $fp = Net::SSLeay::X509_get_fingerprint($cert, 'sha256');
+ };
+ $err = $@;
+ if ($err || !defined($fp) || $fp eq '') {
+ &$clear_old() if $clear;
+ next;
+ }
+
+ my $old_fp = $cert_cache_nodes->{$node};
+ $cert_cache_fingerprints->{$fp} = 1;
+ $cert_cache_nodes->{$node} = $fp;
+
+ if (defined($old_fp) && $fp ne $old_fp) {
+ delete $cert_cache_fingerprints->{$old_fp};
+ }
+ }
+}
+
+sub check_cert_fingerprint {
+ my ($cert) = @_;
+
+ # clear cache every 30 minutes at least
+ update_cert_cache(undef, 1) if time() - $cert_cache_timestamp >= 60*30;
+
+ # get fingerprint of server certificate
+ my $fp;
+ eval {
+ $fp = Net::SSLeay::X509_get_fingerprint($cert, 'sha256');
+ };
+ return 0 if $@ || !defined($fp) || $fp eq ''; # error
+
+ my $check = sub {
+ for my $expected (keys %$cert_cache_fingerprints) {
+ return 1 if $fp eq $expected;
+ }
+ return 0;
+ };
+
+ return 1 if &$check();
+
+ # clear cache and retry at most once every minute
+ if (time() - $cert_cache_timestamp >= 60) {
+ syslog ('info', "Could not verify remote node certificate '$fp' with list of pinned certificates, refreshing cache");
+ update_cert_cache();
+ return &$check();
+ }
+
+ return 0;
+}
+
# bash completion helpers
sub complete_next_vmid {
Package: pve-cluster
Architecture: any
Pre-Depends: ${misc:Pre-Depends}
-Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, perlapi-5.20.0, rsync, libsqlite3-0, sqlite3, libfuse2 (>= 2.9.2-4), fuse, corosync-pve (>= 2.3.4-1), libqb0 (>= 0.17.1-1), libpve-common-perl, libglib2.0-0 (>= 2.42.1-1), rsyslog, openssl, librrd4, librrds-perl, rrdcached, libdigest-hmac-perl, libxml-parser-perl, systemd, faketime
+Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, perlapi-5.20.0, rsync, libsqlite3-0, sqlite3, libfuse2 (>= 2.9.2-4), fuse, corosync-pve (>= 2.3.4-1), libqb0 (>= 0.17.1-1), libpve-common-perl, libglib2.0-0 (>= 2.42.1-1), rsyslog, openssl, librrd4, librrds-perl, rrdcached, libdigest-hmac-perl, libxml-parser-perl, systemd, faketime, libcrypt-ssleay-perl
Description: Cluster Infrastructure for Proxmox Virtual Environment
This package contains the Cluster Infrastructure for the Proxmox
Virtual Environment, namely a distributed filesystem to store