X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=PVE%2FAPIServer%2FAnyEvent.pm;h=2e8ca47ca51d9c789dcec0c03b9c31d3073373f4;hb=4a09623bbdb4306ca00685a0f80ce6f05fa42f3b;hp=54e1db8fbdac0fb85e6a5882326ca75242ce9850;hpb=a4d8bbafbe400be78bebeab169963025dc46e29b;p=pve-http-server.git diff --git a/PVE/APIServer/AnyEvent.pm b/PVE/APIServer/AnyEvent.pm old mode 100755 new mode 100644 index 54e1db8..2e8ca47 --- a/PVE/APIServer/AnyEvent.pm +++ b/PVE/APIServer/AnyEvent.pm @@ -184,6 +184,7 @@ sub response { $reqstate->{hdl}->timeout_reset(); $reqstate->{hdl}->timeout($self->{timeout}); + $nocomp = 1 if !$self->{compression}; $nocomp = 1 if !$reqstate->{accept_gzip}; my $code = $resp->code; @@ -552,7 +553,11 @@ sub proxy_request { $headers->{'cookie'} = PVE::APIServer::Formatter::create_auth_cookie($ticket, $self->{cookie_name}) if $ticket; $headers->{'CSRFPreventionToken'} = $token if $token; - $headers->{'Accept-Encoding'} = 'gzip' if $reqstate->{accept_gzip}; + $headers->{'Accept-Encoding'} = 'gzip' if ($reqstate->{accept_gzip} && $self->{compression}); + + if (defined(my $host = $reqstate->{request}->header('Host'))) { + $headers->{Host} = $host; + } my $content; @@ -573,6 +578,9 @@ sub proxy_request { sslv2 => 0, sslv3 => 0, verify => 1, + # be compatible with openssl 1.1, fix for debian bug #923615 + # remove once libanyeven-perl with this fix transitions to buster + dh => 'schmorp2048', verify_cb => sub { my (undef, undef, undef, $depth, undef, undef, $cert) = @_; # we don't care about intermediate or root certificates @@ -637,16 +645,19 @@ sub decode_urlencoded { my ($k, $v) = split(/=/, $kv); $k =~s/\+/ /g; $k =~ s/%([0-9a-fA-F][0-9a-fA-F])/chr(hex($1))/eg; - $v =~s/\+/ /g; - $v =~ s/%([0-9a-fA-F][0-9a-fA-F])/chr(hex($1))/eg; - $v = Encode::decode('utf8', $v); + if (defined($v)) { + $v =~s/\+/ /g; + $v =~ s/%([0-9a-fA-F][0-9a-fA-F])/chr(hex($1))/eg; - if (defined(my $old = $res->{$k})) { - $res->{$k} = "$old\0$v"; - } else { - $res->{$k} = $v; + $v = Encode::decode('utf8', $v); + + if (defined(my $old = $res->{$k})) { + $v = "$old\0$v"; + } } + + $res->{$k} = $v; } return $res; } @@ -890,7 +901,10 @@ sub handle_spice_proxy_request { my ($hdl, $line) = @_; if ($line =~ m!^$proto 200 OK$!) { - &$startproxy(); + # read the empty line after the 200 OK + $reqstate->{proxyhdl}->unshift_read(line => sub{ + &$startproxy(); + }); } else { $reqstate->{hdl}->push_write($line); $self->client_do_disconnect($reqstate); @@ -1187,11 +1201,16 @@ sub unshift_read_header { my $len = $r->header('Content-Length'); + my $host_header = $r->header('Host'); + if (my $rpcenv = $self->{rpcenv}) { + $rpcenv->set_request_host($host_header); + } + # header processing complete - authenticate now my $auth = {}; if ($self->{spiceproxy}) { - my $connect_str = $r->header('Host'); + my $connect_str = $host_header; my ($vmid, $node, $port) = $self->verify_spice_connect_url($connect_str); if (!(defined($vmid) && $node && $port)) { $self->error($reqstate, HTTP_UNAUTHORIZED, "invalid ticket"); @@ -1608,6 +1627,7 @@ sub new { $self->{base_uri} //= "/api2"; $self->{dirs} //= {}; $self->{title} //= 'API Inspector'; + $self->{compression} //= 1; # formatter_config: we pass some configuration values to the Formatter $self->{formatter_config} = {}; @@ -1618,10 +1638,11 @@ sub new { $self->can('generate_csrf_prevention_token'); # add default dirs which includes jquery and bootstrap - my $base = '/usr/share/libpve-http-server-perl'; - add_dirs($self->{dirs}, '/css/' => "$base/css/"); - add_dirs($self->{dirs}, '/js/' => "$base/js/"); - add_dirs($self->{dirs}, '/fonts/' => "$base/fonts/"); + my $jsbase = '/usr/share/javascript'; + add_dirs($self->{dirs}, '/js/' => "$jsbase/"); + # libjs-bootstrap uses symlinks for this, which we do not want to allow.. + my $glyphicons = '/usr/share/fonts/truetype/glyphicons/'; + add_dirs($self->{dirs}, '/js/bootstrap/fonts/' => "$glyphicons"); # init inotify PVE::INotify::inotify_init(); @@ -1641,8 +1662,31 @@ sub new { $self->{end_cond} = AnyEvent->condvar; if ($self->{ssl}) { + my $ssl_defaults = { + # Note: older versions are considered insecure, for example + # search for "Poodle"-Attack + method => 'any', + sslv2 => 0, + sslv3 => 0, + cipher_list => 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256', + honor_cipher_order => 1, + }; + + foreach my $k (keys %$ssl_defaults) { + $self->{ssl}->{$k} //= $ssl_defaults->{$k}; + } + + if (!defined($self->{ssl}->{dh_file})) { + $self->{ssl}->{dh} = 'skip2048'; + } + + my $tls_ctx_flags = &Net::SSLeay::OP_NO_COMPRESSION | &Net::SSLeay::OP_SINGLE_ECDH_USE | &Net::SSLeay::OP_SINGLE_DH_USE; + if ( delete $self->{ssl}->{honor_cipher_order} ) { + $tls_ctx_flags |= &Net::SSLeay::OP_CIPHER_SERVER_PREFERENCE; + } + $self->{tls_ctx} = AnyEvent::TLS->new(%{$self->{ssl}}); - Net::SSLeay::CTX_set_options($self->{tls_ctx}->{ctx}, &Net::SSLeay::OP_NO_COMPRESSION | &Net::SSLeay::OP_SINGLE_ECDH_USE | &Net::SSLeay::OP_SINGLE_DH_USE); + Net::SSLeay::CTX_set_options($self->{tls_ctx}->{ctx}, $tls_ctx_flags); } if ($self->{spiceproxy}) {