X-Git-Url: https://git.proxmox.com/?p=pve-http-server.git;a=blobdiff_plain;f=src%2FPVE%2FAPIServer%2FAnyEvent.pm;h=8533c2f239db819d425b5fe462ab65f5d75be7af;hp=d38cd5ac58b3a09bbbf3386e2016876d2972c423;hb=580d540ea907ba15f64379c5bb69ecf1a49a875f;hpb=5cef57dee97ad3ca3a5307734cfbf2bd655d6e51 diff --git a/src/PVE/APIServer/AnyEvent.pm b/src/PVE/APIServer/AnyEvent.pm index d38cd5a..8533c2f 100644 --- a/src/PVE/APIServer/AnyEvent.pm +++ b/src/PVE/APIServer/AnyEvent.pm @@ -293,11 +293,18 @@ sub response { my $code = $resp->code; my $msg = $resp->message || HTTP::Status::status_message($code); - ($msg) = $msg =~m/^(.*)$/m; my $content = $resp->content; + # multiline mode only checks \n for $, so explicitly check for any \n or \r afterwards + ($msg) = $msg =~ m/^(.*)$/m; + if ($msg =~ /[\r\n]/) { + $code = 400; # bad request from user + $msg = HTTP::Status::status_message($code); + $content = ''; + } + if ($code =~ /^(1\d\d|[23]04)$/) { - # make sure content we have no content + # make sure informational, no content and not modified response send no content $content = ""; } @@ -361,6 +368,7 @@ sub response { } elsif ($delay && $delay > 0) { my $w; $w = AnyEvent->timer(after => $delay, cb => sub { undef $w; # delete reference + return if !$reqstate->{hdl}; # already disconnected $reqstate->{hdl}->push_write($res); $self->finish_response($reqstate); }); @@ -636,7 +644,8 @@ sub websocket_proxy { my $statuscode = unpack ("n", $payload); $self->dprint("websocket received close. status code: '$statuscode'"); if (my $proxyhdl = $reqstate->{proxyhdl}) { - $proxyhdl->{block_disconnect} = 1 if length $proxyhdl->{wbuf} > 0; + $proxyhdl->{block_disconnect} = 1 if length $proxyhdl->{wbuf}; + $proxyhdl->push_shutdown(); } $hdl->push_shutdown(); @@ -693,6 +702,14 @@ sub proxy_request { eval { my $target; my $keep_alive = 1; + + # stringify URI object and verify it starts with a slash + $uri = "$uri"; + if ($uri !~ m@^/@) { + $self->error($reqstate, 400, "invalid proxy uri"); + return; + } + if ($host eq 'localhost') { $target = "http://$host:85$uri"; # keep alive for localhost is not worth (connection setup is about 0.2ms) @@ -879,7 +896,7 @@ sub handle_api2_request { $params = extract_params($r, $method); } - delete $params->{_dc}; # remove disable cache parameter + delete $params->{_dc} if $params; # remove disable cache parameter my $clientip = $reqstate->{peer_host}; @@ -1252,10 +1269,11 @@ sub file_upload_multipart { } else { my $elapsed = tv_interval($rstate->{starttime}); - my $rate = int($rstate->{bytes}/($elapsed*1024*1024)); - syslog('info', "multipart upload complete " . - "(size: %d time: %ds rate: %.2fMiB/s md5sum: $rstate->{md5sum})", - $rstate->{bytes}, $elapsed, $rate); + my $rate = int($rstate->{bytes} / ($elapsed * 1024 * 1024)); + syslog('info', + "multipart upload complete (size: %d time: %ds rate: %.2fMiB/s md5sum: %s)", + $rstate->{bytes}, $elapsed, $rate, $rstate->{md5sum} + ); $self->handle_api2_request($reqstate, $auth, $method, $path, $rstate); } } @@ -1493,7 +1511,9 @@ sub unshift_read_header { outfh => $outfh, }; $reqstate->{tmpfilename} = $tmpfilename; - $reqstate->{hdl}->on_read(sub { $self->file_upload_multipart($reqstate, $auth, $method, $path, $state); }); + $reqstate->{hdl}->on_read(sub { + $self->file_upload_multipart($reqstate, $auth, $method, $path, $state); + }); return; } @@ -1884,6 +1904,9 @@ sub new { honor_cipher_order => 1, }; + # workaround until anyevent supports TLS 1.3 ciphersuites directly + my $ciphersuites = delete $self->{ssl}->{ciphersuites}; + foreach my $k (keys %$ssl_defaults) { $self->{ssl}->{$k} //= $ssl_defaults->{$k}; } @@ -1900,9 +1923,18 @@ sub new { if (delete $self->{ssl}->{honor_cipher_order}) { $tls_ctx_flags |= &Net::SSLeay::OP_CIPHER_SERVER_PREFERENCE; } + # workaround until anyevent supports disabling TLS 1.3 directly + if (exists($self->{ssl}->{tlsv1_3}) && !$self->{ssl}->{tlsv1_3}) { + $tls_ctx_flags |= &Net::SSLeay::OP_NO_TLSv1_3; + } + $self->{tls_ctx} = AnyEvent::TLS->new(%{$self->{ssl}}); Net::SSLeay::CTX_set_options($self->{tls_ctx}->{ctx}, $tls_ctx_flags); + if (defined($ciphersuites)) { + warn "Failed to set TLS 1.3 ciphersuites '$ciphersuites'\n" + if !Net::SSLeay::CTX_set_ciphersuites($self->{tls_ctx}->{ctx}, $ciphersuites); + } } if ($self->{spiceproxy}) {