xref: /qemu/tests/qtest/migration/tls-tests.c (revision c6e1f60cc73c787317316bb2956f9a95a5daee15)
1 /*
2  * QTest testcases for TLS migration
3  *
4  * Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates
5  *   based on the vhost-user-test.c that is:
6  *      Copyright (c) 2014 Virtual Open Systems Sarl.
7  *
8  * This work is licensed under the terms of the GNU GPL, version 2 or later.
9  * See the COPYING file in the top-level directory.
10  *
11  */
12 
13 #include "qemu/osdep.h"
14 #include "crypto/tlscredspsk.h"
15 #include "libqtest.h"
16 #include "migration/framework.h"
17 #include "migration/migration-qmp.h"
18 #include "migration/migration-util.h"
19 
20 #include "tests/unit/crypto-tls-psk-helpers.h"
21 #ifdef CONFIG_TASN1
22 # include "tests/unit/crypto-tls-x509-helpers.h"
23 #endif /* CONFIG_TASN1 */
24 
25 
26 struct TestMigrateTLSPSKData {
27     char *workdir;
28     char *workdiralt;
29     char *pskfile;
30     char *pskfilealt;
31 };
32 
33 static char *tmpfs;
34 
35 static void *
migrate_hook_start_tls_psk_common(QTestState * from,QTestState * to,bool mismatch)36 migrate_hook_start_tls_psk_common(QTestState *from,
37                                   QTestState *to,
38                                   bool mismatch)
39 {
40     struct TestMigrateTLSPSKData *data =
41         g_new0(struct TestMigrateTLSPSKData, 1);
42 
43     data->workdir = g_strdup_printf("%s/tlscredspsk0", tmpfs);
44     data->pskfile = g_strdup_printf("%s/%s", data->workdir,
45                                     QCRYPTO_TLS_CREDS_PSKFILE);
46     g_mkdir_with_parents(data->workdir, 0700);
47     test_tls_psk_init(data->pskfile);
48 
49     if (mismatch) {
50         data->workdiralt = g_strdup_printf("%s/tlscredspskalt0", tmpfs);
51         data->pskfilealt = g_strdup_printf("%s/%s", data->workdiralt,
52                                            QCRYPTO_TLS_CREDS_PSKFILE);
53         g_mkdir_with_parents(data->workdiralt, 0700);
54         test_tls_psk_init_alt(data->pskfilealt);
55     }
56 
57     qtest_qmp_assert_success(from,
58                              "{ 'execute': 'object-add',"
59                              "  'arguments': { 'qom-type': 'tls-creds-psk',"
60                              "                 'id': 'tlscredspsk0',"
61                              "                 'endpoint': 'client',"
62                              "                 'dir': %s,"
63                              "                 'username': 'qemu'} }",
64                              data->workdir);
65 
66     qtest_qmp_assert_success(to,
67                              "{ 'execute': 'object-add',"
68                              "  'arguments': { 'qom-type': 'tls-creds-psk',"
69                              "                 'id': 'tlscredspsk0',"
70                              "                 'endpoint': 'server',"
71                              "                 'dir': %s } }",
72                              mismatch ? data->workdiralt : data->workdir);
73 
74     migrate_set_parameter_str(from, "tls-creds", "tlscredspsk0");
75     migrate_set_parameter_str(to, "tls-creds", "tlscredspsk0");
76 
77     return data;
78 }
79 
80 static void *
migrate_hook_start_tls_psk_match(QTestState * from,QTestState * to)81 migrate_hook_start_tls_psk_match(QTestState *from,
82                                  QTestState *to)
83 {
84     return migrate_hook_start_tls_psk_common(from, to, false);
85 }
86 
87 static void *
migrate_hook_start_tls_psk_mismatch(QTestState * from,QTestState * to)88 migrate_hook_start_tls_psk_mismatch(QTestState *from,
89                                     QTestState *to)
90 {
91     return migrate_hook_start_tls_psk_common(from, to, true);
92 }
93 
94 static void
migrate_hook_end_tls_psk(QTestState * from,QTestState * to,void * opaque)95 migrate_hook_end_tls_psk(QTestState *from,
96                          QTestState *to,
97                          void *opaque)
98 {
99     struct TestMigrateTLSPSKData *data = opaque;
100 
101     test_tls_psk_cleanup(data->pskfile);
102     if (data->pskfilealt) {
103         test_tls_psk_cleanup(data->pskfilealt);
104     }
105     rmdir(data->workdir);
106     if (data->workdiralt) {
107         rmdir(data->workdiralt);
108     }
109 
110     g_free(data->workdiralt);
111     g_free(data->pskfilealt);
112     g_free(data->workdir);
113     g_free(data->pskfile);
114     g_free(data);
115 }
116 
117 #ifdef CONFIG_TASN1
118 typedef struct {
119     char *workdir;
120     char *keyfile;
121     char *cacert;
122     char *servercert;
123     char *serverkey;
124     char *clientcert;
125     char *clientkey;
126 } TestMigrateTLSX509Data;
127 
128 typedef struct {
129     bool verifyclient;
130     bool clientcert;
131     bool hostileclient;
132     bool authzclient;
133     const char *certhostname;
134     const char *certipaddr;
135 } TestMigrateTLSX509;
136 
137 static void *
migrate_hook_start_tls_x509_common(QTestState * from,QTestState * to,TestMigrateTLSX509 * args)138 migrate_hook_start_tls_x509_common(QTestState *from,
139                                    QTestState *to,
140                                    TestMigrateTLSX509 *args)
141 {
142     TestMigrateTLSX509Data *data = g_new0(TestMigrateTLSX509Data, 1);
143 
144     data->workdir = g_strdup_printf("%s/tlscredsx5090", tmpfs);
145     data->keyfile = g_strdup_printf("%s/key.pem", data->workdir);
146 
147     data->cacert = g_strdup_printf("%s/ca-cert.pem", data->workdir);
148     data->serverkey = g_strdup_printf("%s/server-key.pem", data->workdir);
149     data->servercert = g_strdup_printf("%s/server-cert.pem", data->workdir);
150     if (args->clientcert) {
151         data->clientkey = g_strdup_printf("%s/client-key.pem", data->workdir);
152         data->clientcert = g_strdup_printf("%s/client-cert.pem", data->workdir);
153     }
154 
155     g_mkdir_with_parents(data->workdir, 0700);
156 
157     test_tls_init(data->keyfile);
158 #ifndef _WIN32
159     g_assert(link(data->keyfile, data->serverkey) == 0);
160 #else
161     g_assert(CreateHardLink(data->serverkey, data->keyfile, NULL) != 0);
162 #endif
163     if (args->clientcert) {
164 #ifndef _WIN32
165         g_assert(link(data->keyfile, data->clientkey) == 0);
166 #else
167         g_assert(CreateHardLink(data->clientkey, data->keyfile, NULL) != 0);
168 #endif
169     }
170 
171     TLS_ROOT_REQ_SIMPLE(cacertreq, data->cacert);
172     if (args->clientcert) {
173         TLS_CERT_REQ_SIMPLE_CLIENT(servercertreq, cacertreq,
174                                    args->hostileclient ?
175                                    QCRYPTO_TLS_TEST_CLIENT_HOSTILE_NAME :
176                                    QCRYPTO_TLS_TEST_CLIENT_NAME,
177                                    data->clientcert);
178         test_tls_deinit_cert(&servercertreq);
179     }
180 
181     TLS_CERT_REQ_SIMPLE_SERVER(clientcertreq, cacertreq,
182                                data->servercert,
183                                args->certhostname,
184                                args->certipaddr);
185     test_tls_deinit_cert(&clientcertreq);
186     test_tls_deinit_cert(&cacertreq);
187 
188     qtest_qmp_assert_success(from,
189                              "{ 'execute': 'object-add',"
190                              "  'arguments': { 'qom-type': 'tls-creds-x509',"
191                              "                 'id': 'tlscredsx509client0',"
192                              "                 'endpoint': 'client',"
193                              "                 'dir': %s,"
194                              "                 'sanity-check': true,"
195                              "                 'verify-peer': true} }",
196                              data->workdir);
197     migrate_set_parameter_str(from, "tls-creds", "tlscredsx509client0");
198     if (args->certhostname) {
199         migrate_set_parameter_str(from, "tls-hostname", args->certhostname);
200     }
201 
202     qtest_qmp_assert_success(to,
203                              "{ 'execute': 'object-add',"
204                              "  'arguments': { 'qom-type': 'tls-creds-x509',"
205                              "                 'id': 'tlscredsx509server0',"
206                              "                 'endpoint': 'server',"
207                              "                 'dir': %s,"
208                              "                 'sanity-check': true,"
209                              "                 'verify-peer': %i} }",
210                              data->workdir, args->verifyclient);
211     migrate_set_parameter_str(to, "tls-creds", "tlscredsx509server0");
212 
213     if (args->authzclient) {
214         qtest_qmp_assert_success(to,
215                                  "{ 'execute': 'object-add',"
216                                  "  'arguments': { 'qom-type': 'authz-simple',"
217                                  "                 'id': 'tlsauthz0',"
218                                  "                 'identity': %s} }",
219                                  "CN=" QCRYPTO_TLS_TEST_CLIENT_NAME);
220         migrate_set_parameter_str(to, "tls-authz", "tlsauthz0");
221     }
222 
223     return data;
224 }
225 
226 /*
227  * The normal case: match server's cert hostname against
228  * whatever host we were telling QEMU to connect to (if any)
229  */
230 static void *
migrate_hook_start_tls_x509_default_host(QTestState * from,QTestState * to)231 migrate_hook_start_tls_x509_default_host(QTestState *from,
232                                          QTestState *to)
233 {
234     TestMigrateTLSX509 args = {
235         .verifyclient = true,
236         .clientcert = true,
237         .certipaddr = "127.0.0.1"
238     };
239     return migrate_hook_start_tls_x509_common(from, to, &args);
240 }
241 
242 /*
243  * The unusual case: the server's cert is different from
244  * the address we're telling QEMU to connect to (if any),
245  * so we must give QEMU an explicit hostname to validate
246  */
247 static void *
migrate_hook_start_tls_x509_override_host(QTestState * from,QTestState * to)248 migrate_hook_start_tls_x509_override_host(QTestState *from,
249                                           QTestState *to)
250 {
251     TestMigrateTLSX509 args = {
252         .verifyclient = true,
253         .clientcert = true,
254         .certhostname = "qemu.org",
255     };
256     return migrate_hook_start_tls_x509_common(from, to, &args);
257 }
258 
259 /*
260  * The unusual case: the server's cert is different from
261  * the address we're telling QEMU to connect to, and so we
262  * expect the client to reject the server
263  */
264 static void *
migrate_hook_start_tls_x509_mismatch_host(QTestState * from,QTestState * to)265 migrate_hook_start_tls_x509_mismatch_host(QTestState *from,
266                                           QTestState *to)
267 {
268     TestMigrateTLSX509 args = {
269         .verifyclient = true,
270         .clientcert = true,
271         .certipaddr = "10.0.0.1",
272     };
273     return migrate_hook_start_tls_x509_common(from, to, &args);
274 }
275 
276 static void *
migrate_hook_start_tls_x509_friendly_client(QTestState * from,QTestState * to)277 migrate_hook_start_tls_x509_friendly_client(QTestState *from,
278                                             QTestState *to)
279 {
280     TestMigrateTLSX509 args = {
281         .verifyclient = true,
282         .clientcert = true,
283         .authzclient = true,
284         .certipaddr = "127.0.0.1",
285     };
286     return migrate_hook_start_tls_x509_common(from, to, &args);
287 }
288 
289 static void *
migrate_hook_start_tls_x509_hostile_client(QTestState * from,QTestState * to)290 migrate_hook_start_tls_x509_hostile_client(QTestState *from,
291                                            QTestState *to)
292 {
293     TestMigrateTLSX509 args = {
294         .verifyclient = true,
295         .clientcert = true,
296         .hostileclient = true,
297         .authzclient = true,
298         .certipaddr = "127.0.0.1",
299     };
300     return migrate_hook_start_tls_x509_common(from, to, &args);
301 }
302 
303 /*
304  * The case with no client certificate presented,
305  * and no server verification
306  */
307 static void *
migrate_hook_start_tls_x509_allow_anon_client(QTestState * from,QTestState * to)308 migrate_hook_start_tls_x509_allow_anon_client(QTestState *from,
309                                               QTestState *to)
310 {
311     TestMigrateTLSX509 args = {
312         .certipaddr = "127.0.0.1",
313     };
314     return migrate_hook_start_tls_x509_common(from, to, &args);
315 }
316 
317 /*
318  * The case with no client certificate presented,
319  * and server verification rejecting
320  */
321 static void *
migrate_hook_start_tls_x509_reject_anon_client(QTestState * from,QTestState * to)322 migrate_hook_start_tls_x509_reject_anon_client(QTestState *from,
323                                                QTestState *to)
324 {
325     TestMigrateTLSX509 args = {
326         .verifyclient = true,
327         .certipaddr = "127.0.0.1",
328     };
329     return migrate_hook_start_tls_x509_common(from, to, &args);
330 }
331 
332 static void
migrate_hook_end_tls_x509(QTestState * from,QTestState * to,void * opaque)333 migrate_hook_end_tls_x509(QTestState *from,
334                           QTestState *to,
335                           void *opaque)
336 {
337     TestMigrateTLSX509Data *data = opaque;
338 
339     test_tls_cleanup(data->keyfile);
340     g_free(data->keyfile);
341 
342     unlink(data->cacert);
343     g_free(data->cacert);
344     unlink(data->servercert);
345     g_free(data->servercert);
346     unlink(data->serverkey);
347     g_free(data->serverkey);
348 
349     if (data->clientcert) {
350         unlink(data->clientcert);
351         g_free(data->clientcert);
352     }
353     if (data->clientkey) {
354         unlink(data->clientkey);
355         g_free(data->clientkey);
356     }
357 
358     rmdir(data->workdir);
359     g_free(data->workdir);
360 
361     g_free(data);
362 }
363 #endif /* CONFIG_TASN1 */
364 
test_postcopy_tls_psk(void)365 static void test_postcopy_tls_psk(void)
366 {
367     MigrateCommon args = {
368         .start_hook = migrate_hook_start_tls_psk_match,
369         .end_hook = migrate_hook_end_tls_psk,
370     };
371 
372     test_postcopy_common(&args);
373 }
374 
test_postcopy_preempt_tls_psk(void)375 static void test_postcopy_preempt_tls_psk(void)
376 {
377     MigrateCommon args = {
378         .start_hook = migrate_hook_start_tls_psk_match,
379         .end_hook = migrate_hook_end_tls_psk,
380         .start = {
381             .caps[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT] = true,
382         },
383     };
384 
385     test_postcopy_common(&args);
386 }
387 
test_postcopy_recovery_tls_psk(void)388 static void test_postcopy_recovery_tls_psk(void)
389 {
390     MigrateCommon args = {
391         .start_hook = migrate_hook_start_tls_psk_match,
392         .end_hook = migrate_hook_end_tls_psk,
393     };
394 
395     test_postcopy_recovery_common(&args);
396 }
397 
test_multifd_postcopy_recovery_tls_psk(void)398 static void test_multifd_postcopy_recovery_tls_psk(void)
399 {
400     MigrateCommon args = {
401         .start_hook = migrate_hook_start_tls_psk_match,
402         .end_hook = migrate_hook_end_tls_psk,
403         .start = {
404             .caps[MIGRATION_CAPABILITY_MULTIFD] = true,
405         },
406     };
407 
408     test_postcopy_recovery_common(&args);
409 }
410 
411 /* This contains preempt+recovery+tls test altogether */
test_postcopy_preempt_all(void)412 static void test_postcopy_preempt_all(void)
413 {
414     MigrateCommon args = {
415         .start_hook = migrate_hook_start_tls_psk_match,
416         .end_hook = migrate_hook_end_tls_psk,
417         .start = {
418             .caps[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT] = true,
419         },
420     };
421 
422     test_postcopy_recovery_common(&args);
423 }
424 
test_multifd_postcopy_preempt_recovery_tls_psk(void)425 static void test_multifd_postcopy_preempt_recovery_tls_psk(void)
426 {
427     MigrateCommon args = {
428         .start_hook = migrate_hook_start_tls_psk_match,
429         .end_hook = migrate_hook_end_tls_psk,
430         .start = {
431             .caps[MIGRATION_CAPABILITY_MULTIFD] = true,
432             .caps[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT] = true,
433         },
434     };
435 
436     test_postcopy_recovery_common(&args);
437 }
438 
test_precopy_unix_tls_psk(void)439 static void test_precopy_unix_tls_psk(void)
440 {
441     g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
442     MigrateCommon args = {
443         .connect_uri = uri,
444         .listen_uri = uri,
445         .start_hook = migrate_hook_start_tls_psk_match,
446         .end_hook = migrate_hook_end_tls_psk,
447     };
448 
449     test_precopy_common(&args);
450 }
451 
452 #ifdef CONFIG_TASN1
test_precopy_unix_tls_x509_default_host(void)453 static void test_precopy_unix_tls_x509_default_host(void)
454 {
455     g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
456     MigrateCommon args = {
457         .start = {
458             .hide_stderr = true,
459         },
460         .connect_uri = uri,
461         .listen_uri = uri,
462         .start_hook = migrate_hook_start_tls_x509_default_host,
463         .end_hook = migrate_hook_end_tls_x509,
464         .result = MIG_TEST_FAIL_DEST_QUIT_ERR,
465     };
466 
467     test_precopy_common(&args);
468 }
469 
test_precopy_unix_tls_x509_override_host(void)470 static void test_precopy_unix_tls_x509_override_host(void)
471 {
472     g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
473     MigrateCommon args = {
474         .connect_uri = uri,
475         .listen_uri = uri,
476         .start_hook = migrate_hook_start_tls_x509_override_host,
477         .end_hook = migrate_hook_end_tls_x509,
478     };
479 
480     test_precopy_common(&args);
481 }
482 #endif /* CONFIG_TASN1 */
483 
test_precopy_tcp_tls_psk_match(void)484 static void test_precopy_tcp_tls_psk_match(void)
485 {
486     MigrateCommon args = {
487         .listen_uri = "tcp:127.0.0.1:0",
488         .start_hook = migrate_hook_start_tls_psk_match,
489         .end_hook = migrate_hook_end_tls_psk,
490     };
491 
492     test_precopy_common(&args);
493 }
494 
test_precopy_tcp_tls_psk_mismatch(void)495 static void test_precopy_tcp_tls_psk_mismatch(void)
496 {
497     MigrateCommon args = {
498         .start = {
499             .hide_stderr = true,
500         },
501         .listen_uri = "tcp:127.0.0.1:0",
502         .start_hook = migrate_hook_start_tls_psk_mismatch,
503         .end_hook = migrate_hook_end_tls_psk,
504         .result = MIG_TEST_FAIL,
505     };
506 
507     test_precopy_common(&args);
508 }
509 
510 #ifdef CONFIG_TASN1
test_precopy_tcp_tls_x509_default_host(void)511 static void test_precopy_tcp_tls_x509_default_host(void)
512 {
513     MigrateCommon args = {
514         .listen_uri = "tcp:127.0.0.1:0",
515         .start_hook = migrate_hook_start_tls_x509_default_host,
516         .end_hook = migrate_hook_end_tls_x509,
517     };
518 
519     test_precopy_common(&args);
520 }
521 
test_precopy_tcp_tls_x509_override_host(void)522 static void test_precopy_tcp_tls_x509_override_host(void)
523 {
524     MigrateCommon args = {
525         .listen_uri = "tcp:127.0.0.1:0",
526         .start_hook = migrate_hook_start_tls_x509_override_host,
527         .end_hook = migrate_hook_end_tls_x509,
528     };
529 
530     test_precopy_common(&args);
531 }
532 
test_precopy_tcp_tls_x509_mismatch_host(void)533 static void test_precopy_tcp_tls_x509_mismatch_host(void)
534 {
535     MigrateCommon args = {
536         .start = {
537             .hide_stderr = true,
538         },
539         .listen_uri = "tcp:127.0.0.1:0",
540         .start_hook = migrate_hook_start_tls_x509_mismatch_host,
541         .end_hook = migrate_hook_end_tls_x509,
542         .result = MIG_TEST_FAIL_DEST_QUIT_ERR,
543     };
544 
545     test_precopy_common(&args);
546 }
547 
test_precopy_tcp_tls_x509_friendly_client(void)548 static void test_precopy_tcp_tls_x509_friendly_client(void)
549 {
550     MigrateCommon args = {
551         .listen_uri = "tcp:127.0.0.1:0",
552         .start_hook = migrate_hook_start_tls_x509_friendly_client,
553         .end_hook = migrate_hook_end_tls_x509,
554     };
555 
556     test_precopy_common(&args);
557 }
558 
test_precopy_tcp_tls_x509_hostile_client(void)559 static void test_precopy_tcp_tls_x509_hostile_client(void)
560 {
561     MigrateCommon args = {
562         .start = {
563             .hide_stderr = true,
564         },
565         .listen_uri = "tcp:127.0.0.1:0",
566         .start_hook = migrate_hook_start_tls_x509_hostile_client,
567         .end_hook = migrate_hook_end_tls_x509,
568         .result = MIG_TEST_FAIL,
569     };
570 
571     test_precopy_common(&args);
572 }
573 
test_precopy_tcp_tls_x509_allow_anon_client(void)574 static void test_precopy_tcp_tls_x509_allow_anon_client(void)
575 {
576     MigrateCommon args = {
577         .listen_uri = "tcp:127.0.0.1:0",
578         .start_hook = migrate_hook_start_tls_x509_allow_anon_client,
579         .end_hook = migrate_hook_end_tls_x509,
580     };
581 
582     test_precopy_common(&args);
583 }
584 
test_precopy_tcp_tls_x509_reject_anon_client(void)585 static void test_precopy_tcp_tls_x509_reject_anon_client(void)
586 {
587     MigrateCommon args = {
588         .start = {
589             .hide_stderr = true,
590         },
591         .listen_uri = "tcp:127.0.0.1:0",
592         .start_hook = migrate_hook_start_tls_x509_reject_anon_client,
593         .end_hook = migrate_hook_end_tls_x509,
594         .result = MIG_TEST_FAIL,
595     };
596 
597     test_precopy_common(&args);
598 }
599 #endif /* CONFIG_TASN1 */
600 
601 static void *
migrate_hook_start_multifd_tcp_tls_psk_match(QTestState * from,QTestState * to)602 migrate_hook_start_multifd_tcp_tls_psk_match(QTestState *from,
603                                              QTestState *to)
604 {
605     migrate_hook_start_precopy_tcp_multifd_common(from, to, "none");
606     return migrate_hook_start_tls_psk_match(from, to);
607 }
608 
609 static void *
migrate_hook_start_multifd_tcp_tls_psk_mismatch(QTestState * from,QTestState * to)610 migrate_hook_start_multifd_tcp_tls_psk_mismatch(QTestState *from,
611                                                 QTestState *to)
612 {
613     migrate_hook_start_precopy_tcp_multifd_common(from, to, "none");
614     return migrate_hook_start_tls_psk_mismatch(from, to);
615 }
616 
617 #ifdef CONFIG_TASN1
618 static void *
migrate_hook_start_multifd_tls_x509_default_host(QTestState * from,QTestState * to)619 migrate_hook_start_multifd_tls_x509_default_host(QTestState *from,
620                                                  QTestState *to)
621 {
622     migrate_hook_start_precopy_tcp_multifd_common(from, to, "none");
623     return migrate_hook_start_tls_x509_default_host(from, to);
624 }
625 
626 static void *
migrate_hook_start_multifd_tls_x509_override_host(QTestState * from,QTestState * to)627 migrate_hook_start_multifd_tls_x509_override_host(QTestState *from,
628                                                   QTestState *to)
629 {
630     migrate_hook_start_precopy_tcp_multifd_common(from, to, "none");
631     return migrate_hook_start_tls_x509_override_host(from, to);
632 }
633 
634 static void *
migrate_hook_start_multifd_tls_x509_mismatch_host(QTestState * from,QTestState * to)635 migrate_hook_start_multifd_tls_x509_mismatch_host(QTestState *from,
636                                                   QTestState *to)
637 {
638     migrate_hook_start_precopy_tcp_multifd_common(from, to, "none");
639     return migrate_hook_start_tls_x509_mismatch_host(from, to);
640 }
641 
642 static void *
migrate_hook_start_multifd_tls_x509_allow_anon_client(QTestState * from,QTestState * to)643 migrate_hook_start_multifd_tls_x509_allow_anon_client(QTestState *from,
644                                                       QTestState *to)
645 {
646     migrate_hook_start_precopy_tcp_multifd_common(from, to, "none");
647     return migrate_hook_start_tls_x509_allow_anon_client(from, to);
648 }
649 
650 static void *
migrate_hook_start_multifd_tls_x509_reject_anon_client(QTestState * from,QTestState * to)651 migrate_hook_start_multifd_tls_x509_reject_anon_client(QTestState *from,
652                                                        QTestState *to)
653 {
654     migrate_hook_start_precopy_tcp_multifd_common(from, to, "none");
655     return migrate_hook_start_tls_x509_reject_anon_client(from, to);
656 }
657 #endif /* CONFIG_TASN1 */
658 
test_multifd_tcp_tls_psk_match(void)659 static void test_multifd_tcp_tls_psk_match(void)
660 {
661     MigrateCommon args = {
662         .listen_uri = "defer",
663         .start_hook = migrate_hook_start_multifd_tcp_tls_psk_match,
664         .end_hook = migrate_hook_end_tls_psk,
665         .start = {
666             .caps[MIGRATION_CAPABILITY_MULTIFD] = true,
667         },
668     };
669     test_precopy_common(&args);
670 }
671 
test_multifd_tcp_tls_psk_mismatch(void)672 static void test_multifd_tcp_tls_psk_mismatch(void)
673 {
674     MigrateCommon args = {
675         .start = {
676             .hide_stderr = true,
677             .caps[MIGRATION_CAPABILITY_MULTIFD] = true,
678         },
679         .listen_uri = "defer",
680         .start_hook = migrate_hook_start_multifd_tcp_tls_psk_mismatch,
681         .end_hook = migrate_hook_end_tls_psk,
682         .result = MIG_TEST_FAIL,
683     };
684     test_precopy_common(&args);
685 }
686 
test_multifd_postcopy_tcp_tls_psk_match(void)687 static void test_multifd_postcopy_tcp_tls_psk_match(void)
688 {
689     MigrateCommon args = {
690         .start = {
691             .caps[MIGRATION_CAPABILITY_MULTIFD] = true,
692             .caps[MIGRATION_CAPABILITY_POSTCOPY_RAM] = true,
693         },
694         .listen_uri = "defer",
695         .start_hook = migrate_hook_start_multifd_tcp_tls_psk_match,
696         .end_hook = migrate_hook_end_tls_psk,
697     };
698 
699     test_precopy_common(&args);
700 }
701 
702 #ifdef CONFIG_TASN1
test_multifd_tcp_tls_x509_default_host(void)703 static void test_multifd_tcp_tls_x509_default_host(void)
704 {
705     MigrateCommon args = {
706         .listen_uri = "defer",
707         .start_hook = migrate_hook_start_multifd_tls_x509_default_host,
708         .end_hook = migrate_hook_end_tls_x509,
709         .start = {
710             .caps[MIGRATION_CAPABILITY_MULTIFD] = true,
711         },
712     };
713     test_precopy_common(&args);
714 }
715 
test_multifd_tcp_tls_x509_override_host(void)716 static void test_multifd_tcp_tls_x509_override_host(void)
717 {
718     MigrateCommon args = {
719         .listen_uri = "defer",
720         .start_hook = migrate_hook_start_multifd_tls_x509_override_host,
721         .end_hook = migrate_hook_end_tls_x509,
722         .start = {
723             .caps[MIGRATION_CAPABILITY_MULTIFD] = true,
724         },
725     };
726     test_precopy_common(&args);
727 }
728 
test_multifd_tcp_tls_x509_mismatch_host(void)729 static void test_multifd_tcp_tls_x509_mismatch_host(void)
730 {
731     /*
732      * This has different behaviour to the non-multifd case.
733      *
734      * In non-multifd case when client aborts due to mismatched
735      * cert host, the server has already started trying to load
736      * migration state, and so it exits with I/O failure.
737      *
738      * In multifd case when client aborts due to mismatched
739      * cert host, the server is still waiting for the other
740      * multifd connections to arrive so hasn't started trying
741      * to load migration state, and thus just aborts the migration
742      * without exiting.
743      */
744     MigrateCommon args = {
745         .start = {
746             .hide_stderr = true,
747             .caps[MIGRATION_CAPABILITY_MULTIFD] = true,
748         },
749         .listen_uri = "defer",
750         .start_hook = migrate_hook_start_multifd_tls_x509_mismatch_host,
751         .end_hook = migrate_hook_end_tls_x509,
752         .result = MIG_TEST_FAIL,
753     };
754     test_precopy_common(&args);
755 }
756 
test_multifd_tcp_tls_x509_allow_anon_client(void)757 static void test_multifd_tcp_tls_x509_allow_anon_client(void)
758 {
759     MigrateCommon args = {
760         .listen_uri = "defer",
761         .start_hook = migrate_hook_start_multifd_tls_x509_allow_anon_client,
762         .end_hook = migrate_hook_end_tls_x509,
763         .start = {
764             .caps[MIGRATION_CAPABILITY_MULTIFD] = true,
765         },
766     };
767     test_precopy_common(&args);
768 }
769 
test_multifd_tcp_tls_x509_reject_anon_client(void)770 static void test_multifd_tcp_tls_x509_reject_anon_client(void)
771 {
772     MigrateCommon args = {
773         .start = {
774             .hide_stderr = true,
775             .caps[MIGRATION_CAPABILITY_MULTIFD] = true,
776         },
777         .listen_uri = "defer",
778         .start_hook = migrate_hook_start_multifd_tls_x509_reject_anon_client,
779         .end_hook = migrate_hook_end_tls_x509,
780         .result = MIG_TEST_FAIL,
781     };
782     test_precopy_common(&args);
783 }
784 #endif /* CONFIG_TASN1 */
785 
migration_test_add_tls_smoke(MigrationTestEnv * env)786 static void migration_test_add_tls_smoke(MigrationTestEnv *env)
787 {
788     migration_test_add("/migration/precopy/tcp/tls/psk/match",
789                        test_precopy_tcp_tls_psk_match);
790 }
791 
migration_test_add_tls(MigrationTestEnv * env)792 void migration_test_add_tls(MigrationTestEnv *env)
793 {
794     tmpfs = env->tmpfs;
795 
796     migration_test_add_tls_smoke(env);
797 
798     if (!env->full_set) {
799         return;
800     }
801 
802     migration_test_add("/migration/precopy/unix/tls/psk",
803                        test_precopy_unix_tls_psk);
804 
805     if (env->has_uffd) {
806         /*
807          * NOTE: psk test is enough for postcopy, as other types of TLS
808          * channels are tested under precopy.  Here what we want to test is the
809          * general postcopy path that has TLS channel enabled.
810          */
811         migration_test_add("/migration/postcopy/tls/psk",
812                            test_postcopy_tls_psk);
813         migration_test_add("/migration/postcopy/recovery/tls/psk",
814                            test_postcopy_recovery_tls_psk);
815         migration_test_add("/migration/postcopy/preempt/tls/psk",
816                            test_postcopy_preempt_tls_psk);
817         migration_test_add("/migration/postcopy/preempt/recovery/tls/psk",
818                            test_postcopy_preempt_all);
819         migration_test_add("/migration/multifd+postcopy/recovery/tls/psk",
820                            test_multifd_postcopy_recovery_tls_psk);
821         migration_test_add(
822             "/migration/multifd+postcopy/preempt/recovery/tls/psk",
823             test_multifd_postcopy_preempt_recovery_tls_psk);
824     }
825 #ifdef CONFIG_TASN1
826     migration_test_add("/migration/precopy/unix/tls/x509/default-host",
827                        test_precopy_unix_tls_x509_default_host);
828     migration_test_add("/migration/precopy/unix/tls/x509/override-host",
829                        test_precopy_unix_tls_x509_override_host);
830 #endif /* CONFIG_TASN1 */
831 
832     migration_test_add("/migration/precopy/tcp/tls/psk/mismatch",
833                        test_precopy_tcp_tls_psk_mismatch);
834 #ifdef CONFIG_TASN1
835     migration_test_add("/migration/precopy/tcp/tls/x509/default-host",
836                        test_precopy_tcp_tls_x509_default_host);
837     migration_test_add("/migration/precopy/tcp/tls/x509/override-host",
838                        test_precopy_tcp_tls_x509_override_host);
839     migration_test_add("/migration/precopy/tcp/tls/x509/mismatch-host",
840                        test_precopy_tcp_tls_x509_mismatch_host);
841     migration_test_add("/migration/precopy/tcp/tls/x509/friendly-client",
842                        test_precopy_tcp_tls_x509_friendly_client);
843     migration_test_add("/migration/precopy/tcp/tls/x509/hostile-client",
844                        test_precopy_tcp_tls_x509_hostile_client);
845     migration_test_add("/migration/precopy/tcp/tls/x509/allow-anon-client",
846                        test_precopy_tcp_tls_x509_allow_anon_client);
847     migration_test_add("/migration/precopy/tcp/tls/x509/reject-anon-client",
848                        test_precopy_tcp_tls_x509_reject_anon_client);
849 #endif /* CONFIG_TASN1 */
850 
851     migration_test_add("/migration/multifd/tcp/tls/psk/match",
852                        test_multifd_tcp_tls_psk_match);
853     migration_test_add("/migration/multifd/tcp/tls/psk/mismatch",
854                        test_multifd_tcp_tls_psk_mismatch);
855     if (env->has_uffd) {
856         migration_test_add("/migration/multifd+postcopy/tcp/tls/psk/match",
857                            test_multifd_postcopy_tcp_tls_psk_match);
858     }
859 #ifdef CONFIG_TASN1
860     migration_test_add("/migration/multifd/tcp/tls/x509/default-host",
861                        test_multifd_tcp_tls_x509_default_host);
862     migration_test_add("/migration/multifd/tcp/tls/x509/override-host",
863                        test_multifd_tcp_tls_x509_override_host);
864     migration_test_add("/migration/multifd/tcp/tls/x509/mismatch-host",
865                        test_multifd_tcp_tls_x509_mismatch_host);
866     migration_test_add("/migration/multifd/tcp/tls/x509/allow-anon-client",
867                        test_multifd_tcp_tls_x509_allow_anon_client);
868     migration_test_add("/migration/multifd/tcp/tls/x509/reject-anon-client",
869                        test_multifd_tcp_tls_x509_reject_anon_client);
870 #endif /* CONFIG_TASN1 */
871 }
872