]>
Commit | Line | Data |
---|---|---|
e1226365 DB |
1 | /* |
2 | * QEMU migration TLS support | |
3 | * | |
4 | * Copyright (c) 2015 Red Hat, Inc. | |
5 | * | |
6 | * This library is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU Lesser General Public | |
8 | * License as published by the Free Software Foundation; either | |
ef19b50d | 9 | * version 2.1 of the License, or (at your option) any later version. |
e1226365 DB |
10 | * |
11 | * This library is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | * Lesser General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU Lesser General Public | |
17 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. | |
18 | * | |
19 | */ | |
20 | ||
21 | #include "qemu/osdep.h" | |
dd4339c5 | 22 | #include "channel.h" |
6666c96a | 23 | #include "migration.h" |
41d64227 | 24 | #include "tls.h" |
e1226365 DB |
25 | #include "crypto/tlscreds.h" |
26 | #include "qemu/error-report.h" | |
27 | #include "qapi/error.h" | |
28 | #include "trace.h" | |
29 | ||
30 | static QCryptoTLSCreds * | |
31 | migration_tls_get_creds(MigrationState *s, | |
32 | QCryptoTLSCredsEndpoint endpoint, | |
33 | Error **errp) | |
34 | { | |
35 | Object *creds; | |
36 | QCryptoTLSCreds *ret; | |
37 | ||
38 | creds = object_resolve_path_component( | |
39 | object_get_objects_root(), s->parameters.tls_creds); | |
40 | if (!creds) { | |
41 | error_setg(errp, "No TLS credentials with id '%s'", | |
42 | s->parameters.tls_creds); | |
43 | return NULL; | |
44 | } | |
45 | ret = (QCryptoTLSCreds *)object_dynamic_cast( | |
46 | creds, TYPE_QCRYPTO_TLS_CREDS); | |
47 | if (!ret) { | |
48 | error_setg(errp, "Object with id '%s' is not TLS credentials", | |
49 | s->parameters.tls_creds); | |
50 | return NULL; | |
51 | } | |
5590f65f | 52 | if (!qcrypto_tls_creds_check_endpoint(ret, endpoint, errp)) { |
e1226365 DB |
53 | return NULL; |
54 | } | |
55 | ||
e1226365 DB |
56 | return ret; |
57 | } | |
58 | ||
59 | ||
60e705c5 | 60 | static void migration_tls_incoming_handshake(QIOTask *task, |
e1226365 DB |
61 | gpointer opaque) |
62 | { | |
60e705c5 DB |
63 | QIOChannel *ioc = QIO_CHANNEL(qio_task_get_source(task)); |
64 | Error *err = NULL; | |
e1226365 | 65 | |
60e705c5 | 66 | if (qio_task_propagate_error(task, &err)) { |
e1226365 | 67 | trace_migration_tls_incoming_handshake_error(error_get_pretty(err)); |
60e705c5 | 68 | error_report_err(err); |
e1226365 DB |
69 | } else { |
70 | trace_migration_tls_incoming_handshake_complete(); | |
54314711 | 71 | migration_channel_process_incoming(ioc); |
e1226365 DB |
72 | } |
73 | object_unref(OBJECT(ioc)); | |
74 | } | |
75 | ||
22724f49 DB |
76 | void migration_tls_channel_process_incoming(MigrationState *s, |
77 | QIOChannel *ioc, | |
78 | Error **errp) | |
e1226365 DB |
79 | { |
80 | QCryptoTLSCreds *creds; | |
81 | QIOChannelTLS *tioc; | |
82 | ||
83 | creds = migration_tls_get_creds( | |
84 | s, QCRYPTO_TLS_CREDS_ENDPOINT_SERVER, errp); | |
85 | if (!creds) { | |
86 | return; | |
87 | } | |
88 | ||
89 | tioc = qio_channel_tls_new_server( | |
90 | ioc, creds, | |
d2f1d29b | 91 | s->parameters.tls_authz, |
e1226365 DB |
92 | errp); |
93 | if (!tioc) { | |
94 | return; | |
95 | } | |
96 | ||
97 | trace_migration_tls_incoming_handshake_start(); | |
6f01f136 | 98 | qio_channel_set_name(QIO_CHANNEL(tioc), "migration-tls-incoming"); |
e1226365 DB |
99 | qio_channel_tls_handshake(tioc, |
100 | migration_tls_incoming_handshake, | |
101 | NULL, | |
1939ccda | 102 | NULL, |
e1226365 DB |
103 | NULL); |
104 | } | |
105 | ||
106 | ||
60e705c5 | 107 | static void migration_tls_outgoing_handshake(QIOTask *task, |
e1226365 DB |
108 | gpointer opaque) |
109 | { | |
110 | MigrationState *s = opaque; | |
60e705c5 DB |
111 | QIOChannel *ioc = QIO_CHANNEL(qio_task_get_source(task)); |
112 | Error *err = NULL; | |
e1226365 | 113 | |
60e705c5 | 114 | if (qio_task_propagate_error(task, &err)) { |
e1226365 | 115 | trace_migration_tls_outgoing_handshake_error(error_get_pretty(err)); |
e1226365 DB |
116 | } else { |
117 | trace_migration_tls_outgoing_handshake_complete(); | |
e1226365 | 118 | } |
688a3dcb | 119 | migration_channel_connect(s, ioc, NULL, err); |
e1226365 DB |
120 | object_unref(OBJECT(ioc)); |
121 | } | |
122 | ||
bfb790e7 CZ |
123 | QIOChannelTLS *migration_tls_client_create(MigrationState *s, |
124 | QIOChannel *ioc, | |
125 | const char *hostname, | |
126 | Error **errp) | |
e1226365 DB |
127 | { |
128 | QCryptoTLSCreds *creds; | |
e1226365 DB |
129 | |
130 | creds = migration_tls_get_creds( | |
131 | s, QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT, errp); | |
132 | if (!creds) { | |
bfb790e7 | 133 | return NULL; |
e1226365 DB |
134 | } |
135 | ||
4af245dc | 136 | if (s->parameters.tls_hostname && *s->parameters.tls_hostname) { |
e1226365 DB |
137 | hostname = s->parameters.tls_hostname; |
138 | } | |
e1226365 | 139 | |
66997c42 | 140 | return qio_channel_tls_new_client(ioc, creds, hostname, errp); |
bfb790e7 CZ |
141 | } |
142 | ||
143 | void migration_tls_channel_connect(MigrationState *s, | |
144 | QIOChannel *ioc, | |
145 | const char *hostname, | |
146 | Error **errp) | |
147 | { | |
148 | QIOChannelTLS *tioc; | |
149 | ||
150 | tioc = migration_tls_client_create(s, ioc, hostname, errp); | |
e1226365 DB |
151 | if (!tioc) { |
152 | return; | |
153 | } | |
154 | ||
d8053e73 CZ |
155 | /* Save hostname into MigrationState for handshake */ |
156 | s->hostname = g_strdup(hostname); | |
e1226365 | 157 | trace_migration_tls_outgoing_handshake_start(hostname); |
6f01f136 | 158 | qio_channel_set_name(QIO_CHANNEL(tioc), "migration-tls-outgoing"); |
e1226365 DB |
159 | qio_channel_tls_handshake(tioc, |
160 | migration_tls_outgoing_handshake, | |
161 | s, | |
1939ccda | 162 | NULL, |
e1226365 DB |
163 | NULL); |
164 | } | |
85a8578e PX |
165 | |
166 | bool migrate_channel_requires_tls_upgrade(QIOChannel *ioc) | |
167 | { | |
168 | if (!migrate_use_tls()) { | |
169 | return false; | |
170 | } | |
171 | ||
172 | return !object_dynamic_cast(OBJECT(ioc), TYPE_QIO_CHANNEL_TLS); | |
173 | } |