master
c 1,356 lines 37.2 KB
Raw
1 /*
2 * D-Bus VNC server (qemu-vnc) end-to-end test
3 *
4 * Copyright (c) 2026 Red Hat, Inc.
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9 #include "qemu/osdep.h"
10 #include <gio/gio.h>
11 #include <gvnc.h>
12 #include <sys/un.h>
13 #include "qemu/sockets.h"
14 #include "libqtest.h"
15 #include "qemu-vnc1.h"
16 #ifdef CONFIG_TASN1
17 #include "tests/unit/crypto-tls-x509-helpers.h"
18 #endif
19
20 #define VNC_TEST_TIMEOUT_MS 10000
21
22 typedef struct DbusTest {
23 QTestState *qts;
24 GSubprocess *vnc_subprocess;
25 GTestDBus *bus;
26 GDBusConnection *bus_conn;
27 GMainLoop *loop;
28 char *vnc_sock_path;
29 char *tmp_dir;
30 char *bus_addr;
31 } DbusTest;
32
33 typedef struct LifecycleData {
34 DbusTest *dt;
35 QemuVnc1Server *server_proxy;
36 VncConnection *conn;
37 char *client_path;
38 gboolean got_connected;
39 gboolean got_initialized;
40 gboolean got_disconnected;
41 } LifecycleData;
42
43 static QemuVnc1Server *
44 create_server_proxy(GDBusConnection *bus_conn, GError **errp)
45 {
46 return qemu_vnc1_server_proxy_new_sync(
47 bus_conn,
48 G_DBUS_PROXY_FLAGS_NONE,
49 "org.qemu.vnc",
50 "/org/qemu/Vnc1/Server",
51 NULL, errp);
52 }
53
54 static void
55 on_vnc_error(VncConnection *self, const char *msg)
56 {
57 g_error("vnc-error: %s", msg);
58 }
59
60 static void
61 on_vnc_auth_failure(VncConnection *self, const char *msg)
62 {
63 g_error("vnc-auth-failure: %s", msg);
64 }
65
66 static void
67 on_vnc_initialized(VncConnection *self, GMainLoop *loop)
68 {
69 const char *name = vnc_connection_get_name(self);
70
71 g_assert_cmpstr(name, ==, "QEMU (dbus-vnc-test)");
72 g_main_loop_quit(loop);
73 }
74
75 static gboolean
76 timeout_cb(gpointer data)
77 {
78 g_error("test timed out");
79 return G_SOURCE_REMOVE;
80 }
81
82 static int
83 connect_unix_socket(const char *path)
84 {
85 int fd;
86 struct sockaddr_un addr = { .sun_family = AF_UNIX };
87
88 fd = socket(AF_UNIX, SOCK_STREAM, 0);
89 g_assert(fd >= 0);
90
91 snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path);
92
93 if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
94 close(fd);
95 return -1;
96 }
97 return fd;
98 }
99
100 static int
101 wait_for_vnc_socket(const char *path, int timeout_ms)
102 {
103 int elapsed = 0;
104 const int interval = 50;
105
106 while (elapsed < timeout_ms) {
107 int fd = connect_unix_socket(path);
108
109 if (fd >= 0) {
110 return fd;
111 }
112
113 g_usleep(interval * 1000);
114 elapsed += interval;
115 }
116 return -1;
117 }
118
119 static GSubprocess *
120 spawn_qemu_vnc(int dbus_fd, const char *sock_path)
121 {
122 const char *binary;
123 g_autoptr(GError) err = NULL;
124 g_autoptr(GSubprocessLauncher) launcher = NULL;
125 GSubprocess *proc;
126 g_autofree char *fd_str = NULL;
127 g_autofree char *vnc_addr = NULL;
128
129 binary = g_getenv("QTEST_QEMU_VNC_BINARY");
130 g_assert(binary != NULL);
131
132 fd_str = g_strdup_printf("%d", dbus_fd);
133 vnc_addr = g_strdup_printf("unix:%s", sock_path);
134
135 launcher = g_subprocess_launcher_new(G_SUBPROCESS_FLAGS_NONE);
136 g_subprocess_launcher_take_fd(launcher, dbus_fd, dbus_fd);
137
138 proc = g_subprocess_launcher_spawn(launcher, &err,
139 binary,
140 "--dbus-p2p-fd", fd_str,
141 "--vnc-addr", vnc_addr,
142 NULL);
143 g_assert_no_error(err);
144 g_assert(proc != NULL);
145
146 return proc;
147 }
148
149 static GSubprocess *
150 spawn_qemu_vnc_bus_full(const char *dbus_addr, const char *sock_path,
151 const char *const *extra_args)
152 {
153 const char *binary;
154 g_autoptr(GError) err = NULL;
155 g_autoptr(GSubprocessLauncher) launcher = NULL;
156 g_autoptr(GPtrArray) argv = NULL;
157 GSubprocess *proc;
158 g_autofree char *vnc_addr = NULL;
159
160 binary = g_getenv("QTEST_QEMU_VNC_BINARY");
161 g_assert(binary != NULL);
162
163 vnc_addr = g_strdup_printf("unix:%s", sock_path);
164
165 argv = g_ptr_array_new();
166 g_ptr_array_add(argv, (gpointer)binary);
167 g_ptr_array_add(argv, (gpointer)"--dbus-address");
168 g_ptr_array_add(argv, (gpointer)dbus_addr);
169 g_ptr_array_add(argv, (gpointer)"--bus-name");
170 g_ptr_array_add(argv, (gpointer)"org.qemu");
171 g_ptr_array_add(argv, (gpointer)"--vnc-addr");
172 g_ptr_array_add(argv, (gpointer)vnc_addr);
173
174 if (extra_args) {
175 for (int i = 0; extra_args[i]; i++) {
176 g_ptr_array_add(argv, (gpointer)extra_args[i]);
177 }
178 }
179
180 g_ptr_array_add(argv, NULL);
181
182 launcher = g_subprocess_launcher_new(G_SUBPROCESS_FLAGS_NONE);
183 proc = g_subprocess_launcher_spawnv(launcher,
184 (const char *const *)argv->pdata, &err);
185 g_assert_no_error(err);
186 g_assert(proc != NULL);
187
188 return proc;
189 }
190
191
192 static void
193 name_appeared_cb(GDBusConnection *connection,
194 const gchar *name,
195 const gchar *name_owner,
196 gpointer user_data)
197 {
198 gboolean *appeared = user_data;
199 *appeared = TRUE;
200 }
201
202 static bool
203 setup_dbus_test_full(DbusTest *dt, const char *const *vnc_extra_args)
204 {
205 g_autoptr(GError) err = NULL;
206 g_auto(GStrv) addr_parts = NULL;
207 g_autofree char *qemu_args = NULL;
208
209 if (!g_getenv("QTEST_QEMU_VNC_BINARY")) {
210 g_test_skip("QTEST_QEMU_VNC_BINARY not set");
211 return false;
212 }
213
214 dt->bus = g_test_dbus_new(G_TEST_DBUS_NONE);
215 g_test_dbus_up(dt->bus);
216
217 /* remove ,guid=foo part */
218 addr_parts = g_strsplit(g_test_dbus_get_bus_address(dt->bus), ",", 2);
219 dt->bus_addr = g_strdup(addr_parts[0]);
220
221 dt->bus_conn = g_dbus_connection_new_for_address_sync(
222 g_test_dbus_get_bus_address(dt->bus),
223 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
224 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
225 NULL, NULL, &err);
226 g_assert_no_error(err);
227
228 qemu_args = g_strdup_printf("-display dbus,addr=%s "
229 "-name dbus-vnc-test", dt->bus_addr);
230 dt->qts = qtest_init(qemu_args);
231
232 dt->tmp_dir = g_dir_make_tmp("dbus-vnc-test-XXXXXX", NULL);
233 g_assert(dt->tmp_dir != NULL);
234 dt->vnc_sock_path = g_build_filename(dt->tmp_dir, "vnc.sock", NULL);
235 dt->vnc_subprocess = spawn_qemu_vnc_bus_full(dt->bus_addr,
236 dt->vnc_sock_path,
237 vnc_extra_args);
238
239 /*
240 * Wait for the org.qemu.vnc bus name to appear, which indicates
241 * qemu-vnc has fully initialized (connected to QEMU, set up the
242 * display, exported its D-Bus interfaces, and opened the VNC
243 * socket).
244 */
245 {
246 guint watch_id, timeout_id;
247 gboolean appeared = FALSE;
248
249 watch_id = g_bus_watch_name_on_connection(
250 dt->bus_conn, "org.qemu.vnc",
251 G_BUS_NAME_WATCHER_FLAGS_NONE,
252 name_appeared_cb, NULL, &appeared, NULL);
253 timeout_id = g_timeout_add_seconds(10, timeout_cb, NULL);
254
255 while (!appeared) {
256 if (!g_main_context_iteration(NULL, TRUE)) {
257 break;
258 }
259 }
260
261 g_bus_unwatch_name(watch_id);
262 g_source_remove(timeout_id);
263
264 if (!appeared) {
265 g_test_fail();
266 g_test_message("Timed out waiting for org.qemu.vnc bus name");
267 return false;
268 }
269 }
270
271 return true;
272 }
273
274 static bool
275 setup_dbus_test(DbusTest *dt)
276 {
277 return setup_dbus_test_full(dt, NULL);
278 }
279
280 static void
281 cleanup_dbus_test(DbusTest *dt)
282 {
283 if (dt->bus_conn) {
284 g_dbus_connection_close_sync(dt->bus_conn, NULL, NULL);
285 g_object_unref(dt->bus_conn);
286 }
287 if (dt->vnc_subprocess) {
288 g_subprocess_force_exit(dt->vnc_subprocess);
289 g_subprocess_wait(dt->vnc_subprocess, NULL, NULL);
290 g_object_unref(dt->vnc_subprocess);
291 }
292 if (dt->vnc_sock_path) {
293 unlink(dt->vnc_sock_path);
294 g_free(dt->vnc_sock_path);
295 }
296 if (dt->tmp_dir) {
297 rmdir(dt->tmp_dir);
298 g_free(dt->tmp_dir);
299 }
300 if (dt->qts) {
301 qtest_quit(dt->qts);
302 }
303 if (dt->bus) {
304 g_test_dbus_down(dt->bus);
305 g_object_unref(dt->bus);
306 }
307 g_free(dt->bus_addr);
308 }
309
310 static void
311 test_dbus_vnc_basic(void)
312 {
313 DbusTest dt = { 0 };
314 VncConnection *conn = NULL;
315 GMainLoop *loop = NULL;
316 int pair[2];
317 int vnc_fd;
318 guint timeout_id;
319
320 if (!g_getenv("QTEST_QEMU_VNC_BINARY")) {
321 g_test_skip("QTEST_QEMU_VNC_BINARY not set");
322 return;
323 }
324
325 dt.qts = qtest_init("-display dbus,p2p=yes -name dbus-vnc-test");
326
327 g_assert_cmpint(qemu_socketpair(AF_UNIX, SOCK_STREAM, 0, pair), ==, 0);
328 qtest_qmp_add_client(dt.qts, "@dbus-display", pair[1]);
329 close(pair[1]);
330
331 dt.tmp_dir = g_dir_make_tmp("dbus-vnc-test-XXXXXX", NULL);
332 g_assert(dt.tmp_dir != NULL);
333 dt.vnc_sock_path = g_build_filename(dt.tmp_dir, "vnc.sock", NULL);
334
335 dt.vnc_subprocess = spawn_qemu_vnc(pair[0], dt.vnc_sock_path);
336
337 vnc_fd = wait_for_vnc_socket(dt.vnc_sock_path, VNC_TEST_TIMEOUT_MS);
338 g_assert(vnc_fd >= 0);
339
340 loop = g_main_loop_new(NULL, FALSE);
341
342 conn = vnc_connection_new();
343 g_signal_connect(conn, "vnc-error",
344 G_CALLBACK(on_vnc_error), NULL);
345 g_signal_connect(conn, "vnc-auth-failure",
346 G_CALLBACK(on_vnc_auth_failure), NULL);
347 g_signal_connect(conn, "vnc-initialized",
348 G_CALLBACK(on_vnc_initialized), loop);
349 vnc_connection_set_auth_type(conn, VNC_CONNECTION_AUTH_NONE);
350 vnc_connection_open_fd(conn, vnc_fd);
351
352 timeout_id = g_timeout_add_seconds(10, timeout_cb, NULL);
353 g_main_loop_run(loop);
354 g_source_remove(timeout_id);
355
356 if (conn) {
357 vnc_connection_shutdown(conn);
358 g_object_unref(conn);
359 }
360 g_clear_pointer(&loop, g_main_loop_unref);
361 cleanup_dbus_test(&dt);
362 }
363
364 static void
365 test_dbus_vnc_server_props(void)
366 {
367 DbusTest dt = { 0 };
368 QemuVnc1Server *proxy = NULL;
369 g_autoptr(GError) err = NULL;
370 const gchar *const *clients;
371 GVariant *listeners;
372
373 if (!setup_dbus_test(&dt)) {
374 goto cleanup;
375 }
376
377 proxy = create_server_proxy(dt.bus_conn, &err);
378 g_assert_no_error(err);
379 g_assert_nonnull(proxy);
380
381 g_assert_cmpstr(qemu_vnc1_server_get_name(proxy), ==,
382 "dbus-vnc-test");
383 g_assert_cmpstr(qemu_vnc1_server_get_auth(proxy), ==,
384 "none");
385 g_assert_cmpstr(qemu_vnc1_server_get_vencrypt_sub_auth(proxy), ==,
386 "");
387
388 clients = qemu_vnc1_server_get_clients(proxy);
389 g_assert_nonnull(clients);
390 g_assert_cmpint(g_strv_length((gchar **)clients), ==, 0);
391
392 listeners = qemu_vnc1_server_get_listeners(proxy);
393 g_assert_nonnull(listeners);
394 g_assert_cmpint(g_variant_n_children(listeners), >, 0);
395
396 cleanup:
397 g_clear_object(&proxy);
398 cleanup_dbus_test(&dt);
399 }
400
401 static void
402 on_client_connected(QemuVnc1Server *proxy,
403 const gchar *client_path,
404 LifecycleData *data)
405 {
406 data->got_connected = TRUE;
407 data->client_path = g_strdup(client_path);
408 }
409
410 static void
411 on_client_initialized(QemuVnc1Server *proxy,
412 const gchar *client_path,
413 LifecycleData *data)
414 {
415 data->got_initialized = TRUE;
416 g_main_loop_quit(data->dt->loop);
417 }
418
419 static void
420 on_client_disconnected(QemuVnc1Server *proxy,
421 const gchar *client_path,
422 LifecycleData *data)
423 {
424 data->got_disconnected = TRUE;
425 g_main_loop_quit(data->dt->loop);
426 }
427
428 static void
429 test_dbus_vnc_client_lifecycle(void)
430 {
431 DbusTest dt = { 0 };
432 QemuVnc1Server *server_proxy = NULL;
433 QemuVnc1Client *client_proxy = NULL;
434 g_autoptr(GError) err = NULL;
435 LifecycleData ldata = { 0 };
436 int vnc_fd;
437 guint timeout_id;
438
439 if (!setup_dbus_test(&dt)) {
440 goto cleanup;
441 }
442
443 server_proxy = create_server_proxy(dt.bus_conn, &err);
444 g_assert_no_error(err);
445
446 ldata.dt = &dt;
447 ldata.server_proxy = server_proxy;
448
449 g_signal_connect(server_proxy, "client-connected",
450 G_CALLBACK(on_client_connected), &ldata);
451 g_signal_connect(server_proxy, "client-initialized",
452 G_CALLBACK(on_client_initialized), &ldata);
453 g_signal_connect(server_proxy, "client-disconnected",
454 G_CALLBACK(on_client_disconnected), &ldata);
455
456 vnc_fd = wait_for_vnc_socket(dt.vnc_sock_path, VNC_TEST_TIMEOUT_MS);
457 g_assert(vnc_fd >= 0);
458
459 ldata.conn = vnc_connection_new();
460 g_signal_connect(ldata.conn, "vnc-error",
461 G_CALLBACK(on_vnc_error), NULL);
462 g_signal_connect(ldata.conn, "vnc-auth-failure",
463 G_CALLBACK(on_vnc_auth_failure), NULL);
464 vnc_connection_set_auth_type(ldata.conn, VNC_CONNECTION_AUTH_NONE);
465 vnc_connection_open_fd(ldata.conn, vnc_fd);
466
467 /* wait for ClientInitialized */
468 dt.loop = g_main_loop_new(NULL, FALSE);
469 timeout_id = g_timeout_add_seconds(10, timeout_cb, NULL);
470 g_main_loop_run(dt.loop);
471 g_source_remove(timeout_id);
472
473 g_assert_true(ldata.got_connected);
474 g_assert_true(ldata.got_initialized);
475 g_assert_nonnull(ldata.client_path);
476
477 /* Check client properties while still connected */
478 client_proxy = qemu_vnc1_client_proxy_new_sync(
479 dt.bus_conn,
480 G_DBUS_PROXY_FLAGS_NONE,
481 "org.qemu.vnc",
482 ldata.client_path,
483 NULL, &err);
484 g_assert_no_error(err);
485
486 g_assert_cmpstr(qemu_vnc1_client_get_family(client_proxy), ==,
487 "unix");
488 g_assert_false(qemu_vnc1_client_get_web_socket(client_proxy));
489 g_assert_cmpstr(qemu_vnc1_client_get_x509_dname(client_proxy), ==,
490 "");
491 g_assert_cmpstr(qemu_vnc1_client_get_sasl_username(client_proxy),
492 ==, "");
493
494 /* disconnect and wait for ClientDisconnected */
495 vnc_connection_shutdown(ldata.conn);
496 timeout_id = g_timeout_add_seconds(10, timeout_cb, NULL);
497 g_main_loop_run(dt.loop);
498 g_source_remove(timeout_id);
499
500 g_assert_true(ldata.got_disconnected);
501
502 g_object_unref(ldata.conn);
503 g_main_loop_unref(dt.loop);
504 dt.loop = NULL;
505 g_free(ldata.client_path);
506
507 cleanup:
508 g_clear_object(&server_proxy);
509 g_clear_object(&client_proxy);
510 cleanup_dbus_test(&dt);
511 }
512
513 static void
514 test_dbus_vnc_no_password(void)
515 {
516 DbusTest dt = { 0 };
517 QemuVnc1Server *proxy = NULL;
518 g_autoptr(GError) err = NULL;
519 gboolean ret;
520
521 if (!setup_dbus_test(&dt)) {
522 goto cleanup;
523 }
524
525 proxy = create_server_proxy(dt.bus_conn, &err);
526 g_assert_no_error(err);
527
528 /*
529 * With default auth=none, SetPassword should return an error
530 * because VNC password authentication is not enabled.
531 */
532 ret = qemu_vnc1_server_call_set_password_sync(
533 proxy, "secret",
534 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
535 g_assert_false(ret);
536 g_assert_error(err, G_DBUS_ERROR, G_DBUS_ERROR_FAILED);
537 g_clear_error(&err);
538
539 ret = qemu_vnc1_server_call_expire_password_sync(
540 proxy, "never",
541 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
542 g_assert_no_error(err);
543 g_assert_true(ret);
544
545 ret = qemu_vnc1_server_call_expire_password_sync(
546 proxy, "+3600",
547 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
548 g_assert_no_error(err);
549 g_assert_true(ret);
550
551 cleanup:
552 g_clear_object(&proxy);
553 cleanup_dbus_test(&dt);
554 }
555
556 typedef struct PasswordData {
557 DbusTest *dt;
558 VncConnection *conn;
559 const char *password;
560 gboolean auth_succeeded;
561 gboolean auth_failed;
562 } PasswordData;
563
564 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
565 static void
566 on_pw_vnc_auth_credential(VncConnection *conn, GValueArray *creds,
567 PasswordData *data)
568 {
569 for (guint i = 0; i < creds->n_values; i++) {
570 int type = g_value_get_enum(g_value_array_get_nth(creds, i));
571
572 if (type == VNC_CONNECTION_CREDENTIAL_PASSWORD) {
573 vnc_connection_set_credential(conn, type, data->password);
574 }
575 }
576 }
577 G_GNUC_END_IGNORE_DEPRECATIONS
578
579 static void
580 on_pw_vnc_initialized(VncConnection *conn, PasswordData *data)
581 {
582 data->auth_succeeded = TRUE;
583 g_main_loop_quit(data->dt->loop);
584 }
585
586 static void
587 on_pw_vnc_auth_failure(VncConnection *conn, const char *msg,
588 PasswordData *data)
589 {
590 data->auth_failed = TRUE;
591 g_main_loop_quit(data->dt->loop);
592 }
593
594 static void
595 on_pw_vnc_error(VncConnection *conn, const char *msg,
596 PasswordData *data)
597 {
598 data->auth_failed = TRUE;
599 g_main_loop_quit(data->dt->loop);
600 }
601
602 static void
603 test_dbus_vnc_password_auth(void)
604 {
605 DbusTest dt = { 0 };
606 QemuVnc1Server *proxy = NULL;
607 g_autoptr(GError) err = NULL;
608 PasswordData pdata = { 0 };
609 const char *extra_args[] = { "--password", NULL };
610 int vnc_fd;
611 guint timeout_id;
612 gboolean ret;
613
614 if (!setup_dbus_test_full(&dt, extra_args)) {
615 goto cleanup;
616 }
617
618 proxy = create_server_proxy(dt.bus_conn, &err);
619 g_assert_no_error(err);
620
621 g_assert_cmpstr(qemu_vnc1_server_get_auth(proxy), ==, "vnc");
622
623 ret = qemu_vnc1_server_call_set_password_sync(
624 proxy, "testpass123",
625 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
626 g_assert_no_error(err);
627 g_assert_true(ret);
628
629 vnc_fd = wait_for_vnc_socket(dt.vnc_sock_path, VNC_TEST_TIMEOUT_MS);
630 g_assert(vnc_fd >= 0);
631
632 pdata.dt = &dt;
633 pdata.password = "testpass123";
634 pdata.conn = vnc_connection_new();
635
636 g_signal_connect(pdata.conn, "vnc-error",
637 G_CALLBACK(on_pw_vnc_error), &pdata);
638 g_signal_connect(pdata.conn, "vnc-auth-failure",
639 G_CALLBACK(on_pw_vnc_auth_failure), &pdata);
640 g_signal_connect(pdata.conn, "vnc-auth-credential",
641 G_CALLBACK(on_pw_vnc_auth_credential), &pdata);
642 g_signal_connect(pdata.conn, "vnc-initialized",
643 G_CALLBACK(on_pw_vnc_initialized), &pdata);
644 vnc_connection_set_auth_type(pdata.conn, VNC_CONNECTION_AUTH_VNC);
645 vnc_connection_open_fd(pdata.conn, vnc_fd);
646
647 dt.loop = g_main_loop_new(NULL, FALSE);
648 timeout_id = g_timeout_add_seconds(10, timeout_cb, NULL);
649 g_main_loop_run(dt.loop);
650 g_source_remove(timeout_id);
651
652 g_assert_true(pdata.auth_succeeded);
653 g_assert_false(pdata.auth_failed);
654
655 vnc_connection_shutdown(pdata.conn);
656 g_object_unref(pdata.conn);
657 g_main_loop_unref(dt.loop);
658 dt.loop = NULL;
659
660 cleanup:
661 g_clear_object(&proxy);
662 cleanup_dbus_test(&dt);
663 }
664
665 static void
666 test_dbus_vnc_sasl_authz_no_sasl(void)
667 {
668 const char *binary;
669 g_autoptr(GError) err = NULL;
670 g_autoptr(GSubprocess) proc = NULL;
671 gboolean ok;
672
673 binary = g_getenv("QTEST_QEMU_VNC_BINARY");
674 if (!binary) {
675 g_test_skip("QTEST_QEMU_VNC_BINARY not set");
676 return;
677 }
678
679 proc = g_subprocess_new(G_SUBPROCESS_FLAGS_STDERR_SILENCE,
680 &err,
681 binary,
682 "--sasl-authz", "authz0",
683 NULL);
684 g_assert_no_error(err);
685 g_assert_nonnull(proc);
686
687 ok = g_subprocess_wait(proc, NULL, &err);
688 g_assert_no_error(err);
689 g_assert_true(ok);
690 g_assert_false(g_subprocess_get_successful(proc));
691 }
692
693 #ifdef CONFIG_VNC_SASL
694 static void
695 test_dbus_vnc_sasl_server_props(void)
696 {
697 DbusTest dt = { 0 };
698 QemuVnc1Server *proxy = NULL;
699 g_autoptr(GError) err = NULL;
700 const char *extra_args[] = { "--sasl", NULL };
701
702 if (!setup_dbus_test_full(&dt, extra_args)) {
703 goto cleanup;
704 }
705
706 proxy = create_server_proxy(dt.bus_conn, &err);
707 g_assert_no_error(err);
708 g_assert_nonnull(proxy);
709
710 g_assert_cmpstr(qemu_vnc1_server_get_auth(proxy), ==, "sasl");
711
712 cleanup:
713 g_clear_object(&proxy);
714 cleanup_dbus_test(&dt);
715 }
716
717 #define SASL_TEST_USER "testuser"
718 #define SASL_TEST_PASS "testpass123"
719
720 typedef struct SaslAuthData {
721 DbusTest *dt;
722 const char *username;
723 const char *password;
724 gboolean auth_succeeded;
725 gboolean auth_failed;
726 } SaslAuthData;
727
728 typedef struct SaslTestData {
729 DbusTest dt;
730 SaslAuthData sdata;
731 char *sasl_dir;
732 char *db_path;
733 } SaslTestData;
734
735 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
736 static void
737 on_sasl_vnc_auth_credential(VncConnection *conn, GValueArray *creds,
738 SaslAuthData *data)
739 {
740 for (guint i = 0; i < creds->n_values; i++) {
741 int type = g_value_get_enum(g_value_array_get_nth(creds, i));
742
743 switch (type) {
744 case VNC_CONNECTION_CREDENTIAL_USERNAME:
745 vnc_connection_set_credential(conn, type, data->username);
746 break;
747 case VNC_CONNECTION_CREDENTIAL_PASSWORD:
748 vnc_connection_set_credential(conn, type, data->password);
749 break;
750 }
751 }
752 }
753 G_GNUC_END_IGNORE_DEPRECATIONS
754
755 static void
756 on_sasl_vnc_initialized(VncConnection *conn, SaslAuthData *data)
757 {
758 data->auth_succeeded = TRUE;
759 g_main_loop_quit(data->dt->loop);
760 }
761
762 static void
763 on_sasl_vnc_auth_failure(VncConnection *conn, const char *msg,
764 SaslAuthData *data)
765 {
766 data->auth_failed = TRUE;
767 g_main_loop_quit(data->dt->loop);
768 }
769
770 static void
771 on_sasl_vnc_error(VncConnection *conn, const char *msg,
772 SaslAuthData *data)
773 {
774 data->auth_failed = TRUE;
775 g_main_loop_quit(data->dt->loop);
776 }
777
778 /*
779 * Create a SASL configuration directory with a qemu.conf and a
780 * sasldb2 user database. Returns the path to the sasldb file,
781 * or NULL if saslpasswd2 is not available.
782 */
783 static char *
784 create_sasl_config(const char *dir, const char *username,
785 const char *password)
786 {
787 g_autofree char *conf_path = g_strdup_printf("%s/qemu.conf", dir);
788 g_autofree char *db_path = g_strdup_printf("%s/sasldb2", dir);
789 g_autoptr(GError) err = NULL;
790 g_autoptr(GSubprocess) proc = NULL;
791 g_autofree char *conf = NULL;
792 GOutputStream *stdin_stream;
793 gboolean ok;
794
795 /* use PLAIN, and local auxprop sasldb plugin */
796 conf = g_strdup_printf(
797 "mech_list: plain\n"
798 "pwcheck_method: auxprop\n"
799 "auxprop_plugin: sasldb\n"
800 "sasldb_path: %s\n", db_path);
801 g_assert_true(g_file_set_contents(conf_path, conf, -1, NULL));
802
803 proc = g_subprocess_new(
804 G_SUBPROCESS_FLAGS_STDIN_PIPE |
805 G_SUBPROCESS_FLAGS_STDOUT_SILENCE |
806 G_SUBPROCESS_FLAGS_STDERR_SILENCE,
807 &err,
808 "saslpasswd2", "-f", db_path, "-a", "qemu", "-p", "-c",
809 username, NULL);
810 if (!proc) {
811 return NULL;
812 }
813
814 stdin_stream = g_subprocess_get_stdin_pipe(proc);
815 g_output_stream_write_all(stdin_stream, password,
816 strlen(password), NULL, NULL, NULL);
817 g_output_stream_close(stdin_stream, NULL, NULL);
818
819 ok = g_subprocess_wait_check(proc, NULL, &err);
820 if (!ok) {
821 return NULL;
822 }
823
824 return g_strdup(db_path);
825 }
826
827 static void
828 cleanup_sasl_config(const char *dir, const char *db_path)
829 {
830 g_autofree char *conf = g_strdup_printf("%s/qemu.conf", dir);
831
832 unlink(conf);
833 if (db_path) {
834 unlink(db_path);
835 }
836 rmdir(dir);
837 }
838
839 /*
840 * Set up SASL environment: create temp config dir, sasldb, and
841 * start qemu-vnc with the given extra_args. Returns FALSE if the
842 * test should be skipped.
843 */
844 static gboolean
845 setup_sasl_test(SaslTestData *st, const char **extra_args)
846 {
847 if (!g_getenv("QTEST_QEMU_VNC_BINARY")) {
848 g_test_skip("QTEST_QEMU_VNC_BINARY not set");
849 return FALSE;
850 }
851
852 st->sasl_dir = g_dir_make_tmp("dbus-vnc-sasl-XXXXXX", NULL);
853 g_assert_nonnull(st->sasl_dir);
854
855 st->db_path = create_sasl_config(st->sasl_dir, SASL_TEST_USER,
856 SASL_TEST_PASS);
857 if (!st->db_path) {
858 g_test_skip("saslpasswd2 not available or failed");
859 cleanup_sasl_config(st->sasl_dir, NULL);
860 return FALSE;
861 }
862
863 g_setenv("SASL_CONF_PATH", st->sasl_dir, TRUE);
864
865 if (!setup_dbus_test_full(&st->dt, extra_args)) {
866 return FALSE;
867 }
868
869 return TRUE;
870 }
871
872 /*
873 * Connect to the VNC server using SASL and run the main loop
874 * until authentication completes or times out.
875 */
876 static void
877 run_sasl_auth(SaslTestData *st, const char *username,
878 const char *password)
879 {
880 VncConnection *conn;
881 guint timeout_id;
882 int vnc_fd;
883
884 st->sdata.dt = &st->dt;
885 st->sdata.username = username;
886 st->sdata.password = password;
887
888 vnc_fd = wait_for_vnc_socket(st->dt.vnc_sock_path, VNC_TEST_TIMEOUT_MS);
889 g_assert(vnc_fd >= 0);
890
891 conn = vnc_connection_new();
892 g_signal_connect(conn, "vnc-error",
893 G_CALLBACK(on_sasl_vnc_error), &st->sdata);
894 g_signal_connect(conn, "vnc-auth-failure",
895 G_CALLBACK(on_sasl_vnc_auth_failure), &st->sdata);
896 g_signal_connect(conn, "vnc-auth-credential",
897 G_CALLBACK(on_sasl_vnc_auth_credential),
898 &st->sdata);
899 g_signal_connect(conn, "vnc-initialized",
900 G_CALLBACK(on_sasl_vnc_initialized), &st->sdata);
901 vnc_connection_set_auth_type(conn, VNC_CONNECTION_AUTH_SASL);
902 vnc_connection_open_fd(conn, vnc_fd);
903
904 st->dt.loop = g_main_loop_new(NULL, FALSE);
905 timeout_id = g_timeout_add_seconds(10, timeout_cb, NULL);
906 g_main_loop_run(st->dt.loop);
907 g_source_remove(timeout_id);
908
909 g_signal_handlers_disconnect_by_data(conn, &st->sdata);
910 vnc_connection_shutdown(conn);
911 g_object_unref(conn);
912 g_main_loop_unref(st->dt.loop);
913 st->dt.loop = NULL;
914 }
915
916 static void
917 cleanup_sasl_test(SaslTestData *st)
918 {
919 cleanup_dbus_test(&st->dt);
920 g_unsetenv("SASL_CONF_PATH");
921 cleanup_sasl_config(st->sasl_dir, st->db_path);
922 g_free(st->sasl_dir);
923 g_free(st->db_path);
924 }
925
926 static void
927 test_dbus_vnc_sasl_auth(void)
928 {
929 SaslTestData st = { 0 };
930 const char *extra_args[] = { "--sasl", NULL };
931
932 if (!setup_sasl_test(&st, extra_args)) {
933 return;
934 }
935
936 run_sasl_auth(&st, SASL_TEST_USER, SASL_TEST_PASS);
937
938 g_assert_true(st.sdata.auth_succeeded);
939 g_assert_false(st.sdata.auth_failed);
940
941 cleanup_sasl_test(&st);
942 }
943
944 static void
945 test_dbus_vnc_sasl_auth_bad_password(void)
946 {
947 SaslTestData st = { 0 };
948 const char *extra_args[] = { "--sasl", NULL };
949
950 if (!setup_sasl_test(&st, extra_args)) {
951 return;
952 }
953
954 run_sasl_auth(&st, SASL_TEST_USER, "wrongpassword");
955
956 g_assert_false(st.sdata.auth_succeeded);
957 g_assert_true(st.sdata.auth_failed);
958
959 cleanup_sasl_test(&st);
960 }
961
962 static void
963 test_dbus_vnc_sasl_authz_denied(void)
964 {
965 SaslTestData st = { 0 };
966 const char *extra_args[] = {
967 "--sasl",
968 "--object",
969 "authz-simple,id=authz0,identity=otheruser",
970 "--sasl-authz", "authz0",
971 NULL
972 };
973
974 if (!setup_sasl_test(&st, extra_args)) {
975 return;
976 }
977
978 run_sasl_auth(&st, SASL_TEST_USER, SASL_TEST_PASS);
979
980 g_assert_false(st.sdata.auth_succeeded);
981 g_assert_true(st.sdata.auth_failed);
982
983 cleanup_sasl_test(&st);
984 }
985 #endif /* CONFIG_VNC_SASL */
986
987 static void
988 test_dbus_vnc_tls_authz_no_creds(void)
989 {
990 const char *binary;
991 g_autoptr(GError) err = NULL;
992 g_autoptr(GSubprocess) proc = NULL;
993 gboolean ok;
994
995 binary = g_getenv("QTEST_QEMU_VNC_BINARY");
996 if (!binary) {
997 g_test_skip("QTEST_QEMU_VNC_BINARY not set");
998 return;
999 }
1000
1001 proc = g_subprocess_new(G_SUBPROCESS_FLAGS_STDERR_SILENCE,
1002 &err,
1003 binary,
1004 "--tls-authz", "authz0",
1005 NULL);
1006 g_assert_no_error(err);
1007 g_assert_nonnull(proc);
1008
1009 ok = g_subprocess_wait(proc, NULL, &err);
1010 g_assert_no_error(err);
1011 g_assert_true(ok);
1012 g_assert_false(g_subprocess_get_successful(proc));
1013 }
1014
1015 #ifdef CONFIG_TASN1
1016 #define CLIENT_CERT_CN "qemu-vnc-test"
1017
1018 static char *
1019 create_tls_certs(const char *dir)
1020 {
1021 char *keyfile = g_strdup_printf("%s/key.pem", dir);
1022 char *cacert = g_strdup_printf("%s/ca-cert.pem", dir);
1023 char *servercert = g_strdup_printf("%s/server-cert.pem", dir);
1024 char *serverkey = g_strdup_printf("%s/server-key.pem", dir);
1025 char *clientcert = g_strdup_printf("%s/client-cert.pem", dir);
1026
1027 test_tls_init(keyfile);
1028 g_assert(link(keyfile, serverkey) == 0);
1029
1030 TLS_ROOT_REQ_SIMPLE(cacertreq, cacert);
1031 TLS_CERT_REQ_SIMPLE_SERVER(servercertreq, cacertreq,
1032 servercert, "localhost", NULL);
1033 TLS_CERT_REQ_SIMPLE_CLIENT(clientcertreq, cacertreq,
1034 CLIENT_CERT_CN, clientcert);
1035
1036 test_tls_deinit_cert(&clientcertreq);
1037 test_tls_deinit_cert(&servercertreq);
1038 test_tls_deinit_cert(&cacertreq);
1039
1040 g_free(cacert);
1041 g_free(servercert);
1042 g_free(serverkey);
1043 g_free(clientcert);
1044 return keyfile;
1045 }
1046
1047 static void
1048 cleanup_tls_certs(const char *dir, const char *keyfile)
1049 {
1050 g_autofree char *cacert = g_strdup_printf("%s/ca-cert.pem", dir);
1051 g_autofree char *servercert = g_strdup_printf("%s/server-cert.pem", dir);
1052 g_autofree char *serverkey = g_strdup_printf("%s/server-key.pem", dir);
1053 g_autofree char *clientcert = g_strdup_printf("%s/client-cert.pem", dir);
1054
1055 unlink(cacert);
1056 unlink(servercert);
1057 unlink(serverkey);
1058 unlink(clientcert);
1059 unlink(keyfile);
1060 test_tls_cleanup(keyfile);
1061 rmdir(dir);
1062 }
1063
1064 /*
1065 * Do a minimal VNC/VeNCrypt negotiation on @fd up to the point where
1066 * the TLS handshake should begin, then perform a GnuTLS handshake
1067 * using the given credentials.
1068 */
1069 static bool
1070 try_raw_tls_connect(int fd, gnutls_certificate_credentials_t cred)
1071 {
1072 char buf[13];
1073 uint8_t num_types, type;
1074 uint8_t vencrypt_ver[2], ack;
1075 uint8_t num_sub;
1076 uint32_t subtype;
1077 gnutls_session_t session;
1078 int ret;
1079 bool success;
1080
1081 /* RFB version exchange */
1082 g_assert_cmpint(read(fd, buf, 12), ==, 12);
1083 g_assert_cmpint(write(fd, "RFB 003.008\n", 12), ==, 12);
1084
1085 /* Select VeNCrypt (type 19) from the auth list */
1086 g_assert_cmpint(read(fd, &num_types, 1), ==, 1);
1087 for (int i = 0; i < num_types; i++) {
1088 g_assert_cmpint(read(fd, &type, 1), ==, 1);
1089 }
1090 type = 19;
1091 g_assert_cmpint(write(fd, &type, 1), ==, 1);
1092
1093 /* VeNCrypt version exchange */
1094 g_assert_cmpint(read(fd, vencrypt_ver, 2), ==, 2);
1095 g_assert_cmpint(write(fd, vencrypt_ver, 2), ==, 2);
1096 g_assert_cmpint(read(fd, &ack, 1), ==, 1);
1097 g_assert_cmpint(ack, ==, 0);
1098
1099 /* Select x509-none (260) sub-auth */
1100 g_assert_cmpint(read(fd, &num_sub, 1), ==, 1);
1101 for (int i = 0; i < num_sub; i++) {
1102 g_assert_cmpint(read(fd, &subtype, 4), ==, 4);
1103 }
1104 subtype = htonl(260);
1105 g_assert_cmpint(write(fd, &subtype, 4), ==, 4);
1106
1107 /* Server sends 1-byte ack (1 = accepted) before TLS starts */
1108 g_assert_cmpint(read(fd, &ack, 1), ==, 1);
1109 g_assert_cmpint(ack, ==, 1);
1110
1111 /* TLS handshake */
1112 g_assert_cmpint(gnutls_init(&session, GNUTLS_CLIENT), >=, 0);
1113 g_assert_cmpint(
1114 gnutls_set_default_priority(session), >=, 0);
1115 g_assert_cmpint(
1116 gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cred),
1117 >=, 0);
1118 gnutls_transport_set_int(session, fd);
1119
1120 do {
1121 ret = gnutls_handshake(session);
1122 } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
1123
1124 if (ret < 0) {
1125 success = false;
1126 } else {
1127 /*
1128 * Try reading the VNC security-result (4 bytes) — if the
1129 * server rejected us it will have closed the connection.
1130 */
1131 char tmp[4];
1132 do {
1133 ret = gnutls_record_recv(session, tmp, sizeof(tmp));
1134 } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
1135 success = (ret > 0);
1136 }
1137
1138 gnutls_deinit(session);
1139 return success;
1140 }
1141
1142 static void
1143 test_dbus_vnc_tls_server_props(void)
1144 {
1145 DbusTest dt = { 0 };
1146 QemuVnc1Server *proxy = NULL;
1147 g_autoptr(GError) err = NULL;
1148 g_autofree char *tls_dir = NULL;
1149 g_autofree char *keyfile = NULL;
1150
1151 if (!g_getenv("QTEST_QEMU_VNC_BINARY")) {
1152 g_test_skip("QTEST_QEMU_VNC_BINARY not set");
1153 return;
1154 }
1155
1156 tls_dir = g_dir_make_tmp("dbus-vnc-tls-XXXXXX", NULL);
1157 g_assert_nonnull(tls_dir);
1158 keyfile = create_tls_certs(tls_dir);
1159
1160 {
1161 const char *extra_args[] = {
1162 "--tls-creds", tls_dir, NULL
1163 };
1164 if (!setup_dbus_test_full(&dt, extra_args)) {
1165 goto cleanup;
1166 }
1167 }
1168
1169 proxy = create_server_proxy(dt.bus_conn, &err);
1170 g_assert_no_error(err);
1171 g_assert_nonnull(proxy);
1172
1173 g_assert_cmpstr(qemu_vnc1_server_get_auth(proxy), ==, "vencrypt");
1174 g_assert_cmpstr(qemu_vnc1_server_get_vencrypt_sub_auth(proxy), ==,
1175 "x509-none");
1176
1177 /*
1178 * With verify-peer=no, a client without a certificate should
1179 * be able to connect successfully through TLS.
1180 */
1181 {
1182 g_autofree char *ca_path =
1183 g_strdup_printf("%s/ca-cert.pem", tls_dir);
1184 gnutls_certificate_credentials_t cred;
1185 int fd;
1186
1187 g_assert_cmpint(
1188 gnutls_certificate_allocate_credentials(&cred), >=, 0);
1189 g_assert_cmpint(
1190 gnutls_certificate_set_x509_trust_file(
1191 cred, ca_path, GNUTLS_X509_FMT_PEM), >=, 0);
1192
1193 fd = wait_for_vnc_socket(dt.vnc_sock_path, VNC_TEST_TIMEOUT_MS);
1194 g_assert(fd >= 0);
1195 g_assert_true(try_raw_tls_connect(fd, cred));
1196 close(fd);
1197
1198 gnutls_certificate_free_credentials(cred);
1199 }
1200
1201 cleanup:
1202 g_clear_object(&proxy);
1203 cleanup_dbus_test(&dt);
1204 cleanup_tls_certs(tls_dir, keyfile);
1205 }
1206
1207 static void
1208 test_dbus_vnc_tls_authz(void)
1209 {
1210 DbusTest dt = { 0 };
1211 g_autofree char *tls_dir = NULL;
1212 g_autofree char *keyfile = NULL;
1213 g_autofree char *ca_path = NULL;
1214
1215 if (!g_getenv("QTEST_QEMU_VNC_BINARY")) {
1216 g_test_skip("QTEST_QEMU_VNC_BINARY not set");
1217 return;
1218 }
1219
1220 tls_dir = g_dir_make_tmp("dbus-vnc-tls-XXXXXX", NULL);
1221 g_assert_nonnull(tls_dir);
1222 keyfile = create_tls_certs(tls_dir);
1223
1224 /*
1225 * The client cert has CN=qemu-vnc-test, so the DN string
1226 * reported by GnuTLS is "CN=qemu-vnc-test". Configure
1227 * authz-simple to accept exactly that identity.
1228 */
1229 {
1230 g_autofree char *identity =
1231 g_strdup_printf("CN=%s", CLIENT_CERT_CN);
1232 const char *extra_args[] = {
1233 "--tls-creds", tls_dir,
1234 "--object",
1235 NULL, /* filled below */
1236 "--tls-authz", "authz0",
1237 NULL
1238 };
1239 g_autofree char *object_arg =
1240 g_strdup_printf("authz-simple,id=authz0,identity=%s", identity);
1241 extra_args[3] = object_arg;
1242
1243 if (!setup_dbus_test_full(&dt, extra_args)) {
1244 goto cleanup;
1245 }
1246 }
1247
1248 ca_path = g_strdup_printf("%s/ca-cert.pem", tls_dir);
1249
1250 /*
1251 * Connect without a client certificate.
1252 * With verify-peer=yes the TLS handshake must fail.
1253 */
1254 {
1255 gnutls_certificate_credentials_t cred;
1256 int fd;
1257
1258 g_assert_cmpint(
1259 gnutls_certificate_allocate_credentials(&cred), >=, 0);
1260 g_assert_cmpint(
1261 gnutls_certificate_set_x509_trust_file(
1262 cred, ca_path, GNUTLS_X509_FMT_PEM), >=, 0);
1263
1264 fd = wait_for_vnc_socket(dt.vnc_sock_path, VNC_TEST_TIMEOUT_MS);
1265 g_assert(fd >= 0);
1266 g_assert_false(try_raw_tls_connect(fd, cred));
1267 close(fd);
1268
1269 gnutls_certificate_free_credentials(cred);
1270 }
1271
1272 /*
1273 * Connect with a valid client certificate whose DN
1274 * matches the authz-simple identity. This must succeed.
1275 */
1276 {
1277 g_autofree char *cert_path =
1278 g_strdup_printf("%s/client-cert.pem", tls_dir);
1279 g_autofree char *key_path =
1280 g_strdup_printf("%s/key.pem", tls_dir);
1281 gnutls_certificate_credentials_t cred;
1282 int fd;
1283
1284 g_assert_cmpint(
1285 gnutls_certificate_allocate_credentials(&cred), >=, 0);
1286 g_assert_cmpint(
1287 gnutls_certificate_set_x509_trust_file(
1288 cred, ca_path, GNUTLS_X509_FMT_PEM), >=, 0);
1289 g_assert_cmpint(
1290 gnutls_certificate_set_x509_key_file(
1291 cred, cert_path, key_path, GNUTLS_X509_FMT_PEM), >=, 0);
1292
1293 fd = wait_for_vnc_socket(dt.vnc_sock_path, VNC_TEST_TIMEOUT_MS);
1294 g_assert(fd >= 0);
1295 g_assert_true(try_raw_tls_connect(fd, cred));
1296 close(fd);
1297
1298 gnutls_certificate_free_credentials(cred);
1299 }
1300
1301 cleanup:
1302 cleanup_dbus_test(&dt);
1303 cleanup_tls_certs(tls_dir, keyfile);
1304 }
1305 #endif /* CONFIG_TASN1 */
1306
1307 int
1308 main(int argc, char **argv)
1309 {
1310 g_log_set_always_fatal(G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL);
1311
1312 /*
1313 * Flaky test:
1314 * ERROR:../tests/qtest/dbus-vnc-test.c:621:test_dbus_vnc_password_auth:
1315 * assertion failed (qemu_vnc1_server_get_auth(proxy) == "vnc"): ("none" ==
1316 * "vnc")
1317 */
1318 if (!getenv("QEMU_TEST_FLAKY_TESTS")) {
1319 g_test_skip("QEMU_TEST_FLAKY_TESTS not set");
1320 return 0;
1321 }
1322 if (getenv("GTK_VNC_DEBUG")) {
1323 vnc_util_set_debug(true);
1324 }
1325
1326 g_test_init(&argc, &argv, NULL);
1327
1328 qtest_add_func("/dbus-vnc/basic", test_dbus_vnc_basic);
1329 qtest_add_func("/dbus-vnc/server-props", test_dbus_vnc_server_props);
1330 qtest_add_func("/dbus-vnc/client-lifecycle",
1331 test_dbus_vnc_client_lifecycle);
1332 qtest_add_func("/dbus-vnc/no-password", test_dbus_vnc_no_password);
1333 qtest_add_func("/dbus-vnc/password-auth", test_dbus_vnc_password_auth);
1334 qtest_add_func("/dbus-vnc/sasl-authz-no-sasl",
1335 test_dbus_vnc_sasl_authz_no_sasl);
1336 #ifdef CONFIG_VNC_SASL
1337 qtest_add_func("/dbus-vnc/sasl-server-props",
1338 test_dbus_vnc_sasl_server_props);
1339 qtest_add_func("/dbus-vnc/sasl-auth",
1340 test_dbus_vnc_sasl_auth);
1341 qtest_add_func("/dbus-vnc/sasl-auth-bad-password",
1342 test_dbus_vnc_sasl_auth_bad_password);
1343 qtest_add_func("/dbus-vnc/sasl-authz-denied",
1344 test_dbus_vnc_sasl_authz_denied);
1345 #endif
1346 qtest_add_func("/dbus-vnc/tls-authz-no-creds",
1347 test_dbus_vnc_tls_authz_no_creds);
1348 #ifdef CONFIG_TASN1
1349 qtest_add_func("/dbus-vnc/tls-server-props",
1350 test_dbus_vnc_tls_server_props);
1351 qtest_add_func("/dbus-vnc/tls-authz",
1352 test_dbus_vnc_tls_authz);
1353 #endif
1354
1355 return g_test_run();
1356 }