diff --git a/CVE-2022-31081-2.patch b/CVE-2022-31081-2.patch deleted file mode 100644 index 81faa40..0000000 --- a/CVE-2022-31081-2.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 8dc5269d59e2d5d9eb1647d82c449ccd880f7fd0 Mon Sep 17 00:00:00 2001 -From: Theo van Hoesel -Date: Tue, 21 Jun 2022 20:00:47 +0000 -Subject: [PATCH] Include reason in response body content - ---- - lib/HTTP/Daemon.pm | 10 ++++++---- - 1 file changed, 6 insertions(+), 4 deletions(-) - -diff --git a/lib/HTTP/Daemon.pm b/lib/HTTP/Daemon.pm -index a5112b3..2d022ae 100644 ---- a/lib/HTTP/Daemon.pm -+++ b/lib/HTTP/Daemon.pm -@@ -299,16 +299,18 @@ READ_HEADER: - # check that they are all numbers (RFC: Content-Length = 1*DIGIT) - my @nums = grep { /^[0-9]+$/} @vals; - unless (@vals == @nums) { -- $self->send_error(400); -- $self->reason("Content-Length value must be a unsigned integer"); -+ my $reason = "Content-Length value must be an unsigned integer"; -+ $self->send_error(400, $reason); -+ $self->reason($reason); - return; - } - # check they are all the same - my $len = shift @nums; - foreach (@nums) { - next if $_ == $len; -- $self->send_error(400); -- $self->reason("Content-Length values are not the same"); -+ my $reason = "Content-Length values are not the same"; -+ $self->send_error(400, $reason); -+ $self->reason($reason); - return; - } - # ensure we have now a fixed header, with only 1 value diff --git a/CVE-2022-31081-Add-new-test-for-Content-Length-issues.patch b/CVE-2022-31081-Add-new-test-for-Content-Length-issues.patch deleted file mode 100644 index a628cc2..0000000 --- a/CVE-2022-31081-Add-new-test-for-Content-Length-issues.patch +++ /dev/null @@ -1,312 +0,0 @@ -From faebad54455c2c2919e234202362570925fb99d1 Mon Sep 17 00:00:00 2001 -From: Theo van Hoesel -Date: Tue, 21 Jun 2022 20:30:36 +0000 -Subject: [PATCH] Add new test for Content-Length issues - -prove we fixed CVE-2022-31081 - -From 211a29732760c9887c15e8dc344e15cf8cdf2807 Mon Sep 17 00:00:00 2001 -From: Theo van Hoesel -Date: Mon, 27 Jun 2022 22:42:31 +0200 -Subject: [PATCH 1/3] Fix tests to match with correct grammar in error message - -From 2b7fd55a55313b6f04c92fbfee6458d1f7b908fd Mon Sep 17 00:00:00 2001 -From: Theo van Hoesel -Date: Mon, 27 Jun 2022 22:44:11 +0200 -Subject: [PATCH 2/3] Remove warnings about Subroutine write_content_body - redefined - -From cfa63717a3aeedf6aaec16c4091098c05c2d7e01 Mon Sep 17 00:00:00 2001 -From: Theo van Hoesel -Date: Mon, 27 Jun 2022 23:33:05 +0200 -Subject: [PATCH 3/3] Send some body to see what we get returned ---- - t/content_length.t | 282 +++++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 282 insertions(+) - create mode 100644 t/content_length.t - ---- /dev/null -+++ b/t/content_length.t -@@ -0,0 +1,282 @@ -+use strict; -+use warnings; -+ -+use Test::More 0.98; -+ -+use Config; -+ -+use HTTP::Daemon; -+use HTTP::Response; -+use HTTP::Status; -+use HTTP::Tiny 0.042; -+ -+patch_http_tiny(); # do not fix Content-Length, we want to forge something bad -+ -+plan skip_all => "This system cannot fork" unless can_fork(); -+ -+my $BASE_URL; -+my @TESTS = get_tests(); -+ -+for my $test (@TESTS) { -+ -+ my $http_daemon = HTTP::Daemon->new() or die "HTTP::Daemon->new: $!"; -+ $BASE_URL = $http_daemon->url; -+ -+ my $pid = fork; -+ die "fork: $!" if !defined $pid; -+ if ($pid == 0) { -+ accept_requests($http_daemon); -+ } -+ -+ my $resp = http_test_request($test); -+ -+ ok $resp, $test->{title}; -+ -+ is $resp->{status}, $test->{status}, -+ "... and has expected status"; -+ -+ like $resp->{content}, $test->{like}, -+ "... and body does match" -+ if $test->{like}; -+ -+} -+ -+done_testing; -+ -+ -+ -+sub get_tests{ -+ { -+ title => "Hello World Request ... it works as expected", -+ path => "hello-world", -+ status => 200, -+ like => qr/^Hello World$/, -+ }, -+ { -+ title => "Positive Content Length", -+ method => "POST", -+ body => "ABCDEFGH", -+ headers => { -+ 'Content-Length' => '+6', # quotes are needed to retain plus-sign -+ }, -+ status => 400, -+ like => qr/value must be an unsigned integer/, -+ }, -+ { -+ title => "Negative Content Length", -+ method => "POST", -+ body => "ABCDEFGH", -+ headers => { -+ 'Content-Length' => '-5', -+ }, -+ status => 400, -+ like => qr/value must be an unsigned integer/, -+ }, -+ { -+ title => "Non Integer Content Length", -+ method => "POST", -+ body => "ABCDEFGH", -+ headers => { -+ 'Content-Length' => '3.14', -+ }, -+ status => 400, -+ like => qr/value must be an unsigned integer/, -+ }, -+ { -+ title => "Explicit Content Length ... with exact length", -+ method => "POST", -+ headers => { -+ 'Content-Length' => '8', -+ }, -+ body => "ABCDEFGH", -+ status => 200, -+ like => qr/^ABCDEFGH$/, -+ }, -+ { -+ title => "Implicit Content Length ... will always pass", -+ method => "POST", -+ body => "ABCDEFGH", -+ status => 200, -+ like => qr/^ABCDEFGH$/, -+ }, -+ { -+ title => "Shorter Content Length ... gets truncated", -+ method => "POST", -+ headers => { -+ 'Content-Length' => '4', -+ }, -+ body => "ABCDEFGH", -+ status => 200, -+ like => qr/^ABCD$/, -+ }, -+ { -+ title => "Different Content Length ... must fail", -+ method => "POST", -+ headers => { -+ 'Content-Length' => ['8', '4'], -+ }, -+ body => "ABCDEFGH", -+ status => 400, -+ like => qr/values are not the same/, -+ }, -+ { -+ title => "Underscore Content Length ... must match", -+ method => "POST", -+ headers => { -+ 'Content_Length' => '4', -+ }, -+ body => "ABCDEFGH", -+ status => 400, -+ like => qr/values are not the same/, -+ }, -+ { -+ title => "Longer Content Length ... gets timeout", -+ method => "POST", -+ headers => { -+ 'Content-Length' => '9', -+ }, -+ body => "ABCDEFGH", -+ status => 599, # silly code !!! -+ like => qr/^Timeout/, -+ }, -+ -+} -+ -+ -+ -+sub router_table { -+ { -+ '/hello-world' => { -+ 'GET' => sub { -+ my $resp = HTTP::Response->new(200); -+ $resp->content('Hello World'); -+ return $resp; -+ }, -+ }, -+ -+ '/' => { -+ 'POST' => sub { -+ my $rqst = shift; -+ -+ my $body = $rqst->content(); -+ -+ my $resp = HTTP::Response->new(200); -+ $resp->content($body); -+ -+ return $resp -+ }, -+ }, -+ } -+} -+ -+ -+ -+sub can_fork { -+ $Config{d_fork} || (($^O eq 'MSWin32' || $^O eq 'NetWare') -+ and $Config{useithreads} -+ and $Config{ccflags} =~ /-DPERL_IMPLICIT_SYS/); -+} -+ -+ -+ -+# run the mini HTTP dispatcher that can handle various routes / methods -+sub accept_requests{ -+ my $http_daemon = shift; -+ while (my $conn = $http_daemon->accept) { -+ while (my $rqst = $conn->get_request) { -+ if (my $resp = dispatch_request($rqst)) { -+ $conn->send_response($resp); -+ } -+ } -+ $conn->close; -+ undef($conn); -+ $http_daemon->close; -+ exit 1; -+ } -+} -+ -+ -+ -+sub dispatch_request{ -+ my $rqst = shift -+ or return; -+ my $path = $rqst->uri->path -+ or return; -+ my $meth = $rqst->method -+ or return; -+ my $code = router_table()->{$path}{$meth} -+ or return HTTP::Response->new(RC_NOT_FOUND); -+ my $resp = $code->($rqst); -+ return $resp; -+} -+ -+ -+ -+sub http_test_request { -+ my $test = shift; -+ my $http_client = HTTP::Tiny->new( -+ timeout => 5, -+ proxy => undef, -+ http_proxy => undef, -+ https_proxy => undef, -+ ); -+ my $resp; -+ eval { -+ local $SIG{ALRM} = sub { die "Timeout\n" }; -+ alarm 2; -+ $resp = $http_client->request( -+ $test->{method} || "GET", -+ $BASE_URL . ($test->{path} || ""), -+ { -+ headers => $test->{headers}, -+ content => $test->{body} -+ }, -+ ); -+ }; -+ my $err = $@; -+ alarm 0; -+ diag $err if $err; -+ -+ return $resp -+} -+ -+ -+ -+sub patch_http_tiny { -+ -+ # we need to patch write_content_body -+ # this is part of HTTP::Tiny internal module HTTP::Tiny::Handle -+ # -+ # the below code is from the original HTTP::Tiny module, where just two lines -+ # have been commented out -+ -+ no strict 'refs'; -+ no warnings; -+ -+ *HTTP::Tiny::Handle::write_content_body = sub { -+ @_ == 2 || die(q/Usage: $handle->write_content_body(request)/ . "\n"); -+ my ($self, $request) = @_; -+ -+ my ($len, $content_length) = (0, $request->{headers}{'content-length'}); -+ while () { -+ my $data = $request->{cb}->(); -+ -+ defined $data && length $data -+ or last; -+ -+ if ( $] ge '5.008' ) { -+ utf8::downgrade($data, 1) -+ or die(qq/Wide character in write_content()\n/); -+ } -+ -+ $len += $self->write($data); -+ } -+ -+# this should not be checked during our tests, we want to forge bad requests -+# -+# $len == $content_length -+# or die(qq/Content-Length mismatch (got: $len expected: $content_length)\n/); -+ -+ return $len; -+ }; -+} diff --git a/CVE-2022-31081.patch b/CVE-2022-31081.patch deleted file mode 100644 index dfd212e..0000000 --- a/CVE-2022-31081.patch +++ /dev/null @@ -1,50 +0,0 @@ -From e84475de51d6fd7b29354a997413472a99db70b2 Mon Sep 17 00:00:00 2001 -From: Theo van Hoesel -Date: Thu, 16 Jun 2022 08:28:30 +0000 -Subject: [PATCH] Fix Content-Length ', '-separated string issues - -After a security issue, we ensure we comply to -RFC-7230 -- HTTP/1.1 Message Syntax and Routing -- section 3.3.2 -- Content-Length -- section 3.3.3 -- Message Body Length ---- - lib/HTTP/Daemon.pm | 26 ++++++++++++++++++++++++++ - 1 file changed, 26 insertions(+) - -diff --git a/lib/HTTP/Daemon.pm b/lib/HTTP/Daemon.pm -index c0cdf76..a5112b3 100644 ---- a/lib/HTTP/Daemon.pm -+++ b/lib/HTTP/Daemon.pm -@@ -288,6 +288,32 @@ READ_HEADER: - } - elsif ($len) { - -+ # After a security issue, we ensure we comply to -+ # RFC-7230 -- HTTP/1.1 Message Syntax and Routing -+ # section 3.3.2 -- Content-Length -+ # section 3.3.3 -- Message Body Length -+ -+ # split and clean up Content-Length ', ' separated string -+ my @vals = map {my $str = $_; $str =~ s/^\s+//; $str =~ s/\s+$//; $str } -+ split ',', $len; -+ # check that they are all numbers (RFC: Content-Length = 1*DIGIT) -+ my @nums = grep { /^[0-9]+$/} @vals; -+ unless (@vals == @nums) { -+ $self->send_error(400); -+ $self->reason("Content-Length value must be a unsigned integer"); -+ return; -+ } -+ # check they are all the same -+ my $len = shift @nums; -+ foreach (@nums) { -+ next if $_ == $len; -+ $self->send_error(400); -+ $self->reason("Content-Length values are not the same"); -+ return; -+ } -+ # ensure we have now a fixed header, with only 1 value -+ $r->header('Content-Length' => $len); -+ - # Plain body specified by "Content-Length" - my $missing = $len - length($buf); - while ($missing > 0) { diff --git a/HTTP-Daemon-6.14.tar.gz b/HTTP-Daemon-6.14.tar.gz deleted file mode 100644 index 001ce59..0000000 --- a/HTTP-Daemon-6.14.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f0767e7f3cbb80b21313c761f07ad8ed253bce9fa2d0ba806b3fb72d309b2e1d -size 46940 diff --git a/HTTP-Daemon-6.16.tar.gz b/HTTP-Daemon-6.16.tar.gz new file mode 100644 index 0000000..0b2d210 --- /dev/null +++ b/HTTP-Daemon-6.16.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b38d092725e6fa4e0c4dc2a47e157070491bafa0dbe16c78a358e806aa7e173d +size 45830 diff --git a/perl-HTTP-Daemon.changes b/perl-HTTP-Daemon.changes index 013af6c..bc6cc5c 100644 --- a/perl-HTTP-Daemon.changes +++ b/perl-HTTP-Daemon.changes @@ -1,3 +1,31 @@ +------------------------------------------------------------------- +Thu Mar 9 16:44:14 UTC 2023 - Tina Müller + +- Remove patches + - CVE-2022-31081-2.patch + - CVE-2022-31081-Add-new-test-for-Content-Length-issues.patch + - CVE-2022-31081.patch + They were fixed upstream (bsc#1201157) + +------------------------------------------------------------------- +Sat Feb 25 03:06:35 UTC 2023 - Tina Müller + +- updated to 6.16 + see /usr/share/doc/packages/perl-HTTP-Daemon/Changes + + 6.16 2023-02-24 03:07:14Z + - Bump LWP::UserAgent to 6.37 in TestSuggests (GH#65) (Olaf Alders) + + 6.15 2023-02-22 22:02:46Z + - Fix CVE-2022-31081: Inconsistent Interpretation of HTTP Requests + Correctly handle multiple Content-Length headers and its variants + (Theo van Hoesel) + Closes "Discrepancies in the Parsing of Content Length header ..." (GH#56) + (blessingcharles) + - kill test server with KILL rather than QUIT (GH#63) (Graham Knop) + - Create TestServer test lib for running daemon process (GH#62) (Graham Knop) + - Clean up tests (GH#61) (Graham Knop) + ------------------------------------------------------------------- Wed Jul 13 09:04:49 UTC 2022 - Otto Hollmann diff --git a/perl-HTTP-Daemon.spec b/perl-HTTP-Daemon.spec index fc40853..376923a 100644 --- a/perl-HTTP-Daemon.spec +++ b/perl-HTTP-Daemon.spec @@ -1,7 +1,7 @@ # # spec file for package perl-HTTP-Daemon # -# Copyright (c) 2022 SUSE LLC +# Copyright (c) 2023 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,18 +18,13 @@ %define cpan_name HTTP-Daemon Name: perl-HTTP-Daemon -Version: 6.14 +Version: 6.16 Release: 0 -Summary: Simple http server class License: Artistic-1.0 OR GPL-1.0-or-later +Summary: Simple http server class URL: https://metacpan.org/release/%{cpan_name} Source0: https://cpan.metacpan.org/authors/id/O/OA/OALDERS/%{cpan_name}-%{version}.tar.gz Source1: cpanspec.yml -# PATCH-FIX-SECURITY bsc#1201157 otto.hollmann@suse.com -# Fix request smuggling in HTTP::Daemon -Patch0: CVE-2022-31081.patch -Patch1: CVE-2022-31081-2.patch -Patch2: CVE-2022-31081-Add-new-test-for-Content-Length-issues.patch BuildArch: noarch BuildRequires: perl BuildRequires: perl-macros @@ -37,14 +32,12 @@ BuildRequires: perl(HTTP::Date) >= 6 BuildRequires: perl(HTTP::Request) >= 6 BuildRequires: perl(HTTP::Response) >= 6 BuildRequires: perl(HTTP::Status) >= 6 -BuildRequires: perl(HTTP::Tiny) >= 0.042 BuildRequires: perl(IO::Socket::IP) >= 0.32 BuildRequires: perl(LWP::MediaTypes) >= 6 BuildRequires: perl(Module::Build::Tiny) >= 0.034 BuildRequires: perl(Module::Metadata) BuildRequires: perl(Test::More) >= 0.98 BuildRequires: perl(Test::Needs) -BuildRequires: perl(URI) Requires: perl(HTTP::Date) >= 6 Requires: perl(HTTP::Request) >= 6 Requires: perl(HTTP::Response) >= 6 @@ -70,8 +63,7 @@ method on this object will read data from the client and return an back various responses. %prep -%autosetup -n %{cpan_name}-%{version} -p1 -find . -type f ! -path "*/t/*" ! -name "*.pl" ! -path "*/bin/*" ! -path "*/script/*" ! -name "configure" -print0 | xargs -0 chmod 644 +%autosetup -n %{cpan_name}-%{version} %build perl Build.PL --installdirs=vendor