Apache-Test

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

=head1 CHANGES

=over 3

=item 1.43 Nov 7 2021

Our implementation of "which" should not search
for a program in the elements of PATH when program
already contains a path. [rjung]

Fix hash generation when the openssl command
was overwritten with the environment variable
"APACHE_TEST_OPENSSL_CMD". [rjung]

Add new config option limitrequestline needed
when the local directory paths are long. [rjung]

=item 1.42 Aug 28 2019

Fix loading apache_test_config.pm for recent perls in which '.' is
no longer in @INC by default. [Steve Hay]

=item 1.41 Jul 11 2019

Set DefaultStateDir for > 2.5.1 and add -t_state to override. [jorton]

Inherit config via IncludeOptional as well as Include. [jorton]

Increase size of MinSpare, MaxSpare and MaxClients to improve httpd test
framework runs with worker and preform MPMs. [rjung]

Changed the openssl version detection to work with other *SSL libraries.
[icing]

Switch test framework from using Net::SSL for
raw TLS sockets to IO::Socket::SSL. [rjung]

Fix mod_ssl tests under OpenSSL 1.1.1 / TLSv1.3. [jorton]

Add cwd to generated lib path in TEST script since Perl >=5.26 don't
do that any more. [jorton]

Override loglevel to trace8 if running in 2.4. [covener]

Allow an empty PREFIX. [sf]

Add need_min_apache_fix(). [covener]

=item 1.40 Sep 6 2016

Specify licence (Apache 2.0) in META.yml. [Steve Hay, CPAN RT#111359]

Fix broken POD. [Steve Hay]

Switch argument order in "openssl gendsa". [rjung]

Add (limited) checks for *_SAN_*_n and *_DN_Email variables. [kbrand]

Update key sizes and message digest to what is common in 2015. [kbrand]

=item 1.39 Apr 21 2015

Test scripts can now test if perl has a fork() implementation available by
using the Apache::Test::need_fork() function. [Steve Hay]

Changes  view on Meta::CPAN

caused them. [Stas]

Apache::TestSmoke now scans for core files, just like Apache::TestRun
does [Stas]

Allow the creation of name based virtual hosts by supplying
<VirtualHost servername:module> containers in .conf.in$ files.
[André Malo]

fix Apache::TestSSLCA to generate a separate index.txt file for each
module, as on certain platforms openssl fails to re-use the same
file. [Stas]

remove the unused example section from t/conf/extra.conf.in, it made
an assumption that mod_auth is available [Stas]

in the autogenerated t/conf/httpd.conf include mod_alias and mod_mime
loading, in case they were built as a shared object and wasn't loaded
from the system-wide httpd.conf from which Apache::Test inherits the
config. [Stas]

LICENSE  view on Meta::CPAN

      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing

README  view on Meta::CPAN

% t/TEST -trace=warning
the available modes are:
  emerg alert crit error warning notice info debug

turn on -v and LWP trace (1 is the default) mode in Apache::TestRequest
% t/TEST -d lwp t/modules/access.t

turn on -v and LWP trace mode (level 2) in Apache::TestRequest
% t/TEST -d lwp=2 t/modules/access.t

run all tests through mod_ssl
% t/TEST -ssl

run all tests with HTTP/1.1 (keep alive) requests
% t/TEST -http11 -ssl

run all tests with HTTP/1.1 (keep alive) requests through mod_ssl
% t/TEST -http11

run all tests through mod_proxy
% t/TEST -proxy



##################
# Stress testing #
##################

lib/Apache/Test.pm  view on Meta::CPAN

}

use vars qw(@ISA @EXPORT %EXPORT_TAGS $VERSION %SubTests @SkipReasons);

$VERSION = '1.43';

my @need = qw(need_lwp need_http11 need_cgi need_access need_auth
              need_module need_apache need_min_apache_version need_min_apache_fix
              need_apache_version need_perl need_min_perl_version
              need_min_module_version need_threads need_fork need_apache_mpm
              need_php need_php4 need_ssl need_imagemap need_cache_disk);

my @have = map { (my $need = $_) =~ s/need/have/; $need } @need;

@ISA = qw(Exporter);
@EXPORT = (qw(sok plan skip_reason under_construction need),
           @need, @have);

%SubTests = ();
@SkipReasons = ();

lib/Apache/Test.pm  view on Meta::CPAN

    if (Apache::TestRequest::install_http11()) {
        return 1;
    }
    else {
        push @SkipReasons,
           "LWP version 5.60+ required for HTTP/1.1 support";
        return 0;
    }
}

sub need_ssl {
    my $vars = vars();
    need_module([$vars->{ssl_module_name}, 'IO::Socket::SSL']);
}

sub need_lwp {
    require Apache::TestRequest;
    if (Apache::TestRequest::has_lwp()) {
        return 1;
    }
    else {
        push @SkipReasons, "libwww-perl is not installed";
        return 0;

lib/Apache/Test.pm  view on Meta::CPAN

server versions.

=over

=item need_http11

  plan tests => 5, need_http11;

Require HTTP/1.1 support.

=item need_ssl

  plan tests => 5, need_ssl;

Require SSL support.

Not exported by default.

=item need_lwp

  plan tests => 5, need_lwp;

Require LWP support.

lib/Apache/TestBuild.pm  view on Meta::CPAN

    require Apache::TestConfig;
    require Apache::TestTrace;
    Apache::TestTrace->import;

    my $self = bless {
        prefix => '/usr/local/apache',
        cwd => Cwd::cwd(),
        cvsroot => 'cvs.apache.org:/home/cvs',
        cvs => \@cvs,
        cvstag => "",
        ssldir => "",
        mpms => default_mpms(),
        make => $Config{make},
        builds => {},
        name => "",
        extra_config => {
            'httpd-2.0' => [],
        },
        @_,
    }, $class;

    #XXX
    if (my $c = $self->{extra_config}->{'2.0'}) {
        $self->{extra_config}->{'httpd-2.0'} = $c;
    }

    for my $dir (@dirs) {
        $self->default_dir($dir);
    }

    if ($self->{ssldir}) {
        push @{ $self->{extra_config}->{'httpd-2.0'} },
          '--enable-ssl', "--with-ssl=$self->{ssldir}";
    }

    $self;
}

sub init {
    my $self = shift;

    for my $dir (@dirs) {
        mkpath($self->{$dir});

lib/Apache/TestBuild.pm  view on Meta::CPAN

    my $name = join '-', $mpm, @$builds, @$configs;

    if (my $tag = $self->cvs_name) {
        $name .= "-$tag";
    }

    $name;
}

#currently the httpd-2.0 build does not properly support static linking
#of ssl libs, force the issue
sub add_ssl_libs {
    my $self = shift;

    my $ssldir = $self->{ssldir};

    return unless $ssldir and -d $ssldir;

    my $name = $self->{current_install_name};

    my $ssl_mod = "$name/modules/ssl";
    info "editing $ssl_mod/modules.mk";

    if (DRYRUN) {
        return;
    }

    my $ssl_mk = "$self->{build}/$ssl_mod/modules.mk";

    open my $fh, $ssl_mk or die "open $ssl_mk: $!";
    my @lines = <$fh>;
    close $fh;

    for (@lines) {
        next unless /SH_LINK/;
        chomp;
        $_ .= " -L$ssldir -lssl -lcrypto\n";
        info 'added ssl libs';
        last;
    }

    open $fh, '>', $ssl_mk or die $!;
    print $fh join "\n", @lines;
    close $fh;
}

sub cvs_name {
    my $self = shift;

    if (my $tag = $self->{cvstag}) {
        $tag =~ s/^-[DAr]//;
        $tag =~ s/\"//g;

lib/Apache/TestBuild.pm  view on Meta::CPAN

    }

    system $cmd;

    open FH, ">.DONE" or die "open .DONE: $!";
    print FH scalar localtime;
    close FH;

    chdir $self->{prefix};

    $self->add_ssl_libs;
}

sub make {
    my($self, @cmds) = @_;

    push @cmds, 'all' unless @cmds;

    for my $name (keys %{ $self->{builds} }) {
        chdir "$self->{build}/$name";
        for my $cmd (@cmds) {

lib/Apache/TestBuild.pm  view on Meta::CPAN

use strict;
use warnings FATAL => 'all';

use lib qw(Apache-Test/lib);
use Apache::TestBuild ();
use Getopt::Long qw(GetOptions);
use Cwd ();

my %options = (
    prefix  => "checkout/build/install prefix",
    ssldir  => "enable ssl with given directory",
    cvstag  => "checkout with given cvs tag",
    cvsroot => "use 'anon' for anonymous cvs",
    version => "apache version (e.g. '2.0')",
    mpms    => "MPMs to build (e.g. 'prefork')",
    flavor  => "build flavor (e.g. 'debug shared')",
    modules => "enable modules (e.g. 'all exp')",
    name    => "change name of the build/install directory",
);

my %opts;

lib/Apache/TestBuild.pm  view on Meta::CPAN

#XXX: could be smarter here, being lazy for the moment
GetOptions(\%opts, map "$_=s", sort keys %options);

if (@ARGV) {
    print "passing extra args to configure: @ARGV\n";
}

my $home = $ENV{HOME};

$opts{prefix}  ||= join '/', Cwd::cwd(), 'farm';
#$opts{ssldir}  ||= '';
#$opts{cvstag}  ||= '';
#$opts{cvsroot} ||= '';
$opts{version} ||= '2.0';
$opts{mpms}    ||= 'prefork';
$opts{flavor}  ||= 'debug-shared';
$opts{modules} ||= 'all-exp';

#my @versions = qw(2.0);

#my @mpms = qw(prefork worker perchild);

lib/Apache/TestConfig.pm  view on Meta::CPAN

   target           => 'name of server binary (default is apxs -q TARGET)',
   apxs             => 'location of apxs (default is from Apache2::BuildConfig)',
   startup_timeout  => 'seconds to wait for the server to start (default is 60)',
   httpd_conf       => 'inherit config from this file (default is apxs derived)',
   httpd_conf_extra => 'inherit additional config from this file',
   minclients       => 'minimum number of concurrent clients (default is 1)',
   maxclients       => 'maximum number of concurrent clients (default is minclients+1)',
   threadsperchild  => 'number of threads per child when using threaded MPMs (default is 10)',
   limitrequestline => 'global LimitRequestLine setting (default is 128)',
   perlpod          => 'location of perl pod documents (for testing downloads)',
   proxyssl_url     => 'url for testing ProxyPass / https (default is localhost)',
   sslca            => 'location of SSL CA (default is $t_conf/ssl/ca)',
   sslcaorg         => 'SSL CA organization to use for tests (default is asf)',
   sslproto         => 'SSL/TLS protocol version(s) to test',
   libmodperl       => 'path to mod_perl\'s .so (full or relative to LIBEXECDIR)',
   defines          => 'values to add as -D defines (for example, "VAR1 VAR2")',
   (map { $_ . '_module_name', "$_ module name"} qw(cgi ssl thread access auth php)),
);

my %filepath_conf_opts = map { $_ => 1 }
    qw(top_dir t_dir t_conf t_logs t_state t_pid_file t_conf_file src_dir serverroot
       documentroot bindir sbindir httpd apxs httpd_conf httpd_conf_extra
       perlpod sslca libmodperl);

sub conf_opt_is_a_filepath {
    my $opt = shift;
    $opt && exists $filepath_conf_opts{$opt};
}

sub usage {
    for my $hash (\%Usage) {
        for (sort keys %$hash){
            printf "  -%-18s %s\n", $_, $hash->{$_};

lib/Apache/TestConfig.pm  view on Meta::CPAN

    	}
    }

    $vars->{t_dir}        ||= catfile $vars->{top_dir}, 't';
    $vars->{serverroot}   ||= $vars->{t_dir};
    $vars->{documentroot} ||= catfile $vars->{serverroot}, 'htdocs';
    $vars->{perlpod}      ||= $self->find_in_inc('pods') ||
                              $self->find_in_inc('pod');
    $vars->{perl}         ||= $^X;
    $vars->{t_conf}       ||= catfile $vars->{serverroot}, 'conf';
    $vars->{sslca}        ||= catfile $vars->{t_conf}, 'ssl', 'ca';
    $vars->{sslcaorg}     ||= 'asf';

    if (!defined($vars->{sslproto}) and eval { require Apache::TestSSLCA; 1; }) {
        $vars->{sslproto} = Apache::TestSSLCA::sslproto();
    }
    else {
        $vars->{sslproto} ||= 'all';
    }

    $vars->{t_logs}       ||= catfile $vars->{serverroot}, 'logs';
    $vars->{t_state}      ||= catfile $vars->{serverroot}, 'state';
    $vars->{t_conf_file}  ||= catfile $vars->{t_conf},   'httpd.conf';
    $vars->{t_pid_file}   ||= catfile $vars->{t_logs},   'httpd.pid';

    if (WINFU) {
        for (keys %$vars) {
            $vars->{$_} =~ s|\\|\/|g if defined $vars->{$_};

lib/Apache/TestConfig.pm  view on Meta::CPAN

        $vars->{maxsparethreadedmpm} = 2 * $vars->{threadsperchild};
    }
    if ($vars->{maxclientsthreadedmpm} < $vars->{maxsparethreadedmpm} + $vars->{threadsperchild}) {
        $vars->{maxclientsthreadedmpm} = $vars->{maxsparethreadedmpm} + $vars->{threadsperchild};
    }

    $vars->{limitrequestline} ||= 128;
    $vars->{limitrequestlinex2} = 2 * $vars->{limitrequestline};

    $vars->{proxy}        ||= 'off';
    $vars->{proxyssl_url} ||= '';
    $vars->{defines}      ||= '';

    $self->{hostport} = $self->hostport;
    $self->{server} = $self->new_test_server;

    return $self;

}

# figure out where httpd is and run extra config hooks which require

lib/Apache/TestConfig.pm  view on Meta::CPAN

    }
    else {
        debug "Using httpd: $vars->{httpd}";
    }

    $self->inherit_config; #see TestConfigParse.pm
    $self->configure_httpd_eapi; #must come after inherit_config

    $self->default_module(cgi    => [qw(mod_cgi mod_cgid)]);
    $self->default_module(thread => [qw(worker threaded)]);
    $self->default_module(ssl    => [qw(mod_ssl)]);
    $self->default_module(access => [qw(mod_access mod_authz_host)]);
    $self->default_module(auth   => [qw(mod_auth mod_auth_basic)]);
    $self->default_module(php    => [qw(sapi_apache2 mod_php4 mod_php5)]);

    $self->{server}->post_config;

    return $self;
}

sub default_module {

lib/Apache/TestConfig.pm  view on Meta::CPAN

sub default_loopback {
    '127.0.0.1';
}

sub port {
    my($self, $module) = @_;

    unless ($module) {
        my $vars = $self->{vars};
        return $self->select_first_port() unless $vars->{scheme} eq 'https';
        $module = $vars->{ssl_module_name};
    }
    return $self->{vhosts}->{$module}->{port};
}

sub hostport {
    my $self = shift;
    my $vars = shift || $self->{vars};
    my $module = shift || '';

    my $name = $vars->{servername};

lib/Apache/TestConfig.pm  view on Meta::CPAN


    return $handle;
}

sub clean {
    my $self = shift;
    $self->{clean_level} = shift || 2; #2 == really clean, 1 == reconfigure

    $self->new_test_server->clean;
    $self->cmodules_clean;
    $self->sslca_clean;

    for (sort keys %{ $self->{clean}->{files} }) {
        if (-e $_) {
            debug "unlink $_";
            unlink $_;
        }
        else {
            debug "unlink $_: $!";
        }
    }

lib/Apache/TestConfig.pm  view on Meta::CPAN

        $namebased = $2 || "";
        $module    = $3;
    }
    else {
        return undef;
    }

    my $vars = $self->{vars};
    my $mods = $self->{modules};
    my $have_module = "$module.c";
    my $ssl_module = $vars->{ssl_module};

    #if module ends with _ssl and it is not the module that implements ssl,
    #then assume this module is a vhost with SSLEngine On (or similar)
    #see mod_echo in extra.conf.in for example
    if ($module =~ /^(mod_\w+)_ssl$/ and $have_module ne $ssl_module) {
        $have_module = "$1.c"; #e.g. s/mod_echo_ssl.c/mod_echo.c/
        return undef unless $mods->{$ssl_module};
    }

    #don't allocate a port if this module is not configured
    #assumes the configuration is inside an <IfModule $have_module>
    if ($module =~ /^mod_/ and not $mods->{$have_module}) {
        return undef;
    }

    #allocate a port and configure this module into $self->{vhosts}
    my $port = $self->new_vhost($module, $namebased);

lib/Apache/TestConfig.pm  view on Meta::CPAN

    }
    else {
        my $dup = Symbol::gensym();
        open $dup, "<&DATA" or die "Can't dup DATA: $!";
        seek $dup, $DATA_pos, 0; # rewind to the beginning
        return $dup; # so we don't close DATA
    }
}

#certain variables may not be available until certain config files
#are generated.  for example, we don't know the ssl port until ssl.conf.in
#is parsed.  ssl port is needed for proxyssl testing

sub check_vars {
    my $self = shift;
    my $vars = $self->{vars};

    unless ($vars->{proxyssl_url}) {
        my $ssl = $self->{vhosts}->{ $vars->{ssl_module_name} };
        if ($ssl) {
            $vars->{proxyssl_url} ||= $ssl->{hostport};
        }

        if ($vars->{proxyssl_url}) {
            unless ($vars->{maxclients_preset}) {
                $vars->{minclients}++;
                $vars->{maxclients}++;
                $vars->{maxspare}++;
                $vars->{startserversthreadedmpm} ++;
                $vars->{minclientsthreadedmpm} += $vars->{threadsperchild};
                $vars->{maxclientsthreadedmpm} += $vars->{threadsperchild};
                $vars->{maxsparethreadedmpm} += $vars->{threadsperchild};
                #In addition allow for some backend processes
                #in keep-alive state. For threaded MPMs we

lib/Apache/TestConfig.pm  view on Meta::CPAN

sub generate_extra_conf {
    my $self = shift;

    my(@extra_conf, @conf_in, @conf_files);

    finddepth(sub {
        return unless /\.in$/;
        push @conf_in, catdir $File::Find::dir, $_;
    }, $self->{vars}->{t_conf});

    #make ssl port always be 8530 when available
    for my $file (@conf_in) {
        if (basename($file) =~ /^ssl/) {
            unshift @conf_files, $file;
        }
        else {
            push @conf_files, $file;
        }
    }

    for my $file (@conf_files) {
        (my $generated = $file) =~ s/\.in$//;
        debug "Will 'Include' $generated config file";

lib/Apache/TestConfig.pm  view on Meta::CPAN

        (my $generated = $file) =~ s/\.in$//;
        my $out = $self->genfile($generated, $file);
        $self->replace_vars($in, $out);

        close $in;
        close $out;

        $self->check_vars;
    }

    #we changed order to give ssl the first port after DEFAULT_PORT
    #but we want extra.conf Included first so vhosts inherit base config
    #such as LimitRequest*
    return [ sort @extra_conf ];
}

sub sslca_can {
    my($self, $check) = @_;

    my $vars = $self->{vars};
    return 0 unless $self->{modules}->{ $vars->{ssl_module} };
    return 0 unless -d "$vars->{t_conf}/ssl";

    require Apache::TestSSLCA;

    if ($check) {
        my $openssl = Apache::TestSSLCA::openssl();
        if (which($openssl)) {
            return 1;
        }

        error "cannot locate '$openssl' program required to generate SSL CA";
        exit(1);
    }

    return 1;
}

sub sslca_generate {
    my $self = shift;

    my $ca = $self->{vars}->{sslca};
    return if $ca and -d $ca; #t/conf/ssl/ca

    return unless $self->sslca_can(1);

    Apache::TestSSLCA::generate($self);
}

sub sslca_clean {
    my $self = shift;

    # XXX: httpd config is required, for now just skip ssl clean if
    # there is none. should probably add some flag which will tell us
    # when httpd_config was already run
    return unless $self->{vars}->{httpd} && $self->{vars}->{ssl_module};

    return unless $self->sslca_can;

    Apache::TestSSLCA::clean($self);
}

#XXX: just a quick hack to support t/TEST -ssl
#outside of httpd-test/perl-framework
sub generate_ssl_conf {
    my $self = shift;
    my $vars = $self->{vars};
    my $conf = "$vars->{t_conf}/ssl";
    my $httpd_test_ssl = "../httpd-test/perl-framework/t/conf/ssl";
    my $ssl_conf = "$vars->{top_dir}/$httpd_test_ssl";

    if (-d $ssl_conf and not -d $conf) {
        $self->gendir($conf);
        for (qw(ssl.conf.in)) {
            $self->cpfile("$ssl_conf/$_", "$conf/$_");
        }
        for (qw(certs keys crl)) {
            $self->symlink("$ssl_conf/$_", "$conf/$_");
        }
    }
}

sub find_in_inc {
    my($self, $dir) = @_;
    for my $path (@INC) {
        my $location = "$path/$dir";
        return $location if -d $location;
    }

lib/Apache/TestRequest.pm  view on Meta::CPAN

    if ($args->{keep_alive}) {
        install_http11();
        eval {
            require LWP::Protocol::https; #https10 is the default
            LWP::Protocol::implementor('https', 'LWP::Protocol::https');
        };
    }

    # in LWP 6, verify_hostname defaults to on, so SSL_ca_file
    # needs to be set accordingly
    if ($have_lwp and $LWP::VERSION >= 6.0 and not exists $args->{ssl_opts}->{SSL_ca_file}) {
        my $vars = Apache::Test::vars();
        my $cafile = "$vars->{sslca}/$vars->{sslcaorg}/certs/ca.crt";
        $args->{ssl_opts}->{SSL_ca_file} = $cafile;
        # IO::Socket:SSL raw socket compatibility
        $conn_opts->{SSL_ca_file} = $cafile;
    }

    eval { $UA ||= __PACKAGE__->new(%$args); };
}

sub user_agent_request_num {
    my $res = shift;
    $res->header('Client-Request-Num') ||  #lwp 5.60

lib/Apache/TestRequest.pm  view on Meta::CPAN


sub vhost_socket {
    my $module = shift;
    local $Apache::TestRequest::Module = $module if $module;

    my $hostport = hostport(Apache::Test::config());

    my($host, $port) = split ':', $hostport;
    my(%args) = (PeerAddr => $host, PeerPort => $port);

    if ($module and ($module =~ /ssl/ || $module eq 'h2')) {
        require IO::Socket::SSL;
        # Add all conn_opts to args
        map {$args{$_} = $conn_opts->{$_}} keys %{$conn_opts};
        return IO::Socket::SSL->new(%args, Timeout => UA_TIMEOUT);
    }
    else {
        require IO::Socket;
        return IO::Socket::INET->new(%args);
    }
}

#IO::Socket::SSL::getline does not correctly handle OpenSSL *_WANT_*.
#Could care less about performance here, just need a getline()
#that returns the same results with or without ssl.
#Inspired from Net::SSLeay::ssl_read_all().
my %getline = (
    'IO::Socket::SSL' => sub {
        my $self = shift;
        # _get_ssl_object in IO::Socket::SSL only meant for internal use!
        # But we need to compensate for unsufficient getline impl there.
        my $ssl = $self->_get_ssl_object;
        my ($got, $rv, $errs);
        my $reply = '';
    
        while (1) {
            ($got, $rv) = Net::SSLeay::read($ssl, 1);
            if (! defined $got) {
                my $err = Net::SSLeay::get_error($ssl, $rv);
                if ($err != Net::SSLeay::ERROR_WANT_READ() and
                    $err != Net::SSLeay::ERROR_WANT_WRITE()) {
                    $errs = Net::SSLeay::print_errs('SSL_read');
                    last;
                }
                next;
            }
            last if $got eq '';  # EOF
            $reply .= $got;
            last if $got eq "\n";

lib/Apache/TestRequest.pm  view on Meta::CPAN

        }
    } until ($found_same_interp);

    return $found_same_interp ? $res : undef;
}


sub set_client_cert {
    my $name = shift;
    my $vars = Apache::Test::vars();
    my $dir = join '/', $vars->{sslca}, $vars->{sslcaorg};

    if ($name) {
        my ($cert, $key) = ("$dir/certs/$name.crt", "$dir/keys/$name.pem");
        # IO::Socket:SSL raw socket compatibility
        $conn_opts->{SSL_cert_file} = $cert;
        $conn_opts->{SSL_key_file} = $key;
        if ($LWP::VERSION >= 6.0) {
            # IO::Socket:SSL doesn't look at environment variables
            if ($UA) {
                $UA->ssl_opts(SSL_cert_file => $cert);
                $UA->ssl_opts(SSL_key_file  => $key);
            } else {
                user_agent(ssl_opts => { SSL_cert_file => $cert,
                                         SSL_key_file  => $key });
            }
        }
    }
    else {
        # IO::Socket:SSL raw socket compatibility
        $conn_opts->{SSL_cert_file} = undef;
        $conn_opts->{SSL_key_file} = undef;
        if ($LWP::VERSION >= 6.0 and $UA) {
            $UA->ssl_opts(SSL_cert_file => undef);
            $UA->ssl_opts(SSL_key_file  => undef);
        }
    }
}

# Only for IO::Socket:SSL raw socket compatibility,
# when using user_agent() already done in its
# constructor.
sub set_ca_cert {
    my $vars = Apache::Test::vars();
    my $cafile = "$vars->{sslca}/$vars->{sslcaorg}/certs/ca.crt";
    $conn_opts->{SSL_ca_file} = $cafile;
}

#want news: urls to work with the LWP shortcuts
#but cant find a clean way to override the default nntp port
#by brute force we trick Net::NTTP into calling FixupNNTP::new
#instead of IO::Socket::INET::new, we fixup the args then forward
#to IO::Socket::INET::new

#also want KeepAlive on for Net::HTTP

lib/Apache/TestRun.pm  view on Meta::CPAN


use subs qw(exit_shell exit_perl);

my $orig_command;
my $orig_cwd;
my $orig_conf_opts;

my %core_files  = ();

my @std_run      = qw(start-httpd run-tests stop-httpd);
my @others       = qw(verbose configure clean help ssl http11 bugreport
                      save no-httpd one-process);
my @flag_opts    = (@std_run, @others);
my @string_opts  = qw(order trace);
my @ostring_opts = qw(proxy ping);
my @debug_opts   = qw(debug);
my @list_opts    = qw(preamble postamble breakpoint);
my @hash_opts    = qw(header);
my @help_opts    = qw(clean help);
my @request_opts = qw(get post head);

lib/Apache/TestRun.pm  view on Meta::CPAN

   'help'            => 'display this message',
   'bugreport'       => 'print the hint how to report problems',
   'preamble'        => 'config to add at the beginning of httpd.conf',
   'postamble'       => 'config to add at the end of httpd.conf',
   'ping[=block]'    => 'test if server is running or port in use',
   'debug[=name]'    => 'start server under debugger name (gdb, ddd, etc.)',
   'breakpoint=bp'   => 'set breakpoints (multiply bp can be set)',
   'header'          => "add headers to (" .
                         join('|', @request_opts) . ") request",
   'http11'          => 'run all tests with HTTP/1.1 (keep alive) requests',
   'ssl'             => 'run tests through ssl',
   'proxy'           => 'proxy requests (default proxy is localhost)',
   'trace=T'         => 'change tracing default to: warning, notice, ' .
                        'info, debug, ...',
   'one-process'     => 'run the server in single process mode',
   (map { $_, "\U$_\E url" } @request_opts),
);

sub fixup {
    #make sure we use an absolute path to perl
    #else Test::Harness uses the perl in our PATH

lib/Apache/TestRun.pm  view on Meta::CPAN

}

sub configure_opts {
    my $self = shift;
    my $save = shift;
    my $refreshed = 0;

    my($test_config, $opts) = ($self->{test_config}, $self->{opts});

    $test_config->{vars}->{scheme} =
      $opts->{ssl} ? 'https' :
        $self->{conf_opts}->{scheme} || 'http';

    if ($opts->{http11}) {
        $ENV{APACHE_TEST_HTTP11} = 1;
    }

    # unless we are already reconfiguring, check for .conf.in files changes
    if (!$$save &&
        (my @reasons =
         $self->{test_config}->need_reconfiguration($self->{conf_opts}))) {

lib/Apache/TestRun.pm  view on Meta::CPAN

    unless ($$save) {
        my $addr = \$config->{vars}->{remote_addr};
        my $remote_addr = $config->our_remote_addr;
        unless ($$addr eq $remote_addr) {
            warning "local ip address has changed, updating config cache";
            $$addr = $remote_addr;
        }
        #update minor changes to cached config
        #without complete regeneration
        #for example this allows switching between
        #'t/TEST' and 't/TEST -ssl'
        $config->sync_vars(qw(scheme proxy remote_addr));
        return;
    }

    my $test_config = $self->{test_config};
    $test_config->sslca_generate;
    $test_config->generate_ssl_conf if $self->{opts}->{ssl};
    $test_config->cmodules_configure;
    $test_config->generate_httpd_conf;
    $test_config->save;

}

sub try_exit_opts {
    my $self = shift;
    my @opts = @_;

lib/Apache/TestSSLCA.pm  view on Meta::CPAN


use constant SSLCA_DB => 'index.txt';

use vars qw(@EXPORT_OK &import);

use subs qw(symlink);

@EXPORT_OK = qw(dn dn_vars dn_oneline);
*import = \&Exporter::import;

my $openssl = $ENV{APACHE_TEST_OPENSSL_CMD} || 'openssl';
my $version = version();

my $CA = 'asf';
my $Config; #global Apache::TestConfig object

my $days     = '-days 365';
my $cakey    = 'keys/ca.pem';
my $cacert   = 'certs/ca.crt';
my $capolicy = '-policy policy_anything';
my $cacrl    = 'crl/ca-bundle.crl';

lib/Apache/TestSSLCA.pm  view on Meta::CPAN

                  "Email" : "emailAddress";

# downgrade to SHA-1 for OpenSSL before 0.9.8
if (Apache::Test::normalize_vstring($version) <
    Apache::Test::normalize_vstring("0.9.8")) {
    $dgst = 'sha1';
    # otherNames in x509v3_config are not supported either
    $san_msupn = $san_dnssrv = "";
}

my $sslproto = "all";

eval { require Net::SSLeay; };
if (Apache::Test::normalize_vstring($version) >= 
    Apache::Test::normalize_vstring("1.1.1")
    && !defined(&Net::SSLeay::CTX_set_post_handshake_auth)) {
    # OpenSSL 1.1.1 disables PHA by default client-side in TLSv1.3 but
    # most clients are not updated to enable it (at time of writing).
    # Many mod_ssl tests require working PHA, so disable v1.3 unless
    # using an updated Net::SSLeay. This is strictly insufficient
    # since an updated IO::Socket::SSL is also needed; to be
    # continued.  Ref: https://github.com/openssl/openssl/issues/6933
    $sslproto = "all -TLSv1.3";
}

my $ca_dn = {
    asf => {
        C  => 'US',
        ST => 'California',
        L  => 'San Francisco',
        O  => 'ASF',
        OU => 'httpd-test',
        CN => '',

lib/Apache/TestSSLCA.pm  view on Meta::CPAN

            $string .= "$k=$tmp";
        }
        else {
            $string .= "/$k=$dn->{$k}";
        }
    }

    $string;
}

sub openssl {
    return $openssl unless @_;

    my $cmd = "$openssl @_";

    info $cmd;

    unless (system($cmd) == 0) {
        my $status = $? >> 8;
        die "system @_ failed (exit status=$status)";
    }
}

my @dirs = qw(keys newcerts certs crl export csr conf proxy);

lib/Apache/TestSSLCA.pm  view on Meta::CPAN

    my $file = config_file($name);

    my $config = "-config $file";

    $config;
}

use constant PASSWORD_CLEARTEXT =>
    Apache::TestConfig::WIN32 || Apache::TestConfig::NETWARE;

#http://www.modssl.org/docs/2.8/ssl_reference.html#ToC21
my $basic_auth_password =
    PASSWORD_CLEARTEXT ? 'password': 'xxj31ZMTZzkVA';
my $digest_auth_hash    = '$1$OXLyS...$Owx8s2/m9/gfkcRVXzgoE/';

sub new_ca {
    writefile('serial', "01\n", 1);

    writefile('ssl.htpasswd',
              join ':', dn_oneline('client_snakeoil'),
              $basic_auth_password);

    openssl req => "-new -x509 -keyout $cakey -out $cacert $days",
                   config('ca');

    export_cert('ca'); #useful for importing into IE
}

sub new_key {
    my $name = shift;

    my $encrypt = @_ ? "@_ $passout" : "";

    my $out = "-out keys/$name.pem $encrypt";

    if ($name =~ /dsa/) {
        #this takes a long time so just do it once
        #don't do this in real life
        unless (-e 'dsa-param') {
            openssl dsaparam => '-inform PEM -out dsa-param 2048';
        }
        openssl gendsa => "$out dsa-param";
    }
    else {
        openssl genrsa => "$out 2048";
    }
}

sub new_cert {
    my $name = shift;

    openssl req => "-new -key keys/$name.pem -out csr/$name.csr",
                   $passin, $passout, config($name);

    sign_cert($name);

    export_cert($name);
}

sub sign_cert {
    my $name = shift;
    my $exts = '';

    $exts = ' -extensions client_ok_ext' if $name =~ /client_ok/;

    $exts = ' -extensions server_ext' if $name =~ /server/;

    openssl ca => "$capolicy -in csr/$name.csr -out certs/$name.crt",
                  $passin, config($name), '-batch', $exts;
}

#handy for importing into a browser such as netscape
sub export_cert {
    my $name = shift;

    return if $name =~ /^server/; #no point in exporting server certs

    openssl pkcs12 => "-export -in certs/$name.crt -inkey keys/$name.pem",
                      "-out export/$name.p12", $passin, $passout;
}

sub revoke_cert {
    my $name = shift;

    my @args = (config('cacrl'), $passin);

    #revokes in the SSLCA_DB database
    openssl ca => "-revoke certs/$name.crt", @args;

    #generates crl from the index.txt database
    openssl ca => "-gencrl -out $cacrl", @args;
}

sub symlink {
    my($file, $symlink) = @_;

    my $what = 'linked';

    if (Apache::TestConfig::WINFU) {
        cp $file, $symlink;
        $what = 'copied';

lib/Apache/TestSSLCA.pm  view on Meta::CPAN

sub hash_certs {
    my($type, $dir) = @_;

    chdir $dir;

    my $dh = DirHandle->new('.') or die "opendir $dir: $!";
    my $n = 0;

    for my $file ($dh->read) {
        next unless $file =~ /\.cr[tl]$/;
        chomp(my $hash = `$openssl $type -noout -hash < $file`);
        next unless $hash;
        my $symlink = "$hash.r$n";
        $n++;
        symlink $file, $symlink;
    }

    close $dh;

    chdir $CA;
}

lib/Apache/TestSSLCA.pm  view on Meta::CPAN

            make_proxy_cert($name);
        }
    }

    hash_certs(crl => 'crl');
}

sub generate {
    $Config = shift;

    $CA = shift || $Config->{vars}->{sslcaorg};

    my $root = $Config->{vars}->{sslca};

    return if -d $root;

    my $pwd  = Cwd::cwd();
    my $base = dirname $root;
    my $dir  = basename $root;

    chdir $base;

    # Ensure the CNs used in the server certs match up with the

lib/Apache/TestSSLCA.pm  view on Meta::CPAN


    setup($CA);

    chdir $pwd;
}

sub clean {
    my $config = shift;

    #rel2abs adds same drive letter for win32 that clean_add_path added
    my $dir = File::Spec->rel2abs($config->{vars}->{sslca});

    unless ($config->{clean}->{dirs}->{$dir}) {
        return; #we did not generate this ca
    }

    unless ($config->{clean_level} > 1) {
        #skip t/TEST -conf
        warning "skipping regeneration of SSL CA; run t/TEST -clean to force";
        return;
    }

    File::Path::rmtree([$dir], 1, 1);
}

#not using Apache::TestConfig methods because the openssl commands
#will generate heaps of files we cannot keep track of

sub writefile {
    my($file, $content) = @_;

    my $fh = Symbol::gensym();
    open $fh, ">$file" or die "open $file: $!";
    print $fh $content;
    close $fh;
}

sub gendir {
    my($dir) = @_;

    return if -d $dir;
    mkdir $dir, 0755;
}

sub version {
    my $devnull = devnull();
    my $version = qx($openssl version 2>$devnull);
    return $1 if $version =~ /^\S+SSL (\S+)/;
    die "FATAL: unable to determine openssl version via `$openssl version` from: $version";
}

sub dgst {
    return $dgst;
}

sub email_field {
    return $email_field;
}

sub sslproto {
    return $sslproto;
}

1;
__END__

lib/Apache/TestServer.pm  view on Meta::CPAN

    my($self, $thing) = @_;
    die "Can't figure out what Apache server generation we are running"
        unless $self->{rev};

    $thing->{$self->{rev}};
}

my @apache_logs = qw(
error_log access_log httpd.pid
apache_runtime_status rewrite_log
ssl_engine_log ssl_request_log
cgisock
);

sub clean {
    my $self = shift;

    my $dir = $self->{config}->{vars}->{t_logs};

    for (@apache_logs) {
        my $file = catfile $dir, $_;



( run in 1.412 second using v1.01-cache-2.11-cpan-acf6aa7dc9e )