channel-tls.c (12694B)
1/* 2 * QEMU I/O channels TLS driver 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.1 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 "qapi/error.h" 23#include "qemu/module.h" 24#include "io/channel-tls.h" 25#include "trace.h" 26#include "qemu/atomic.h" 27 28 29static ssize_t qio_channel_tls_write_handler(const char *buf, 30 size_t len, 31 void *opaque) 32{ 33 QIOChannelTLS *tioc = QIO_CHANNEL_TLS(opaque); 34 ssize_t ret; 35 36 ret = qio_channel_write(tioc->master, buf, len, NULL); 37 if (ret == QIO_CHANNEL_ERR_BLOCK) { 38 errno = EAGAIN; 39 return -1; 40 } else if (ret < 0) { 41 errno = EIO; 42 return -1; 43 } 44 return ret; 45} 46 47static ssize_t qio_channel_tls_read_handler(char *buf, 48 size_t len, 49 void *opaque) 50{ 51 QIOChannelTLS *tioc = QIO_CHANNEL_TLS(opaque); 52 ssize_t ret; 53 54 ret = qio_channel_read(tioc->master, buf, len, NULL); 55 if (ret == QIO_CHANNEL_ERR_BLOCK) { 56 errno = EAGAIN; 57 return -1; 58 } else if (ret < 0) { 59 errno = EIO; 60 return -1; 61 } 62 return ret; 63} 64 65 66QIOChannelTLS * 67qio_channel_tls_new_server(QIOChannel *master, 68 QCryptoTLSCreds *creds, 69 const char *aclname, 70 Error **errp) 71{ 72 QIOChannelTLS *ioc; 73 74 ioc = QIO_CHANNEL_TLS(object_new(TYPE_QIO_CHANNEL_TLS)); 75 76 ioc->master = master; 77 object_ref(OBJECT(master)); 78 79 ioc->session = qcrypto_tls_session_new( 80 creds, 81 NULL, 82 aclname, 83 QCRYPTO_TLS_CREDS_ENDPOINT_SERVER, 84 errp); 85 if (!ioc->session) { 86 goto error; 87 } 88 89 qcrypto_tls_session_set_callbacks( 90 ioc->session, 91 qio_channel_tls_write_handler, 92 qio_channel_tls_read_handler, 93 ioc); 94 95 trace_qio_channel_tls_new_server(ioc, master, creds, aclname); 96 return ioc; 97 98 error: 99 object_unref(OBJECT(ioc)); 100 return NULL; 101} 102 103QIOChannelTLS * 104qio_channel_tls_new_client(QIOChannel *master, 105 QCryptoTLSCreds *creds, 106 const char *hostname, 107 Error **errp) 108{ 109 QIOChannelTLS *tioc; 110 QIOChannel *ioc; 111 112 tioc = QIO_CHANNEL_TLS(object_new(TYPE_QIO_CHANNEL_TLS)); 113 ioc = QIO_CHANNEL(tioc); 114 115 tioc->master = master; 116 if (qio_channel_has_feature(master, QIO_CHANNEL_FEATURE_SHUTDOWN)) { 117 qio_channel_set_feature(ioc, QIO_CHANNEL_FEATURE_SHUTDOWN); 118 } 119 object_ref(OBJECT(master)); 120 121 tioc->session = qcrypto_tls_session_new( 122 creds, 123 hostname, 124 NULL, 125 QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT, 126 errp); 127 if (!tioc->session) { 128 goto error; 129 } 130 131 qcrypto_tls_session_set_callbacks( 132 tioc->session, 133 qio_channel_tls_write_handler, 134 qio_channel_tls_read_handler, 135 tioc); 136 137 trace_qio_channel_tls_new_client(tioc, master, creds, hostname); 138 return tioc; 139 140 error: 141 object_unref(OBJECT(tioc)); 142 return NULL; 143} 144 145struct QIOChannelTLSData { 146 QIOTask *task; 147 GMainContext *context; 148}; 149typedef struct QIOChannelTLSData QIOChannelTLSData; 150 151static gboolean qio_channel_tls_handshake_io(QIOChannel *ioc, 152 GIOCondition condition, 153 gpointer user_data); 154 155static void qio_channel_tls_handshake_task(QIOChannelTLS *ioc, 156 QIOTask *task, 157 GMainContext *context) 158{ 159 Error *err = NULL; 160 QCryptoTLSSessionHandshakeStatus status; 161 162 if (qcrypto_tls_session_handshake(ioc->session, &err) < 0) { 163 trace_qio_channel_tls_handshake_fail(ioc); 164 qio_task_set_error(task, err); 165 qio_task_complete(task); 166 return; 167 } 168 169 status = qcrypto_tls_session_get_handshake_status(ioc->session); 170 if (status == QCRYPTO_TLS_HANDSHAKE_COMPLETE) { 171 trace_qio_channel_tls_handshake_complete(ioc); 172 if (qcrypto_tls_session_check_credentials(ioc->session, 173 &err) < 0) { 174 trace_qio_channel_tls_credentials_deny(ioc); 175 qio_task_set_error(task, err); 176 } else { 177 trace_qio_channel_tls_credentials_allow(ioc); 178 } 179 qio_task_complete(task); 180 } else { 181 GIOCondition condition; 182 QIOChannelTLSData *data = g_new0(typeof(*data), 1); 183 184 data->task = task; 185 data->context = context; 186 187 if (context) { 188 g_main_context_ref(context); 189 } 190 191 if (status == QCRYPTO_TLS_HANDSHAKE_SENDING) { 192 condition = G_IO_OUT; 193 } else { 194 condition = G_IO_IN; 195 } 196 197 trace_qio_channel_tls_handshake_pending(ioc, status); 198 qio_channel_add_watch_full(ioc->master, 199 condition, 200 qio_channel_tls_handshake_io, 201 data, 202 NULL, 203 context); 204 } 205} 206 207 208static gboolean qio_channel_tls_handshake_io(QIOChannel *ioc, 209 GIOCondition condition, 210 gpointer user_data) 211{ 212 QIOChannelTLSData *data = user_data; 213 QIOTask *task = data->task; 214 GMainContext *context = data->context; 215 QIOChannelTLS *tioc = QIO_CHANNEL_TLS( 216 qio_task_get_source(task)); 217 218 g_free(data); 219 qio_channel_tls_handshake_task(tioc, task, context); 220 221 if (context) { 222 g_main_context_unref(context); 223 } 224 225 return FALSE; 226} 227 228void qio_channel_tls_handshake(QIOChannelTLS *ioc, 229 QIOTaskFunc func, 230 gpointer opaque, 231 GDestroyNotify destroy, 232 GMainContext *context) 233{ 234 QIOTask *task; 235 236 task = qio_task_new(OBJECT(ioc), 237 func, opaque, destroy); 238 239 trace_qio_channel_tls_handshake_start(ioc); 240 qio_channel_tls_handshake_task(ioc, task, context); 241} 242 243 244static void qio_channel_tls_init(Object *obj G_GNUC_UNUSED) 245{ 246} 247 248 249static void qio_channel_tls_finalize(Object *obj) 250{ 251 QIOChannelTLS *ioc = QIO_CHANNEL_TLS(obj); 252 253 object_unref(OBJECT(ioc->master)); 254 qcrypto_tls_session_free(ioc->session); 255} 256 257 258static ssize_t qio_channel_tls_readv(QIOChannel *ioc, 259 const struct iovec *iov, 260 size_t niov, 261 int **fds, 262 size_t *nfds, 263 Error **errp) 264{ 265 QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc); 266 size_t i; 267 ssize_t got = 0; 268 269 for (i = 0 ; i < niov ; i++) { 270 ssize_t ret = qcrypto_tls_session_read(tioc->session, 271 iov[i].iov_base, 272 iov[i].iov_len); 273 if (ret < 0) { 274 if (errno == EAGAIN) { 275 if (got) { 276 return got; 277 } else { 278 return QIO_CHANNEL_ERR_BLOCK; 279 } 280 } else if (errno == ECONNABORTED && 281 (qatomic_load_acquire(&tioc->shutdown) & 282 QIO_CHANNEL_SHUTDOWN_READ)) { 283 return 0; 284 } 285 286 error_setg_errno(errp, errno, 287 "Cannot read from TLS channel"); 288 return -1; 289 } 290 got += ret; 291 if (ret < iov[i].iov_len) { 292 break; 293 } 294 } 295 return got; 296} 297 298 299static ssize_t qio_channel_tls_writev(QIOChannel *ioc, 300 const struct iovec *iov, 301 size_t niov, 302 int *fds, 303 size_t nfds, 304 Error **errp) 305{ 306 QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc); 307 size_t i; 308 ssize_t done = 0; 309 310 for (i = 0 ; i < niov ; i++) { 311 ssize_t ret = qcrypto_tls_session_write(tioc->session, 312 iov[i].iov_base, 313 iov[i].iov_len); 314 if (ret <= 0) { 315 if (errno == EAGAIN) { 316 if (done) { 317 return done; 318 } else { 319 return QIO_CHANNEL_ERR_BLOCK; 320 } 321 } 322 323 error_setg_errno(errp, errno, 324 "Cannot write to TLS channel"); 325 return -1; 326 } 327 done += ret; 328 if (ret < iov[i].iov_len) { 329 break; 330 } 331 } 332 return done; 333} 334 335static int qio_channel_tls_set_blocking(QIOChannel *ioc, 336 bool enabled, 337 Error **errp) 338{ 339 QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc); 340 341 return qio_channel_set_blocking(tioc->master, enabled, errp); 342} 343 344static void qio_channel_tls_set_delay(QIOChannel *ioc, 345 bool enabled) 346{ 347 QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc); 348 349 qio_channel_set_delay(tioc->master, enabled); 350} 351 352static void qio_channel_tls_set_cork(QIOChannel *ioc, 353 bool enabled) 354{ 355 QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc); 356 357 qio_channel_set_cork(tioc->master, enabled); 358} 359 360static int qio_channel_tls_shutdown(QIOChannel *ioc, 361 QIOChannelShutdown how, 362 Error **errp) 363{ 364 QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc); 365 366 qatomic_or(&tioc->shutdown, how); 367 368 return qio_channel_shutdown(tioc->master, how, errp); 369} 370 371static int qio_channel_tls_close(QIOChannel *ioc, 372 Error **errp) 373{ 374 QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc); 375 376 return qio_channel_close(tioc->master, errp); 377} 378 379static void qio_channel_tls_set_aio_fd_handler(QIOChannel *ioc, 380 AioContext *ctx, 381 IOHandler *io_read, 382 IOHandler *io_write, 383 void *opaque) 384{ 385 QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc); 386 387 qio_channel_set_aio_fd_handler(tioc->master, ctx, io_read, io_write, opaque); 388} 389 390static GSource *qio_channel_tls_create_watch(QIOChannel *ioc, 391 GIOCondition condition) 392{ 393 QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc); 394 395 return qio_channel_create_watch(tioc->master, condition); 396} 397 398QCryptoTLSSession * 399qio_channel_tls_get_session(QIOChannelTLS *ioc) 400{ 401 return ioc->session; 402} 403 404static void qio_channel_tls_class_init(ObjectClass *klass, 405 void *class_data G_GNUC_UNUSED) 406{ 407 QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass); 408 409 ioc_klass->io_writev = qio_channel_tls_writev; 410 ioc_klass->io_readv = qio_channel_tls_readv; 411 ioc_klass->io_set_blocking = qio_channel_tls_set_blocking; 412 ioc_klass->io_set_delay = qio_channel_tls_set_delay; 413 ioc_klass->io_set_cork = qio_channel_tls_set_cork; 414 ioc_klass->io_close = qio_channel_tls_close; 415 ioc_klass->io_shutdown = qio_channel_tls_shutdown; 416 ioc_klass->io_create_watch = qio_channel_tls_create_watch; 417 ioc_klass->io_set_aio_fd_handler = qio_channel_tls_set_aio_fd_handler; 418} 419 420static const TypeInfo qio_channel_tls_info = { 421 .parent = TYPE_QIO_CHANNEL, 422 .name = TYPE_QIO_CHANNEL_TLS, 423 .instance_size = sizeof(QIOChannelTLS), 424 .instance_init = qio_channel_tls_init, 425 .instance_finalize = qio_channel_tls_finalize, 426 .class_init = qio_channel_tls_class_init, 427}; 428 429static void qio_channel_tls_register_types(void) 430{ 431 type_register_static(&qio_channel_tls_info); 432} 433 434type_init(qio_channel_tls_register_types);