Browse Source

add test for Basic Authentication scheme

Git-Dch: Ignore
tags/debian/1.1.exp8
David Kalnischkies 7 years ago
parent
commit
b0314abb0c
5 changed files with 219 additions and 16 deletions
  1. +21
    -10
      test/integration/framework
  2. +6
    -1
      test/integration/test-apt-cdrom
  3. +106
    -0
      test/integration/test-authentication-basic
  4. +71
    -4
      test/interactive-helper/aptwebserver.cc
  5. +15
    -1
      test/libapt/strutil_test.cc

+ 21
- 10
test/integration/framework View File

@@ -944,23 +944,35 @@ signreleasefiles() {
}

webserverconfig() {
msgtest "Set webserver config option '${1}' to" "$2"
local NOCHECK=false
if [ "$1" = '--no-check' ]; then
NOCHECK=true
shift
fi
local DOWNLOG='rootdir/tmp/download-testfile.log'
local STATUS='rootdir/tmp/webserverconfig.status'
local STATUS='downloaded/webserverconfig.status'
rm -f "$STATUS" "$DOWNLOG"
if downloadfile "http://localhost:8080/_config/set/${1}/${2}" "$STATUS" > "$DOWNLOG"; then
local URI
if [ -n "$2" ]; then
msgtest "Set webserver config option '${1}' to" "$2"
URI="http://localhost:8080/_config/set/${1}/${2}"
else
msgtest 'Clear webserver config option' "${1}"
URI="http://localhost:8080/_config/clear/${1}"
fi
if downloadfile "$URI" "$STATUS" > "$DOWNLOG"; then
msgpass
else
cat "$DOWNLOG" "$STATUS"
cat "$DOWNLOG" "$STATUS" || true
msgfail
fi
testwebserverlaststatuscode '200'
$NOCHECK || testwebserverlaststatuscode '200'
}

rewritesourceslist() {
local APTARCHIVE="file://$(readlink -f "${TMPWORKINGDIRECTORY}/aptarchive")"
for LIST in $(find rootdir/etc/apt/sources.list.d/ -name 'apt-test-*.list'); do
sed -i $LIST -e "s#$APTARCHIVE#${1}#" -e "s#http://localhost:8080/#${1}#" -e "s#http://localhost:4433/#${1}#"
sed -i $LIST -e "s#$APTARCHIVE#${1}#" -e "s#http://localhost:8080/#${1}#" -e "s#https://localhost:4433/#${1}#"
done
}

@@ -1047,7 +1059,7 @@ acquire::cdrom::autodetect 0;" > rootdir/etc/apt/apt.conf.d/00cdrom
mv "${CD}" "${CD}-unmounted"
# we don't want the disk to be modifiable
addtrap 'prefix' "chmod -f -R +w $PWD/rootdir/media/cdrom/dists/ $PWD/rootdir/media/cdrom-unmounted/dists/ || true;"
chmod -R -w rootdir/media/cdrom-unmounted/dists
chmod -R 555 rootdir/media/cdrom-unmounted/dists
}

downloadfile() {
@@ -1055,7 +1067,7 @@ downloadfile() {
apthelper -o Debug::Acquire::${PROTO}=1 \
download-file "$1" "$2" 2>&1 || true
# only if the file exists the download was successful
if [ -e "$2" ]; then
if [ -r "$2" ]; then
return 0
else
return 1
@@ -1312,8 +1324,7 @@ testwebserverlaststatuscode() {
local STATUS='downloaded/webserverstatus-statusfile.log'
rm -f "$DOWNLOG" "$STATUS"
msgtest 'Test last status code from the webserver was' "$1"
downloadfile "http://localhost:8080/_config/find/aptwebserver::last-status-code" "$STATUS" > "$DOWNLOG"
if [ "$(cat "$STATUS")" = "$1" ]; then
if downloadfile "http://localhost:8080/_config/find/aptwebserver::last-status-code" "$STATUS" > "$DOWNLOG" && [ "$(cat "$STATUS")" = "$1" ]; then
msgpass
else
echo >&2


+ 6
- 1
test/integration/test-apt-cdrom View File

@@ -21,7 +21,7 @@ echo 'Description-de: automatisch generiertes Testpaket testing=0.8.15/stable
' >> Translation-de
compressfile Translation-de
rm -f Translation-en Translation-de
chmod -R -w .
chmod -R 555 .
cd - > /dev/null

aptcdromlog() {
@@ -144,3 +144,8 @@ testcdromusage
testsuccess aptget update
testfileequal rootdir/tmp/testsuccess.output 'Reading package lists...'
testcdromusage

msgmsg 'Check that nothing touched our' 'CD-ROM'
for file in $(find rootdir/media/cdrom-unmounted/dists); do
testfilestats "$file" '%U:%G:%a' '=' "${USER}:${USER}:555"
done

+ 106
- 0
test/integration/test-authentication-basic View File

@@ -0,0 +1,106 @@
#!/bin/sh
set -e

TESTDIR=$(readlink -f $(dirname $0))
. $TESTDIR/framework

setupenvironment
configarchitecture 'i386'

insertpackage 'unstable' 'foo' 'all' '1'
setupaptarchive --no-update

changetohttpswebserver --authorization="$(printf '%s' 'star:hunter2' | base64 )"

echo 'See, when YOU type hunter2, it shows to us as *******' > aptarchive/bash

testauthfailure() {
testfailure apthelper download-file "${1}/bash" ./downloaded/bash
# crappy test, but http and https output are wastely different…
testsuccess grep 401 rootdir/tmp/testfailure.output
testsuccess test ! -s ./downloaded/bash
}

testauthsuccess() {
testsuccess apthelper download-file "${1}/bash" ./downloaded/bash
testfileequal ./downloaded/bash "$(cat aptarchive/bash)"
testfilestats ./downloaded/bash '%U:%G:%a' '=' "${USER}:${USER}:644"
rm -f ./downloaded/bash

# lets see if got/retains acceptable permissions
if [ -n "$AUTHCONF" ]; then
if [ "$(id -u)" = '0' ]; then
testfilestats "$AUTHCONF" '%U:%G:%a' '=' "_apt:root:600"
else
testfilestats "$AUTHCONF" '%U:%G:%a' '=' "${USER}:${USER}:600"
fi
fi

rm -rf rootdir/var/lib/apt/lists
testsuccess aptget update
testequal 'Reading package lists...
Building dependency tree...
The following NEW packages will be installed:
foo
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Inst foo (1 unstable [all])
Conf foo (1 unstable [all])' aptget install foo -s
}

authfile() {
local AUTHCONF='rootdir/etc/apt/auth.conf'
rm -f "$AUTHCONF"
printf '%s' "$1" > "$AUTHCONF"
chmod 600 "$AUTHCONF"
}

runtest() {
# unauthorized fails
authfile ''
testauthfailure "$1"

# good auth
authfile 'machine localhost
login star
password hunter2'
testauthsuccess "$1"

# bad auth
authfile 'machine localhost
login anonymous
password hunter2'
testauthfailure "$1"

# 2 stanzas: unmatching + good auth
authfile 'machine debian.org
login debian
password jessie

machine localhost
login star
password hunter2'
testauthsuccess "$1"
}

msgmsg 'server basic auth'
rewritesourceslist 'http://localhost:8080'
runtest 'http://localhost:8080'
rewritesourceslist 'https://localhost:4433'
runtest 'https://localhost:4433'
rewritesourceslist 'http://localhost:8080'

msgmsg 'proxy to server basic auth'
webserverconfig 'aptwebserver::request::absolute' 'uri'
export http_proxy='http://localhost:8080'
runtest 'http://localhost:8080'
unset http_proxy

msgmsg 'proxy basic auth to server basic auth'
webserverconfig 'aptwebserver::proxy-authorization' "$(printf 'moon:deer2' | base64)"
export http_proxy='http://moon:deer2@localhost:8080'
runtest 'http://localhost:8080'

msgmsg 'proxy basic auth to server'
authfile ''
webserverconfig 'aptwebserver::authorization' ''
testauthsuccess 'http://localhost:8080'

+ 71
- 4
test/interactive-helper/aptwebserver.cc View File

@@ -157,9 +157,8 @@ static bool sendData(int const client, std::string const &data) /*{{{*/
}
/*}}}*/
static void sendError(int const client, int const httpcode, std::string const &request,/*{{{*/
bool content, std::string const &error = "")
bool content, std::string const &error = "", std::list<std::string> headers = std::list<std::string>())
{
std::list<std::string> headers;
std::string response("<html><head><title>");
response.append(httpcodeToStr(httpcode)).append("</title></head>");
response.append("<body><h1>").append(httpcodeToStr(httpcode)).append("</h1>");
@@ -367,22 +366,88 @@ static bool parseFirstLine(int const client, std::string const &request,/*{{{*/

// Proxies require absolute uris, so this is a simple proxy-fake option
std::string const absolute = _config->Find("aptwebserver::request::absolute", "uri,path");
if (strncmp(host.c_str(), filename.c_str(), host.length()) == 0)
if (strncmp(host.c_str(), filename.c_str(), host.length()) == 0 && APT::String::Startswith(filename, "/_config/") == false)
{
if (absolute.find("uri") == std::string::npos)
{
sendError(client, 400, request, sendContent, "Request is absoluteURI, but configured to not accept that");
return false;
}

// strip the host from the request to make it an absolute path
filename.erase(0, host.length());

std::string const authConf = _config->Find("aptwebserver::proxy-authorization", "");
std::string auth = LookupTag(request, "Proxy-Authorization", "");
if (authConf.empty() != auth.empty())
{
if (auth.empty())
sendError(client, 407, request, sendContent, "Proxy requires authentication");
else
sendError(client, 407, request, sendContent, "Client wants to authenticate to proxy, but proxy doesn't need it");
return false;
}
if (authConf.empty() == false)
{
char const * const basic = "Basic ";
if (strncmp(auth.c_str(), basic, strlen(basic)) == 0)
{
auth.erase(0, strlen(basic));
if (auth != authConf)
{
sendError(client, 407, request, sendContent, "Proxy-Authentication doesn't match");
return false;
}
}
else
{
std::list<std::string> headers;
headers.push_back("Proxy-Authenticate: Basic");
sendError(client, 407, request, sendContent, "Unsupported Proxy-Authentication Scheme", headers);
return false;
}
}
}
else if (absolute.find("path") == std::string::npos)
else if (absolute.find("path") == std::string::npos && APT::String::Startswith(filename, "/_config/") == false)
{
sendError(client, 400, request, sendContent, "Request is absolutePath, but configured to not accept that");
return false;
}

if (APT::String::Startswith(filename, "/_config/") == false)
{
std::string const authConf = _config->Find("aptwebserver::authorization", "");
std::string auth = LookupTag(request, "Authorization", "");
if (authConf.empty() != auth.empty())
{
if (auth.empty())
sendError(client, 401, request, sendContent, "Server requires authentication");
else
sendError(client, 401, request, sendContent, "Client wants to authenticate to server, but server doesn't need it");
return false;
}
if (authConf.empty() == false)
{
char const * const basic = "Basic ";
if (strncmp(auth.c_str(), basic, strlen(basic)) == 0)
{
auth.erase(0, strlen(basic));
if (auth != authConf)
{
sendError(client, 401, request, sendContent, "Authentication doesn't match");
return false;
}
}
else
{
std::list<std::string> headers;
headers.push_back("WWW-Authenticate: Basic");
sendError(client, 401, request, sendContent, "Unsupported Authentication Scheme", headers);
return false;
}
}
}

size_t paramspos = filename.find('?');
if (paramspos != std::string::npos)
{
@@ -656,6 +721,8 @@ int main(int const argc, const char * argv[])
CommandLine::Args Args[] = {
{0, "port", "aptwebserver::port", CommandLine::HasArg},
{0, "request-absolute", "aptwebserver::request::absolute", CommandLine::HasArg},
{0, "authorization", "aptwebserver::authorization", CommandLine::HasArg},
{0, "proxy-authorization", "aptwebserver::proxy-authorization", CommandLine::HasArg},
{'c',"config-file",0,CommandLine::ConfigFile},
{'o',"option",0,CommandLine::ArbItem},
{0,0,0,0}


+ 15
- 1
test/libapt/strutil_test.cc View File

@@ -85,7 +85,7 @@ TEST(StrUtilTest,EndsWith)
EXPECT_FALSE(Endswith("abcd", "x"));
EXPECT_FALSE(Endswith("abcd", "abcndefg"));
}
TEST(StrUtilTest,StartWith)
TEST(StrUtilTest,StartsWith)
{
using APT::String::Startswith;
EXPECT_TRUE(Startswith("abcd", "a"));
@@ -129,3 +129,17 @@ TEST(StrUtilTest,SubstVar)
EXPECT_EQ(" bb a bb a bb a bb ", SubstVar(" aaa a aaa a aaa a aaa ", "aaa", "bb"));

}
TEST(StrUtilTest,Base64Encode)
{
EXPECT_EQ("QWxhZGRpbjpvcGVuIHNlc2FtZQ==", Base64Encode("Aladdin:open sesame"));
EXPECT_EQ("cGxlYXN1cmUu", Base64Encode("pleasure."));
EXPECT_EQ("bGVhc3VyZS4=", Base64Encode("leasure."));
EXPECT_EQ("ZWFzdXJlLg==", Base64Encode("easure."));
EXPECT_EQ("YXN1cmUu", Base64Encode("asure."));
EXPECT_EQ("c3VyZS4=", Base64Encode("sure."));
EXPECT_EQ("dXJlLg==", Base64Encode("ure."));
EXPECT_EQ("cmUu", Base64Encode("re."));
EXPECT_EQ("ZS4=", Base64Encode("e."));
EXPECT_EQ("Lg==", Base64Encode("."));
EXPECT_EQ("", Base64Encode(""));
}

Loading…
Cancel
Save