summaryrefslogtreecommitdiff
path: root/test/basicserver/testbasicserver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/basicserver/testbasicserver.cpp')
-rw-r--r--test/basicserver/testbasicserver.cpp205
1 files changed, 195 insertions, 10 deletions
diff --git a/test/basicserver/testbasicserver.cpp b/test/basicserver/testbasicserver.cpp
index 6f2def54..9285dfc9 100644
--- a/test/basicserver/testbasicserver.cpp
+++ b/test/basicserver/testbasicserver.cpp
@@ -15,18 +15,17 @@
#include <typeinfo>
-#include "Test.h"
-#include "Daemon.h"
+#include "CollectInBufferStream.h"
#include "Configuration.h"
-#include "ServerStream.h"
-#include "SocketStream.h"
+#include "Daemon.h"
#include "IOStreamGetLine.h"
+#include "ServerControl.h"
+#include "ServerStream.h"
#include "ServerTLS.h"
-#include "CollectInBufferStream.h"
-
+#include "SocketStream.h"
+#include "Test.h"
#include "TestContext.h"
#include "autogen_TestProtocol.h"
-#include "ServerControl.h"
#include "MemLeakFindOn.h"
@@ -98,7 +97,7 @@ void testservers_connection(SocketStream &rStream)
while(!getline.IsEOF())
{
std::string line;
- while(!getline.GetLine(line))
+ while(!getline.GetLine(line, false, SHORT_TIMEOUT))
;
if(line == "QUIT")
{
@@ -208,11 +207,16 @@ const ConfigurationVerify *testserver::GetConfigVerify() const
}
};
+ static ConfigurationVerifyKey root_keys[] =
+ {
+ ssl_security_level_key,
+ };
+
static ConfigurationVerify verify =
{
"root", /* mName */
verifyserver, /* mpSubConfigurations */
- 0, /* mpKeys */
+ root_keys, // mpKeys
ConfigTest_Exists | ConfigTest_LastEntry,
0
};
@@ -449,6 +453,151 @@ void TestStreamReceive(TestProtocolClient &protocol, int value, bool uncertainst
TEST_THAT(count == (24273*3)); // over 64 k of data, definately
}
+bool test_security_level(int cert_level, int test_level, bool expect_failure_on_connect = false)
+{
+ int old_num_failures = num_failures;
+
+ // Context first
+ TLSContext context;
+ if(cert_level == 0)
+ {
+ context.Initialise(false /* client */,
+ "testfiles/clientCerts.pem",
+ "testfiles/clientPrivKey.pem",
+ "testfiles/clientTrustedCAs.pem",
+ test_level); // SecurityLevel
+ }
+ else if(cert_level == 1)
+ {
+ context.Initialise(false /* client */,
+ "testfiles/seclevel2-sha1/ca/clients/1234567-cert.pem",
+ "testfiles/seclevel2-sha1/bbackupd/1234567-key.pem",
+ "testfiles/seclevel2-sha1/ca/roots/serverCA.pem",
+ test_level); // SecurityLevel
+ }
+ else if(cert_level == 2)
+ {
+ context.Initialise(false /* client */,
+ "testfiles/seclevel2-sha256/ca/clients/1234567-cert.pem",
+ "testfiles/seclevel2-sha256/bbackupd/1234567-key.pem",
+ "testfiles/seclevel2-sha256/ca/roots/serverCA.pem",
+ test_level); // SecurityLevel
+ }
+ else
+ {
+ TEST_FAIL_WITH_MESSAGE("No certificates generated for level " << cert_level);
+ return false;
+ }
+
+ SocketStreamTLS conn;
+
+ if(expect_failure_on_connect)
+ {
+ TEST_CHECK_THROWS(
+ conn.Open(context, Socket::TypeINET, "localhost", 2003),
+ ConnectionException, TLSPeerWeakCertificate);
+ }
+ else
+ {
+ conn.Open(context, Socket::TypeINET, "localhost", 2003);
+ }
+
+ return (num_failures == old_num_failures); // no new failures -> good
+}
+
+// Test the certificates that were distributed with the Box Backup source since ancient times,
+// which have only 1024-bit keys, and thus fail with "ee key too small".
+bool test_ancient_certificates()
+{
+ int old_num_failures = num_failures;
+
+ // Level -1 (allow weaker, with warning) should pass with any certificates:
+ TEST_THAT(test_security_level(0, -1)); // cert_level, test_level
+
+ // We do not test level 0 (system-wide default) because the system
+ // may have it set high, and our old certificate will not be usable
+ // in that case, and the user has no way to fix that, so it's not a
+ // useful test.
+
+ // Level 1 (allow weaker, without a warning) should pass with any certificates:
+ TEST_THAT(test_security_level(0, 1)); // cert_level, test_level
+
+#ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL
+ // Level 2 (disallow weaker, without a warning) should NOT pass with old certificates:
+ TEST_CHECK_THROWS(
+ test_security_level(0, 2), // cert_level, test_level
+ ServerException, TLSServerWeakCertificate);
+#else
+ // We have no way to increase the security level, so it should still pass:
+ test_security_level(0, 2); // cert_level, test_level
+#endif
+
+ return (num_failures == old_num_failures); // no new failures -> good
+}
+
+// Test a set of more recent certificates, which have a longer key but are signed using the SHA1
+// algorithm instead of SHA256, which fail with "ca md too weak" instead.
+bool test_old_certificates()
+{
+ int old_num_failures = num_failures;
+
+ // Level -1 (allow weaker, with warning) should pass with any certificates:
+ TEST_THAT(test_security_level(1, -1)); // cert_level, test_level
+
+ // We do not test level 0 (system-wide default) because the system
+ // may have it set high, and our old certificate will not be usable
+ // in that case, and the user has no way to fix that, so it's not a
+ // useful test.
+
+ // Level 1 (allow weaker, without a warning) should pass with any certificates:
+ TEST_THAT(test_security_level(1, 1)); // cert_level, test_level
+
+#ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL
+ // Level 2 (disallow weaker, without a warning) should NOT pass with old certificates:
+ TEST_CHECK_THROWS(
+ test_security_level(1, 2), // cert_level, test_level
+ ServerException, TLSServerWeakCertificate);
+#else
+ // We have no way to increase the security level, so it should still pass:
+ test_security_level(1, 2); // cert_level, test_level
+#endif
+
+ return (num_failures == old_num_failures); // no new failures -> good
+}
+
+
+bool test_new_certificates(bool expect_failure_level_2)
+{
+ int old_num_failures = num_failures;
+
+ // Level -1 (allow weaker, with warning) should pass with any certificates:
+ TEST_THAT(test_security_level(2, -1)); // cert_level, test_level
+
+ // Level 0 (system dependent). This will fail if the user (or their
+ // distro) sets the system-wide security level very high. We check
+ // this because *we* may need to update Box Backup if this happens
+ // again, as it did when Debian increased the default level.
+ // Newly generated certificates may need to be strengthened.
+ // And we may need to update the documentation.
+ TEST_THAT(test_security_level(2, 0)); // cert_level, test_level
+
+ // Level 1 (allow weaker, without a warning) should pass with any certificates:
+ TEST_THAT(test_security_level(2, 1)); // cert_level, test_level
+
+#ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL
+ // Level 2 (disallow weaker, without a warning) should pass with new certificates,
+ // but might fail to connect to a peer with weak (insecure) certificates:
+ TEST_THAT(test_security_level(2, 2, expect_failure_level_2));
+ // cert_level, test_level, expect_failure
+#else
+ // We have no way to increase the security level, so it should not fail to connect to a
+ // daemon with weak certificates:
+ test_security_level(2, 2, false); // cert_level, test_level, expect_failure
+#endif
+
+ return (num_failures == old_num_failures); // no new failures -> good
+}
+
int test(int argc, const char *argv[])
{
@@ -644,6 +793,7 @@ int test(int argc, const char *argv[])
"testfiles/clientCerts.pem",
"testfiles/clientPrivKey.pem",
"testfiles/clientTrustedCAs.pem");
+ // SecurityLevel == -1 by default (old security + warnings)
SocketStreamTLS conn1;
conn1.Open(context, Socket::TypeINET, "localhost", 2003);
@@ -682,6 +832,11 @@ int test(int argc, const char *argv[])
TEST_THAT(ServerIsAlive(pid));
#endif
+ // Try testing with different security levels, check that the behaviour is
+ // as documented at:
+ // https://github.com/boxbackup/boxbackup/wiki/WeakSSLCertificates
+ TEST_THAT(test_ancient_certificates());
+
// Kill it
TEST_THAT(KillServer(pid));
::sleep(1);
@@ -691,6 +846,36 @@ int test(int argc, const char *argv[])
TestRemoteProcessMemLeaks("test-srv3.memleaks");
#endif
}
+
+ cmd = TEST_EXECUTABLE " --test-daemon-args=";
+ cmd += test_args;
+ cmd += " srv3 testfiles/srv3-seclevel2-sha1.conf";
+ pid = LaunchServer(cmd, "testfiles/srv3.pid");
+
+ TEST_THAT(pid != -1 && pid != 0);
+ TEST_THAT(test_old_certificates());
+ TEST_THAT(KillServer(pid));
+
+ cmd = TEST_EXECUTABLE " --test-daemon-args=";
+ cmd += test_args;
+ cmd += " srv3 testfiles/srv3-seclevel2-sha256.conf";
+ pid = LaunchServer(cmd, "testfiles/srv3.pid");
+
+ TEST_THAT(pid != -1 && pid != 0);
+ TEST_THAT(test_new_certificates(false)); // !expect_failure_level_2
+ TEST_THAT(KillServer(pid));
+
+ // Start a daemon using old, insecure certificates. We should get an error when we
+ // try to connect to it:
+
+ cmd = TEST_EXECUTABLE " --test-daemon-args=";
+ cmd += test_args;
+ cmd += " srv3 testfiles/srv3-insecure-daemon.conf";
+ pid = LaunchServer(cmd, "testfiles/srv3.pid");
+
+ TEST_THAT(pid != -1 && pid != 0);
+ TEST_THAT(test_new_certificates(true)); // expect_failure_level_2
+ TEST_THAT(KillServer(pid));
}
//protocolserver:
@@ -698,7 +883,7 @@ int test(int argc, const char *argv[])
{
std::string cmd = TEST_EXECUTABLE " --test-daemon-args=";
cmd += test_args;
- cmd += " srv4 testfiles/srv4.conf";
+ cmd += " srv4 testfiles/srv4-seclevel1.conf";
int pid = LaunchServer(cmd, "testfiles/srv4.pid");
TEST_THAT(pid != -1 && pid != 0);