]> Git Repo - qemu.git/blob - migration/tls.c
Merge remote-tracking branch 'quintela/tags/migration/20170518' into staging
[qemu.git] / migration / tls.c
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
9  * version 2 of the License, or (at your option) any later version.
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"
22 #include "channel.h"
23 #include "migration/migration.h"
24 #include "io/channel-tls.h"
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     }
52     if (ret->endpoint != endpoint) {
53         error_setg(errp,
54                    "Expected TLS credentials for a %s endpoint",
55                    endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT ?
56                    "client" : "server");
57         return NULL;
58     }
59
60     object_ref(OBJECT(ret));
61     return ret;
62 }
63
64
65 static void migration_tls_incoming_handshake(QIOTask *task,
66                                              gpointer opaque)
67 {
68     QIOChannel *ioc = QIO_CHANNEL(qio_task_get_source(task));
69     Error *err = NULL;
70
71     if (qio_task_propagate_error(task, &err)) {
72         trace_migration_tls_incoming_handshake_error(error_get_pretty(err));
73         error_report_err(err);
74     } else {
75         trace_migration_tls_incoming_handshake_complete();
76         migration_channel_process_incoming(migrate_get_current(), ioc);
77     }
78     object_unref(OBJECT(ioc));
79 }
80
81 void migration_tls_channel_process_incoming(MigrationState *s,
82                                             QIOChannel *ioc,
83                                             Error **errp)
84 {
85     QCryptoTLSCreds *creds;
86     QIOChannelTLS *tioc;
87
88     creds = migration_tls_get_creds(
89         s, QCRYPTO_TLS_CREDS_ENDPOINT_SERVER, errp);
90     if (!creds) {
91         return;
92     }
93
94     tioc = qio_channel_tls_new_server(
95         ioc, creds,
96         NULL, /* XXX pass ACL name */
97         errp);
98     if (!tioc) {
99         return;
100     }
101
102     trace_migration_tls_incoming_handshake_start();
103     qio_channel_set_name(QIO_CHANNEL(tioc), "migration-tls-incoming");
104     qio_channel_tls_handshake(tioc,
105                               migration_tls_incoming_handshake,
106                               NULL,
107                               NULL);
108 }
109
110
111 static void migration_tls_outgoing_handshake(QIOTask *task,
112                                              gpointer opaque)
113 {
114     MigrationState *s = opaque;
115     QIOChannel *ioc = QIO_CHANNEL(qio_task_get_source(task));
116     Error *err = NULL;
117
118     if (qio_task_propagate_error(task, &err)) {
119         trace_migration_tls_outgoing_handshake_error(error_get_pretty(err));
120         migrate_fd_error(s, err);
121         error_free(err);
122     } else {
123         trace_migration_tls_outgoing_handshake_complete();
124         migration_channel_connect(s, ioc, NULL);
125     }
126     object_unref(OBJECT(ioc));
127 }
128
129
130 void migration_tls_channel_connect(MigrationState *s,
131                                    QIOChannel *ioc,
132                                    const char *hostname,
133                                    Error **errp)
134 {
135     QCryptoTLSCreds *creds;
136     QIOChannelTLS *tioc;
137
138     creds = migration_tls_get_creds(
139         s, QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT, errp);
140     if (!creds) {
141         return;
142     }
143
144     if (s->parameters.tls_hostname && *s->parameters.tls_hostname) {
145         hostname = s->parameters.tls_hostname;
146     }
147     if (!hostname) {
148         error_setg(errp, "No hostname available for TLS");
149         return;
150     }
151
152     tioc = qio_channel_tls_new_client(
153         ioc, creds, hostname, errp);
154     if (!tioc) {
155         return;
156     }
157
158     trace_migration_tls_outgoing_handshake_start(hostname);
159     qio_channel_set_name(QIO_CHANNEL(tioc), "migration-tls-outgoing");
160     qio_channel_tls_handshake(tioc,
161                               migration_tls_outgoing_handshake,
162                               s,
163                               NULL);
164 }
This page took 0.032339 seconds and 4 git commands to generate.