From 9e24b43cb962d7d0035154a546ef281d0a786162 Mon Sep 17 00:00:00 2001 From: Ryan Chu Date: Wed, 28 Feb 2018 16:48:38 +0100 Subject: [PATCH] Docker-based test servers for network-related Qt autotests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The existing network test server has some limitations. Most notably, it is not accessible by every Qt developer. Also, some services don't allow simultaneous access, which causes flaky test results. Instead of centralizing all the services to one physical machine, the idea is to build up several dedicated servers inside separate Docker containers. 1. Create testserver.pri and integrate it into the make check command of Qt Test. 2. Define QT_TEST_SERVER flag for changing test parameters at compile time. Task-number: QTQAINFRA-1686 Change-Id: I0422ddb97eb8c11b4818771454851d19671253b1 Reviewed-by: Jędrzej Nowacki Reviewed-by: Ryan Chu --- tests/auto/network-settings.h | 19 +++ tests/auto/testserver.pri | 104 ++++++++++++++++ tests/testserver/apache2/apache2.sh | 77 ++++++++++++ tests/testserver/apache2/testdata/dav.conf | 7 ++ .../testserver/apache2/testdata/deflate.conf | 5 + tests/testserver/apache2/testdata/main.conf | 56 +++++++++ .../testserver/apache2/testdata/security.conf | 51 ++++++++ tests/testserver/apache2/testdata/ssl.conf | 2 + .../apache2/testdata/www/cgi-bin/echo.cgi | 11 ++ .../www/htdocs/auth-digest/index.html | 1 + .../testdata/www/htdocs/digest-authfile | 1 + .../apache2/testdata/www/htdocs/fluke.gif | Bin 0 -> 27906 bytes .../apache2/testdata/www/htdocs/index.html | 3 + .../www/htdocs/protected/cgi-bin/md5sum.cgi | 6 + .../testdata/www/htdocs/rfcs-auth/index.html | 1 + tests/testserver/common/ssl.sh | 39 ++++++ tests/testserver/common/startup.sh | 52 ++++++++ .../ssl/private/qt-test-server-key.pem | 15 +++ .../testdata/ssl/qt-test-server-cert.pem | 16 +++ .../common/testdata/system/passwords | 12 ++ tests/testserver/danted/danted.sh | 44 +++++++ .../testdata/danted-authenticating.conf | 19 +++ tests/testserver/danted/testdata/danted.conf | 19 +++ tests/testserver/docker-compose.yml | 89 ++++++++++++++ tests/testserver/ftp-proxy/ftp-proxy.sh | 40 +++++++ tests/testserver/squid/squid.sh | 46 +++++++ .../testdata/squid-authenticating-ntlm.conf | 41 +++++++ tests/testserver/squid/testdata/squid.conf | 46 +++++++ .../testdata/ftp/pub/file-not-readable.txt | 1 + tests/testserver/vsftpd/testdata/vsftpd.conf | 112 ++++++++++++++++++ .../vsftpd/testdata/vsftpd.user_list | 20 ++++ tests/testserver/vsftpd/vsftpd.sh | 66 +++++++++++ 32 files changed, 1021 insertions(+) create mode 100644 tests/auto/testserver.pri create mode 100755 tests/testserver/apache2/apache2.sh create mode 100644 tests/testserver/apache2/testdata/dav.conf create mode 100644 tests/testserver/apache2/testdata/deflate.conf create mode 100644 tests/testserver/apache2/testdata/main.conf create mode 100644 tests/testserver/apache2/testdata/security.conf create mode 100644 tests/testserver/apache2/testdata/ssl.conf create mode 100755 tests/testserver/apache2/testdata/www/cgi-bin/echo.cgi create mode 100644 tests/testserver/apache2/testdata/www/htdocs/auth-digest/index.html create mode 100644 tests/testserver/apache2/testdata/www/htdocs/digest-authfile create mode 100644 tests/testserver/apache2/testdata/www/htdocs/fluke.gif create mode 100644 tests/testserver/apache2/testdata/www/htdocs/index.html create mode 100755 tests/testserver/apache2/testdata/www/htdocs/protected/cgi-bin/md5sum.cgi create mode 100644 tests/testserver/apache2/testdata/www/htdocs/rfcs-auth/index.html create mode 100755 tests/testserver/common/ssl.sh create mode 100755 tests/testserver/common/startup.sh create mode 100644 tests/testserver/common/testdata/ssl/private/qt-test-server-key.pem create mode 100644 tests/testserver/common/testdata/ssl/qt-test-server-cert.pem create mode 100644 tests/testserver/common/testdata/system/passwords create mode 100755 tests/testserver/danted/danted.sh create mode 100644 tests/testserver/danted/testdata/danted-authenticating.conf create mode 100644 tests/testserver/danted/testdata/danted.conf create mode 100644 tests/testserver/docker-compose.yml create mode 100755 tests/testserver/ftp-proxy/ftp-proxy.sh create mode 100755 tests/testserver/squid/squid.sh create mode 100644 tests/testserver/squid/testdata/squid-authenticating-ntlm.conf create mode 100644 tests/testserver/squid/testdata/squid.conf create mode 100644 tests/testserver/vsftpd/testdata/ftp/pub/file-not-readable.txt create mode 100644 tests/testserver/vsftpd/testdata/vsftpd.conf create mode 100644 tests/testserver/vsftpd/testdata/vsftpd.user_list create mode 100755 tests/testserver/vsftpd/vsftpd.sh diff --git a/tests/auto/network-settings.h b/tests/auto/network-settings.h index 16966ced4e..85f93120b1 100644 --- a/tests/auto/network-settings.h +++ b/tests/auto/network-settings.h @@ -27,6 +27,7 @@ ****************************************************************************/ #include +#include #ifdef QT_NETWORK_LIB #include #include @@ -50,7 +51,11 @@ public: } static QString serverDomainName() { +#ifdef QT_TEST_SERVER_DOMAIN + return QString(QT_TEST_SERVER_DOMAIN); // Defined in testserver feature +#else return QString("qt-test-net"); +#endif } static QString serverName() { @@ -137,6 +142,20 @@ public: return true; } + static bool verifyConnection(QString serverName, quint16 port, quint32 retry = 10) + { + QTcpSocket socket; + for (quint32 i = 1; i < retry; i++) { + socket.connectToHost(serverName, port); + if (socket.waitForConnected(1000)) + return true; + // Wait for service to start up + QTest::qWait(1000); + } + socket.connectToHost(serverName, port); + return socket.waitForConnected(1000); + } + // Helper function for usage with QVERIFY2 on sockets. static QByteArray msgSocketError(const QAbstractSocket &s) { diff --git a/tests/auto/testserver.pri b/tests/auto/testserver.pri new file mode 100644 index 0000000000..6a2e6b9d91 --- /dev/null +++ b/tests/auto/testserver.pri @@ -0,0 +1,104 @@ +# Integrating docker-based test servers into Qt Test framework +# +# This file adds support for docker-based test servers built by testcase +# projects that need them. To enable this feature, any automated test can +# include testserver.pri in its project file. This instructs qmake to insert +# additional targets into the generated Makefile. The 'check' target then brings +# up test servers before running the testcase, and shuts them down afterwards. +# +# TESTSERVER_COMPOSE_FILE +# - Contains the path of docker-compose file +# This configuration file defines the services used for autotests. It tells the +# docker engine how to build up the docker images and containers. In qtbase, a +# shared docker-compose file is located in the tests folder. +# Example: TESTSERVER_COMPOSE_FILE = \ +# $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose.yml +# +# The user must run the provisioning scripts in advance before attempting to +# build the test servers. The docker_testserver.sh script is used to build up +# the docker images into the docker-cache. It handles the immutable parts of the +# server installation that rarely need adjustment, such as downloading packages. +# Example: qt5/coin/provisioning/.../testserver/docker_testserver.sh +# +# QT_TEST_SERVER_LIST +# - A list of test servers to bring up for this testcase +# These test servers should be defined in $$TESTSERVER_COMPOSE_FILE. Each +# testcase can define the test servers it depends on. +# Example: QT_TEST_SERVER_LIST = apache2 squid vsftpd ftp-proxy danted +# +# Pre-processor defines needed for the application: +# QT_TEST_SERVER +# - A preprocessor macro used for testcase to change testing parameters at +# compile time +# This macro is predefined for docker-based test servers and is passed as a +# compiler option (-DQT_TEST_SERVER). The testcase can then check whether +# docker-based servers are in use and change the testing parameters, such as +# host name or port number, at compile time. An example can be found in +# network-settings.h. +# +# Example: +# #if defined(QT_TEST_SERVER) +# Change the testing parameters at compile time +# #endif +# +# QT_TEST_SERVER_DOMAIN +# - A preprocessor macro that holds the server domain name +# Provided for the helper functions in network-settings.h. Use function +# serverDomainName() in your application instead. +# +# Additional make targets: +# 1. check_network - A renamed target from the check target of testcase feature. +# 2. testserver_clean - Clean up server containers/images and tidy away related +# files. + +TESTSERVER_COMPOSE_FILE = $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose.yml +TESTSERVER_VERSION = $$system(docker-compose --version) +TESTSERVER_IMAGES = $$system(docker images -aq "qt-test-server-*") + +equals(QMAKE_HOST.os, Windows)|isEmpty(TESTSERVER_VERSION) { + # Make check with server "qt-test-server.qt-test-net" as a fallback + message("testserver: qt-test-server.qt-test-net") +} else { + # Make check with test servers + message("testserver:" $$TESTSERVER_VERSION) + + # Ensure that the docker-compose file is provided. It is a configuration + # file which is mandatory for all docker-compose commands. You can get more + # detail from the description of TESTSERVER_COMPOSE_FILE above. There is + # also an example showing how to configure it manually. + isEmpty(TESTSERVER_COMPOSE_FILE): error("Project variable 'TESTSERVER_COMPOSE_FILE' is not set") + + # Before starting the test servers, it requires the user to run the setup + # script (coin/provisioning/.../testserver/docker_testserver.sh) in advance. + isEmpty(TESTSERVER_IMAGES): error("Docker image qt-test-server-* not found") + + # The domain name is relevant to https keycert (qnetworkreply/crts/qt-test-net-cacert.pem). + DNSDOMAIN = test-net.qt + TEST_ENV += TESTSERVER_DOMAIN=$$DNSDOMAIN + DEFINES += QT_TEST_SERVER QT_TEST_SERVER_DOMAIN=$$shell_quote(\"$${DNSDOMAIN}\") + + # There is no docker bridge on macOS. It is impossible to ping a container. + # Docker docs recommends using port mapping to connect to a container. + equals(QMAKE_HOST.os, Darwin): TEST_ENV += TESTSERVER_BIND_LOCAL=1 + + # Rename the check target of testcase feature + check.target = check_network + testserver_test.target = check + + # Bring up test servers and make sure the services are ready. + testserver_test.commands = $$TEST_ENV docker-compose -f $$TESTSERVER_COMPOSE_FILE up -d \ + --force-recreate --timeout 1 $${QT_TEST_SERVER_LIST} && + + # Check test cases with docker-based test servers. + testserver_test.commands += $(MAKE) check_network; + + # Stop and remove test servers after testing. + testserver_test.commands += $$TEST_ENV docker-compose -f $$TESTSERVER_COMPOSE_FILE down \ + --timeout 1 + + # Destroy test servers and tidy away related files. + testserver_clean.commands = $$TEST_ENV docker-compose -f $$TESTSERVER_COMPOSE_FILE down \ + --rmi all + + QMAKE_EXTRA_TARGETS += testserver_test testserver_clean +} diff --git a/tests/testserver/apache2/apache2.sh b/tests/testserver/apache2/apache2.sh new file mode 100755 index 0000000000..4b0c74e2c4 --- /dev/null +++ b/tests/testserver/apache2/apache2.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash + +############################################################################# +## +## Copyright (C) 2018 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:GPL$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 or (at your option) any later version +## approved by the KDE Free Qt Foundation. The licenses are as published by +## the Free Software Foundation and appearing in the file LICENSE.GPL3 +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +set -ex + +# package apache2 + +# add users +useradd httptest; echo "httptest:httptest" | chpasswd + +# enable apache2 module +/usr/sbin/a2enmod ssl dav_fs headers deflate auth_digest cgi + +# enable apache2 config +cp $TESTDATA/{main,security,ssl,dav}.conf /etc/apache2/conf-available/ +/usr/sbin/a2enconf main security ssl dav + +# install configurations and test data +cp $TESTDATA/deflate.conf /etc/apache2/mods-available/ +mkdir -p -m 1777 /home/writeables/dav # dav.conf +a2dissite '*' # disable all of the default apache2 sites + +# Populate the web-site: +su $USER -c "cp -r $TESTDATA/www ~/www" + +# tst_QNetworkReply::getFromHttp(success-internal) +su $USER -c "cp rfc3252.txt ~/www/htdocs/"; rm rfc3252.txt + +# tst_QNetworkReply::synchronousRequest_data() +su $USER -c "mkdir -p ~/www/htdocs/deflate/" +su $USER -c "ln -s ~/www/htdocs/rfc3252.txt ~/www/htdocs/deflate/" + +# tst_QNetworkReply::headFromHttp(with-authentication) +su $USER -c "ln -s ~/www/htdocs/rfc3252.txt ~/www/htdocs/rfcs-auth/" + +# Duplicate rfc3252.txt 20 times for bigfile tests: +su $USER -c "seq 20 | xargs -i cat ~/www/htdocs/rfc3252.txt >> ~/www/htdocs/bigfile" + +# tst_QNetworkReply::postToHttp(empty) +su $USER -c "ln -s ~/www/htdocs/protected/cgi-bin/md5sum.cgi ~/www/cgi-bin/" + +# tst_QNetworkReply::lastModifiedHeaderForHttp() expects this time-stamp: +touch -d "2007-05-22 12:04:57 GMT" /home/$USER/www/htdocs/fluke.gif + +# Create 10MB file for use by tst_Q*::downloadBigFile and interruption tests: +su $USER -c "/bin/dd if=/dev/zero of=~/www/htdocs/mediumfile bs=1 count=0 seek=10000000" + +# enable service with installed configurations +service apache2 restart diff --git a/tests/testserver/apache2/testdata/dav.conf b/tests/testserver/apache2/testdata/dav.conf new file mode 100644 index 0000000000..c207c2734b --- /dev/null +++ b/tests/testserver/apache2/testdata/dav.conf @@ -0,0 +1,7 @@ +Alias /dav /home/writeables/dav + + DAV On + order allow,deny + allow from all + Require all granted + diff --git a/tests/testserver/apache2/testdata/deflate.conf b/tests/testserver/apache2/testdata/deflate.conf new file mode 100644 index 0000000000..6a15701d49 --- /dev/null +++ b/tests/testserver/apache2/testdata/deflate.conf @@ -0,0 +1,5 @@ +# The default configuration will turn on DEFLATE for files served up +# from everywhere. +# +# For testing purposes, we want DEFLATE off by default, and on only for +# specific paths (which is set elsewhere). diff --git a/tests/testserver/apache2/testdata/main.conf b/tests/testserver/apache2/testdata/main.conf new file mode 100644 index 0000000000..5cfa544623 --- /dev/null +++ b/tests/testserver/apache2/testdata/main.conf @@ -0,0 +1,56 @@ +ServerName apache2.test-net.qt:80 + +NameVirtualHost *:443 + + + + + +SSLEngine On +CustomLog /var/log/apache2/ssl_access.log combined +ErrorLog /var/log/apache2/ssl_error.log + + +# default ubuntu config turns off SSLv2 because it is deprecated. +# Turn it back on so we can test it. +SSLProtocol all + +DocumentRoot /home/qt-test-server/www/htdocs +ScriptAlias /qtest/cgi-bin/ "/home/qt-test-server/www/cgi-bin/" +ScriptAlias /qtest/protected/cgi-bin/ "/home/qt-test-server/www/htdocs/protected/cgi-bin/" +Alias /qtest "/home/qt-test-server/www/htdocs/" + + + Require all granted + + + + AuthType Basic + AuthName "Restricted Files" + AuthUserFile /home/qt-test-server/passwords + Require user httptest + + + + AuthType Digest + AuthName "Digest testing" + AuthDigestProvider file + AuthUserFile /home/qt-test-server/www/htdocs/digest-authfile + Require user httptest + + + + AddOutputFilterByType DEFLATE text/html text/plain text/xml + Header append Vary User-Agent env=!dont-vary + + + + Options +ExecCGI -Includes + AddHandler cgi-script .cgi .pl + Require all granted + + + + + AllowOverride AuthConfig Options + diff --git a/tests/testserver/apache2/testdata/security.conf b/tests/testserver/apache2/testdata/security.conf new file mode 100644 index 0000000000..30a8ee3765 --- /dev/null +++ b/tests/testserver/apache2/testdata/security.conf @@ -0,0 +1,51 @@ +# +# Disable access to the entire file system except for the directories that +# are explicitly allowed later. +# +# This currently breaks the configurations that come with some web application +# Debian packages. It will be made the default for the release after lenny. +# +# +# AllowOverride None +# Order Deny,Allow +# Deny from all +# + + +# Changing the following options will not really affect the security of the +# server, but might make attacks slightly more difficult in some cases. + +# +# ServerTokens +# This directive configures what you return as the Server HTTP response +# Header. The default is 'Full' which sends information about the OS-Type +# and compiled in modules. +# Set to one of: Full | OS | Minimal | Minor | Major | Prod +# where Full conveys the most information, and Prod the least. +# +#ServerTokens Minimal +ServerTokens OS +#ServerTokens Full + +# +# Optionally add a line containing the server version and virtual host +# name to server-generated pages (internal error documents, FTP directory +# listings, mod_status and mod_info output etc., but not CGI generated +# documents or custom error documents). +# Set to "EMail" to also include a mailto: link to the ServerAdmin. +# Set to one of: On | Off | EMail +# +#ServerSignature Off +ServerSignature On + +# +# Allow TRACE method +# +# Set to "extended" to also reflect the request body (only for testing and +# diagnostic purposes). +# +# Set to one of: On | Off | extended +# +#TraceEnable Off +TraceEnable On + diff --git a/tests/testserver/apache2/testdata/ssl.conf b/tests/testserver/apache2/testdata/ssl.conf new file mode 100644 index 0000000000..d6bbaf0da0 --- /dev/null +++ b/tests/testserver/apache2/testdata/ssl.conf @@ -0,0 +1,2 @@ +SSLCertificateFile /home/qt-test-server/ssl-certs/qt-test-server-cert.pem +SSLCertificateKeyFile /home/qt-test-server/ssl-certs/private/qt-test-server-key.pem diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/echo.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/echo.cgi new file mode 100755 index 0000000000..16315a3db6 --- /dev/null +++ b/tests/testserver/apache2/testdata/www/cgi-bin/echo.cgi @@ -0,0 +1,11 @@ +#!/usr/bin/perl + +if ($ENV{'REQUEST_METHOD'} eq "GET") { + $request = $ENV{'QUERY_STRING'}; +} elsif ($ENV{'REQUEST_METHOD'} eq "POST") { + read(STDIN, $request, $ENV{'CONTENT_LENGTH'}) || die "Could not get query\n"; +} + +print "Content-type: text/plain\n\n"; +print $request; + diff --git a/tests/testserver/apache2/testdata/www/htdocs/auth-digest/index.html b/tests/testserver/apache2/testdata/www/htdocs/auth-digest/index.html new file mode 100644 index 0000000000..fa96496aa0 --- /dev/null +++ b/tests/testserver/apache2/testdata/www/htdocs/auth-digest/index.html @@ -0,0 +1 @@ +digest authentication successful diff --git a/tests/testserver/apache2/testdata/www/htdocs/digest-authfile b/tests/testserver/apache2/testdata/www/htdocs/digest-authfile new file mode 100644 index 0000000000..99963901ce --- /dev/null +++ b/tests/testserver/apache2/testdata/www/htdocs/digest-authfile @@ -0,0 +1 @@ +httptest:Digest testing:5f68f4bc3cd2873a3d547558fe7d9782 diff --git a/tests/testserver/apache2/testdata/www/htdocs/fluke.gif b/tests/testserver/apache2/testdata/www/htdocs/fluke.gif new file mode 100644 index 0000000000000000000000000000000000000000..6060cbd4d7ea42f4f61bf0a7a58a36763328a794 GIT binary patch literal 27906 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 EJJZ2V&j0`b literal 0 HcmV?d00001 diff --git a/tests/testserver/apache2/testdata/www/htdocs/index.html b/tests/testserver/apache2/testdata/www/htdocs/index.html new file mode 100644 index 0000000000..abc1df188d --- /dev/null +++ b/tests/testserver/apache2/testdata/www/htdocs/index.html @@ -0,0 +1,3 @@ +

Welcome to qt-test-server

+fluke +

This is a network test server. It serves as a caching ftp and http proxy, transparent http/socks5 proxy, imap, ftp and http server, and more.

diff --git a/tests/testserver/apache2/testdata/www/htdocs/protected/cgi-bin/md5sum.cgi b/tests/testserver/apache2/testdata/www/htdocs/protected/cgi-bin/md5sum.cgi new file mode 100755 index 0000000000..e580462b85 --- /dev/null +++ b/tests/testserver/apache2/testdata/www/htdocs/protected/cgi-bin/md5sum.cgi @@ -0,0 +1,6 @@ +#!/bin/sh + +echo "Content-type: text/plain"; +echo "Content-length: 33" +echo +md5sum | cut -f 1 -d " " diff --git a/tests/testserver/apache2/testdata/www/htdocs/rfcs-auth/index.html b/tests/testserver/apache2/testdata/www/htdocs/rfcs-auth/index.html new file mode 100644 index 0000000000..472e6ce55d --- /dev/null +++ b/tests/testserver/apache2/testdata/www/htdocs/rfcs-auth/index.html @@ -0,0 +1 @@ +you found the secret diff --git a/tests/testserver/common/ssl.sh b/tests/testserver/common/ssl.sh new file mode 100755 index 0000000000..8a4728ad4d --- /dev/null +++ b/tests/testserver/common/ssl.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +############################################################################# +## +## Copyright (C) 2018 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:GPL$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 or (at your option) any later version +## approved by the KDE Free Qt Foundation. The licenses are as published by +## the Free Software Foundation and appearing in the file LICENSE.GPL3 +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +set -ex + +# package ssl + +# install ssl_certs and test data +su $USER -c "mkdir -p -m 700 ~/ssl-certs/private" +su $USER -c "cp $CONFIG/ssl/qt-test-server-cert.pem ~/ssl-certs/" +su $USER -c "cp $CONFIG/ssl/private/qt-test-server-key.pem ~/ssl-certs/private/" diff --git a/tests/testserver/common/startup.sh b/tests/testserver/common/startup.sh new file mode 100755 index 0000000000..10847d3524 --- /dev/null +++ b/tests/testserver/common/startup.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash + +############################################################################# +## +## Copyright (C) 2018 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:GPL$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 or (at your option) any later version +## approved by the KDE Free Qt Foundation. The licenses are as published by +## the Free Software Foundation and appearing in the file LICENSE.GPL3 +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +set -ex + +# export variables +export USER=qt-test-server +export PASS=password +export CONFIG=common/testdata +export TESTDATA=service/testdata + +# add users +useradd -m -s /bin/bash $USER; echo "$USER:$PASS" | chpasswd + +# install configurations and test data +su $USER -c "cp $CONFIG/system/passwords ~/" + +# modules initialization (apache2.sh, ftp-proxy.sh ...) +for RUN_CMD +do $RUN_CMD +done + +# keep-alive in docker detach mode +sleep infinity diff --git a/tests/testserver/common/testdata/ssl/private/qt-test-server-key.pem b/tests/testserver/common/testdata/ssl/private/qt-test-server-key.pem new file mode 100644 index 0000000000..8b7ce5811a --- /dev/null +++ b/tests/testserver/common/testdata/ssl/private/qt-test-server-key.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDNqttv1jTJp/HAvuRBGBniAski5qfVugMunih69F8ad193qRE7 +j37wLsae6zrZEtfBDFHoJFI/I8NCDBHG8hyhQv60wmmDrfdwsRgVzCAoYjDwLBXm +Mxmvw+scwJH3EWiUUPhJNwgy1z5136O8aQAV3s2HD1wCa4LIAX1q8B3ccwIDAQAB +AoGAGiDou+6UykHB3uDhkruDHkmIUBzJmceF+/gv4F8Hbg9YW5VpEQ4L7Guk5C+y +TD2ul2H/TeS/ZjIe7lcmMwYzSLcyeKfaiaV1EhPGjIdvB4ysTN79pfWXQtlpt/Z9 +I/EOoW9XosJ/EOFdpgV0MC9QMTQKMyS0qQLwhBsoAW4DcEECQQDmrWEPNprbEDIH +Sm+KlMH6rdybIvzR3IPlYE6kMjQIWbUmGNxSUT7B/UDh2QeaTT54Rb1Ygnq7gVjC +RHU3wnGxAkEA5D6jI/E/xtQSq0KKVpbOxN1dIo0MVPbO/hI7/pO2DdZIM0O4GL55 +ks83O5ZDTfrVy2Ys/9lqbbq+5FSs+NZ1YwJBANzAXRsO+YDcbdP2Uun+0+fOjEhW +YjV/XyWaVYfil1LKboXn0qhgIbvJXVcEt7bdZwP4UWwracKY1NUMaFSVGvECQQC/ +L3iX8szpT1sT+XjHbytj28jX2C4sPVDFoaB/bltg280+o8rhbyuGvewWDZfzCdlr +tvqalROBNpwPxp3dEkbhAkEAl7N7/7hWbw7Xv69ww7i0jcPduukbtbEY1DTmARhR +rOF5AiztOAe+R94iLzkj63ZU0LcoSAixehp2tdkdtTI4CQ== +-----END RSA PRIVATE KEY----- diff --git a/tests/testserver/common/testdata/ssl/qt-test-server-cert.pem b/tests/testserver/common/testdata/ssl/qt-test-server-cert.pem new file mode 100644 index 0000000000..dae5641a88 --- /dev/null +++ b/tests/testserver/common/testdata/ssl/qt-test-server-cert.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICiTCCAfICCQCqBnF3SPSY7jANBgkqhkiG9w0BAQQFADCBiDELMAkGA1UEChMC +UXQxGTAXBgNVBAsTEENvcmUgQW5kIE5ldHdvcmsxGzAZBgkqhkiG9w0BCQEWDG5v +Ym9keS5xdC5pbzENMAsGA1UEBxMET3NsbzENMAsGA1UECBMET3NsbzELMAkGA1UE +BhMCTk8xFjAUBgNVBAMUDSoudGVzdC1uZXQucXQwHhcNMTgwMzEzMDkyNjQ0WhcN +NDgwMzA1MDkyNjQ0WjCBiDELMAkGA1UEChMCUXQxGTAXBgNVBAsTEENvcmUgQW5k +IE5ldHdvcmsxGzAZBgkqhkiG9w0BCQEWDG5vYm9keS5xdC5pbzENMAsGA1UEBxME +T3NsbzENMAsGA1UECBMET3NsbzELMAkGA1UEBhMCTk8xFjAUBgNVBAMUDSoudGVz +dC1uZXQucXQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM2q22/WNMmn8cC+ +5EEYGeICySLmp9W6Ay6eKHr0Xxp3X3epETuPfvAuxp7rOtkS18EMUegkUj8jw0IM +EcbyHKFC/rTCaYOt93CxGBXMIChiMPAsFeYzGa/D6xzAkfcRaJRQ+Ek3CDLXPnXf +o7xpABXezYcPXAJrgsgBfWrwHdxzAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAwNhw +aKznTaMj6JeHP/kEEwMppRkNjmh4ECdQfT9vYNs45UKSAvCa1dn6ZBZKIdhqKCLn +U2qiIS2783IoisRjFtg8x70S13EsBw/yEL/av+Ca1gQHOIFrOuLqwYbslTHrRXRA +RPzHOl3ZP9FD3mPZ8jyzxYs4x5EM0X26FkAR078= +-----END CERTIFICATE----- diff --git a/tests/testserver/common/testdata/system/passwords b/tests/testserver/common/testdata/system/passwords new file mode 100644 index 0000000000..4e911b3f0e --- /dev/null +++ b/tests/testserver/common/testdata/system/passwords @@ -0,0 +1,12 @@ +# user: foo; passwd: bar +foo:bab.5ZXQdbvEo + +# user: qsockstest; passwd: qsockstest +#qsockstest:S7oOqMpoG6aTk + +# user: qsockstest; passwd: password +qsockstest:Cd3Lv2aD0aiBs + +#user httptest password httptest +httptest:v2fwkDMgrRjRA +# added by mgoetz for tst_qnetworkreply ioPostToHttpFromSocket diff --git a/tests/testserver/danted/danted.sh b/tests/testserver/danted/danted.sh new file mode 100755 index 0000000000..bf3d154f33 --- /dev/null +++ b/tests/testserver/danted/danted.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +############################################################################# +## +## Copyright (C) 2018 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:GPL$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 or (at your option) any later version +## approved by the KDE Free Qt Foundation. The licenses are as published by +## the Free Software Foundation and appearing in the file LICENSE.GPL3 +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +set -ex + +# package dante-server + +# add users +useradd -d /dev/null -s /bin/false qsockstest; echo "qsockstest:$PASS" | chpasswd + +# install configurations and test data +cp $TESTDATA/danted{,-authenticating}.conf /etc/ + +# enable service with installed configurations +service danted start +service danted-authenticating start diff --git a/tests/testserver/danted/testdata/danted-authenticating.conf b/tests/testserver/danted/testdata/danted-authenticating.conf new file mode 100644 index 0000000000..ccb4acc801 --- /dev/null +++ b/tests/testserver/danted/testdata/danted-authenticating.conf @@ -0,0 +1,19 @@ +# A sample danted-authenticating.conf +# See: https://www.inet.no/dante/doc/1.4.x/config/ +logoutput: /var/log/sockd-authenticating.log +internal: eth0 port = 1081 +external: eth0 +method: username +user.privileged: root +user.notprivileged: nobody +user.libwrap: nobody + +client pass { + from: 0.0.0.0/0 to: 0.0.0.0/0 + log: error connect disconnect +} + +pass { + from: 0.0.0.0/0 to: 0.0.0.0/0 + log: error connect disconnect +} diff --git a/tests/testserver/danted/testdata/danted.conf b/tests/testserver/danted/testdata/danted.conf new file mode 100644 index 0000000000..bd0e6a8343 --- /dev/null +++ b/tests/testserver/danted/testdata/danted.conf @@ -0,0 +1,19 @@ +# A sample danted.conf +# See: https://www.inet.no/dante/doc/1.4.x/config/ +logoutput: /var/log/sockd.log +internal: eth0 port = 1080 +external: eth0 +method: username none +user.privileged: proxy +user.notprivileged: nobody +user.libwrap: nobody + +client pass { + from: 0.0.0.0/0 to: 0.0.0.0/0 + log: error connect disconnect +} + +pass { + from: 0.0.0.0/0 to: 0.0.0.0/0 + log: error connect disconnect +} diff --git a/tests/testserver/docker-compose.yml b/tests/testserver/docker-compose.yml new file mode 100644 index 0000000000..334818bc9b --- /dev/null +++ b/tests/testserver/docker-compose.yml @@ -0,0 +1,89 @@ +version: '3.4' + +x-domains: + &testdomain + ${TESTSERVER_DOMAIN:-test-net.qt} + +# The tag of images is used by docker compose file to launch the corresponding +# docker containers. The value of tag comes from the provisioning script +# (coin/provisioning/.../testserver/docker_testserver.sh). The script gets SHA-1 +# of each server context as the tag of docker images. If one of the server +# contexts gets changes, please make sure to update this compose file as well. +# You can run command 'docker images' to list all the tag of test server images. +# For example: +# REPOSITORY TAG IMAGE ID +# qt-test-server-apache2 e2a70c8b169c204e762b375885bd3a26cc40ba48 2ad5c8720317 + +services: + apache2: + image: qt-test-server-apache2:e2a70c8b169c204e762b375885bd3a26cc40ba48 + container_name: qt-test-server-apache2 + domainname: *testdomain + hostname: apache2 + volumes: + - ./common:/common:ro + - ./apache2:/service:ro + entrypoint: common/startup.sh + command: [common/ssl.sh, service/apache2.sh] + + squid: + image: qt-test-server-squid:276768104d3bbf097f4f3d9f3dc472a067852094 + container_name: qt-test-server-squid + domainname: *testdomain + hostname: squid + depends_on: + - apache2 + external_links: + - apache2:apache2.test-net.qt + volumes: + - ./common:/common:ro + - ./squid:/service:ro + entrypoint: common/startup.sh + command: service/squid.sh + + vsftpd: + image: qt-test-server-vsftpd:ab7ecdbbace1bce7642a92ce04e9051c7630376c + container_name: qt-test-server-vsftpd + domainname: *testdomain + hostname: vsftpd + depends_on: + - squid + volumes: + - ./common:/common:ro + - ./vsftpd:/service:ro + entrypoint: common/startup.sh + command: service/vsftpd.sh + + ftp-proxy: + image: qt-test-server-ftp-proxy:4c5734fe60eb450cbf8a96165f67cba19851ec12 + container_name: qt-test-server-ftp-proxy + domainname: *testdomain + hostname: ftp-proxy + depends_on: + - vsftpd + external_links: + - vsftpd:vsftpd.test-net.qt + volumes: + - ./common:/common:ro + - ./ftp-proxy:/service:ro + entrypoint: common/startup.sh + command: service/ftp-proxy.sh + + danted: + image: qt-test-server-danted:8404549745b5601ec3d22dc019258b70438864de + container_name: qt-test-server-danted + domainname: *testdomain + hostname: danted + depends_on: + - apache2 + - vsftpd + - ftp-proxy + external_links: + - apache2:apache2.test-net.qt + - vsftpd:vsftpd.test-net.qt + - ftp-proxy:ftp-proxy.test-net.qt + volumes: + - ./common:/common:ro + - ./danted:/service:ro + entrypoint: common/startup.sh + command: service/danted.sh diff --git a/tests/testserver/ftp-proxy/ftp-proxy.sh b/tests/testserver/ftp-proxy/ftp-proxy.sh new file mode 100755 index 0000000000..087a7b7bcc --- /dev/null +++ b/tests/testserver/ftp-proxy/ftp-proxy.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +############################################################################# +## +## Copyright (C) 2018 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:GPL$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 or (at your option) any later version +## approved by the KDE Free Qt Foundation. The licenses are as published by +## the Free Software Foundation and appearing in the file LICENSE.GPL3 +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +set -ex + +# package ftp-proxy + +# install configurations and test data +sed -i 's/# AllowMagicUser\tno/AllowMagicUser\tyes/' /etc/proxy-suite/ftp-proxy.conf + +# enable service with installed configurations +ftp-proxy -d diff --git a/tests/testserver/squid/squid.sh b/tests/testserver/squid/squid.sh new file mode 100755 index 0000000000..8e413f2f14 --- /dev/null +++ b/tests/testserver/squid/squid.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +############################################################################# +## +## Copyright (C) 2018 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:GPL$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 or (at your option) any later version +## approved by the KDE Free Qt Foundation. The licenses are as published by +## the Free Software Foundation and appearing in the file LICENSE.GPL3 +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +set -ex + +# package squid + +# install configurations and test data +cp $TESTDATA/squid{,-authenticating-ntlm}.conf /etc/squid/ +sed -e 's,NAME=squid,NAME=squid-authenticating-ntlm,' \ + -e 's,CONFIG=/etc/squid/squid.conf,CONFIG=/etc/squid/squid-authenticating-ntlm.conf,' \ + -e 's,SQUID_ARGS="-YC -f $CONFIG",SQUID_ARGS="-D -YC -f $CONFIG",' \ + /etc/init.d/squid >/etc/init.d/squid-authenticating-ntlm +chmod +x /etc/init.d/squid-authenticating-ntlm + +# enable service with installed configurations +service squid start +service squid-authenticating-ntlm start diff --git a/tests/testserver/squid/testdata/squid-authenticating-ntlm.conf b/tests/testserver/squid/testdata/squid-authenticating-ntlm.conf new file mode 100644 index 0000000000..55a74498e9 --- /dev/null +++ b/tests/testserver/squid/testdata/squid-authenticating-ntlm.conf @@ -0,0 +1,41 @@ +pid_filename /var/run/squid-authenticating-ntlm.pid +access_log /var/log/squid/access-authenticating-ntlm.log +cache_log /var/log/squid/cache-authenticating-ntlm.log +cache_store_log /var/log/squid/store-authenticating-ntlm.log +http_port 3130 +hierarchy_stoplist cgi-bin ? +acl QUERY urlpath_regex cgi-bin \? +no_cache deny QUERY +refresh_pattern ^ftp: 1440 20% 10080 +refresh_pattern ^gopher: 1440 0% 1440 +refresh_pattern . 0 20% 4320 +acl port3130 myport 3130 +acl manager proto cache_object +acl localhost src 127.0.0.1/255.255.255.255 +acl to_localhost dst 127.0.0.0/8 +acl SSL_ports port 443 563 +acl Safe_ports port 80 # http +acl Safe_ports port 21 # ftp +acl Safe_ports port 443 563 # https, snews +acl Safe_ports port 70 # gopher +acl Safe_ports port 210 # wais +acl Safe_ports port 1025-65535 # unregistered ports +acl Safe_ports port 280 # http-mgmt +acl Safe_ports port 488 # gss-http +acl Safe_ports port 591 # filemaker +acl Safe_ports port 777 # multiling http +acl CONNECT method CONNECT +http_access allow manager localhost +http_access deny manager +http_access allow localhost + + +# port 3130: ntlm auth +auth_param ntlm program /usr/lib/squid/ntlm_smb_lm_auth --debuglevel=5 --logfile=/var/log/ntlm --log-basename=/var/log/ntlm --helper-protocol=squid-2.5-ntlmssp +auth_param ntlm children 2 +acl ntlm_users proxy_auth REQUIRED +http_access allow port3130 ntlm_users +http_reply_access allow port3130 ntlm_users + +icp_access allow all +coredump_dir /var/cache/squid diff --git a/tests/testserver/squid/testdata/squid.conf b/tests/testserver/squid/testdata/squid.conf new file mode 100644 index 0000000000..da1b13af8c --- /dev/null +++ b/tests/testserver/squid/testdata/squid.conf @@ -0,0 +1,46 @@ +http_port 3128 +http_port 3129 +hierarchy_stoplist cgi-bin ? +acl QUERY urlpath_regex cgi-bin \? +no_cache deny QUERY +refresh_pattern ^ftp: 1440 20% 10080 +refresh_pattern ^gopher: 1440 0% 1440 +refresh_pattern . 0 20% 4320 +acl port3128 myport 3128 +acl port3129 myport 3129 +acl manager proto cache_object +acl localhost src 127.0.0.1/255.255.255.255 +acl to_localhost dst 127.0.0.0/8 +acl SSL_ports port 443 563 +acl Safe_ports port 80 # http +acl Safe_ports port 21 # ftp +acl Safe_ports port 443 563 # https, snews +acl Safe_ports port 70 # gopher +acl Safe_ports port 210 # wais +acl Safe_ports port 1025-65535 # unregistered ports +acl Safe_ports port 280 # http-mgmt +acl Safe_ports port 488 # gss-http +acl Safe_ports port 591 # filemaker +acl Safe_ports port 777 # multiling http +acl CONNECT method CONNECT +http_access allow manager localhost +http_access deny manager +http_access allow localhost + + +# port 3128: no auth required +http_access allow port3128 +http_reply_access allow port3128 + +# port 3129: basic auth +auth_param basic program /usr/lib/squid/basic_ncsa_auth /home/qt-test-server/passwords +auth_param basic children 5 +auth_param basic realm Squid proxy-caching web server +auth_param basic credentialsttl 2 hours +auth_param basic casesensitive off +acl ncsa_users proxy_auth REQUIRED +http_access allow port3129 ncsa_users +http_reply_access allow port3129 ncsa_users + +icp_access allow all +coredump_dir /var/cache/squid diff --git a/tests/testserver/vsftpd/testdata/ftp/pub/file-not-readable.txt b/tests/testserver/vsftpd/testdata/ftp/pub/file-not-readable.txt new file mode 100644 index 0000000000..235fa4d28b --- /dev/null +++ b/tests/testserver/vsftpd/testdata/ftp/pub/file-not-readable.txt @@ -0,0 +1 @@ +If you can read this, you are too close. diff --git a/tests/testserver/vsftpd/testdata/vsftpd.conf b/tests/testserver/vsftpd/testdata/vsftpd.conf new file mode 100644 index 0000000000..6bdb186c9f --- /dev/null +++ b/tests/testserver/vsftpd/testdata/vsftpd.conf @@ -0,0 +1,112 @@ +# Allow anonymous FTP? (Beware - allowed by default if you comment this out). +anonymous_enable=YES +# +# Uncomment this to allow local users to log in. +local_enable=YES +# +# Uncomment this to enable any form of FTP write command. +write_enable=YES +# +# Default umask for local users is 077. You may wish to change this to 022, +# if your users expect that (022 is used by most other ftpd's) +local_umask=022 +# +# Uncomment this to allow the anonymous FTP user to upload files. This only +# has an effect if the above global write enable is activated. Also, you will +# obviously need to create a directory writable by the FTP user. +anon_upload_enable=YES +anon_umask=022 +# +# Uncomment this if you want the anonymous FTP user to be able to create +# new directories. +anon_mkdir_write_enable=YES +anon_other_write_enable=YES +anon_world_readable_only=YES +# +# Activate directory messages - messages given to remote users when they +# go into a certain directory. +dirmessage_enable=YES +# +# Activate logging of uploads/downloads. +xferlog_enable=YES +# +# Make sure PORT transfer connections originate from port 20 (ftp-data). +connect_from_port_20=YES +# +# If you want, you can arrange for uploaded anonymous files to be owned by +# a different user. Note! Using "root" for uploaded files is not +# recommended! +#chown_uploads=YES +#chown_username=ftp +#chown_groupname=ftp +# +# You may override where the log file goes if you like. The default is shown +# below. +#xferlog_file=/var/log/vsftpd.log +# +# If you want, you can have your log file in standard ftpd xferlog format +xferlog_std_format=YES +# +# You may change the default value for timing out an idle session. +#idle_session_timeout=600 +# +# You may change the default value for timing out a data connection. +#data_connection_timeout=120 +# +# It is recommended that you define on your system a unique user which the +# ftp server can use as a totally isolated and unprivileged user. +#nopriv_user=ftpsecure +# +# Enable this and the server will recognize asynchronous ABOR requests. Not +# recommended for security (the code is non-trivial). Not enabling it, +# however, may confuse older FTP clients. +#async_abor_enable=YES +# +# By default the server will pretend to allow ASCII mode but in fact ignore +# the request. Turn on the below options to have the server actually do ASCII +# mangling on files when in ASCII mode. +# Beware that on some FTP servers, ASCII support allows a denial of service +# attack (DoS) via the command "SIZE /big/file" in ASCII mode. vsftpd +# predicted this attack and has always been safe, reporting the size of the +# raw file. +# ASCII mangling is a horrible feature of the protocol. +ascii_upload_enable=YES +ascii_download_enable=YES +# +# You may fully customize the login banner string: +#ftpd_banner=Welcome to blah FTP service. +# +# You may specify a file of disallowed anonymous e-mail addresses. Apparently +# useful for combatting certain DoS attacks. +#deny_email_enable=YES +# (default follows) +#banned_email_file=/etc/vsftpd/banned_emails +# +# You may specify an explicit list of local users to chroot() to their home +# directory. If chroot_local_user is YES, then this list becomes a list of +# users to NOT chroot(). +#chroot_list_enable=YES +# (default follows) +#chroot_list_file=/etc/vsftpd/chroot_list +# +# You may activate the "-R" option to the builtin ls. This is disabled by +# default to avoid remote users being able to cause excessive I/O on large +# sites. However, some broken FTP clients such as "ncftp" and "mirror" assume +# the presence of the "-R" option, so there is a strong case for enabling it. +ls_recurse_enable=YES + +pam_service_name=vsftpd +userlist_enable=YES +#enable for standalone mode +listen=YES +tcp_wrappers=YES + +# Enabling SFTP +#ssl_enable=YES +#allow_anon_ssl=YES +#force_local_data_ssl=NO +#force_local_logins_ssl=NO +#ssl_tlsv1=YES +#ssl_sslv2=NO +#ssl_sslv3=NO +#rsa_cert_file=/etc/vsftpd/vsftpd.pem diff --git a/tests/testserver/vsftpd/testdata/vsftpd.user_list b/tests/testserver/vsftpd/testdata/vsftpd.user_list new file mode 100644 index 0000000000..d283e3d260 --- /dev/null +++ b/tests/testserver/vsftpd/testdata/vsftpd.user_list @@ -0,0 +1,20 @@ +# vsftpd userlist +# If userlist_deny=NO, only allow users in this file +# If userlist_deny=YES (default), never allow users in this file, and +# do not even prompt for a password. +# Note that the default vsftpd pam config also checks /etc/vsftpd.ftpusers +# for users that are denied. +root +bin +daemon +adm +lp +sync +shutdown +halt +mail +news +uucp +operator +games +nobody diff --git a/tests/testserver/vsftpd/vsftpd.sh b/tests/testserver/vsftpd/vsftpd.sh new file mode 100755 index 0000000000..1ba1a8c347 --- /dev/null +++ b/tests/testserver/vsftpd/vsftpd.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash + +############################################################################# +## +## Copyright (C) 2018 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:GPL$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 or (at your option) any later version +## approved by the KDE Free Qt Foundation. The licenses are as published by +## the Free Software Foundation and appearing in the file LICENSE.GPL3 +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +set -ex + +# package vsftpd + +# add users +usermod -d "/home/$USER/ftp/" ftp #existing user +useradd -d "/home/$USER/ftp" -s /bin/bash ftptest; echo "ftptest:$PASS" | chpasswd + +# install configurations and test data +cp $TESTDATA/vsftpd.{conf,user_list} /etc/ + +# Resolve error message "vsftpd failed - probably invalid config" during boot +command='start-stop-daemon --start --background -m --oknodo --pidfile /var/run/vsftpd/vsftpd.pid' +command+=' --exec ${DAEMON}' +sed -i "s,$command.*$,$command; sleep 1," /etc/init.d/vsftpd + +# Populate the FTP sites: +su $USER -c "cp -r $TESTDATA/ftp ~/ftp" +ln -s /home/$USER/ftp /var/ftp + +# tst_QNetworkReply::getFromFtp_data() +su $USER -c "mkdir -p ~/ftp/qtest/" +su $USER -c "cp rfc3252.txt ~/ftp/qtest/"; rm rfc3252.txt + +# Duplicate rfc3252.txt 20 times for bigfile tests: +su $USER -c "seq 20 | xargs -i cat ~/ftp/qtest/rfc3252.txt >> ~/ftp/qtest/bigfile" + +# tst_QNetworkReply::getErrors_data(), testdata with special permissions +su $USER -c "chmod 0600 ~/ftp/pub/file-not-readable.txt" + +# Shared FTP folder (sticky bit) +su $USER -c "mkdir -p -m 1777 ~/ftp/qtest/upload" # FTP incoming dir + +# enable service with installed configurations +service vsftpd restart