1 /* 2 * QEMU Block driver for CURL images 3 * 4 * Copyright (c) 2009 Alexander Graf <agraf@suse.de> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25 #include "qemu/osdep.h" 26 #include "qapi/error.h" 27 #include "qemu/error-report.h" 28 #include "qemu/module.h" 29 #include "qemu/option.h" 30 #include "block/block_int.h" 31 #include "qapi/qmp/qdict.h" 32 #include "qapi/qmp/qstring.h" 33 #include "crypto/secret.h" 34 #include <curl/curl.h> 35 #include "qemu/cutils.h" 36 #include "trace.h" 37 38 // #define DEBUG_VERBOSE 39 40 #if LIBCURL_VERSION_NUM >= 0x071000 41 /* The multi interface timer callback was introduced in 7.16.0 */ 42 #define NEED_CURL_TIMER_CALLBACK 43 #define HAVE_SOCKET_ACTION 44 #endif 45 46 #ifndef HAVE_SOCKET_ACTION 47 /* If curl_multi_socket_action isn't available, define it statically here in 48 * terms of curl_multi_socket. Note that ev_bitmask will be ignored, which is 49 * less efficient but still safe. */ 50 static CURLMcode __curl_multi_socket_action(CURLM *multi_handle, 51 curl_socket_t sockfd, 52 int ev_bitmask, 53 int *running_handles) 54 { 55 return curl_multi_socket(multi_handle, sockfd, running_handles); 56 } 57 #define curl_multi_socket_action __curl_multi_socket_action 58 #endif 59 60 #define PROTOCOLS (CURLPROTO_HTTP | CURLPROTO_HTTPS | \ 61 CURLPROTO_FTP | CURLPROTO_FTPS) 62 63 #define CURL_NUM_STATES 8 64 #define CURL_NUM_ACB 8 65 #define CURL_TIMEOUT_MAX 10000 66 67 #define CURL_BLOCK_OPT_URL "url" 68 #define CURL_BLOCK_OPT_READAHEAD "readahead" 69 #define CURL_BLOCK_OPT_SSLVERIFY "sslverify" 70 #define CURL_BLOCK_OPT_TIMEOUT "timeout" 71 #define CURL_BLOCK_OPT_COOKIE "cookie" 72 #define CURL_BLOCK_OPT_COOKIE_SECRET "cookie-secret" 73 #define CURL_BLOCK_OPT_USERNAME "username" 74 #define CURL_BLOCK_OPT_PASSWORD_SECRET "password-secret" 75 #define CURL_BLOCK_OPT_PROXY_USERNAME "proxy-username" 76 #define CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET "proxy-password-secret" 77 78 #define CURL_BLOCK_OPT_READAHEAD_DEFAULT (256 * 1024) 79 #define CURL_BLOCK_OPT_SSLVERIFY_DEFAULT true 80 #define CURL_BLOCK_OPT_TIMEOUT_DEFAULT 5 81 82 struct BDRVCURLState; 83 struct CURLState; 84 85 static bool libcurl_initialized; 86 87 typedef struct CURLAIOCB { 88 Coroutine *co; 89 QEMUIOVector *qiov; 90 91 uint64_t offset; 92 uint64_t bytes; 93 int ret; 94 95 size_t start; 96 size_t end; 97 } CURLAIOCB; 98 99 typedef struct CURLSocket { 100 int fd; 101 struct CURLState *state; 102 QLIST_ENTRY(CURLSocket) next; 103 } CURLSocket; 104 105 typedef struct CURLState 106 { 107 struct BDRVCURLState *s; 108 CURLAIOCB *acb[CURL_NUM_ACB]; 109 CURL *curl; 110 QLIST_HEAD(, CURLSocket) sockets; 111 char *orig_buf; 112 uint64_t buf_start; 113 size_t buf_off; 114 size_t buf_len; 115 char range[128]; 116 char errmsg[CURL_ERROR_SIZE]; 117 char in_use; 118 } CURLState; 119 120 typedef struct BDRVCURLState { 121 CURLM *multi; 122 QEMUTimer timer; 123 uint64_t len; 124 CURLState states[CURL_NUM_STATES]; 125 char *url; 126 size_t readahead_size; 127 bool sslverify; 128 uint64_t timeout; 129 char *cookie; 130 bool accept_range; 131 AioContext *aio_context; 132 QemuMutex mutex; 133 CoQueue free_state_waitq; 134 char *username; 135 char *password; 136 char *proxyusername; 137 char *proxypassword; 138 } BDRVCURLState; 139 140 static void curl_clean_state(CURLState *s); 141 static void curl_multi_do(void *arg); 142 143 #ifdef NEED_CURL_TIMER_CALLBACK 144 /* Called from curl_multi_do_locked, with s->mutex held. */ 145 static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque) 146 { 147 BDRVCURLState *s = opaque; 148 149 trace_curl_timer_cb(timeout_ms); 150 if (timeout_ms == -1) { 151 timer_del(&s->timer); 152 } else { 153 int64_t timeout_ns = (int64_t)timeout_ms * 1000 * 1000; 154 timer_mod(&s->timer, 155 qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + timeout_ns); 156 } 157 return 0; 158 } 159 #endif 160 161 /* Called from curl_multi_do_locked, with s->mutex held. */ 162 static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, 163 void *userp, void *sp) 164 { 165 BDRVCURLState *s; 166 CURLState *state = NULL; 167 CURLSocket *socket; 168 169 curl_easy_getinfo(curl, CURLINFO_PRIVATE, (char **)&state); 170 s = state->s; 171 172 QLIST_FOREACH(socket, &state->sockets, next) { 173 if (socket->fd == fd) { 174 break; 175 } 176 } 177 if (!socket) { 178 socket = g_new0(CURLSocket, 1); 179 socket->fd = fd; 180 socket->state = state; 181 QLIST_INSERT_HEAD(&state->sockets, socket, next); 182 } 183 184 trace_curl_sock_cb(action, (int)fd); 185 switch (action) { 186 case CURL_POLL_IN: 187 aio_set_fd_handler(s->aio_context, fd, false, 188 curl_multi_do, NULL, NULL, socket); 189 break; 190 case CURL_POLL_OUT: 191 aio_set_fd_handler(s->aio_context, fd, false, 192 NULL, curl_multi_do, NULL, socket); 193 break; 194 case CURL_POLL_INOUT: 195 aio_set_fd_handler(s->aio_context, fd, false, 196 curl_multi_do, curl_multi_do, NULL, socket); 197 break; 198 case CURL_POLL_REMOVE: 199 aio_set_fd_handler(s->aio_context, fd, false, 200 NULL, NULL, NULL, NULL); 201 break; 202 } 203 204 if (action == CURL_POLL_REMOVE) { 205 QLIST_REMOVE(socket, next); 206 g_free(socket); 207 } 208 209 return 0; 210 } 211 212 /* Called from curl_multi_do_locked, with s->mutex held. */ 213 static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque) 214 { 215 BDRVCURLState *s = opaque; 216 size_t realsize = size * nmemb; 217 const char *accept_line = "Accept-Ranges: bytes"; 218 219 if (realsize >= strlen(accept_line) 220 && strncmp((char *)ptr, accept_line, strlen(accept_line)) == 0) { 221 s->accept_range = true; 222 } 223 224 return realsize; 225 } 226 227 /* Called from curl_multi_do_locked, with s->mutex held. */ 228 static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque) 229 { 230 CURLState *s = ((CURLState*)opaque); 231 size_t realsize = size * nmemb; 232 233 trace_curl_read_cb(realsize); 234 235 if (!s || !s->orig_buf) { 236 goto read_end; 237 } 238 239 if (s->buf_off >= s->buf_len) { 240 /* buffer full, read nothing */ 241 goto read_end; 242 } 243 realsize = MIN(realsize, s->buf_len - s->buf_off); 244 memcpy(s->orig_buf + s->buf_off, ptr, realsize); 245 s->buf_off += realsize; 246 247 read_end: 248 /* curl will error out if we do not return this value */ 249 return size * nmemb; 250 } 251 252 /* Called with s->mutex held. */ 253 static bool curl_find_buf(BDRVCURLState *s, uint64_t start, uint64_t len, 254 CURLAIOCB *acb) 255 { 256 int i; 257 uint64_t end = start + len; 258 uint64_t clamped_end = MIN(end, s->len); 259 uint64_t clamped_len = clamped_end - start; 260 261 for (i=0; i<CURL_NUM_STATES; i++) { 262 CURLState *state = &s->states[i]; 263 uint64_t buf_end = (state->buf_start + state->buf_off); 264 uint64_t buf_fend = (state->buf_start + state->buf_len); 265 266 if (!state->orig_buf) 267 continue; 268 if (!state->buf_off) 269 continue; 270 271 // Does the existing buffer cover our section? 272 if ((start >= state->buf_start) && 273 (start <= buf_end) && 274 (clamped_end >= state->buf_start) && 275 (clamped_end <= buf_end)) 276 { 277 char *buf = state->orig_buf + (start - state->buf_start); 278 279 qemu_iovec_from_buf(acb->qiov, 0, buf, clamped_len); 280 if (clamped_len < len) { 281 qemu_iovec_memset(acb->qiov, clamped_len, 0, len - clamped_len); 282 } 283 acb->ret = 0; 284 return true; 285 } 286 287 // Wait for unfinished chunks 288 if (state->in_use && 289 (start >= state->buf_start) && 290 (start <= buf_fend) && 291 (clamped_end >= state->buf_start) && 292 (clamped_end <= buf_fend)) 293 { 294 int j; 295 296 acb->start = start - state->buf_start; 297 acb->end = acb->start + clamped_len; 298 299 for (j=0; j<CURL_NUM_ACB; j++) { 300 if (!state->acb[j]) { 301 state->acb[j] = acb; 302 return true; 303 } 304 } 305 } 306 } 307 308 return false; 309 } 310 311 /* Called with s->mutex held. */ 312 static void curl_multi_check_completion(BDRVCURLState *s) 313 { 314 int msgs_in_queue; 315 316 /* Try to find done transfers, so we can free the easy 317 * handle again. */ 318 for (;;) { 319 CURLMsg *msg; 320 msg = curl_multi_info_read(s->multi, &msgs_in_queue); 321 322 /* Quit when there are no more completions */ 323 if (!msg) 324 break; 325 326 if (msg->msg == CURLMSG_DONE) { 327 int i; 328 CURLState *state = NULL; 329 bool error = msg->data.result != CURLE_OK; 330 331 curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, 332 (char **)&state); 333 334 if (error) { 335 static int errcount = 100; 336 337 /* Don't lose the original error message from curl, since 338 * it contains extra data. 339 */ 340 if (errcount > 0) { 341 error_report("curl: %s", state->errmsg); 342 if (--errcount == 0) { 343 error_report("curl: further errors suppressed"); 344 } 345 } 346 } 347 348 for (i = 0; i < CURL_NUM_ACB; i++) { 349 CURLAIOCB *acb = state->acb[i]; 350 351 if (acb == NULL) { 352 continue; 353 } 354 355 if (!error) { 356 /* Assert that we have read all data */ 357 assert(state->buf_off >= acb->end); 358 359 qemu_iovec_from_buf(acb->qiov, 0, 360 state->orig_buf + acb->start, 361 acb->end - acb->start); 362 363 if (acb->end - acb->start < acb->bytes) { 364 size_t offset = acb->end - acb->start; 365 qemu_iovec_memset(acb->qiov, offset, 0, 366 acb->bytes - offset); 367 } 368 } 369 370 acb->ret = error ? -EIO : 0; 371 state->acb[i] = NULL; 372 qemu_mutex_unlock(&s->mutex); 373 aio_co_wake(acb->co); 374 qemu_mutex_lock(&s->mutex); 375 } 376 377 curl_clean_state(state); 378 break; 379 } 380 } 381 } 382 383 /* Called with s->mutex held. */ 384 static void curl_multi_do_locked(CURLSocket *socket) 385 { 386 BDRVCURLState *s = socket->state->s; 387 int running; 388 int r; 389 390 if (!s->multi) { 391 return; 392 } 393 394 do { 395 r = curl_multi_socket_action(s->multi, socket->fd, 0, &running); 396 } while (r == CURLM_CALL_MULTI_PERFORM); 397 } 398 399 static void curl_multi_do(void *arg) 400 { 401 CURLSocket *socket = arg; 402 BDRVCURLState *s = socket->state->s; 403 404 qemu_mutex_lock(&s->mutex); 405 curl_multi_do_locked(socket); 406 curl_multi_check_completion(s); 407 qemu_mutex_unlock(&s->mutex); 408 } 409 410 static void curl_multi_timeout_do(void *arg) 411 { 412 #ifdef NEED_CURL_TIMER_CALLBACK 413 BDRVCURLState *s = (BDRVCURLState *)arg; 414 int running; 415 416 if (!s->multi) { 417 return; 418 } 419 420 qemu_mutex_lock(&s->mutex); 421 curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running); 422 423 curl_multi_check_completion(s); 424 qemu_mutex_unlock(&s->mutex); 425 #else 426 abort(); 427 #endif 428 } 429 430 /* Called with s->mutex held. */ 431 static CURLState *curl_find_state(BDRVCURLState *s) 432 { 433 CURLState *state = NULL; 434 int i; 435 436 for (i = 0; i < CURL_NUM_STATES; i++) { 437 if (!s->states[i].in_use) { 438 state = &s->states[i]; 439 state->in_use = 1; 440 break; 441 } 442 } 443 return state; 444 } 445 446 static int curl_init_state(BDRVCURLState *s, CURLState *state) 447 { 448 if (!state->curl) { 449 state->curl = curl_easy_init(); 450 if (!state->curl) { 451 return -EIO; 452 } 453 curl_easy_setopt(state->curl, CURLOPT_URL, s->url); 454 curl_easy_setopt(state->curl, CURLOPT_SSL_VERIFYPEER, 455 (long) s->sslverify); 456 curl_easy_setopt(state->curl, CURLOPT_SSL_VERIFYHOST, 457 s->sslverify ? 2L : 0L); 458 if (s->cookie) { 459 curl_easy_setopt(state->curl, CURLOPT_COOKIE, s->cookie); 460 } 461 curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, (long)s->timeout); 462 curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION, 463 (void *)curl_read_cb); 464 curl_easy_setopt(state->curl, CURLOPT_WRITEDATA, (void *)state); 465 curl_easy_setopt(state->curl, CURLOPT_PRIVATE, (void *)state); 466 curl_easy_setopt(state->curl, CURLOPT_AUTOREFERER, 1); 467 curl_easy_setopt(state->curl, CURLOPT_FOLLOWLOCATION, 1); 468 curl_easy_setopt(state->curl, CURLOPT_NOSIGNAL, 1); 469 curl_easy_setopt(state->curl, CURLOPT_ERRORBUFFER, state->errmsg); 470 curl_easy_setopt(state->curl, CURLOPT_FAILONERROR, 1); 471 472 if (s->username) { 473 curl_easy_setopt(state->curl, CURLOPT_USERNAME, s->username); 474 } 475 if (s->password) { 476 curl_easy_setopt(state->curl, CURLOPT_PASSWORD, s->password); 477 } 478 if (s->proxyusername) { 479 curl_easy_setopt(state->curl, 480 CURLOPT_PROXYUSERNAME, s->proxyusername); 481 } 482 if (s->proxypassword) { 483 curl_easy_setopt(state->curl, 484 CURLOPT_PROXYPASSWORD, s->proxypassword); 485 } 486 487 /* Restrict supported protocols to avoid security issues in the more 488 * obscure protocols. For example, do not allow POP3/SMTP/IMAP see 489 * CVE-2013-0249. 490 * 491 * Restricting protocols is only supported from 7.19.4 upwards. 492 */ 493 #if LIBCURL_VERSION_NUM >= 0x071304 494 curl_easy_setopt(state->curl, CURLOPT_PROTOCOLS, PROTOCOLS); 495 curl_easy_setopt(state->curl, CURLOPT_REDIR_PROTOCOLS, PROTOCOLS); 496 #endif 497 498 #ifdef DEBUG_VERBOSE 499 curl_easy_setopt(state->curl, CURLOPT_VERBOSE, 1); 500 #endif 501 } 502 503 QLIST_INIT(&state->sockets); 504 state->s = s; 505 506 return 0; 507 } 508 509 /* Called with s->mutex held. */ 510 static void curl_clean_state(CURLState *s) 511 { 512 int j; 513 for (j = 0; j < CURL_NUM_ACB; j++) { 514 assert(!s->acb[j]); 515 } 516 517 if (s->s->multi) 518 curl_multi_remove_handle(s->s->multi, s->curl); 519 520 while (!QLIST_EMPTY(&s->sockets)) { 521 CURLSocket *socket = QLIST_FIRST(&s->sockets); 522 523 QLIST_REMOVE(socket, next); 524 g_free(socket); 525 } 526 527 s->in_use = 0; 528 529 qemu_co_enter_next(&s->s->free_state_waitq, &s->s->mutex); 530 } 531 532 static void curl_parse_filename(const char *filename, QDict *options, 533 Error **errp) 534 { 535 qdict_put_str(options, CURL_BLOCK_OPT_URL, filename); 536 } 537 538 static void curl_detach_aio_context(BlockDriverState *bs) 539 { 540 BDRVCURLState *s = bs->opaque; 541 int i; 542 543 qemu_mutex_lock(&s->mutex); 544 for (i = 0; i < CURL_NUM_STATES; i++) { 545 if (s->states[i].in_use) { 546 curl_clean_state(&s->states[i]); 547 } 548 if (s->states[i].curl) { 549 curl_easy_cleanup(s->states[i].curl); 550 s->states[i].curl = NULL; 551 } 552 g_free(s->states[i].orig_buf); 553 s->states[i].orig_buf = NULL; 554 } 555 if (s->multi) { 556 curl_multi_cleanup(s->multi); 557 s->multi = NULL; 558 } 559 qemu_mutex_unlock(&s->mutex); 560 561 timer_del(&s->timer); 562 } 563 564 static void curl_attach_aio_context(BlockDriverState *bs, 565 AioContext *new_context) 566 { 567 BDRVCURLState *s = bs->opaque; 568 569 aio_timer_init(new_context, &s->timer, 570 QEMU_CLOCK_REALTIME, SCALE_NS, 571 curl_multi_timeout_do, s); 572 573 assert(!s->multi); 574 s->multi = curl_multi_init(); 575 s->aio_context = new_context; 576 curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb); 577 #ifdef NEED_CURL_TIMER_CALLBACK 578 curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s); 579 curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb); 580 #endif 581 } 582 583 static QemuOptsList runtime_opts = { 584 .name = "curl", 585 .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head), 586 .desc = { 587 { 588 .name = CURL_BLOCK_OPT_URL, 589 .type = QEMU_OPT_STRING, 590 .help = "URL to open", 591 }, 592 { 593 .name = CURL_BLOCK_OPT_READAHEAD, 594 .type = QEMU_OPT_SIZE, 595 .help = "Readahead size", 596 }, 597 { 598 .name = CURL_BLOCK_OPT_SSLVERIFY, 599 .type = QEMU_OPT_BOOL, 600 .help = "Verify SSL certificate" 601 }, 602 { 603 .name = CURL_BLOCK_OPT_TIMEOUT, 604 .type = QEMU_OPT_NUMBER, 605 .help = "Curl timeout" 606 }, 607 { 608 .name = CURL_BLOCK_OPT_COOKIE, 609 .type = QEMU_OPT_STRING, 610 .help = "Pass the cookie or list of cookies with each request" 611 }, 612 { 613 .name = CURL_BLOCK_OPT_COOKIE_SECRET, 614 .type = QEMU_OPT_STRING, 615 .help = "ID of secret used as cookie passed with each request" 616 }, 617 { 618 .name = CURL_BLOCK_OPT_USERNAME, 619 .type = QEMU_OPT_STRING, 620 .help = "Username for HTTP auth" 621 }, 622 { 623 .name = CURL_BLOCK_OPT_PASSWORD_SECRET, 624 .type = QEMU_OPT_STRING, 625 .help = "ID of secret used as password for HTTP auth", 626 }, 627 { 628 .name = CURL_BLOCK_OPT_PROXY_USERNAME, 629 .type = QEMU_OPT_STRING, 630 .help = "Username for HTTP proxy auth" 631 }, 632 { 633 .name = CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET, 634 .type = QEMU_OPT_STRING, 635 .help = "ID of secret used as password for HTTP proxy auth", 636 }, 637 { /* end of list */ } 638 }, 639 }; 640 641 642 static int curl_open(BlockDriverState *bs, QDict *options, int flags, 643 Error **errp) 644 { 645 BDRVCURLState *s = bs->opaque; 646 CURLState *state = NULL; 647 QemuOpts *opts; 648 Error *local_err = NULL; 649 const char *file; 650 const char *cookie; 651 const char *cookie_secret; 652 double d; 653 const char *secretid; 654 const char *protocol_delimiter; 655 int ret; 656 657 ret = bdrv_apply_auto_read_only(bs, "curl driver does not support writes", 658 errp); 659 if (ret < 0) { 660 return ret; 661 } 662 663 if (!libcurl_initialized) { 664 ret = curl_global_init(CURL_GLOBAL_ALL); 665 if (ret) { 666 error_setg(errp, "libcurl initialization failed with %d", ret); 667 return -EIO; 668 } 669 libcurl_initialized = true; 670 } 671 672 qemu_mutex_init(&s->mutex); 673 opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); 674 qemu_opts_absorb_qdict(opts, options, &local_err); 675 if (local_err) { 676 error_propagate(errp, local_err); 677 goto out_noclean; 678 } 679 680 s->readahead_size = qemu_opt_get_size(opts, CURL_BLOCK_OPT_READAHEAD, 681 CURL_BLOCK_OPT_READAHEAD_DEFAULT); 682 if ((s->readahead_size & 0x1ff) != 0) { 683 error_setg(errp, "HTTP_READAHEAD_SIZE %zd is not a multiple of 512", 684 s->readahead_size); 685 goto out_noclean; 686 } 687 688 s->timeout = qemu_opt_get_number(opts, CURL_BLOCK_OPT_TIMEOUT, 689 CURL_BLOCK_OPT_TIMEOUT_DEFAULT); 690 if (s->timeout > CURL_TIMEOUT_MAX) { 691 error_setg(errp, "timeout parameter is too large or negative"); 692 goto out_noclean; 693 } 694 695 s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY, 696 CURL_BLOCK_OPT_SSLVERIFY_DEFAULT); 697 698 cookie = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE); 699 cookie_secret = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE_SECRET); 700 701 if (cookie && cookie_secret) { 702 error_setg(errp, 703 "curl driver cannot handle both cookie and cookie secret"); 704 goto out_noclean; 705 } 706 707 if (cookie_secret) { 708 s->cookie = qcrypto_secret_lookup_as_utf8(cookie_secret, errp); 709 if (!s->cookie) { 710 goto out_noclean; 711 } 712 } else { 713 s->cookie = g_strdup(cookie); 714 } 715 716 file = qemu_opt_get(opts, CURL_BLOCK_OPT_URL); 717 if (file == NULL) { 718 error_setg(errp, "curl block driver requires an 'url' option"); 719 goto out_noclean; 720 } 721 722 if (!strstart(file, bs->drv->protocol_name, &protocol_delimiter) || 723 !strstart(protocol_delimiter, "://", NULL)) 724 { 725 error_setg(errp, "%s curl driver cannot handle the URL '%s' (does not " 726 "start with '%s://')", bs->drv->protocol_name, file, 727 bs->drv->protocol_name); 728 goto out_noclean; 729 } 730 731 s->username = g_strdup(qemu_opt_get(opts, CURL_BLOCK_OPT_USERNAME)); 732 secretid = qemu_opt_get(opts, CURL_BLOCK_OPT_PASSWORD_SECRET); 733 734 if (secretid) { 735 s->password = qcrypto_secret_lookup_as_utf8(secretid, errp); 736 if (!s->password) { 737 goto out_noclean; 738 } 739 } 740 741 s->proxyusername = g_strdup( 742 qemu_opt_get(opts, CURL_BLOCK_OPT_PROXY_USERNAME)); 743 secretid = qemu_opt_get(opts, CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET); 744 if (secretid) { 745 s->proxypassword = qcrypto_secret_lookup_as_utf8(secretid, errp); 746 if (!s->proxypassword) { 747 goto out_noclean; 748 } 749 } 750 751 trace_curl_open(file); 752 qemu_co_queue_init(&s->free_state_waitq); 753 s->aio_context = bdrv_get_aio_context(bs); 754 s->url = g_strdup(file); 755 qemu_mutex_lock(&s->mutex); 756 state = curl_find_state(s); 757 qemu_mutex_unlock(&s->mutex); 758 if (!state) { 759 goto out_noclean; 760 } 761 762 // Get file size 763 764 if (curl_init_state(s, state) < 0) { 765 goto out; 766 } 767 768 s->accept_range = false; 769 curl_easy_setopt(state->curl, CURLOPT_NOBODY, 1); 770 curl_easy_setopt(state->curl, CURLOPT_HEADERFUNCTION, 771 curl_header_cb); 772 curl_easy_setopt(state->curl, CURLOPT_HEADERDATA, s); 773 if (curl_easy_perform(state->curl)) 774 goto out; 775 if (curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d)) { 776 goto out; 777 } 778 /* Prior CURL 7.19.4 return value of 0 could mean that the file size is not 779 * know or the size is zero. From 7.19.4 CURL returns -1 if size is not 780 * known and zero if it is really zero-length file. */ 781 #if LIBCURL_VERSION_NUM >= 0x071304 782 if (d < 0) { 783 pstrcpy(state->errmsg, CURL_ERROR_SIZE, 784 "Server didn't report file size."); 785 goto out; 786 } 787 #else 788 if (d <= 0) { 789 pstrcpy(state->errmsg, CURL_ERROR_SIZE, 790 "Unknown file size or zero-length file."); 791 goto out; 792 } 793 #endif 794 795 s->len = d; 796 797 if ((!strncasecmp(s->url, "http://", strlen("http://")) 798 || !strncasecmp(s->url, "https://", strlen("https://"))) 799 && !s->accept_range) { 800 pstrcpy(state->errmsg, CURL_ERROR_SIZE, 801 "Server does not support 'range' (byte ranges)."); 802 goto out; 803 } 804 trace_curl_open_size(s->len); 805 806 qemu_mutex_lock(&s->mutex); 807 curl_clean_state(state); 808 qemu_mutex_unlock(&s->mutex); 809 curl_easy_cleanup(state->curl); 810 state->curl = NULL; 811 812 curl_attach_aio_context(bs, bdrv_get_aio_context(bs)); 813 814 qemu_opts_del(opts); 815 return 0; 816 817 out: 818 error_setg(errp, "CURL: Error opening file: %s", state->errmsg); 819 curl_easy_cleanup(state->curl); 820 state->curl = NULL; 821 out_noclean: 822 qemu_mutex_destroy(&s->mutex); 823 g_free(s->cookie); 824 g_free(s->url); 825 g_free(s->username); 826 g_free(s->proxyusername); 827 g_free(s->proxypassword); 828 qemu_opts_del(opts); 829 return -EINVAL; 830 } 831 832 static void curl_setup_preadv(BlockDriverState *bs, CURLAIOCB *acb) 833 { 834 CURLState *state; 835 int running; 836 837 BDRVCURLState *s = bs->opaque; 838 839 uint64_t start = acb->offset; 840 uint64_t end; 841 842 qemu_mutex_lock(&s->mutex); 843 844 // In case we have the requested data already (e.g. read-ahead), 845 // we can just call the callback and be done. 846 if (curl_find_buf(s, start, acb->bytes, acb)) { 847 goto out; 848 } 849 850 // No cache found, so let's start a new request 851 for (;;) { 852 state = curl_find_state(s); 853 if (state) { 854 break; 855 } 856 qemu_co_queue_wait(&s->free_state_waitq, &s->mutex); 857 } 858 859 if (curl_init_state(s, state) < 0) { 860 curl_clean_state(state); 861 acb->ret = -EIO; 862 goto out; 863 } 864 865 acb->start = 0; 866 acb->end = MIN(acb->bytes, s->len - start); 867 868 state->buf_off = 0; 869 g_free(state->orig_buf); 870 state->buf_start = start; 871 state->buf_len = MIN(acb->end + s->readahead_size, s->len - start); 872 end = start + state->buf_len - 1; 873 state->orig_buf = g_try_malloc(state->buf_len); 874 if (state->buf_len && state->orig_buf == NULL) { 875 curl_clean_state(state); 876 acb->ret = -ENOMEM; 877 goto out; 878 } 879 state->acb[0] = acb; 880 881 snprintf(state->range, 127, "%" PRIu64 "-%" PRIu64, start, end); 882 trace_curl_setup_preadv(acb->bytes, start, state->range); 883 curl_easy_setopt(state->curl, CURLOPT_RANGE, state->range); 884 885 if (curl_multi_add_handle(s->multi, state->curl) != CURLM_OK) { 886 state->acb[0] = NULL; 887 acb->ret = -EIO; 888 889 curl_clean_state(state); 890 goto out; 891 } 892 893 /* Tell curl it needs to kick things off */ 894 curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running); 895 896 out: 897 qemu_mutex_unlock(&s->mutex); 898 } 899 900 static int coroutine_fn curl_co_preadv(BlockDriverState *bs, 901 uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags) 902 { 903 CURLAIOCB acb = { 904 .co = qemu_coroutine_self(), 905 .ret = -EINPROGRESS, 906 .qiov = qiov, 907 .offset = offset, 908 .bytes = bytes 909 }; 910 911 curl_setup_preadv(bs, &acb); 912 while (acb.ret == -EINPROGRESS) { 913 qemu_coroutine_yield(); 914 } 915 return acb.ret; 916 } 917 918 static void curl_close(BlockDriverState *bs) 919 { 920 BDRVCURLState *s = bs->opaque; 921 922 trace_curl_close(); 923 curl_detach_aio_context(bs); 924 qemu_mutex_destroy(&s->mutex); 925 926 g_free(s->cookie); 927 g_free(s->url); 928 g_free(s->username); 929 g_free(s->proxyusername); 930 g_free(s->proxypassword); 931 } 932 933 static int64_t curl_getlength(BlockDriverState *bs) 934 { 935 BDRVCURLState *s = bs->opaque; 936 return s->len; 937 } 938 939 static void curl_refresh_filename(BlockDriverState *bs) 940 { 941 BDRVCURLState *s = bs->opaque; 942 943 /* "readahead" and "timeout" do not change the guest-visible data, 944 * so ignore them */ 945 if (s->sslverify != CURL_BLOCK_OPT_SSLVERIFY_DEFAULT || 946 s->cookie || s->username || s->password || s->proxyusername || 947 s->proxypassword) 948 { 949 return; 950 } 951 952 pstrcpy(bs->exact_filename, sizeof(bs->exact_filename), s->url); 953 } 954 955 956 static const char *const curl_strong_runtime_opts[] = { 957 CURL_BLOCK_OPT_URL, 958 CURL_BLOCK_OPT_SSLVERIFY, 959 CURL_BLOCK_OPT_COOKIE, 960 CURL_BLOCK_OPT_COOKIE_SECRET, 961 CURL_BLOCK_OPT_USERNAME, 962 CURL_BLOCK_OPT_PASSWORD_SECRET, 963 CURL_BLOCK_OPT_PROXY_USERNAME, 964 CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET, 965 966 NULL 967 }; 968 969 static BlockDriver bdrv_http = { 970 .format_name = "http", 971 .protocol_name = "http", 972 973 .instance_size = sizeof(BDRVCURLState), 974 .bdrv_parse_filename = curl_parse_filename, 975 .bdrv_file_open = curl_open, 976 .bdrv_close = curl_close, 977 .bdrv_getlength = curl_getlength, 978 979 .bdrv_co_preadv = curl_co_preadv, 980 981 .bdrv_detach_aio_context = curl_detach_aio_context, 982 .bdrv_attach_aio_context = curl_attach_aio_context, 983 984 .bdrv_refresh_filename = curl_refresh_filename, 985 .strong_runtime_opts = curl_strong_runtime_opts, 986 }; 987 988 static BlockDriver bdrv_https = { 989 .format_name = "https", 990 .protocol_name = "https", 991 992 .instance_size = sizeof(BDRVCURLState), 993 .bdrv_parse_filename = curl_parse_filename, 994 .bdrv_file_open = curl_open, 995 .bdrv_close = curl_close, 996 .bdrv_getlength = curl_getlength, 997 998 .bdrv_co_preadv = curl_co_preadv, 999 1000 .bdrv_detach_aio_context = curl_detach_aio_context, 1001 .bdrv_attach_aio_context = curl_attach_aio_context, 1002 1003 .bdrv_refresh_filename = curl_refresh_filename, 1004 .strong_runtime_opts = curl_strong_runtime_opts, 1005 }; 1006 1007 static BlockDriver bdrv_ftp = { 1008 .format_name = "ftp", 1009 .protocol_name = "ftp", 1010 1011 .instance_size = sizeof(BDRVCURLState), 1012 .bdrv_parse_filename = curl_parse_filename, 1013 .bdrv_file_open = curl_open, 1014 .bdrv_close = curl_close, 1015 .bdrv_getlength = curl_getlength, 1016 1017 .bdrv_co_preadv = curl_co_preadv, 1018 1019 .bdrv_detach_aio_context = curl_detach_aio_context, 1020 .bdrv_attach_aio_context = curl_attach_aio_context, 1021 1022 .bdrv_refresh_filename = curl_refresh_filename, 1023 .strong_runtime_opts = curl_strong_runtime_opts, 1024 }; 1025 1026 static BlockDriver bdrv_ftps = { 1027 .format_name = "ftps", 1028 .protocol_name = "ftps", 1029 1030 .instance_size = sizeof(BDRVCURLState), 1031 .bdrv_parse_filename = curl_parse_filename, 1032 .bdrv_file_open = curl_open, 1033 .bdrv_close = curl_close, 1034 .bdrv_getlength = curl_getlength, 1035 1036 .bdrv_co_preadv = curl_co_preadv, 1037 1038 .bdrv_detach_aio_context = curl_detach_aio_context, 1039 .bdrv_attach_aio_context = curl_attach_aio_context, 1040 1041 .bdrv_refresh_filename = curl_refresh_filename, 1042 .strong_runtime_opts = curl_strong_runtime_opts, 1043 }; 1044 1045 static void curl_block_init(void) 1046 { 1047 bdrv_register(&bdrv_http); 1048 bdrv_register(&bdrv_https); 1049 bdrv_register(&bdrv_ftp); 1050 bdrv_register(&bdrv_ftps); 1051 } 1052 1053 block_init(curl_block_init); 1054