1 /* 2 * Secure Shell (ssh) backend for QEMU. 3 * 4 * Copyright (C) 2013 Red Hat Inc., Richard W.M. Jones <rjones@redhat.com> 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 27 #include <libssh2.h> 28 #include <libssh2_sftp.h> 29 30 #include "block/block_int.h" 31 #include "qapi/error.h" 32 #include "qemu/error-report.h" 33 #include "qemu/sockets.h" 34 #include "qemu/uri.h" 35 #include "qapi/qmp/qint.h" 36 #include "qapi/qmp/qstring.h" 37 38 /* DEBUG_SSH=1 enables the DPRINTF (debugging printf) statements in 39 * this block driver code. 40 * 41 * TRACE_LIBSSH2=<bitmask> enables tracing in libssh2 itself. Note 42 * that this requires that libssh2 was specially compiled with the 43 * `./configure --enable-debug' option, so most likely you will have 44 * to compile it yourself. The meaning of <bitmask> is described 45 * here: http://www.libssh2.org/libssh2_trace.html 46 */ 47 #define DEBUG_SSH 0 48 #define TRACE_LIBSSH2 0 /* or try: LIBSSH2_TRACE_SFTP */ 49 50 #define DPRINTF(fmt, ...) \ 51 do { \ 52 if (DEBUG_SSH) { \ 53 fprintf(stderr, "ssh: %-15s " fmt "\n", \ 54 __func__, ##__VA_ARGS__); \ 55 } \ 56 } while (0) 57 58 typedef struct BDRVSSHState { 59 /* Coroutine. */ 60 CoMutex lock; 61 62 /* SSH connection. */ 63 int sock; /* socket */ 64 LIBSSH2_SESSION *session; /* ssh session */ 65 LIBSSH2_SFTP *sftp; /* sftp session */ 66 LIBSSH2_SFTP_HANDLE *sftp_handle; /* sftp remote file handle */ 67 68 /* See ssh_seek() function below. */ 69 int64_t offset; 70 bool offset_op_read; 71 72 /* File attributes at open. We try to keep the .filesize field 73 * updated if it changes (eg by writing at the end of the file). 74 */ 75 LIBSSH2_SFTP_ATTRIBUTES attrs; 76 77 /* Used to warn if 'flush' is not supported. */ 78 char *hostport; 79 bool unsafe_flush_warning; 80 } BDRVSSHState; 81 82 static void ssh_state_init(BDRVSSHState *s) 83 { 84 memset(s, 0, sizeof *s); 85 s->sock = -1; 86 s->offset = -1; 87 qemu_co_mutex_init(&s->lock); 88 } 89 90 static void ssh_state_free(BDRVSSHState *s) 91 { 92 g_free(s->hostport); 93 if (s->sftp_handle) { 94 libssh2_sftp_close(s->sftp_handle); 95 } 96 if (s->sftp) { 97 libssh2_sftp_shutdown(s->sftp); 98 } 99 if (s->session) { 100 libssh2_session_disconnect(s->session, 101 "from qemu ssh client: " 102 "user closed the connection"); 103 libssh2_session_free(s->session); 104 } 105 if (s->sock >= 0) { 106 close(s->sock); 107 } 108 } 109 110 static void GCC_FMT_ATTR(3, 4) 111 session_error_setg(Error **errp, BDRVSSHState *s, const char *fs, ...) 112 { 113 va_list args; 114 char *msg; 115 116 va_start(args, fs); 117 msg = g_strdup_vprintf(fs, args); 118 va_end(args); 119 120 if (s->session) { 121 char *ssh_err; 122 int ssh_err_code; 123 124 /* This is not an errno. See <libssh2.h>. */ 125 ssh_err_code = libssh2_session_last_error(s->session, 126 &ssh_err, NULL, 0); 127 error_setg(errp, "%s: %s (libssh2 error code: %d)", 128 msg, ssh_err, ssh_err_code); 129 } else { 130 error_setg(errp, "%s", msg); 131 } 132 g_free(msg); 133 } 134 135 static void GCC_FMT_ATTR(3, 4) 136 sftp_error_setg(Error **errp, BDRVSSHState *s, const char *fs, ...) 137 { 138 va_list args; 139 char *msg; 140 141 va_start(args, fs); 142 msg = g_strdup_vprintf(fs, args); 143 va_end(args); 144 145 if (s->sftp) { 146 char *ssh_err; 147 int ssh_err_code; 148 unsigned long sftp_err_code; 149 150 /* This is not an errno. See <libssh2.h>. */ 151 ssh_err_code = libssh2_session_last_error(s->session, 152 &ssh_err, NULL, 0); 153 /* See <libssh2_sftp.h>. */ 154 sftp_err_code = libssh2_sftp_last_error((s)->sftp); 155 156 error_setg(errp, 157 "%s: %s (libssh2 error code: %d, sftp error code: %lu)", 158 msg, ssh_err, ssh_err_code, sftp_err_code); 159 } else { 160 error_setg(errp, "%s", msg); 161 } 162 g_free(msg); 163 } 164 165 static void GCC_FMT_ATTR(2, 3) 166 sftp_error_report(BDRVSSHState *s, const char *fs, ...) 167 { 168 va_list args; 169 170 va_start(args, fs); 171 error_vprintf(fs, args); 172 173 if ((s)->sftp) { 174 char *ssh_err; 175 int ssh_err_code; 176 unsigned long sftp_err_code; 177 178 /* This is not an errno. See <libssh2.h>. */ 179 ssh_err_code = libssh2_session_last_error(s->session, 180 &ssh_err, NULL, 0); 181 /* See <libssh2_sftp.h>. */ 182 sftp_err_code = libssh2_sftp_last_error((s)->sftp); 183 184 error_printf(": %s (libssh2 error code: %d, sftp error code: %lu)", 185 ssh_err, ssh_err_code, sftp_err_code); 186 } 187 188 va_end(args); 189 error_printf("\n"); 190 } 191 192 static int parse_uri(const char *filename, QDict *options, Error **errp) 193 { 194 URI *uri = NULL; 195 QueryParams *qp; 196 int i; 197 198 uri = uri_parse(filename); 199 if (!uri) { 200 return -EINVAL; 201 } 202 203 if (strcmp(uri->scheme, "ssh") != 0) { 204 error_setg(errp, "URI scheme must be 'ssh'"); 205 goto err; 206 } 207 208 if (!uri->server || strcmp(uri->server, "") == 0) { 209 error_setg(errp, "missing hostname in URI"); 210 goto err; 211 } 212 213 if (!uri->path || strcmp(uri->path, "") == 0) { 214 error_setg(errp, "missing remote path in URI"); 215 goto err; 216 } 217 218 qp = query_params_parse(uri->query); 219 if (!qp) { 220 error_setg(errp, "could not parse query parameters"); 221 goto err; 222 } 223 224 if(uri->user && strcmp(uri->user, "") != 0) { 225 qdict_put(options, "user", qstring_from_str(uri->user)); 226 } 227 228 qdict_put(options, "host", qstring_from_str(uri->server)); 229 230 if (uri->port) { 231 qdict_put(options, "port", qint_from_int(uri->port)); 232 } 233 234 qdict_put(options, "path", qstring_from_str(uri->path)); 235 236 /* Pick out any query parameters that we understand, and ignore 237 * the rest. 238 */ 239 for (i = 0; i < qp->n; ++i) { 240 if (strcmp(qp->p[i].name, "host_key_check") == 0) { 241 qdict_put(options, "host_key_check", 242 qstring_from_str(qp->p[i].value)); 243 } 244 } 245 246 query_params_free(qp); 247 uri_free(uri); 248 return 0; 249 250 err: 251 if (uri) { 252 uri_free(uri); 253 } 254 return -EINVAL; 255 } 256 257 static void ssh_parse_filename(const char *filename, QDict *options, 258 Error **errp) 259 { 260 if (qdict_haskey(options, "user") || 261 qdict_haskey(options, "host") || 262 qdict_haskey(options, "port") || 263 qdict_haskey(options, "path") || 264 qdict_haskey(options, "host_key_check")) { 265 error_setg(errp, "user, host, port, path, host_key_check cannot be used at the same time as a file option"); 266 return; 267 } 268 269 parse_uri(filename, options, errp); 270 } 271 272 static int check_host_key_knownhosts(BDRVSSHState *s, 273 const char *host, int port, Error **errp) 274 { 275 const char *home; 276 char *knh_file = NULL; 277 LIBSSH2_KNOWNHOSTS *knh = NULL; 278 struct libssh2_knownhost *found; 279 int ret, r; 280 const char *hostkey; 281 size_t len; 282 int type; 283 284 hostkey = libssh2_session_hostkey(s->session, &len, &type); 285 if (!hostkey) { 286 ret = -EINVAL; 287 session_error_setg(errp, s, "failed to read remote host key"); 288 goto out; 289 } 290 291 knh = libssh2_knownhost_init(s->session); 292 if (!knh) { 293 ret = -EINVAL; 294 session_error_setg(errp, s, 295 "failed to initialize known hosts support"); 296 goto out; 297 } 298 299 home = getenv("HOME"); 300 if (home) { 301 knh_file = g_strdup_printf("%s/.ssh/known_hosts", home); 302 } else { 303 knh_file = g_strdup_printf("/root/.ssh/known_hosts"); 304 } 305 306 /* Read all known hosts from OpenSSH-style known_hosts file. */ 307 libssh2_knownhost_readfile(knh, knh_file, LIBSSH2_KNOWNHOST_FILE_OPENSSH); 308 309 r = libssh2_knownhost_checkp(knh, host, port, hostkey, len, 310 LIBSSH2_KNOWNHOST_TYPE_PLAIN| 311 LIBSSH2_KNOWNHOST_KEYENC_RAW, 312 &found); 313 switch (r) { 314 case LIBSSH2_KNOWNHOST_CHECK_MATCH: 315 /* OK */ 316 DPRINTF("host key OK: %s", found->key); 317 break; 318 case LIBSSH2_KNOWNHOST_CHECK_MISMATCH: 319 ret = -EINVAL; 320 session_error_setg(errp, s, 321 "host key does not match the one in known_hosts" 322 " (found key %s)", found->key); 323 goto out; 324 case LIBSSH2_KNOWNHOST_CHECK_NOTFOUND: 325 ret = -EINVAL; 326 session_error_setg(errp, s, "no host key was found in known_hosts"); 327 goto out; 328 case LIBSSH2_KNOWNHOST_CHECK_FAILURE: 329 ret = -EINVAL; 330 session_error_setg(errp, s, 331 "failure matching the host key with known_hosts"); 332 goto out; 333 default: 334 ret = -EINVAL; 335 session_error_setg(errp, s, "unknown error matching the host key" 336 " with known_hosts (%d)", r); 337 goto out; 338 } 339 340 /* known_hosts checking successful. */ 341 ret = 0; 342 343 out: 344 if (knh != NULL) { 345 libssh2_knownhost_free(knh); 346 } 347 g_free(knh_file); 348 return ret; 349 } 350 351 static unsigned hex2decimal(char ch) 352 { 353 if (ch >= '0' && ch <= '9') { 354 return (ch - '0'); 355 } else if (ch >= 'a' && ch <= 'f') { 356 return 10 + (ch - 'a'); 357 } else if (ch >= 'A' && ch <= 'F') { 358 return 10 + (ch - 'A'); 359 } 360 361 return -1; 362 } 363 364 /* Compare the binary fingerprint (hash of host key) with the 365 * host_key_check parameter. 366 */ 367 static int compare_fingerprint(const unsigned char *fingerprint, size_t len, 368 const char *host_key_check) 369 { 370 unsigned c; 371 372 while (len > 0) { 373 while (*host_key_check == ':') 374 host_key_check++; 375 if (!qemu_isxdigit(host_key_check[0]) || 376 !qemu_isxdigit(host_key_check[1])) 377 return 1; 378 c = hex2decimal(host_key_check[0]) * 16 + 379 hex2decimal(host_key_check[1]); 380 if (c - *fingerprint != 0) 381 return c - *fingerprint; 382 fingerprint++; 383 len--; 384 host_key_check += 2; 385 } 386 return *host_key_check - '\0'; 387 } 388 389 static int 390 check_host_key_hash(BDRVSSHState *s, const char *hash, 391 int hash_type, size_t fingerprint_len, Error **errp) 392 { 393 const char *fingerprint; 394 395 fingerprint = libssh2_hostkey_hash(s->session, hash_type); 396 if (!fingerprint) { 397 session_error_setg(errp, s, "failed to read remote host key"); 398 return -EINVAL; 399 } 400 401 if(compare_fingerprint((unsigned char *) fingerprint, fingerprint_len, 402 hash) != 0) { 403 error_setg(errp, "remote host key does not match host_key_check '%s'", 404 hash); 405 return -EPERM; 406 } 407 408 return 0; 409 } 410 411 static int check_host_key(BDRVSSHState *s, const char *host, int port, 412 const char *host_key_check, Error **errp) 413 { 414 /* host_key_check=no */ 415 if (strcmp(host_key_check, "no") == 0) { 416 return 0; 417 } 418 419 /* host_key_check=md5:xx:yy:zz:... */ 420 if (strncmp(host_key_check, "md5:", 4) == 0) { 421 return check_host_key_hash(s, &host_key_check[4], 422 LIBSSH2_HOSTKEY_HASH_MD5, 16, errp); 423 } 424 425 /* host_key_check=sha1:xx:yy:zz:... */ 426 if (strncmp(host_key_check, "sha1:", 5) == 0) { 427 return check_host_key_hash(s, &host_key_check[5], 428 LIBSSH2_HOSTKEY_HASH_SHA1, 20, errp); 429 } 430 431 /* host_key_check=yes */ 432 if (strcmp(host_key_check, "yes") == 0) { 433 return check_host_key_knownhosts(s, host, port, errp); 434 } 435 436 error_setg(errp, "unknown host_key_check setting (%s)", host_key_check); 437 return -EINVAL; 438 } 439 440 static int authenticate(BDRVSSHState *s, const char *user, Error **errp) 441 { 442 int r, ret; 443 const char *userauthlist; 444 LIBSSH2_AGENT *agent = NULL; 445 struct libssh2_agent_publickey *identity; 446 struct libssh2_agent_publickey *prev_identity = NULL; 447 448 userauthlist = libssh2_userauth_list(s->session, user, strlen(user)); 449 if (strstr(userauthlist, "publickey") == NULL) { 450 ret = -EPERM; 451 error_setg(errp, 452 "remote server does not support \"publickey\" authentication"); 453 goto out; 454 } 455 456 /* Connect to ssh-agent and try each identity in turn. */ 457 agent = libssh2_agent_init(s->session); 458 if (!agent) { 459 ret = -EINVAL; 460 session_error_setg(errp, s, "failed to initialize ssh-agent support"); 461 goto out; 462 } 463 if (libssh2_agent_connect(agent)) { 464 ret = -ECONNREFUSED; 465 session_error_setg(errp, s, "failed to connect to ssh-agent"); 466 goto out; 467 } 468 if (libssh2_agent_list_identities(agent)) { 469 ret = -EINVAL; 470 session_error_setg(errp, s, 471 "failed requesting identities from ssh-agent"); 472 goto out; 473 } 474 475 for(;;) { 476 r = libssh2_agent_get_identity(agent, &identity, prev_identity); 477 if (r == 1) { /* end of list */ 478 break; 479 } 480 if (r < 0) { 481 ret = -EINVAL; 482 session_error_setg(errp, s, 483 "failed to obtain identity from ssh-agent"); 484 goto out; 485 } 486 r = libssh2_agent_userauth(agent, user, identity); 487 if (r == 0) { 488 /* Authenticated! */ 489 ret = 0; 490 goto out; 491 } 492 /* Failed to authenticate with this identity, try the next one. */ 493 prev_identity = identity; 494 } 495 496 ret = -EPERM; 497 error_setg(errp, "failed to authenticate using publickey authentication " 498 "and the identities held by your ssh-agent"); 499 500 out: 501 if (agent != NULL) { 502 /* Note: libssh2 implementation implicitly calls 503 * libssh2_agent_disconnect if necessary. 504 */ 505 libssh2_agent_free(agent); 506 } 507 508 return ret; 509 } 510 511 static QemuOptsList ssh_runtime_opts = { 512 .name = "ssh", 513 .head = QTAILQ_HEAD_INITIALIZER(ssh_runtime_opts.head), 514 .desc = { 515 { 516 .name = "host", 517 .type = QEMU_OPT_STRING, 518 .help = "Host to connect to", 519 }, 520 { 521 .name = "port", 522 .type = QEMU_OPT_NUMBER, 523 .help = "Port to connect to", 524 }, 525 { 526 .name = "path", 527 .type = QEMU_OPT_STRING, 528 .help = "Path of the image on the host", 529 }, 530 { 531 .name = "user", 532 .type = QEMU_OPT_STRING, 533 .help = "User as which to connect", 534 }, 535 { 536 .name = "host_key_check", 537 .type = QEMU_OPT_STRING, 538 .help = "Defines how and what to check the host key against", 539 }, 540 }, 541 }; 542 543 static int connect_to_ssh(BDRVSSHState *s, QDict *options, 544 int ssh_flags, int creat_mode, Error **errp) 545 { 546 int r, ret; 547 QemuOpts *opts = NULL; 548 Error *local_err = NULL; 549 const char *host, *user, *path, *host_key_check; 550 int port; 551 552 opts = qemu_opts_create(&ssh_runtime_opts, NULL, 0, &error_abort); 553 qemu_opts_absorb_qdict(opts, options, &local_err); 554 if (local_err) { 555 ret = -EINVAL; 556 error_propagate(errp, local_err); 557 goto err; 558 } 559 560 host = qemu_opt_get(opts, "host"); 561 if (!host) { 562 ret = -EINVAL; 563 error_setg(errp, "No hostname was specified"); 564 goto err; 565 } 566 567 port = qemu_opt_get_number(opts, "port", 22); 568 569 path = qemu_opt_get(opts, "path"); 570 if (!path) { 571 ret = -EINVAL; 572 error_setg(errp, "No path was specified"); 573 goto err; 574 } 575 576 user = qemu_opt_get(opts, "user"); 577 if (!user) { 578 user = g_get_user_name(); 579 if (!user) { 580 error_setg_errno(errp, errno, "Can't get user name"); 581 ret = -errno; 582 goto err; 583 } 584 } 585 586 host_key_check = qemu_opt_get(opts, "host_key_check"); 587 if (!host_key_check) { 588 host_key_check = "yes"; 589 } 590 591 /* Construct the host:port name for inet_connect. */ 592 g_free(s->hostport); 593 s->hostport = g_strdup_printf("%s:%d", host, port); 594 595 /* Open the socket and connect. */ 596 s->sock = inet_connect(s->hostport, errp); 597 if (s->sock < 0) { 598 ret = -EIO; 599 goto err; 600 } 601 602 /* Create SSH session. */ 603 s->session = libssh2_session_init(); 604 if (!s->session) { 605 ret = -EINVAL; 606 session_error_setg(errp, s, "failed to initialize libssh2 session"); 607 goto err; 608 } 609 610 #if TRACE_LIBSSH2 != 0 611 libssh2_trace(s->session, TRACE_LIBSSH2); 612 #endif 613 614 r = libssh2_session_handshake(s->session, s->sock); 615 if (r != 0) { 616 ret = -EINVAL; 617 session_error_setg(errp, s, "failed to establish SSH session"); 618 goto err; 619 } 620 621 /* Check the remote host's key against known_hosts. */ 622 ret = check_host_key(s, host, port, host_key_check, errp); 623 if (ret < 0) { 624 goto err; 625 } 626 627 /* Authenticate. */ 628 ret = authenticate(s, user, errp); 629 if (ret < 0) { 630 goto err; 631 } 632 633 /* Start SFTP. */ 634 s->sftp = libssh2_sftp_init(s->session); 635 if (!s->sftp) { 636 session_error_setg(errp, s, "failed to initialize sftp handle"); 637 ret = -EINVAL; 638 goto err; 639 } 640 641 /* Open the remote file. */ 642 DPRINTF("opening file %s flags=0x%x creat_mode=0%o", 643 path, ssh_flags, creat_mode); 644 s->sftp_handle = libssh2_sftp_open(s->sftp, path, ssh_flags, creat_mode); 645 if (!s->sftp_handle) { 646 session_error_setg(errp, s, "failed to open remote file '%s'", path); 647 ret = -EINVAL; 648 goto err; 649 } 650 651 qemu_opts_del(opts); 652 653 r = libssh2_sftp_fstat(s->sftp_handle, &s->attrs); 654 if (r < 0) { 655 sftp_error_setg(errp, s, "failed to read file attributes"); 656 return -EINVAL; 657 } 658 659 return 0; 660 661 err: 662 if (s->sftp_handle) { 663 libssh2_sftp_close(s->sftp_handle); 664 } 665 s->sftp_handle = NULL; 666 if (s->sftp) { 667 libssh2_sftp_shutdown(s->sftp); 668 } 669 s->sftp = NULL; 670 if (s->session) { 671 libssh2_session_disconnect(s->session, 672 "from qemu ssh client: " 673 "error opening connection"); 674 libssh2_session_free(s->session); 675 } 676 s->session = NULL; 677 678 qemu_opts_del(opts); 679 680 return ret; 681 } 682 683 static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags, 684 Error **errp) 685 { 686 BDRVSSHState *s = bs->opaque; 687 int ret; 688 int ssh_flags; 689 690 ssh_state_init(s); 691 692 ssh_flags = LIBSSH2_FXF_READ; 693 if (bdrv_flags & BDRV_O_RDWR) { 694 ssh_flags |= LIBSSH2_FXF_WRITE; 695 } 696 697 /* Start up SSH. */ 698 ret = connect_to_ssh(s, options, ssh_flags, 0, errp); 699 if (ret < 0) { 700 goto err; 701 } 702 703 /* Go non-blocking. */ 704 libssh2_session_set_blocking(s->session, 0); 705 706 return 0; 707 708 err: 709 if (s->sock >= 0) { 710 close(s->sock); 711 } 712 s->sock = -1; 713 714 return ret; 715 } 716 717 static QemuOptsList ssh_create_opts = { 718 .name = "ssh-create-opts", 719 .head = QTAILQ_HEAD_INITIALIZER(ssh_create_opts.head), 720 .desc = { 721 { 722 .name = BLOCK_OPT_SIZE, 723 .type = QEMU_OPT_SIZE, 724 .help = "Virtual disk size" 725 }, 726 { /* end of list */ } 727 } 728 }; 729 730 static int ssh_create(const char *filename, QemuOpts *opts, Error **errp) 731 { 732 int r, ret; 733 int64_t total_size = 0; 734 QDict *uri_options = NULL; 735 BDRVSSHState s; 736 ssize_t r2; 737 char c[1] = { '\0' }; 738 739 ssh_state_init(&s); 740 741 /* Get desired file size. */ 742 total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), 743 BDRV_SECTOR_SIZE); 744 DPRINTF("total_size=%" PRIi64, total_size); 745 746 uri_options = qdict_new(); 747 r = parse_uri(filename, uri_options, errp); 748 if (r < 0) { 749 ret = r; 750 goto out; 751 } 752 753 r = connect_to_ssh(&s, uri_options, 754 LIBSSH2_FXF_READ|LIBSSH2_FXF_WRITE| 755 LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC, 756 0644, errp); 757 if (r < 0) { 758 ret = r; 759 goto out; 760 } 761 762 if (total_size > 0) { 763 libssh2_sftp_seek64(s.sftp_handle, total_size-1); 764 r2 = libssh2_sftp_write(s.sftp_handle, c, 1); 765 if (r2 < 0) { 766 sftp_error_setg(errp, &s, "truncate failed"); 767 ret = -EINVAL; 768 goto out; 769 } 770 s.attrs.filesize = total_size; 771 } 772 773 ret = 0; 774 775 out: 776 ssh_state_free(&s); 777 if (uri_options != NULL) { 778 QDECREF(uri_options); 779 } 780 return ret; 781 } 782 783 static void ssh_close(BlockDriverState *bs) 784 { 785 BDRVSSHState *s = bs->opaque; 786 787 ssh_state_free(s); 788 } 789 790 static int ssh_has_zero_init(BlockDriverState *bs) 791 { 792 BDRVSSHState *s = bs->opaque; 793 /* Assume false, unless we can positively prove it's true. */ 794 int has_zero_init = 0; 795 796 if (s->attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) { 797 if (s->attrs.permissions & LIBSSH2_SFTP_S_IFREG) { 798 has_zero_init = 1; 799 } 800 } 801 802 return has_zero_init; 803 } 804 805 static void restart_coroutine(void *opaque) 806 { 807 Coroutine *co = opaque; 808 809 DPRINTF("co=%p", co); 810 811 qemu_coroutine_enter(co); 812 } 813 814 static coroutine_fn void set_fd_handler(BDRVSSHState *s, BlockDriverState *bs) 815 { 816 int r; 817 IOHandler *rd_handler = NULL, *wr_handler = NULL; 818 Coroutine *co = qemu_coroutine_self(); 819 820 r = libssh2_session_block_directions(s->session); 821 822 if (r & LIBSSH2_SESSION_BLOCK_INBOUND) { 823 rd_handler = restart_coroutine; 824 } 825 if (r & LIBSSH2_SESSION_BLOCK_OUTBOUND) { 826 wr_handler = restart_coroutine; 827 } 828 829 DPRINTF("s->sock=%d rd_handler=%p wr_handler=%p", s->sock, 830 rd_handler, wr_handler); 831 832 aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock, 833 false, rd_handler, wr_handler, co); 834 } 835 836 static coroutine_fn void clear_fd_handler(BDRVSSHState *s, 837 BlockDriverState *bs) 838 { 839 DPRINTF("s->sock=%d", s->sock); 840 aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock, 841 false, NULL, NULL, NULL); 842 } 843 844 /* A non-blocking call returned EAGAIN, so yield, ensuring the 845 * handlers are set up so that we'll be rescheduled when there is an 846 * interesting event on the socket. 847 */ 848 static coroutine_fn void co_yield(BDRVSSHState *s, BlockDriverState *bs) 849 { 850 set_fd_handler(s, bs); 851 qemu_coroutine_yield(); 852 clear_fd_handler(s, bs); 853 } 854 855 /* SFTP has a function `libssh2_sftp_seek64' which seeks to a position 856 * in the remote file. Notice that it just updates a field in the 857 * sftp_handle structure, so there is no network traffic and it cannot 858 * fail. 859 * 860 * However, `libssh2_sftp_seek64' does have a catastrophic effect on 861 * performance since it causes the handle to throw away all in-flight 862 * reads and buffered readahead data. Therefore this function tries 863 * to be intelligent about when to call the underlying libssh2 function. 864 */ 865 #define SSH_SEEK_WRITE 0 866 #define SSH_SEEK_READ 1 867 #define SSH_SEEK_FORCE 2 868 869 static void ssh_seek(BDRVSSHState *s, int64_t offset, int flags) 870 { 871 bool op_read = (flags & SSH_SEEK_READ) != 0; 872 bool force = (flags & SSH_SEEK_FORCE) != 0; 873 874 if (force || op_read != s->offset_op_read || offset != s->offset) { 875 DPRINTF("seeking to offset=%" PRIi64, offset); 876 libssh2_sftp_seek64(s->sftp_handle, offset); 877 s->offset = offset; 878 s->offset_op_read = op_read; 879 } 880 } 881 882 static coroutine_fn int ssh_read(BDRVSSHState *s, BlockDriverState *bs, 883 int64_t offset, size_t size, 884 QEMUIOVector *qiov) 885 { 886 ssize_t r; 887 size_t got; 888 char *buf, *end_of_vec; 889 struct iovec *i; 890 891 DPRINTF("offset=%" PRIi64 " size=%zu", offset, size); 892 893 ssh_seek(s, offset, SSH_SEEK_READ); 894 895 /* This keeps track of the current iovec element ('i'), where we 896 * will write to next ('buf'), and the end of the current iovec 897 * ('end_of_vec'). 898 */ 899 i = &qiov->iov[0]; 900 buf = i->iov_base; 901 end_of_vec = i->iov_base + i->iov_len; 902 903 /* libssh2 has a hard-coded limit of 2000 bytes per request, 904 * although it will also do readahead behind our backs. Therefore 905 * we may have to do repeated reads here until we have read 'size' 906 * bytes. 907 */ 908 for (got = 0; got < size; ) { 909 again: 910 DPRINTF("sftp_read buf=%p size=%zu", buf, end_of_vec - buf); 911 r = libssh2_sftp_read(s->sftp_handle, buf, end_of_vec - buf); 912 DPRINTF("sftp_read returned %zd", r); 913 914 if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) { 915 co_yield(s, bs); 916 goto again; 917 } 918 if (r < 0) { 919 sftp_error_report(s, "read failed"); 920 s->offset = -1; 921 return -EIO; 922 } 923 if (r == 0) { 924 /* EOF: Short read so pad the buffer with zeroes and return it. */ 925 qemu_iovec_memset(qiov, got, 0, size - got); 926 return 0; 927 } 928 929 got += r; 930 buf += r; 931 s->offset += r; 932 if (buf >= end_of_vec && got < size) { 933 i++; 934 buf = i->iov_base; 935 end_of_vec = i->iov_base + i->iov_len; 936 } 937 } 938 939 return 0; 940 } 941 942 static coroutine_fn int ssh_co_readv(BlockDriverState *bs, 943 int64_t sector_num, 944 int nb_sectors, QEMUIOVector *qiov) 945 { 946 BDRVSSHState *s = bs->opaque; 947 int ret; 948 949 qemu_co_mutex_lock(&s->lock); 950 ret = ssh_read(s, bs, sector_num * BDRV_SECTOR_SIZE, 951 nb_sectors * BDRV_SECTOR_SIZE, qiov); 952 qemu_co_mutex_unlock(&s->lock); 953 954 return ret; 955 } 956 957 static int ssh_write(BDRVSSHState *s, BlockDriverState *bs, 958 int64_t offset, size_t size, 959 QEMUIOVector *qiov) 960 { 961 ssize_t r; 962 size_t written; 963 char *buf, *end_of_vec; 964 struct iovec *i; 965 966 DPRINTF("offset=%" PRIi64 " size=%zu", offset, size); 967 968 ssh_seek(s, offset, SSH_SEEK_WRITE); 969 970 /* This keeps track of the current iovec element ('i'), where we 971 * will read from next ('buf'), and the end of the current iovec 972 * ('end_of_vec'). 973 */ 974 i = &qiov->iov[0]; 975 buf = i->iov_base; 976 end_of_vec = i->iov_base + i->iov_len; 977 978 for (written = 0; written < size; ) { 979 again: 980 DPRINTF("sftp_write buf=%p size=%zu", buf, end_of_vec - buf); 981 r = libssh2_sftp_write(s->sftp_handle, buf, end_of_vec - buf); 982 DPRINTF("sftp_write returned %zd", r); 983 984 if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) { 985 co_yield(s, bs); 986 goto again; 987 } 988 if (r < 0) { 989 sftp_error_report(s, "write failed"); 990 s->offset = -1; 991 return -EIO; 992 } 993 /* The libssh2 API is very unclear about this. A comment in 994 * the code says "nothing was acked, and no EAGAIN was 995 * received!" which apparently means that no data got sent 996 * out, and the underlying channel didn't return any EAGAIN 997 * indication. I think this is a bug in either libssh2 or 998 * OpenSSH (server-side). In any case, forcing a seek (to 999 * discard libssh2 internal buffers), and then trying again 1000 * works for me. 1001 */ 1002 if (r == 0) { 1003 ssh_seek(s, offset + written, SSH_SEEK_WRITE|SSH_SEEK_FORCE); 1004 co_yield(s, bs); 1005 goto again; 1006 } 1007 1008 written += r; 1009 buf += r; 1010 s->offset += r; 1011 if (buf >= end_of_vec && written < size) { 1012 i++; 1013 buf = i->iov_base; 1014 end_of_vec = i->iov_base + i->iov_len; 1015 } 1016 1017 if (offset + written > s->attrs.filesize) 1018 s->attrs.filesize = offset + written; 1019 } 1020 1021 return 0; 1022 } 1023 1024 static coroutine_fn int ssh_co_writev(BlockDriverState *bs, 1025 int64_t sector_num, 1026 int nb_sectors, QEMUIOVector *qiov) 1027 { 1028 BDRVSSHState *s = bs->opaque; 1029 int ret; 1030 1031 qemu_co_mutex_lock(&s->lock); 1032 ret = ssh_write(s, bs, sector_num * BDRV_SECTOR_SIZE, 1033 nb_sectors * BDRV_SECTOR_SIZE, qiov); 1034 qemu_co_mutex_unlock(&s->lock); 1035 1036 return ret; 1037 } 1038 1039 static void unsafe_flush_warning(BDRVSSHState *s, const char *what) 1040 { 1041 if (!s->unsafe_flush_warning) { 1042 error_report("warning: ssh server %s does not support fsync", 1043 s->hostport); 1044 if (what) { 1045 error_report("to support fsync, you need %s", what); 1046 } 1047 s->unsafe_flush_warning = true; 1048 } 1049 } 1050 1051 #ifdef HAS_LIBSSH2_SFTP_FSYNC 1052 1053 static coroutine_fn int ssh_flush(BDRVSSHState *s, BlockDriverState *bs) 1054 { 1055 int r; 1056 1057 DPRINTF("fsync"); 1058 again: 1059 r = libssh2_sftp_fsync(s->sftp_handle); 1060 if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) { 1061 co_yield(s, bs); 1062 goto again; 1063 } 1064 if (r == LIBSSH2_ERROR_SFTP_PROTOCOL && 1065 libssh2_sftp_last_error(s->sftp) == LIBSSH2_FX_OP_UNSUPPORTED) { 1066 unsafe_flush_warning(s, "OpenSSH >= 6.3"); 1067 return 0; 1068 } 1069 if (r < 0) { 1070 sftp_error_report(s, "fsync failed"); 1071 return -EIO; 1072 } 1073 1074 return 0; 1075 } 1076 1077 static coroutine_fn int ssh_co_flush(BlockDriverState *bs) 1078 { 1079 BDRVSSHState *s = bs->opaque; 1080 int ret; 1081 1082 qemu_co_mutex_lock(&s->lock); 1083 ret = ssh_flush(s, bs); 1084 qemu_co_mutex_unlock(&s->lock); 1085 1086 return ret; 1087 } 1088 1089 #else /* !HAS_LIBSSH2_SFTP_FSYNC */ 1090 1091 static coroutine_fn int ssh_co_flush(BlockDriverState *bs) 1092 { 1093 BDRVSSHState *s = bs->opaque; 1094 1095 unsafe_flush_warning(s, "libssh2 >= 1.4.4"); 1096 return 0; 1097 } 1098 1099 #endif /* !HAS_LIBSSH2_SFTP_FSYNC */ 1100 1101 static int64_t ssh_getlength(BlockDriverState *bs) 1102 { 1103 BDRVSSHState *s = bs->opaque; 1104 int64_t length; 1105 1106 /* Note we cannot make a libssh2 call here. */ 1107 length = (int64_t) s->attrs.filesize; 1108 DPRINTF("length=%" PRIi64, length); 1109 1110 return length; 1111 } 1112 1113 static BlockDriver bdrv_ssh = { 1114 .format_name = "ssh", 1115 .protocol_name = "ssh", 1116 .instance_size = sizeof(BDRVSSHState), 1117 .bdrv_parse_filename = ssh_parse_filename, 1118 .bdrv_file_open = ssh_file_open, 1119 .bdrv_create = ssh_create, 1120 .bdrv_close = ssh_close, 1121 .bdrv_has_zero_init = ssh_has_zero_init, 1122 .bdrv_co_readv = ssh_co_readv, 1123 .bdrv_co_writev = ssh_co_writev, 1124 .bdrv_getlength = ssh_getlength, 1125 .bdrv_co_flush_to_disk = ssh_co_flush, 1126 .create_opts = &ssh_create_opts, 1127 }; 1128 1129 static void bdrv_ssh_init(void) 1130 { 1131 int r; 1132 1133 r = libssh2_init(0); 1134 if (r != 0) { 1135 fprintf(stderr, "libssh2 initialization failed, %d\n", r); 1136 exit(EXIT_FAILURE); 1137 } 1138 1139 bdrv_register(&bdrv_ssh); 1140 } 1141 1142 block_init(bdrv_ssh_init); 1143