From c6300a3ac7a812aa1ba9582c6334a21789a106d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20R=C3=BChsen?= Date: Mon, 3 Nov 2014 11:37:02 +0100 Subject: [PATCH] * added new test Test-proxied-https-auth-keepalive.px This test similar to Test-proxied-https-auth except that his test simulates a persistent connection to the destination server. --- tests/ChangeLog | 4 + tests/Makefile.am | 1 + tests/Test-proxied-https-auth-keepalive.px | 163 +++++++++++++++++++++ 3 files changed, 168 insertions(+) create mode 100755 tests/Test-proxied-https-auth-keepalive.px diff --git a/tests/ChangeLog b/tests/ChangeLog index 3a3f65e8..4b12d7a1 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,7 @@ +2014-11-03 Tim Ruehsen + + * added new test Test-proxied-https-auth-keepalive.px + 2014-11-03 Tim Ruehsen * Test-proxied-https-auth.px: add valgrind support, diff --git a/tests/Makefile.am b/tests/Makefile.am index 58ef5b77..dad3d1c3 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -112,6 +112,7 @@ PX_TESTS = \ Test-O.px \ Test--post-file.px \ Test-proxied-https-auth.px \ + Test-proxied-https-auth-keepalive.px \ Test-proxy-auth-basic.px \ Test-restrict-ascii.px \ Test-Restrict-Lowercase.px \ diff --git a/tests/Test-proxied-https-auth-keepalive.px b/tests/Test-proxied-https-auth-keepalive.px new file mode 100755 index 00000000..349778a1 --- /dev/null +++ b/tests/Test-proxied-https-auth-keepalive.px @@ -0,0 +1,163 @@ +#!/usr/bin/env perl +# Simulate a tunneling proxy to a HTTPS URL that needs authentication. +# Use a persistent connection (Connection: keep-alive) + +use strict; +use warnings; + +use WgetFeature qw(https); +use WgetTests; # For $WGETPATH. + +my $cert_path; +my $key_path; +my $srcdir; + +if (@ARGV) { + $srcdir = shift @ARGV; +} elsif (defined $ENV{srcdir}) { + $srcdir = $ENV{srcdir}; +} + +if (defined $srcdir) { + $key_path = "$srcdir/certs/server-key.pem"; + $cert_path = "$srcdir/certs/server-cert.pem"; +} else { + $key_path = "certs/server-key.pem"; + $cert_path = "certs/server-cert.pem"; +} + + +use HTTP::Daemon; +use HTTP::Request; +use IO::Socket::SSL; + +my $SOCKET = HTTP::Daemon->new (LocalAddr => 'localhost', + ReuseAddr => 1) or die "Cannot create server!!!"; + +sub get_request { + my $conn = shift; + my $content = ''; + my $line; + + while (defined ($line = <$conn>)) { + $content .= $line; + last if $line eq "\r\n"; + } + + my $rqst = HTTP::Request->parse($content) + or die "Couldn't parse request:\n$content\n"; + + return $rqst; +} + +sub do_server { + my ($synch_callback) = @_; + my $s = $SOCKET; + my $conn; + my $rqst; + my $rspn; + + # sync with the parent + $synch_callback->(); + + # Simulate a HTTPS proxy server with tunneling. + + $conn = $s->accept; + $rqst = $conn->get_request; + die "Method not CONNECT\n" if ($rqst->method ne 'CONNECT'); + $rspn = HTTP::Response->new(200, 'OK'); + $conn->send_response($rspn); + + # Now switch from plain to SSL (for simulating a transparent tunnel + # to an HTTPS server). + + my %options = ( + SSL_server => 1, + SSL_passwd_cb => sub { return "Hello"; }); + $options{SSL_cert_file} = $cert_path if ($cert_path); + $options{SSL_key_file} = $key_path if ($key_path); + my @options = %options; + $conn = IO::Socket::SSL->new_from_fd($conn->fileno, @options) + or die "Couldn't initiate SSL"; + + for my $expect_inner_auth (0, 1) { + # TODO: expect no auth the first time, request it, expect it the second + # time. + + $rqst = &get_request($conn) + or die "Didn't get proxied request\n"; + + unless ($expect_inner_auth) { + die "Early proxied auth\n" if $rqst->header('Authorization'); + + $rspn = HTTP::Response->new(401, 'Unauthorized', [ + 'WWW-Authenticate' => 'Basic realm="gondor"', + Connection => 'keep-alive' + ]); + } else { + die "No proxied auth\n" unless $rqst->header('Authorization'); + + $rspn = HTTP::Response->new(200, 'OK', [ + 'Content-Type' => 'text/plain', + 'Connection' => 'close', + ], "foobarbaz\n"); + } + + $rspn->protocol('HTTP/1.0'); + print STDERR "=====\n"; + print STDERR $rspn->as_string; + print STDERR "\n=====\n"; + print $conn $rspn->as_string; + } + + $conn->close; + undef $conn; + undef $s; +} + +sub fork_server { + pipe(FROM_CHILD, TO_PARENT) or die "Cannot create pipe!"; + select((select(TO_PARENT), $| = 1)[0]); + + my $pid = fork(); + if ($pid < 0) { + die "Cannot fork"; + } elsif ($pid == 0) { + # child + close FROM_CHILD; + do_server(sub { print TO_PARENT "SYNC\n"; close TO_PARENT }); + exit 0; + } else { + # parent + close TO_PARENT; + chomp(my $line = ); + close FROM_CHILD; + } + + return $pid; +} + +unlink "needs-auth.txt"; +my $pid = &fork_server; + +my $cmdline = $WgetTest::WGETPATH . " --user=fiddle-dee-dee" + . " --password=Dodgson -e https_proxy=localhost:{{port}}" + . " --no-check-certificate" + . " https://no.such.domain/needs-auth.txt"; +$cmdline =~ s/{{port}}/$SOCKET->sockport()/e; + +my $valgrind = $ENV{VALGRIND_TESTS}; +if (!defined $valgrind || $valgrind eq "" || $valgrind == 0) { + # Valgrind not requested - leave $cmdline as it is +} elsif ($valgrind == 1) { + $cmdline = "valgrind --error-exitcode=301 --leak-check=yes --track-origins=yes " . $cmdline; +} else { + $cmdline = $valgrind . " " . $cmdline; +} + +my $code = system($cmdline . " 2>&1") >> 8; +unlink "needs-auth.txt"; + +warn "Got code: $code\n" if $code; +kill ('TERM', $pid); +exit ($code != 0);