Skip to content

Commit af5d513

Browse files
tls: test multiple certificates with client preference selection
Add tests to verify that when multiple certificates (RSA and ECDSA) are configured, the server correctly selects the certificate based on the client's signature algorithm preferences. Assisted-by: Claude <noreply@anthropic.com>
1 parent 1ce3504 commit af5d513

File tree

1 file changed

+71
-16
lines changed

1 file changed

+71
-16
lines changed

src/tls/test-server.c

Lines changed: 71 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
/* this has a corresponding mock-server.key */
3232
#define CERTFILE SRCDIR "/test/data/mock-server.crt"
3333
#define KEYFILE SRCDIR "/test/data/mock-server.key"
34+
#define ECC_CERTFILE SRCDIR "/test/data/mock-ecc.crt"
35+
#define ECC_KEYFILE SRCDIR "/test/data/mock-ecc.key"
3436

3537
#define CLIENT_CERTFILE SRCDIR "/src/tls/ca/alice.pem"
3638
#define CLIENT_KEYFILE SRCDIR "/src/tls/ca/alice.key"
@@ -50,11 +52,15 @@ typedef struct {
5052
typedef struct {
5153
const char *certfile;
5254
const char *keyfile;
55+
const char *certfile2;
56+
const char *keyfile2;
5357
int cert_request_mode;
5458
int idle_timeout;
5559
const char *client_crt;
5660
const char *client_key;
5761
const char *client_fingerprint;
62+
const char *priority;
63+
int expected_pk_algo;
5864
} TestFixture;
5965

6066
static const TestFixture fixture_separate_crt_key = {
@@ -93,6 +99,24 @@ static const TestFixture fixture_run_idle = {
9399
.idle_timeout = 1,
94100
};
95101

102+
static const TestFixture fixture_multiple_certs_ecdsa = {
103+
.certfile = CERTFILE,
104+
.keyfile = KEYFILE,
105+
.certfile2 = ECC_CERTFILE,
106+
.keyfile2 = ECC_KEYFILE,
107+
.priority = "NORMAL:-SIGN-ALL:+SIGN-ECDSA-SECP256R1-SHA256",
108+
.expected_pk_algo = GNUTLS_PK_ECDSA,
109+
};
110+
111+
static const TestFixture fixture_multiple_certs_rsa = {
112+
.certfile = CERTFILE,
113+
.keyfile = KEYFILE,
114+
.certfile2 = ECC_CERTFILE,
115+
.keyfile2 = ECC_KEYFILE,
116+
.priority = "NORMAL:-SIGN-ALL:+SIGN-RSA-SHA256:+SIGN-RSA-PSS-RSAE-SHA256",
117+
.expected_pk_algo = GNUTLS_PK_RSA,
118+
};
119+
96120
/* for forking test cases, where server's SIGCHLD handling gets in the way */
97121
static void
98122
block_sigchld (void)
@@ -296,7 +320,10 @@ assert_https_outcome (TestCase *tc,
296320

297321
g_assert_cmpint (gnutls_init (&session, GNUTLS_CLIENT), ==, GNUTLS_E_SUCCESS);
298322
gnutls_transport_set_int (session, fd);
299-
g_assert_cmpint (gnutls_set_default_priority (session), ==, GNUTLS_E_SUCCESS);
323+
if (fixture && fixture->priority)
324+
g_assert_cmpint (gnutls_priority_set_direct (session, fixture->priority, NULL), ==, GNUTLS_E_SUCCESS);
325+
else
326+
g_assert_cmpint (gnutls_set_default_priority (session), ==, GNUTLS_E_SUCCESS);
300327
gnutls_handshake_set_timeout(session, 5000);
301328
g_assert_cmpint (gnutls_certificate_allocate_credentials (&xcred), ==, GNUTLS_E_SUCCESS);
302329
g_assert_cmpint (gnutls_certificate_set_x509_system_trust (xcred), >=, 0);
@@ -325,6 +352,17 @@ assert_https_outcome (TestCase *tc,
325352
g_assert (server_certs);
326353
g_assert_cmpuint (server_certs_len, ==, expected_server_certs);
327354

355+
/* check server certificate algorithm if requested */
356+
if (fixture && fixture->expected_pk_algo)
357+
{
358+
gnutls_x509_crt_t cert;
359+
g_assert_cmpint (gnutls_x509_crt_init (&cert), ==, GNUTLS_E_SUCCESS);
360+
g_assert_cmpint (gnutls_x509_crt_import (cert, &server_certs[0], GNUTLS_X509_FMT_DER),
361+
==, GNUTLS_E_SUCCESS);
362+
g_assert_cmpint (gnutls_x509_crt_get_pk_algorithm (cert, NULL), ==, fixture->expected_pk_algo);
363+
gnutls_x509_crt_deinit (cert);
364+
}
365+
328366
/* send request, read response */
329367
len = gnutls_record_send (session, request, sizeof (request));
330368
if (len < 0 && expect_tls_failure)
@@ -435,13 +473,20 @@ setup (TestCase *tc, gconstpointer data)
435473

436474
if (fixture && fixture->certfile)
437475
{
438-
/* Set up certs directory with 0.cert and 0.key */
476+
/* Set up certs directory with 0.crt and 0.key */
439477
g_autofree gchar *certs_dir = g_build_filename (tc->runtime_dir, "tls/server", NULL);
440-
g_assert_cmpint (g_mkdir (certs_dir, 0700), ==, 0);
441-
g_autofree gchar *cert_link = g_build_filename (certs_dir, "0.crt", NULL);
442-
g_autofree gchar *key_link = g_build_filename (certs_dir, "0.key", NULL);
443-
g_assert_cmpint (symlink (fixture->certfile, cert_link), ==, 0);
444-
g_assert_cmpint (symlink (fixture->keyfile, key_link), ==, 0);
478+
g_assert_cmpint (g_mkdir_with_parents (certs_dir, 0700), ==, 0);
479+
480+
const char *sources[] = { fixture->certfile, fixture->keyfile,
481+
fixture->certfile2, fixture->keyfile2 };
482+
const char *dests[] = { "0.crt", "0.key", "1.crt", "1.key" };
483+
for (int i = 0; i < G_N_ELEMENTS (sources) && sources[i]; i++)
484+
{
485+
g_autofree gchar *contents = NULL;
486+
g_autofree gchar *dest = g_build_filename (certs_dir, dests[i], NULL);
487+
g_assert (g_file_get_contents (sources[i], &contents, NULL, NULL));
488+
g_assert (g_file_set_contents (dest, contents, -1, NULL));
489+
}
445490

446491
int cert_dirfd = open (certs_dir, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
447492
g_assert_cmpint (cert_dirfd, >=, 0);
@@ -494,17 +539,23 @@ teardown (TestCase *tc, gconstpointer data)
494539
g_assert_cmpint (g_rmdir (tc->clients_dir), ==, 0);
495540
g_free (tc->clients_dir);
496541

497-
/* Clean up certs.d if it exists */
498-
g_autofree gchar *certs_dir = g_build_filename (tc->runtime_dir, "certs.d", NULL);
499-
if (g_file_test (certs_dir, G_FILE_TEST_IS_DIR))
542+
/* Clean up tls dir if it exists */
543+
g_autofree gchar *tls_dir = g_build_filename (tc->runtime_dir, "tls", NULL);
544+
if (g_file_test (tls_dir, G_FILE_TEST_IS_DIR))
500545
{
501-
g_autofree gchar *cert_file = g_build_filename (certs_dir, "0.crt", NULL);
502-
g_autofree gchar *key_file = g_build_filename (certs_dir, "0.key", NULL);
503-
g_unlink (cert_file);
504-
g_unlink (key_file);
505-
g_assert_cmpint (g_rmdir (certs_dir), ==, 0);
546+
g_autofree gchar *certs_dir = g_build_filename (tls_dir, "server", NULL);
547+
if (g_file_test (certs_dir, G_FILE_TEST_IS_DIR))
548+
{
549+
const char *files[] = { "0.crt", "0.key", "1.crt", "1.key", NULL };
550+
for (int i = 0; files[i]; i++)
551+
{
552+
g_autofree gchar *path = g_build_filename (certs_dir, files[i], NULL);
553+
g_unlink (path);
554+
}
555+
g_assert_cmpint (g_rmdir (certs_dir), ==, 0);
556+
}
557+
g_assert_cmpint (g_rmdir (tls_dir), ==, 0);
506558
}
507-
508559
g_assert_cmpint (g_rmdir (tc->runtime_dir), ==, 0);
509560
g_free (tc->runtime_dir);
510561

@@ -911,6 +962,10 @@ main (int argc, char *argv[])
911962
setup, test_tls_blocked_handshake, teardown);
912963
g_test_add ("/server/mixed-protocols", TestCase, &fixture_separate_crt_key,
913964
setup, test_mixed_protocols, teardown);
965+
g_test_add ("/server/tls/multiple-certs/ecdsa", TestCase, &fixture_multiple_certs_ecdsa,
966+
setup, test_tls_no_client_cert, teardown);
967+
g_test_add ("/server/tls/multiple-certs/rsa", TestCase, &fixture_multiple_certs_rsa,
968+
setup, test_tls_no_client_cert, teardown);
914969
g_test_add ("/server/run-idle", TestCase, &fixture_run_idle,
915970
setup, test_run_idle, teardown);
916971
g_test_add ("/server/ipv4/connection", TestCase, NULL,

0 commit comments

Comments
 (0)